Files
zap/grpc_comparison_test.go
Zach Kelling 22a2a4c72d ZAP: Zero-Allocation Protocol for high-performance AI agent communication
- Zero-copy binary serialization (2.9ns parse, 0 allocations)
- 17x faster than MCP JSON-RPC, 11x less memory, 29x fewer allocations
- mDNS peer discovery with automatic mesh networking
- Request/response correlation for async RPC calls
- MCP bridge for auto-discovering and accelerating MCP servers
- 20 example tools (file, search, code, git, API)
- Consensus reaching agreement in ~450µs
- Environmental: 96% energy reduction at scale (~91 tonnes CO2/year saved)

Benchmarks (Apple M1 Max):
  BenchmarkZAPParse:     2.9 ns/op, 0 B/op, 0 allocs/op
  BenchmarkZAPToolCall:  322 ns/op, 256 B/op, 2 allocs/op
  BenchmarkMCPToolCall:  5579 ns/op, 2826 B/op, 58 allocs/op
2026-01-26 12:09:33 -08:00

214 lines
3.9 KiB
Go

// Copyright (C) 2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package zap
import (
"encoding/json"
"testing"
)
// Simulated protobuf-style message for comparison
// This uses manual varint encoding to simulate protobuf overhead
type ProtoMessage struct {
Id uint64
Value uint64
Count uint32
Active bool
}
// Simple manual encoding to simulate protobuf overhead
func (m *ProtoMessage) MarshalSimple() []byte {
buf := make([]byte, 32)
n := 0
// Field 1: id (varint)
buf[n] = 0x08 // field 1, varint
n++
n += encodeVarint(buf[n:], m.Id)
// Field 2: value (varint)
buf[n] = 0x10 // field 2, varint
n++
n += encodeVarint(buf[n:], m.Value)
// Field 3: count (varint)
buf[n] = 0x18 // field 3, varint
n++
n += encodeVarint(buf[n:], uint64(m.Count))
// Field 4: active (varint)
buf[n] = 0x20 // field 4, varint
n++
if m.Active {
buf[n] = 1
} else {
buf[n] = 0
}
n++
return buf[:n]
}
func (m *ProtoMessage) UnmarshalSimple(data []byte) error {
i := 0
for i < len(data) {
tag := data[i]
i++
field := tag >> 3
switch field {
case 1:
v, n := decodeVarint(data[i:])
m.Id = v
i += n
case 2:
v, n := decodeVarint(data[i:])
m.Value = v
i += n
case 3:
v, n := decodeVarint(data[i:])
m.Count = uint32(v)
i += n
case 4:
m.Active = data[i] != 0
i++
}
}
return nil
}
func encodeVarint(buf []byte, v uint64) int {
i := 0
for v >= 0x80 {
buf[i] = byte(v) | 0x80
v >>= 7
i++
}
buf[i] = byte(v)
return i + 1
}
func decodeVarint(data []byte) (uint64, int) {
var v uint64
for i, b := range data {
v |= uint64(b&0x7f) << (7 * i)
if b < 0x80 {
return v, i + 1
}
}
return v, len(data)
}
// JSON message for comparison
type JSONMessage struct {
Id uint64 `json:"id"`
Value uint64 `json:"value"`
Count uint32 `json:"count"`
Active bool `json:"active"`
}
// Benchmark: Protobuf-style encoding (simulated)
func BenchmarkProtobufEncode(b *testing.B) {
msg := &ProtoMessage{
Id: 12345678,
Value: 0xDEADBEEF,
Count: 12345,
Active: true,
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
msg.Id = uint64(i)
_ = msg.MarshalSimple()
}
}
// Benchmark: Protobuf-style decoding (simulated)
func BenchmarkProtobufDecode(b *testing.B) {
msg := &ProtoMessage{
Id: 12345678,
Value: 0xDEADBEEF,
Count: 12345,
Active: true,
}
data := msg.MarshalSimple()
result := &ProtoMessage{}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
result.UnmarshalSimple(data)
}
}
// Benchmark: JSON encoding
func BenchmarkJSONEncode(b *testing.B) {
msg := &JSONMessage{
Id: 12345678,
Value: 0xDEADBEEF,
Count: 12345,
Active: true,
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
msg.Id = uint64(i)
_, _ = json.Marshal(msg)
}
}
// Benchmark: JSON decoding
func BenchmarkJSONDecode(b *testing.B) {
msg := &JSONMessage{
Id: 12345678,
Value: 0xDEADBEEF,
Count: 12345,
Active: true,
}
data, _ := json.Marshal(msg)
result := &JSONMessage{}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = json.Unmarshal(data, result)
}
}
// Comparison summary test
func TestSerializationComparison(t *testing.T) {
// ZAP
zapBuilder := NewBuilder(256)
obj := zapBuilder.StartObject(64)
obj.SetUint64(0, 12345678)
obj.SetUint64(8, 0xDEADBEEF)
obj.SetUint32(16, 12345)
obj.SetBool(20, true)
obj.FinishAsRoot()
zapData := zapBuilder.Finish()
// Protobuf (simulated)
protoMsg := &ProtoMessage{
Id: 12345678,
Value: 0xDEADBEEF,
Count: 12345,
Active: true,
}
protoData := protoMsg.MarshalSimple()
// JSON
jsonMsg := &JSONMessage{
Id: 12345678,
Value: 0xDEADBEEF,
Count: 12345,
Active: true,
}
jsonData, _ := json.Marshal(jsonMsg)
t.Logf("Message sizes:")
t.Logf(" ZAP: %d bytes", len(zapData))
t.Logf(" Protobuf: %d bytes", len(protoData))
t.Logf(" JSON: %d bytes", len(jsonData))
}