如何在Golang中制造stack overflow 故障

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 大家都知道golang的栈的动态增长的,并且是放在堆上的,理论上可以相当的大,那么怎么才能制造一个stack overflow 故障呢? 其实只要人为的加入循环引用就能做到 package main import ( //"github.com/json-iterator/go" "encoding/json" ) type A struct { ElementB *B } type B struct { ElementA *A } func main(){ a := A{} b := B{} a.ElementB = &b b.ElementA = &a //var json = jsoniter.ConfigCompatibleWithStandardLibrary json.Marshal(a) } 栈溢出,程序奔溃,并输出 ╰─$ go run test_stackoverflow2.go runtime: goroutine stack exceeds 1000000000-byte limit fatal error: stack overflow runtime stack: runtime.throw(0x10e2e65, 0xe) /usr/local/Cellar/go/1.11.2/libexec/src/runtime/panic.go:608 +0x72 runtime.newstack() /usr/local/Cellar/go/1.11.2/libexec/src/runtime/stack.go:1008 +0x729 runtime.morestack() /usr/local/Cellar/go/1.11.2/libexec/src/runtime/asm_amd64.s:429 +0x8f goroutine 1 [running]: encoding/json.(*structEncoder).encode(0xc0000642d0, 0xc00007e000, 0x10c8d40, 0xc00000c030, 0x199, 0x100) 看来默认栈的最大大小也就1GB。 这个例子其实源于真实的线上故障,经过测试无论是标准的Json库,或是jsoniter都无法避免此问题。 另外如果Golang编译器,或者Marshal函数能够对递归的深度做出判断,超过一定深度就报错,在栈溢出前,抛出err,避免栈溢出,程序崩溃 后记 已经给json-iterator/go 提了issue,并且提了pull request。 有需要也可以直接使用我个改进库vearne/json-iterator-go 默认递归的最大层级限制是1000 ...

November 30, 2018 · 1 min

json-iterator 使用要注意的大坑

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1. 前言 众所周知, Golang标准库"encoding/json"的性能并不好,现在比较热的替代库是"json-iterator/go" 传送门: json-iterator/go 我们的日志打成json格式,然后做集中收集,为了提高性能用json-iterator替换encoding/json。打火焰图,却发现(JSON序列化日志)耗时占总时间的比重没有下降 2. 重新测试 难道json-iterator出的性能压测数据都是吹牛逼,只要自己又重新测试了一下,以下是测试代码 json_test.go package tjson import ( "testing" "encoding/json" jsoniter "github.com/json-iterator/go" ) type Car struct { Name string Name1 string Name2 string Name3 string } func BenchmarkStructJsoniter(b *testing.B) { c := Car{Name1:"xxxxxxxxxxxxx", Name2:"xxxxxxxxxxxxxxxxxxxx", Name3:"xxxxxxxxxxxxxxxxxx", Name: "buickxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"} for i := 0; i < b.N; i++ { //use b.N for looping jsoniter.Marshal(&c) } } func BenchmarkStructStd(b *testing.B) { c := Car{Name1:"xxxxxxxxxxxxx", Name2:"xxxxxxxxxxxxxxxxxxxx", Name3:"xxxxxxxxxxxxxxxxxx", Name: "buickxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"} for i := 0; i < b.N; i++ { //use b.N for looping json.Marshal(&c) } } func BenchmarkMapJsoniter(b *testing.B) { mymap := make(map[string]string, 10000) mymap["Name1"] = "xxxxxxxxxxxxx" mymap["Name2"] = "xxxxxxxxxxxxxxxxxxxx" mymap["Name3"] = "xxxxxxxxxxxxxxxxxx" mymap["Name"] = "buickxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" for i := 0; i < b.N; i++ { //use b.N for looping jsoniter.Marshal(&mymap) } } func BenchmarkMapStd(b *testing.B) { mymap := make(map[string]string, 10000) mymap["Name1"] = "xxxxxxxxxxxxx" mymap["Name2"] = "xxxxxxxxxxxxxxxxxxxx" mymap["Name3"] = "xxxxxxxxxxxxxxxxxx" mymap["Name"] = "buickxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" for i := 0; i < b.N; i++ { //use b.N for looping json.Marshal(&mymap) } } BenchMark脚本 ...

March 28, 2018 · 2 min