Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor #560

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from
Draft
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
wip benchmark
matheusd committed Jun 4, 2024

Verified

This commit was signed with the committer’s verified signature.
matheusd Matheus Degiovani
commit 7c36466fca07d2b01321f6126bc579ff35554542
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@ module capnproto.org/go/capnp/v3
go 1.19

require (

github.com/alecthomas/go_serialization_benchmarks/goserbench v0.0.0
github.com/colega/zeropool v0.0.0-20230505084239-6fb4a4f75381
github.com/kylelemons/godebug v1.1.0
github.com/stretchr/testify v1.8.2
@@ -12,6 +14,8 @@ require (
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
)

replace github.com/alecthomas/go_serialization_benchmarks/goserbench => /home/user/testes/vendor/alecthomas/go_serialization_benchmarks/goserbench

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/philhofer/fwd v1.1.1 // indirect
31 changes: 30 additions & 1 deletion internal/aircraftlib/experimental.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package aircraftlib

import capnp "capnproto.org/go/capnp/v3"
import (
math "math"

capnp "capnproto.org/go/capnp/v3"
)

// Experimental: This could replace NewRootBenchmarkA without having to modify
// the public API.
@@ -27,3 +31,28 @@ func (s BenchmarkA) UpdateName(v string) error {
func (s BenchmarkA) NameField() (capnp.TextField, error) {
return capnp.Struct(s).TextField(0)
}

func (s BenchmarkA) FlatSetPhone(v string) error {
return capnp.Struct(s).FlatSetNewText(1, v)
}

func (s BenchmarkA) PhoneField() (capnp.TextField, error) {
return capnp.Struct(s).TextField(1)
}

func (s *BenchmarkA) SetMoneyp(v float64) {
bits := math.Float64bits(v)
(*capnp.Struct)(s).SetUint64p(16, bits)
}

func (s *BenchmarkA) SetSpousep(v bool) {
(*capnp.Struct)(s).SetBitp(96, v)
}

func (s *BenchmarkA) SetSiblingsp(v int32) {
(*capnp.Struct)(s).SetUint32p(8, uint32(v))
}

func (s *BenchmarkA) SetBirthDayp(v int64) {
(*capnp.Struct)(s).SetUint64p(0, uint64(v))
}
105 changes: 105 additions & 0 deletions my_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package capnp_test

import (
"strings"
"testing"

"capnproto.org/go/capnp/v3"
"capnproto.org/go/capnp/v3/internal/aircraftlib"

"github.com/alecthomas/go_serialization_benchmarks/goserbench"

Check failure on line 10 in my_test.go

GitHub Actions / Go 1.19 GOARCH=amd64

github.com/alecthomas/go_serialization_benchmarks/goserbench@v0.0.0: replacement directory /home/user/testes/vendor/alecthomas/go_serialization_benchmarks/goserbench does not exist

Check failure on line 10 in my_test.go

GitHub Actions / Go 1.19 GOARCH=386

github.com/alecthomas/go_serialization_benchmarks/goserbench@v0.0.0: replacement directory /home/user/testes/vendor/alecthomas/go_serialization_benchmarks/goserbench does not exist

Check failure on line 10 in my_test.go

GitHub Actions / Go 1.20 GOARCH=amd64

github.com/alecthomas/go_serialization_benchmarks/goserbench@v0.0.0: replacement directory /home/user/testes/vendor/alecthomas/go_serialization_benchmarks/goserbench does not exist

Check failure on line 10 in my_test.go

GitHub Actions / Go 1.20 GOARCH=386

github.com/alecthomas/go_serialization_benchmarks/goserbench@v0.0.0: replacement directory /home/user/testes/vendor/alecthomas/go_serialization_benchmarks/goserbench does not exist
)

func BenchmarkSetText05(b *testing.B) {
@@ -90,3 +93,105 @@
}
}
}

type CapNProtoSerializer struct {
msg capnp.Message
arena *capnp.SimpleSingleSegmentArena
c *aircraftlib.BenchmarkA

fieldName *capnp.TextField
fieldPhone *capnp.TextField
}

func (x *CapNProtoSerializer) Marshal(o interface{}) ([]byte, error) {
a := o.(*goserbench.SmallStruct)
/*
x.msg.ResetForRead(x.arena)
seg, err := x.msg.Segment(0)
if err != nil {
return nil, err
}

c, err := aircraftlib.AllocateNewRootBenchmark(&x.msg)
if err != nil {
return nil, err
}
*/

c := x.c
c.SetBirthDay(a.BirthDay.UnixNano())
c.SetSiblingsp(int32(a.Siblings))
c.SetSpousep(a.Spouse)
c.SetMoneyp(a.Money) // c.SetMoney(a.Money)
x.fieldName.Set(a.Name) // c.FlatSetName(a.Name) // c.SetName(a.Name)
x.fieldPhone.Set(a.Phone) // c.FlatSetPhone(a.Phone) // c.SetPhone(a.Phone)

return x.arena.Data(0)
}

func (x *CapNProtoSerializer) Unmarshal(d []byte, i interface{}) error {
/*
a := i.(*goserbench.SmallStruct)

s, _, err := capn.ReadFromMemoryZeroCopy(d)
if err != nil {
return err

}
o := aircraftlib.ReadRootBenchmarkA(s)
a.Name = o.Name()
a.BirthDay = time.Unix(0, o.BirthDay())
a.Phone = o.Phone()
a.Siblings = int(o.Siblings())
a.Spouse = o.Spouse()
a.Money = o.Money()
return nil
*/
return nil
}

func NewCapNProtoSerializer() goserbench.Serializer {
arena := &capnp.SimpleSingleSegmentArena{}
var msg capnp.Message
msg.ResetForRead(arena)
msg.ResetReadLimit(1 << 31)

a, err := aircraftlib.AllocateNewRootBenchmark(&msg)
if err != nil {
panic(err)
}
if err := a.SetName(strings.Repeat("a", goserbench.MaxSmallStructNameSize)); err != nil {
panic(err)
}
if err := a.SetPhone(strings.Repeat("a", goserbench.MaxSmallStructNameSize)); err != nil {
panic(err)
}

fieldName, err := a.NameField()
if err != nil {
panic(err)
}
fieldPhone, err := a.PhoneField()
if err != nil {
panic(err)
}

return &CapNProtoSerializer{
arena: arena,
c: &a,
fieldName: &fieldName,
fieldPhone: &fieldPhone,
}

}

func BenchmarkGoserBench(b *testing.B) {
b.Run("marshal", func(b *testing.B) {
goserbench.BenchMarshalSmallStruct(b, NewCapNProtoSerializer())
})

b.Run("unmarshal", func(b *testing.B) {
goserbench.BenchUnmarshalSmallStruct(b, NewCapNProtoSerializer(), false)
})

}
11 changes: 10 additions & 1 deletion segment.go
Original file line number Diff line number Diff line change
@@ -76,7 +76,16 @@ func (s *Segment) readRawPointer(addr address) rawPointer {
}

func (s *Segment) writeUint8(addr address, val uint8) {
s.slice(addr, 1)[0] = val
// s.slice(addr, 1)[0] = val
s.data[addr] = val
}

func (s *Segment) setBit(addr address, off uint8) {
s.data[addr] |= 1 << off
}

func (s *Segment) clearBit(addr address, off uint8) {
s.data[addr] &^= 1 << off
}

func (s *Segment) writeUint16(addr address, val uint16) {
63 changes: 61 additions & 2 deletions struct.go
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package capnp

import (
"bytes"
"encoding/binary"
"errors"
"unsafe"

@@ -366,7 +367,7 @@ func (p Struct) pointerAddress(i uint16) address {
}

// bitInData reports whether bit is inside p's data section.
func (p Struct) bitInData(bit BitOffset) bool {
func (p *Struct) bitInData(bit BitOffset) bool {
return p.seg != nil && bit < BitOffset(p.size.DataSize*8)
}

@@ -394,7 +395,21 @@ func (p Struct) SetBit(n BitOffset, v bool) {
p.seg.writeUint8(addr, b)
}

func (p Struct) dataAddress(off DataOffset, sz Size) (addr address, ok bool) {
func (p *Struct) SetBitp(n BitOffset, v bool) {
if !p.bitInData(n) {
panic("capnp: set field outside struct boundaries")
}
addr := p.off.addOffset(n.offset())
b := p.seg.readUint8(addr)
if v {
b |= n.mask()
} else {
b &^= n.mask()
}
p.seg.writeUint8(addr, b)
}

func (p *Struct) dataAddress(off DataOffset, sz Size) (addr address, ok bool) {
if p.seg == nil || Size(off)+sz > p.size.DataSize {
return 0, false
}
@@ -464,6 +479,14 @@ func (p Struct) SetUint32(off DataOffset, v uint32) {
p.seg.writeUint32(addr, v)
}

func (p *Struct) SetUint32p(off DataOffset, v uint32) {
addr, ok := p.dataAddress(off, 4)
if !ok {
panic("capnp: set field outside struct boundaries")
}
p.seg.writeUint32(addr, v)
}

// SetUint64 sets the 64-bit integer that is off bytes from the start of the struct to v.
func (p Struct) SetUint64(off DataOffset, v uint64) {
addr, ok := p.dataAddress(off, 8)
@@ -473,6 +496,42 @@ func (p Struct) SetUint64(off DataOffset, v uint64) {
p.seg.writeUint64(addr, v)
}

func (p *Struct) SetUint64p(off DataOffset, v uint64) {
addr, ok := p.dataAddress(off, 8)
if !ok {
panic("capnp: set field outside struct boundaries")
}

// p.seg.writeUint64(addr, v)
b := p.seg.slice(addr, 8)
binary.LittleEndian.PutUint64(b, v)

/*
b := p.seg.slice(addr, 8)
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
b[3] = byte(v >> 24)
b[4] = byte(v >> 32)
b[5] = byte(v >> 40)
b[6] = byte(v >> 48)
b[7] = byte(v >> 56)
*/
/*
b := p.seg.data
_ = b[addr+7]
b[addr] = byte(v)
b[addr+1] = byte(v >> 8)
b[addr+2] = byte(v >> 16)
b[addr+3] = byte(v >> 24)
b[addr+4] = byte(v >> 32)
b[addr+5] = byte(v >> 40)
b[addr+6] = byte(v >> 48)
b[addr+7] = byte(v >> 56)
*/

}

// structFlags is a bitmask of flags for a pointer.
type structFlags uint8