Introduction
Sonic is a JSON library for Go developed by ByteDance that uses just-in-time (JIT) compilation to generate optimized marshal/unmarshal code at runtime. It serves as a drop-in replacement for encoding/json while delivering significantly higher throughput.
What Sonic Does
- Serializes and deserializes JSON using JIT-compiled codecs for each Go type
- Provides a lazy-parsing API (sonic.Get) for extracting values without full unmarshal
- Uses SIMD instructions (AVX2, SSE) on x86 for accelerated string processing
- Offers a drop-in compatible API matching
encoding/jsonsignatures - Supports generic JSON manipulation via an ast.Node tree without struct definitions
Architecture Overview
Sonic generates machine code at runtime for each struct type it encounters. On the first marshal/unmarshal call, it inspects the struct's fields and tags via reflection, then emits optimized native code using an internal assembler. Subsequent calls skip reflection entirely and execute the JIT-compiled codec directly. The parser uses SIMD to scan for delimiters and escape characters, reducing per-byte processing cost.
Self-Hosting & Configuration
- Install with
go get github.com/bytedance/sonic— requires Go 1.17+ - Replace
encoding/jsonimports withgithub.com/bytedance/sonic— API is compatible - On non-amd64 platforms, sonic falls back to a generic Go implementation automatically
- Configure encoder options:
sonic.ConfigDefault,sonic.ConfigStd,sonic.ConfigFastest - Use
sonic.Pretouch()at init time to pre-generate codecs and avoid first-call latency
Key Features
- JIT compilation eliminates reflection overhead on hot paths
- SIMD-accelerated string escaping and number parsing on x86_64
- Lazy-load API (
sonic.Get) for partial JSON reads without full deserialization - AST-based generic JSON manipulation without defining Go structs
- Fallback mode for non-amd64 architectures with no code changes
Comparison with Similar Tools
- encoding/json — standard library uses reflection on every call; sonic JIT-compiles once
- json-iterator — code-generation approach; sonic uses runtime JIT for simpler integration
- easyjson — requires a separate code-gen step; sonic works at runtime with no build tooling
- GJSON — read-only path queries; sonic handles full marshal/unmarshal plus lazy parsing
FAQ
Q: Does sonic work on ARM or Apple Silicon? A: Yes, it falls back to a compatible Go implementation on non-amd64 platforms. Performance is still good but without SIMD acceleration.
Q: Is sonic safe for concurrent use? A: Yes, the generated codecs are immutable and safe to call from multiple goroutines.
Q: Can I use sonic with existing struct tags?
A: Yes, it supports the same json struct tags as encoding/json.
Q: What is the performance improvement over encoding/json? A: Benchmarks show 2-5x improvement for marshaling and up to 5-10x for unmarshaling, depending on the payload structure.