binary encoding and some changes to nson benchmarks.

This commit is contained in:
fiatjaf
2023-11-02 15:28:01 -03:00
parent 1789d43d51
commit 4c72e16f3e
7 changed files with 484 additions and 29 deletions
+20
View File
@@ -35,3 +35,23 @@ It's explained better in the NIP proposal linked above, but the idea is that we
a special JSON attribute called `"nson"`, and then the reader can just pull the strings directly from the JSON blob
without having to parse the full JSON syntax. Also for fields of static size we don't even need that. This is only
possible because Nostr events have a static and strict format.
## Update: comparison with `easyjson`
Another comparison, using the `easyjson` library that is already built in `go-nostr`, shows that the performance gains
are only of 2x (the standard library JSON encoding is just too slow).
```
goos: linux
goarch: amd64
pkg: github.com/nbd-wtf/go-nostr/nson
cpu: AMD Ryzen 3 3200G with Radeon Vega Graphics
BenchmarkNSONEncoding/easyjson.Marshal-4 21511 54849 ns/op
BenchmarkNSONEncoding/nson.Marshal-4 4810 297624 ns/op
BenchmarkNSONDecoding/easyjson.Unmarshal-4 25196 46652 ns/op
BenchmarkNSONDecoding/nson.Unmarshal-4 61117 22933 ns/op
BenchmarkNSONDecoding/easyjson.Unmarshal+sig-4 303 4110988 ns/op
BenchmarkNSONDecoding/nson.Unmarshal+sig-4 296 3881435 ns/op
PASS
ok github.com/nbd-wtf/go-nostr/nson
```
+8 -29
View File
@@ -4,6 +4,7 @@ import (
"encoding/json"
"testing"
"github.com/mailru/easyjson"
"github.com/nbd-wtf/go-nostr"
)
@@ -153,10 +154,10 @@ func BenchmarkNSONEncoding(b *testing.B) {
events[i] = evt
}
b.Run("json.Marshal", func(b *testing.B) {
b.Run("easyjson.Marshal", func(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, evt := range events {
json.Marshal(evt)
easyjson.Marshal(evt)
}
}
})
@@ -168,32 +169,22 @@ func BenchmarkNSONEncoding(b *testing.B) {
}
}
})
b.Run("nson.Marshal to bytes", func(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, evt := range events {
MarshalBytes(evt)
}
}
})
}
func BenchmarkNSONDecoding(b *testing.B) {
events := make([]string, len(normalEvents))
eventsB := make([][]byte, len(normalEvents))
for i, jevt := range normalEvents {
evt := &nostr.Event{}
json.Unmarshal([]byte(jevt), evt)
nevt, _ := Marshal(evt)
events[i] = nevt
eventsB[i] = []byte(nevt)
}
b.Run("json.Unmarshal", func(b *testing.B) {
b.Run("easyjson.Unmarshal", func(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, nevt := range events {
evt := &nostr.Event{}
err := json.Unmarshal([]byte(nevt), evt)
err := easyjson.Unmarshal([]byte(nevt), evt)
if err != nil {
b.Fatalf("failed to unmarshal: %s", err)
}
@@ -213,23 +204,11 @@ func BenchmarkNSONDecoding(b *testing.B) {
}
})
b.Run("nson.Unmarshal from bytes", func(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, nevt := range eventsB {
evt := &nostr.Event{}
err := UnmarshalBytes(nevt, evt)
if err != nil {
b.Fatalf("failed to unmarshal: %s", err)
}
}
}
})
b.Run("json.Unmarshal + sig verification", func(b *testing.B) {
b.Run("easyjson.Unmarshal+sig", func(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, nevt := range events {
evt := &nostr.Event{}
err := json.Unmarshal([]byte(nevt), evt)
err := easyjson.Unmarshal([]byte(nevt), evt)
if err != nil {
b.Fatalf("failed to unmarshal: %s", err)
}
@@ -238,7 +217,7 @@ func BenchmarkNSONDecoding(b *testing.B) {
}
})
b.Run("nson.Unmarshal + sig verification", func(b *testing.B) {
b.Run("nson.Unmarshal+sig", func(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, nevt := range events {
evt := &nostr.Event{}