48 【golang】json的效率
本文将主要做如下几方面的测试:
1,构造一个[100]struct的数组,然后来测试它的json编码后的字符串 或者([]byte),首先关心它的功能是否正常;
2,在很早之前,我们在使用golang版本的json编解码时,发现:同PHP的json编解码相比,golang的效率似乎要低,而且要低不少;
3,基于2的背景,我们希望测试新的golang版本中json编码方面是否有所提升,比较的版本是:Go1.3.3,Go1.9;
4,我们可以用程序的一次性执行来测试它的功能,但是如果多次测试,我们需要构造一个多次测试的环境;
关于3,我们需要做点功课,在同一台机器上部署两个版本的go:https://blog.csdn.net/min2015/article/details/77913910,这个博客或许能有所帮助。
另附:go的各个版本下载地址:https://golang.org/dl/
关于4,我们也需要做点功课,如何能用go test工具来辅助我们处理。这篇文章或许能帮助到我们:http://www.flysnow.org/2017/05/21/go-in-action-go-benchmark-test.html
实验环境准备:
1,创建一个目录,随便一个目录就行,比如我们叫json:mkdir json;
2,构造两个go文件:json.go, json_test.go
json.go代码如下:
package myjson import "fmt"
import "math/rand"
import "time"
//import "os"
import "strconv"
import "encoding/json" type user struct {
Name string `json:"nameabcd"`
Age int `json:"age"`
Desc string `json:"desc"`
} func generate() {
var userRows []user = []user{} var u user
for i := 1; i < 100; i++ {
u.Age = 10 is := strconv.Itoa(i)
u.Name = "name" + is u.Desc = GetText(300) userRows = append(userRows, u) u = user{}
} _, _ = json.Marshal(userRows)
//fmt.Println(string(o))
//os.Exit(1) //构造100个struct
//构造每一个struct: name, age, desc
// name = name + index
// age = rand(10, 40)
// desc = getRandomText(300)
// json.Encode(struct100)
} var _ = fmt.Sprintf("") func GetText(slen int) string {
character := "abcdefghjkmnpqrstuvwxyABCDEFGHJKLMNPQRSTUVWXYZ023456789,:.;-+";
maxlen := int32(len(character)) var result string
rand.Seed(time.Now().UnixNano())
for i:= 0; i < slen; i++ {
idx := rand.Int31n(maxlen)
result += (string)(character[idx])
}
return result
}
json_test.go代码如下:
package myjson
import "testing"
func BenchmarkJson(b *testing.B) {
for i := 0; i < b.N; i++ {
generate()
}
}
测试1:直接用go benchmark 来测试BenchmarkJson方法。
$ go test -bench=. -run=none
goos: linux
goarch: amd64
BenchmarkJson 300 4361737 ns/op
PASS
ok _/home/luwenwei/go/maps/1 1.761s
测试2:使用go benchmark的mem监控工具来测试BenchmarkJson方法。
$ go test -bench=. -benchmem -run=none
goos: linux
goarch: amd64
BenchmarkJson 300 4466717 ns/op 4957588 B/op 59417 allocs/op
PASS
ok _/home/luwenwei/go/maps/1 1.802s
可以看到带有-benchmem的选项时,在benchmark测试时能够知道内存分配的次数和内存大小。
测试3:作为和测试2的对比组,用go1.3.3来做测试。
1$ ~/download/go1.3.3/go/bin/go test -bench=. -benchmem -run=none
warning: GOPATH set to GOROOT (/home/luwenwei/download/go1.3.3/go) has no effect
testing: warning: no tests to run
PASS
BenchmarkJson 200 8994506 ns/op 5078644 B/op 44185 allocs/op
ok _/home/luwenwei/go/maps/1 2.645s
测试对比结果如下:
| 测试2(Go1.9) | 测试3(Go1.3.3) | |
| 内存分配次数 | 59147 | 44184 |
| 内存分配大小(B) | 4957588 | 5078644 |
| 每次操作耗时 | 4.4ms | 8.99ms |
测试结果对比情况说明:go1.9的内存分配次数更多,但是每次操作耗时更短,依赖于go的版本升级(猜测:对json处理的优化,split hot stack的问题,由分配栈做link改为连续的内存)
而且这个对比结果还说明了,我们的程序有优化空间,100次的struct构建,却要花费44万次内存分配我们觉得有点扯。
基于这个有点扯的直觉,我们对程序进行了优化。
优化的重点放在了,GetText函数。
优化后的代码:
func GetText(slen int) string {
character := "abcdefghjkmnpqrstuvwxyABCDEFGHJKLMNPQRSTUVWXYZ023456789,:.;-+";
maxlen := int32(len(character))
var r []byte = make([]byte, slen)
//var result string
rand.Seed(time.Now().UnixNano())
for i:= 0; i < slen; i++ {
idx := rand.Int31n(maxlen)
r[i] = character[idx]
//result += (string)(character[idx])
}
return (string)(r)
//return result
}
优化后的测试结果。
测试4:go1.9对优化再次benchmark。
$ go test -bench=. -benchmem -run=none
goos: linux
goarch: amd64
BenchmarkJson 1000 1836617 ns/op 171504 B/op 314 allocs/op
PASS
ok _/home/luwenwei/go/maps/1 2.028s
测试5:go1.3.3.对优化再次benchmark
$ ~/download/go1.3.3/go/bin/go test -bench=. -benchmem -run=none
warning: GOPATH set to GOROOT (/home/luwenwei/download/go1.3.3/go) has no effect
testing: warning: no tests to run
PASS
BenchmarkJson 1000 2221624 ns/op 171772 B/op 268 allocs/op
ok _/home/luwenwei/go/maps/1 2.455s
测试5,测试4,和之前的测试3,测试2,对比,每个op耗时更短,从测试2的4.4ms,降低到测试4的1.8ms。这个优化带来的效果是显著的,甚至比版本的升级带来的速度提升更明显。
| 测试2(Go1.9) | 测试3(Go1.3.3) | 测试4-优化(Go1.9) | 测试5-优化(Go1.3.3) | |
| 内存分配次数 | 59K | 44K | 314 | 268 |
| 内存分配大小 | 4.9MB | 5MB | 171KB | 171KB |
| 每次操作耗时 | 4.4ms | 8.99ms | 1.8ms | 2.2ms |
从程序的维度来看,这次优化带来的提升是显著的,在动态内存分配上[]byte要优于string的附加;
从Go版本的维度来看,Go1.9比Go1.3.3对json的编码速度而言,更有优势;
从工具的维度来看,go test更偏向于对功能的测试,go test benchmark更偏向于对程序的性能测试,而且benchmark是个很好的工具,它能够胜任较简单的模块测试,帮助我们发现模块中的性能问题。
如果对整个project做性能测试,pprof工具要更好,如果怀疑某个模块有问题,再在这个模块上使用benchmark来精准定位,是个合理的性能瓶颈定位方法。
附录:
关于golang的json,我们可能想了解更多:https://gobyexample.com/json
48 【golang】json的效率的更多相关文章
- Golang Json文件解析为结构体工具-json2go
代码地址如下:http://www.demodashi.com/demo/14946.html 概述 json2go是一个基于Golang开发的轻量json文件解析.转换命令行工具,目前支持转换输出到 ...
- 为什么golang的开发效率高(编译型的强类型语言、工程角度高、在开发上的高效率主要来自于后发优势,编译快、避免趁编译时间找产品妹妹搭讪,既是强类型语言又有gc,只要通过编译,非业务毛病就很少了)
作者:阿猫链接:https://www.zhihu.com/question/21098952/answer/21813840来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出 ...
- golang gob 有什么优势? gob/protobuf/json/xml 效率对比,benchmark 压力测试
TODO 待研究: https://blog.csdn.net/love_se/article/details/7941876 https://blog.csdn.net/wangshubo1989/ ...
- golang json string remove field
golang中如何移除多余的field? 同样是json结构,不能像js 的json一样 delete key 直接移除,网上找了很多相似的,还没找到解决办法,先mark一下 感谢大神提供解决思路,设 ...
- golang json
1.Go语言的JSON 库 Go语言自带的JSON转换库为 encoding/json 1.1)其中把对象转换为JSON的方法(函数)为 json.Marshal(),其函数原型如下 func Mar ...
- golang json用法讲解
简介 json格式可以算我们日常最常用的序列化格式之一了,Go语言作为一个由Google开发,号称互联网的C语言的语言,自然也对JSON格式支持很好.但是Go语言是个强类型语言,对格式要求极其严格而J ...
- golang json html escape unicode
https://play.golang.org/p/FAH-XS-QMC https://github.com/gin-gonic/gin/issues/693 package main import ...
- golang json数组拼接
2016年06月16日 15:38:25 阅读数:2575 标签: golangjson数组 更多 个人分类: golang func main() { a := []byte(`{"P ...
- Golang JSON操作汇总
直接把结构体编码成json数据 package main import ( "encoding/json" "fmt" _ "os" ) t ...
随机推荐
- List Leaves
Given a tree, you are supposed to list all the leaves in the order of top down, and left to right. I ...
- linux上安装mysql5.6
CentOS-6.6+MySQL-5.6 部署环境操作系统:CentOS-6.6-x86_64-bin-DVD1.isoMySQL 版本:mysql-5.6.26.tar.gz操作用户:root系统 ...
- 通过ldap验证svn服务
1.简单介绍: 这里需要介绍一点的就是svn服务器的验证是需要通过SASL机制的,那么SASL全称为(Simple Authentication and security Layer),是一种用来扩充 ...
- Subline_Text3消除更新提示
很简单的一个小问题,去除SubLine text的更新问题,在网上看了很多资料也不可以,原来是因为注册码和版本的问题,在这简单做个记录. 关于安装问题就不说啦 百度文库安装方法 安装完成之后一定要注册 ...
- 配置NFS
主机端 sudo apt-get install nfs-kernel-server 修改配置文件 sudo vim /etc/exports 添加: /home/nfs/fs_qtopia *(rw ...
- NFS服务器工作原理
一.NFS简介 NFS是Network File System的缩写,中文称为网络文件系统,它的主要功能是通过网络(一个局域网)让不同的主机系统之间可以共享文件或目录,NFS的客户端(一般为应用服务器 ...
- python-day6面向对象、类的继承
@面向对象三大特性:封装encapsulation.继承inheritance.多态(一个接口,多个实现)polymorphism. @面向对象介绍http://www.cnblogs.com/ale ...
- PHP截取特定字符串前后
$email = '13366540193@163.com' ;$domain = strstr ( $email , '@' );echo $domain ; // 打印 @163. ...
- 慕课网c#开发轻松入门6-8最终项目
下面是一些同学的姓名和对应的考试分数,请输出他们的平均分和高于平均分的同学姓名. 运行效果如下: using System; using System.Collections.Generic; usi ...
- xcode9.4 报错 error:The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.
原因 http | https 协议 不能正常使用 找到的解决方案 但是在字段名上有了变化,不过复制进去 还是会自动选择对应的 解决办法 1. 在Info.plist中添加 App Transpor ...