If you like to see the video on this blog, then here is the link of the video: https://www.youtube.com/watch?v=FCID6eezGTU
As a developer it is our day-to-day job converting the data from the byte type (received from the network wire in the form of response) to your API response struct. In this blog we will see how we can do that efficiently and in a optimized manner(consume low CPU and Memory)
I will compare two libraries, SONIC and JSON and will perform the benchmark test for these two libraries and check which is optimal for our use case.
Test Criteria:
The payload is divided into three parts.
- Small size struct
- Medium size struct
- Large size struct
- Extra Large size struct
*About the operation: *
It will consist a method which is performing two operations, first marshalling and then unmarshalling.
func MarshallingUnmarshallingJSON(t1 []album) {
var result []*album
byteReponse, _ := json.Marshal(t1)
json.Unmarshal(byteReponse, &result)
}
func MarshallingUnmarshallingSONIC(t1 []album) {
var result []album
byteReponse, _ := sonic.Marshal(t1)
sonic.Unmarshal(byteReponse, &result)
}
Result array size lies in four categories, and the benchmark result is as follows:
func BenchmarkJSON(b *testing.B) {
// Small, Medium, Large, Extra Large
var input = []int{10, 50, 100, 400}
for _, v := range input {
albums := BuildResponse(v)
b.Run(fmt.Sprintf("input_size_%d", v), func(b *testing.B) {
for i := 0; i < b.N; i++ {
MarshallingUnmarshallingJSON(albums)
}
})
}
}
func BenchmarkSonic(b *testing.B) {
// Small, Medium, Large, Extra Large
var input = []int{10, 50, 100, 400}
for _, v := range input {
albums := BuildResponse(v)
b.Run(fmt.Sprintf("input_size_%d", v), func(b *testing.B) {
for i := 0; i < b.N; i++ {
MarshallingUnmarshallingSONIC(albums)
}
})
}
}
And the results after benchmark test are as follows:
SONIC
Name | Operation | ns/op | B/op | allocs/op |
---|---|---|---|---|
BenchmarkSonic/input_size_10-4 | 184616 | 10799 ns/op | 3787 B/op | 11 allocs/op |
BenchmarkSonic/input_size_50-4 | 39327 | 31660 ns/op | 15188 B/op | 12 allocs/op |
BenchmarkSonic/input_size_100-4 | 20794 | 55688 ns/op | 34839 B/op | 13 allocs/op |
BenchmarkSonic/input_size_400-4 | 5713 | 213816 ns/op | 130859 B/op | 14 allocs/op |
JSON
Name | Operation | ns/op | B/op | allocs/op |
---|---|---|---|---|
BenchmarkJSON/input_size_10-4 | 21874 | 57925 ns/op | 2689 B/op | 57 allocs/op |
BenchmarkJSON/input_size_50-4 | 4152 | 273070 ns/op | 12053 B/op | 265 allocs/op |
BenchmarkJSON/input_size_100-4 | 2942 | 390126 ns/op | 24157 B/op | 519 allocs/op |
BenchmarkJSON/input_size_400-4 | 930 | 1406397 ns/op | 96853 B/op | 2025 allocs/op |
In all dimensions, SONIC is the clear winner and recommended for the use as it saves your memory and CPU.
Youtube Channel: https://www.youtube.com/@codepiper
Top comments (3)
try this:
github.com/sugawarayuuta/sonnet
Will do the profiling for this library, thanks man
Keep us posted of your findings, makes an interesting read :-)