diff --git a/go.mod b/go.mod index 313c46b..81aec73 100644 --- a/go.mod +++ b/go.mod @@ -33,6 +33,7 @@ require ( go.mongodb.org/mongo-driver v1.11.1 google.golang.org/protobuf v1.28.1 gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 + karmem.org v1.2.9 zombiezen.com/go/capnproto2 v2.18.2+incompatible ) diff --git a/go.sum b/go.sum index a18eb0e..cf39eba 100644 --- a/go.sum +++ b/go.sum @@ -481,6 +481,8 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +karmem.org v1.2.9 h1:K+U8+SmBe1THbzNLWE3cf/K4QZanOYTXlSUm1z8g2Nk= +karmem.org v1.2.9/go.mod h1:H+GxZ6T9lIJdD4toG7jeQyaahxOrw6uc4jls7KoPq1M= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= zombiezen.com/go/capnproto2 v2.18.2+incompatible h1:v3BD1zbruvffn7zjJUU5Pn8nZAB11bhZSQC4W+YnnKo= zombiezen.com/go/capnproto2 v2.18.2+incompatible/go.mod h1:XO5Pr2SbXgqZwn0m0Ru54QBqpOf4K5AYBO+8LAOBQEQ= diff --git a/karmem-structdef.km b/karmem-structdef.km new file mode 100644 index 0000000..e827b16 --- /dev/null +++ b/karmem-structdef.km @@ -0,0 +1,10 @@ +karmem karmemmodels @packed(true) @golang.package(`km`); + +struct KarmemA inline { + Name []char; + Birthday int64; + Phone []char; + Siblings int32; + Spouse bool; + Money float64; +} diff --git a/km/karmemmodels_generated.go b/km/karmemmodels_generated.go new file mode 100644 index 0000000..4a2e57f --- /dev/null +++ b/km/karmemmodels_generated.go @@ -0,0 +1,156 @@ +package km + +import ( + karmem "karmem.org/golang" + "unsafe" +) + +var _ unsafe.Pointer + +var _Null = [37]byte{} +var _NullReader = karmem.NewReader(_Null[:]) + +type ( + PacketIdentifier uint64 +) + +const ( + PacketIdentifierKarmemA = 2488188364914332533 +) + +type KarmemA struct { + Name string + Birthday int64 + Phone string + Siblings int32 + Spouse bool + Money float64 +} + +func NewKarmemA() KarmemA { + return KarmemA{} +} + +func (x *KarmemA) PacketIdentifier() PacketIdentifier { + return PacketIdentifierKarmemA +} + +func (x *KarmemA) Reset() { + x.Read((*KarmemAViewer)(unsafe.Pointer(&_Null[0])), _NullReader) +} + +func (x *KarmemA) WriteAsRoot(writer *karmem.Writer) (offset uint, err error) { + return x.Write(writer, 0) +} + +func (x *KarmemA) Write(writer *karmem.Writer, start uint) (offset uint, err error) { + offset = start + size := uint(37) + if offset == 0 { + offset, err = writer.Alloc(size) + if err != nil { + return 0, err + } + } + __NameSize := uint(1 * len(x.Name)) + __NameOffset, err := writer.Alloc(__NameSize) + if err != nil { + return 0, err + } + writer.Write4At(offset+0, uint32(__NameOffset)) + writer.Write4At(offset+0+4, uint32(__NameSize)) + __NameSlice := [3]uint{*(*uint)(unsafe.Pointer(&x.Name)), __NameSize, __NameSize} + writer.WriteAt(__NameOffset, *(*[]byte)(unsafe.Pointer(&__NameSlice))) + __BirthdayOffset := offset + 8 + writer.Write8At(__BirthdayOffset, *(*uint64)(unsafe.Pointer(&x.Birthday))) + __PhoneSize := uint(1 * len(x.Phone)) + __PhoneOffset, err := writer.Alloc(__PhoneSize) + if err != nil { + return 0, err + } + writer.Write4At(offset+16, uint32(__PhoneOffset)) + writer.Write4At(offset+16+4, uint32(__PhoneSize)) + __PhoneSlice := [3]uint{*(*uint)(unsafe.Pointer(&x.Phone)), __PhoneSize, __PhoneSize} + writer.WriteAt(__PhoneOffset, *(*[]byte)(unsafe.Pointer(&__PhoneSlice))) + __SiblingsOffset := offset + 24 + writer.Write4At(__SiblingsOffset, *(*uint32)(unsafe.Pointer(&x.Siblings))) + __SpouseOffset := offset + 28 + writer.Write1At(__SpouseOffset, *(*uint8)(unsafe.Pointer(&x.Spouse))) + __MoneyOffset := offset + 29 + writer.Write8At(__MoneyOffset, *(*uint64)(unsafe.Pointer(&x.Money))) + + return offset, nil +} + +func (x *KarmemA) ReadAsRoot(reader *karmem.Reader) { + x.Read(NewKarmemAViewer(reader, 0), reader) +} + +func (x *KarmemA) Read(viewer *KarmemAViewer, reader *karmem.Reader) { + __NameString := viewer.Name(reader) + if x.Name != __NameString { + __NameStringCopy := make([]byte, len(__NameString)) + copy(__NameStringCopy, __NameString) + x.Name = *(*string)(unsafe.Pointer(&__NameStringCopy)) + } + x.Birthday = viewer.Birthday() + __PhoneString := viewer.Phone(reader) + if x.Phone != __PhoneString { + __PhoneStringCopy := make([]byte, len(__PhoneString)) + copy(__PhoneStringCopy, __PhoneString) + x.Phone = *(*string)(unsafe.Pointer(&__PhoneStringCopy)) + } + x.Siblings = viewer.Siblings() + x.Spouse = viewer.Spouse() + x.Money = viewer.Money() +} + +type KarmemAViewer [37]byte + +func NewKarmemAViewer(reader *karmem.Reader, offset uint32) (v *KarmemAViewer) { + if !reader.IsValidOffset(offset, 37) { + return (*KarmemAViewer)(unsafe.Pointer(&_Null[0])) + } + v = (*KarmemAViewer)(unsafe.Add(reader.Pointer, offset)) + return v +} + +func (x *KarmemAViewer) size() uint32 { + return 37 +} +func (x *KarmemAViewer) Name(reader *karmem.Reader) (v string) { + offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 0)) + size := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 0+4)) + if !reader.IsValidOffset(offset, size) { + return "" + } + length := uintptr(size / 1) + slice := [3]uintptr{ + uintptr(unsafe.Add(reader.Pointer, offset)), length, length, + } + return *(*string)(unsafe.Pointer(&slice)) +} +func (x *KarmemAViewer) Birthday() (v int64) { + return *(*int64)(unsafe.Add(unsafe.Pointer(x), 8)) +} +func (x *KarmemAViewer) Phone(reader *karmem.Reader) (v string) { + offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 16)) + size := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 16+4)) + if !reader.IsValidOffset(offset, size) { + return "" + } + length := uintptr(size / 1) + slice := [3]uintptr{ + uintptr(unsafe.Add(reader.Pointer, offset)), length, length, + } + return *(*string)(unsafe.Pointer(&slice)) +} +func (x *KarmemAViewer) Siblings() (v int32) { + return *(*int32)(unsafe.Add(unsafe.Pointer(x), 24)) +} +func (x *KarmemAViewer) Spouse() (v bool) { + return *(*bool)(unsafe.Add(unsafe.Pointer(x), 28)) +} +func (x *KarmemAViewer) Money() (v float64) { + return *(*float64)(unsafe.Add(unsafe.Pointer(x), 29)) +} diff --git a/serialization_benchmarks_test.go b/serialization_benchmarks_test.go index 1513b25..b60fd40 100644 --- a/serialization_benchmarks_test.go +++ b/serialization_benchmarks_test.go @@ -14,6 +14,7 @@ import ( "github.com/Sereal/Sereal/Go/sereal" "github.com/alecthomas/binary" + "github.com/alecthomas/go_serialization_benchmarks/km" "github.com/davecgh/go-xdr/xdr" capn "github.com/glycerine/go-capnproto" "github.com/gogo/protobuf/jsonpb" @@ -35,6 +36,7 @@ import ( "go.dedis.ch/protobuf" mongobson "go.mongodb.org/mongo-driver/bson" "gopkg.in/mgo.v2/bson" + karmem "karmem.org/golang" capnp "zombiezen.com/go/capnproto2" ) @@ -1767,3 +1769,47 @@ func Benchmark_MusgoUnsafe_Unmarshal(b *testing.B) { } } } + +// karmem.org/golang + +type KarmemSerializer struct { + writer *karmem.Writer +} + +func (s *KarmemSerializer) Marshal(o interface{}) ([]byte, error) { + a := o.(*A) + + w := s.writer + k := km.KarmemA{ + Name: a.Name, + Birthday: a.BirthDay.UnixNano(), + Phone: a.Phone, + Siblings: int32(a.Siblings), + Spouse: a.Spouse, + Money: a.Money, + } + w.Reset() + _, err := k.WriteAsRoot(w) + return w.Bytes(), err +} + +func (s *KarmemSerializer) Unmarshal(d []byte, i interface{}) error { + a := i.(*A) + v := karmem.NewReader(d) + k := km.NewKarmemAViewer(v, 0) + a.Name = k.Name(v) + a.BirthDay = time.Unix(0, k.Birthday()) + a.Phone = k.Phone(v) + a.Siblings = int(k.Siblings()) + a.Spouse = k.Spouse() + a.Money = k.Money() + return nil +} + +func Benchmark_Karmem_Marshal(b *testing.B) { + benchMarshal(b, &KarmemSerializer{karmem.NewWriter(1024)}) +} + +func Benchmark_Karmem_Unmarshal(b *testing.B) { + benchUnmarshal(b, &KarmemSerializer{karmem.NewWriter(1024)}) +}