Giter Site home page Giter Site logo

inkeliz / karmem Goto Github PK

View Code? Open in Web Editor NEW
639.0 6.0 25.0 8.04 MB

Karmem is a fast binary serialization format, faster than Google Flatbuffers and optimized for TinyGo and WASM.

License: BSD 3-Clause "New" or "Revised" License

Markdown 4.23% JSON 0.32% TypeScript 6.84% Swift 10.28% Zig 8.68% Go Module 0.19% Go Checksums 0.98% Go 36.67% INI 0.01% C 9.06% YAML 1.37% Makefile 1.12% Odin 7.60% C# 12.14% XML 0.51%
golang assemblyscript random-access serialization swift zig c go webassembly csharp

karmem's Introduction

KARMEM

builds.sr.ht status Coverage Status Go Report Card GitHub license

Karmem is a fast binary serialization format. The priority of Karmem is to be easy to use while been fast as possible. It's optimized to take Golang and TinyGo's maximum performance and is efficient for repeatable reads, reading different content of the same type. Karmem demonstrates to be ten times faster than Google Flatbuffers, with the additional overhead of bounds-checking included.

⚠️ Karmem still under development, the API is not stable. However, serialization-format itself is unlike to change and should remain backward compatible with older versions.

Contents

Motivation

Karmem was create to solve one single issue: make easy to transfer data between WebAssembly host and guest. While still portable for non-WebAssembly languages. We are experimenting with an "event-command pattern" between wasm-host and wasm-guest in one project, but sharing data is very expensive, and FFI calls are not cheap either. Karmem encodes once and shares the same content with multiple guests, regardless of the language, making it very efficient. Also, even using Object-API to decode, it's fast enough, and Karmem was designed to take advantage of that pattern, avoid allocations, and re-use the same struct for multiple data.

Why not use Witx? It is good project and aimed to WASM, however it seems more complex and defines not just data-structure, but functions, which I'm trying to avoid. Also, it is not intended to be portable to non-wasm. Why not use Flatbuffers? We tried, but it's not fast enough and also causes panics due to the lack of bound-checking. Why not use Cap'n'Proto? It's a good alternative but lacks implementation for Zig and AssemblyScript, which is top-priority, it also has more allocations and the generated API is harder to use, compared than Karmem.

Usage

That is a small example of how use Karmem.

Schema

karmem app @packed(true) @golang.package(`app`);  
  
enum SocialNetwork uint8 { Unknown; Facebook; Instagram; Twitter; TikTok; }  
  
struct ProfileData table {  
    Network  SocialNetwork;  
    Username []char;  
    ID       uint64;  
}  
  
struct Profile inline {  
    Data ProfileData;  
}  
  
struct AccountData table {  
    ID       uint64;  
    Email    []char;  
    Profiles []Profile;  
}

Generate the code using go run karmem.org/cmd/karmem build --golang -o "km" app.km.

Encoding

In order to encode, use should create an native struct and then encode it.

var writerPool = sync.Pool{New: func() any { return karmem.NewWriter(1024) }}

func main() {
	writer := writerPool.Get().(*karmem.Writer)

	content := app.AccountData{
		ID:    42,
		Email: "[email protected]",
		Profiles: []app.Profile{
			{Data: app.ProfileData{
				Network:  app.SocialNetworkFacebook,
				Username: "inkeliz",
				ID:       123,
			}},
			{Data: app.ProfileData{
				Network:  app.SocialNetworkFacebook,
				Username: "karmem",
				ID:       231,
			}},
			{Data: app.ProfileData{
				Network:  app.SocialNetworkInstagram,
				Username: "inkeliz",
				ID:       312,
			}},
		},
	}

	if _, err := content.WriteAsRoot(writer); err != nil {
		panic(err)
	}

	encoded := writer.Bytes()
	_ = encoded // Do something with encoded data

	writer.Reset()
	writerPool.Put(writer)
}

Reading

Instead of decoding it to another struct, you can read some fields directly, without any additional decoding. In this example, we only need the username of each profile.

func decodes(encoded []byte) {
	reader := karmem.NewReader(encoded)
	account := app.NewAccountDataViewer(reader, 0)

	profiles := account.Profiles(reader)
	for i := range profiles {
		fmt.Println(profiles[i].Data(reader).Username(reader))
	}
}

Notice: we use NewAccountDataViewer, any Viewer is just a Viewer, and doesn't copy the backend data. Some languages (C#, AssemblyScript) uses UTF-16, while Karmem uses UTF-8, in those cases you have some performance penalty.

Decoding

You can also decode it to an existent struct. In some cases, it's better if you re-use the same struct for multiples reads.

var accountPool = sync.Pool{New: func() any { return new(app.AccountData) }}

func decodes(encoded []byte) {
	account := accountPool.Get().(*app.AccountData)
	account.ReadAsRoot(karmem.NewReader(encoded))

	profiles := account.Profiles
	for i := range profiles {
		fmt.Println(profiles[i].Data.Username)
	}

	accountPool.Put(account)
}

Benchmark

Flatbuffers vs Karmem

Using similar schema with Flatbuffers and Karmem. Karmem is almost 10 times faster than Google Flatbuffers.

Native (MacOS/ARM64 - M1):

name               old time/op    new time/op    delta
EncodeObjectAPI-8    2.54ms ± 0%    0.51ms ± 0%   -79.85%  (p=0.008 n=5+5)
DecodeObjectAPI-8    3.57ms ± 0%    0.20ms ± 0%   -94.30%  (p=0.008 n=5+5)
DecodeSumVec3-8      1.44ms ± 0%    0.16ms ± 0%   -88.86%  (p=0.008 n=5+5)

name               old alloc/op   new alloc/op   delta
EncodeObjectAPI-8    12.1kB ± 0%     0.0kB       -100.00%  (p=0.008 n=5+5)
DecodeObjectAPI-8    2.87MB ± 0%    0.00MB       -100.00%  (p=0.008 n=5+5)
DecodeSumVec3-8       0.00B          0.00B           ~     (all equal)

name               old allocs/op  new allocs/op  delta
EncodeObjectAPI-8     1.00k ± 0%     0.00k       -100.00%  (p=0.008 n=5+5)
DecodeObjectAPI-8      110k ± 0%        0k       -100.00%  (p=0.008 n=5+5)
DecodeSumVec3-8        0.00           0.00           ~     (all equal)

WebAssembly on Wazero (MacOS/ARM64 - M1):

name               old time/op    new time/op    delta
EncodeObjectAPI-8    17.2ms ± 0%     4.0ms ± 0%  -76.51%  (p=0.008 n=5+5)
DecodeObjectAPI-8    50.7ms ± 2%     1.9ms ± 0%  -96.18%  (p=0.008 n=5+5)
DecodeSumVec3-8      5.74ms ± 0%    0.75ms ± 0%  -86.87%  (p=0.008 n=5+5)

name               old alloc/op   new alloc/op   delta
EncodeObjectAPI-8    3.28kB ± 0%    3.02kB ± 0%   -7.80%  (p=0.008 n=5+5)
DecodeObjectAPI-8    3.47MB ± 2%    0.02MB ± 0%  -99.56%  (p=0.008 n=5+5)
DecodeSumVec3-8      1.25kB ± 0%    1.25kB ± 0%     ~     (all equal)

name               old allocs/op  new allocs/op  delta
EncodeObjectAPI-8      4.00 ± 0%      4.00 ± 0%     ~     (all equal)
DecodeObjectAPI-8      5.00 ± 0%      4.00 ± 0%  -20.00%  (p=0.008 n=5+5)
DecodeSumVec3-8        5.00 ± 0%      5.00 ± 0%     ~     (all equal)

Raw-Struct vs Karmem

The performance is nearly the same when comparing reading non-serialized data from a native struct and reading it from a karmem-serialized data.

Native (MacOS/ARM64 - M1):

name             old time/op    new time/op    delta
DecodeSumVec3-8     154µs ± 0%     160µs ± 0%  +4.36%  (p=0.008 n=5+5)

name             old alloc/op   new alloc/op   delta
DecodeSumVec3-8     0.00B          0.00B         ~     (all equal)

name             old allocs/op  new allocs/op  delta
DecodeSumVec3-8      0.00           0.00         ~     (all equal)

Karmem vs Karmem

That is an comparison with all supported languages.

WebAssembly on Wazero (MacOS/ARM64 - M1):

name \ time/op     result/wasi-go-km.out  result/wasi-as-km.out  result/wasi-zig-km.out  result/wasi-swift-km.out  result/wasi-c-km.out  result/wasi-odin-km.out  result/wasi-dotnet-km.out
DecodeSumVec3-8               757µs ± 0%            1651µs ± 0%              369µs ± 0%               9145µs ± 6%            368µs ± 0%              1330µs ± 0%               75671µs ± 0% 
DecodeObjectAPI-8            1.59ms ± 0%            6.13ms ± 0%             1.04ms ± 0%              30.59ms ±34%           0.90ms ± 1%              4.06ms ± 0%              231.72ms ± 0% 
EncodeObjectAPI-8            3.96ms ± 0%            4.51ms ± 1%             1.20ms ± 0%               8.26ms ± 0%           1.03ms ± 0%              5.19ms ± 0%              237.99ms ± 0% 

name \ alloc/op    result/wasi-go-km.out  result/wasi-as-km.out  result/wasi-zig-km.out  result/wasi-swift-km.out  result/wasi-c-km.out  result/wasi-odin-km.out  result/wasi-dotnet-km.out 
DecodeSumVec3-8              1.25kB ± 0%           21.75kB ± 0%             1.25kB ± 0%               1.82kB ± 0%           1.25kB ± 0%              5.34kB ± 0%              321.65kB ± 0% 
DecodeObjectAPI-8            15.0kB ± 0%           122.3kB ± 1%            280.8kB ± 1%              108.6kB ± 3%            1.2kB ± 0%              23.8kB ± 0%               386.5kB ± 0% 
EncodeObjectAPI-8            3.02kB ± 0%           58.00kB ± 1%             1.23kB ± 0%               1.82kB ± 0%           1.23kB ± 0%              8.91kB ± 0%              375.82kB ± 0% 

name \ allocs/op   result/wasi-go-km.out  result/wasi-as-km.out  result/wasi-zig-km.out  result/wasi-swift-km.out  result/wasi-c-km.out  result/wasi-odin-km.out  result/wasi-dotnet-km.out 
DecodeSumVec3-8                5.00 ± 0%              5.00 ± 0%               5.00 ± 0%                32.00 ± 0%             5.00 ± 0%                6.00 ± 0%                 11.00 ± 0% 
DecodeObjectAPI-8              5.00 ± 0%              4.00 ± 0%               4.00 ± 0%                32.00 ± 0%             4.00 ± 0%                6.00 ± 0%                340.00 ± 0% 
EncodeObjectAPI-8              4.00 ± 0%              3.00 ± 0%               3.00 ± 0%                30.00 ± 0%             3.00 ± 0%                5.00 ± 0%                 40.00 ± 0% 

Languages

Currently, we have focus on WebAssembly, and because of that those are the languages supported:

  • AssemblyScript 0.20.16
  • C/Emscripten
  • C#/.NET 7
  • Golang 1.19/TinyGo 0.25.0
  • Odin
  • Swift 5.7/SwiftWasm 5.7
  • Zig 0.10

Some languages still under development, and doesn't have any backward compatibility promise. We will try to keep up with the latest version. Currently, the API generated and the libraries should not consider stable.

Features

Features Go/TinyGo Zig AssemblyScript Swift C C#/.NET Odin
Performance Good Excellent Good Poor Excellent Horrible Good
Priority High High High Low High Medium Low
Encoding
Object Encoding ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
Raw Encoding
Zero-Copy
Decoding
Object Decoding ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
Object Re-Use ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
Random-Access ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
Zero-Copy ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
Zero-Copy-String ✔️ ✔️ ✔️ ✔️ ✔️
Native Array ✔️ ✔️ ✔️ ❌️ ✔️

Schema

Karmem uses a custom schema language, which defines structs, enums and types.

Example

The schema is very simple to understand and define:

karmem game @packed(true) @golang.package(`km`) @assemblyscript.import(`../../assemblyscript/karmem`);

enum Team uint8 {Humans;Orcs;Zombies;Robots;Aliens;}

struct Vec3 inline {
    X float32;
    Y float32;
    Z float32;
}

struct MonsterData table {
    Pos       Vec3;
    Mana      int16;
    Health    int16;
    Name      []char;
    Team      Team;
    Inventory [<128]byte;
    Hitbox    [4]float64;
    Status    []int32;
    Path      [<128]Vec3;
}

struct Monster inline {
    Data MonsterData;
}

struct State table {
    Monsters [<2000]Monster;
}

Header:

Every file must begin with: karmem {name} [@tag()];. Other optional tags can be defined, as shown above, it's recommended to use the @packed(true) option.

Types:

Primitives:

  • Unsigned Integers: uint8, uint16, uint32, uint64
  • Signed Integers: int8, int16, int32, int64
  • Floats: float32, float64
  • Boolean: bool
  • Byte: byte, char

It's not possible to define optional or nullable types.

Arrays:

  • Fixed: [{Length}]{Type} (example: [123]uint16, [3]float32)
  • Dynamic: []{Type} (example: []char, []uint64)
  • Limited: [<{Length}]{Type} (example: [<512]float64, [<42]byte)

It's not possible to have slice of tables or slices of enums or slice of slices. However, it's possible to wrap those types inside one inline-struct.

Struct:

Currently, Karmem has two structs types: inline and table.

Inline: Inline structs, as the name suggests, are inlined when used. That reduces the size and may improve the performance. However, it can't have their definition changed. In order words: you can't edit the field of one inline struct without breaking compatibility.

struct Vec3 inline {
    X float32;
    Y float32;
    Z float32;
}

That struct is exactly the same of [3]float32 and will have the same serialization result. Because of that, any change of this struct (for instance, change it to float64 or adding new fields) will break the compatibility.

Tables: Tables can be used when backward compatibility matters. For example, tables can have new fields append at the bottom without breaking compatibility.

struct User table {
    Name     []char;
    Email    []char;
    Password []char;
}

Let's consider that you need another field... For tables, it's not an issue:

struct User table {
    Name      []char;
    Email     []char;
    Password  []char;
    Telephone []char;
}

Since it's a table, you can add new fields at the bottom of the struct, and both versions are compatible between them. If the message is sent to a client that doesn't understand the new field, it will be ignored. If one outdated client sends a message to a newer client, the new field will have the default value (0, false, empty string, etc).

Enums:

Enums can be used as an alias to Integers type, such as uint8.

enum Team uint8 {
    Unknown;
    Humans;
    Orcs;
    Zombies = 255;
}

Enums must start with a zero value, the default value in all cases. If the value of any enum is omitted, it will use the order of enum as value.

Generator

Once you have a schema defined, you can generate the code. First, you need to karmem installed, get it from the releases page or run it with go.

karmem build --assemblyscript -o "output-folder" your-schema.km

If you already have Golang installed, you can use go karmem.org/cmd/karmem build --zig -o "output-folder" your-schema.km instead.

Commands:

build

  • --zig: Enable generation for Zig
  • --swift: Enable generation for Swift/SwiftWasm
  • --odin: Enable generation for Odin
  • --golang: Enable generation for Golang/TinyGo
  • --dotnet: Enable generation for .NET
  • --c: Enable generation for C
  • --assemblyscript: Enable generation for AssemblyScript
  • -o <dir>: Defines the output folder
  • <input-file>: Defines the input schema

Security

Karmem is fast and is also aimed to be secure and stable for general usage.

Out Of Bounds

Karmem includes bounds-checking to prevent out-of-bounds reading and avoid crashes and panics. That is something that Google Flatbuffers doesn't have, and malformed content will cause panic. However, it doesn't fix all possible vulnerabilities.

Resource Exhaustion

Karmem allows one pointer/offset can be re-used multiple times in the same message. Unfortunately, that behaviour makes it possible for a short message to generate more extensive arrays than the message size. Currently, the only mitigation for that issue is using Limited-Arrays instead of Arrays and avoiding Object-API decode.

Data Leak

Karmem doesn't clear the memory before encoding, that may leak information from the previous message or from system memory itself. That can be solved using @packed(true) tag, as previously described. The packed tag will remove padding from the message, which will prevent the leak. Alternatively, you can clear the memory before encoding, manually.

Limitations

Karmem have some limitations compared to other serialization libraries, such as:

Maximum Size

Similar to Google Protobuf and Google Flatbuffers, Karmem has a maximum size of 2GB. That is the maximum size of the entire message, not the maximum size of each array. This limitation is due to the fact that WASM is designed to be 32-bit, and the maximum size of 2GB seems adequate for the current needs. The current Writer doesn't enforce this limitation, but reading a message that is bigger than 2GB will cause undefined behaviour.

Arrays of Arrays/Tables

Karmem doesn't support arrays of arrays or arrays of tables. However, it's possible to wrap those types inside one inline-struct, as mentioned above. That limitation was imposed to take advantage of native arrays/slice from the language. Most languages encapsulates the pointer and the size of the array inside a struct-like, that requires the size of each element to be known, consequently preventing arrays of items with variable size/strides.

UTF-8

Karmem only supports UTF-8 and doesn't support other encodings.

karmem's People

Contributors

aviradinsky avatar codefromthecrypt avatar culmat avatar evacchi avatar inkeliz avatar marckleinebudde avatar maxgraey avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

karmem's Issues

Option to use small dynamic array header

Currently, the dynamic array header takes 16 bytes, including padding. It can be reduce to 8 bytes, by removing the size_each in the header.

That field is not used, since non-inline structs and contents can't be used in dynamic array. That change is not backward-compatible, but we can make it optional.

That change can be combined with #65, which will make the serialized content smaller.

Option to generate code following language-specific naming convention

Currently, Karmem generates codes that is golang-like for all programing-languages. That creates some weird situations. For instance, on AssemblyScript, most methods are named with lowercase: function toString(): string instead of function ToString(): string.

Some languages is common to use camelCase or snake_case instead of the current PascalCase.


In order to make it easier, we can change the IDL to allow _ in the name, which can be replaced (or used) depending on the language. The usage of PascalCase should be ignored, and not converted to Pascal_Case. That makes this change also backward compatible, and only new IDLs (and generators) will take the advantage of such feature.

Restrict conflicting names and reserved names

Currently, the only limitation related to naming is:

  • Must be A-Z
  • Must not start with number

That may cause issues depending on the language used, since some words can be reserved by the language or internally by karmem itself (such as SizeOf() function).

The goal is to have a list of words that can't be used as name.

Option to generate self-contained code (remove dependency on karmem library)

Currently, Karmem have two components:

  • Code Generation
  • Karmem Library

This may add some issues since you need to get the library and also use code generator. Another option is to "combine" both of them, so one option --contained (and equivalent header option) can be used to include the Karmem library inside the generated code. The major issue is the C code, since it requires prefix and code change for each package.

Remove text/template

Currently, the generator uses text/template to generate the code. That is good and simple, but might add some performance issues and is not supported on TinyGo.

Performance question

Readme says flat buffers are slow and implies this is faster. Does it mean only in WASM context or in general? For example using purely Go code and serializing and reading with this instead of FB, would it yield performance or not?

Support for Unions

Used heavily in my flat buffer code for event type switching but appears to be missing here.

Add short type aliases for schema

I see basic type names inspired by Go type system. But most of modern languages like Rust, zig, AS and WebAssembly WAT btw has a short type notation. So I propose add this aliases:

byte     ->  u8
char     ->  i8
int16    ->  i16
uint16   ->  u16
int32    ->  i32
uint32   ->  u32
int64    ->  i64
uint64   ->  u64
float32  ->  f64
float64  ->  f64

[]char   ->  str

[go] Add a Writable interface to ease the process to encode structs to Writer

I've been experimenting with karmem and I found that it would be useful to have an interface to describe writeable structs, something like:

// Writable writes an encoded representation of the type to the underlying Writer.
type Writable interface {
	WriteAsRoot(*Writer) (uint, error)
}

This would help to create helper method to encode different type of generated structs, i.e. I have something like

func ToPtr(writable Writable, w *karmem.Writer ) (uint32, uint32) {
	if _, err := writable.WriteAsRoot(w); err != nil {
		panic(err)
	}

	buf := w.Bytes()
	ptr := &buf[0]
	unsafePtr := uintptr(unsafe.Pointer(ptr))

	return uint32(unsafePtr), uint32(len(buf))
}

Upload .NET package to NuGet

The C#/.NET package manager is NuGet, we could upload the Karmem library directly to NuGet. That will make easier to use Karmem.

Json interoperability

Very nice project for wasm interop.

i want to use this but I need to also need to be able to export and import json data.

I am guessing this is probably out of scope but I figured it’s worth asking .

The use case is that tons of users have json everywhere and I need an On-ramp to make it easy to bring in that json from their data silo.

It would be useful if the generator could gen a json —> kramen serialiser so that json can be converted in Karmen.

Schema formatter

Similar to go fmt, we can create some standard format for Karmem, which can be used with karmem fmt.

Option to check version update and auto-update

Karmem relies on unsafe code, very heavily, and that may add some security issues. In order to mitigate it, we could check for updates in the compiler.

The checks could be performed in the background. If one update is found, it will output one message in the stdout. Another option to check update can be implemented, such as: karmem upgrade or similar.

Support for Comments/Documentation

Currently, we don't support comments or documentation comment.

We should be able to add comments such as:

// Represents the foo struct
struct foo inline {
      // Represents the bar content
      bar []char;
}

Also, the code-generator should include some default comment, which can be disable:

// Bar is Foo field (your_document.km:2)
// Represents the foo struct
func (x *Foo) Bar() string {

}

The first comment is the default, which must follow the language convention. The second line is the user-defined comment, if the field contains one of them.

Option to clear padding-bytes

Currently, Karmem doesn't clears the padding. Each field contains one "tail-padding", which is responsible to align each struct by 8 bytes.

Internally, each struct uses a mix of packed struct and aligned struct. Each field of the struct is packed, doesn't have padding between them. However, the struct itself is padded, with one padding as the last field. The size of the padding is the minimum amount of bytes to fits into 8 bytes blocks. So, the struct MUST have 8 bytes, 16 bytes, 24 bytes, 32 bytes...

In general:

struct Foo inline {
      ItemOne uint32;    // [Index: 0] - 4 bytes
      ItemTwo uint8;     // [Index: 4] - 1 byte
                         // [Index: 5] - 3 byte
}

The Foo will have 8 bytes. In that case, with 3 bytes as "tail-padding".


The content of the padding is ignored, and is useless. In case of table the size of the padding doesn't includes in the "Size" field, in the header.

However, currently, Karmem doesn't clears that value. Because of that, some data can be leaked, and remain unmodified. That can be considered one privacy issue or security issue, since partial data can be leaked. We need to address that somehow. That also makes impossible to compare generated karmem encoded directly, without decoding.


That undefined behavior/ bug was noticed while fuzzing and testing random IDL.

Correction on Golang+Protobuf comment

This library looks pretty cool! That said, there's an incorrect statement in the README:

That is something that Google Protobuf doesn't have, and malformed content will cause panic.

This is untrue. proto.Unmarshal returns an error when the data received isn't valid. gRPC would never be taken seriously if it fell over when a bad message is received...

Can I use Karmem for communicating with WASM app in browser?

Hello,

Sorry, this could be a noob question. I have this use case: an application written in TinyGo which I compile into target=wasm. This application uses Karmem for its API declared in *.km file. It means that this app has a function like ExecuteCmd(cmdPtr int32, cmdLen int32) where cmd - is a Karmem message, some Go generated struct type.

Now, I want to run my wasm app in browser. To call ExecuteCmd I have to somehow pass a cmd data to it. It means that I need to construct an instance of cmd (in Javascipt/Typescript I guess...), serialize it into an array of bytes, copy those bytes into wasm's memory, get address of the begining + length of that message and finally call the ExecuteCmd.

The missing part here is that Karmem does not support code generation of *.km into JavaScript/TypeScript. And that is why - I cannot use Karmem in browser. Is this correct? Or maybe there is another way of doing it?

Kind regards.

CLI/Generator flag to replace headers tags

Currently, import and package name are defined in-scheme header. We need to have options to overwrite those options in the cli-generaetor, such as -pkg="name", -import="/path/to/" and so on.

Option to use structs without tail-padding

Currently, Karmem is one mixed of packed and unpacked. It doesn't have padding between fields, but have one "tail-padding", one padding at the end of the struct, that enforces the content to have alignment of 8 bytes.

Support array of strings

This is not possible:

struct Foo inline {
    Bars [][]char;
}

So, at the moment we have to do:

struct Str inline {
    Value []char;
}
struct Foo inline {
    Bars []Str;
}

This is not very convenient.

Improve C# performance

The C#/.NET version is significantly slower than any other language. That needs some investigation to find why that is so slow

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.