当前位置: 首页 > news >正文

天河门户网站建设公司免费域名注册网站

天河门户网站建设公司,免费域名注册网站,微信平台的微网站怎么做的,wordpress头像缓存插件背景 ​ 如果让我评选最伟大的数据结构,在我心中答案只有两个,数组和哈希表,这两个是我的程序的重要组成部分,同时也是我饭碗的重要组成部分。slice和map简洁明了的API很容易让我们有一种他们提供了无限大的空间,可以…

背景

​ 如果让我评选最伟大的数据结构,在我心中答案只有两个,数组和哈希表,这两个是我的程序的重要组成部分,同时也是我饭碗的重要组成部分。slice和map简洁明了的API很容易让我们有一种他们提供了无限大的空间,可以容纳无限多的数据。然而,我们内心都有一面明镜,知道他们这些岁月静好的背后是通过扩容操作替我们负重前行。在nutsdb有slice和map来构建关键的数据结构或者处理数据,为了探究slice和map的使用对性能有没有影响,有多大影响,由此评估需不需要对这两个数据结构的使用方式进行优化。于是对slice和map扩容对性能的影响这个问题做了一些探究。总结出了一些文章。这是这个系列的第一篇文章。对slice扩容对性能的影响的研究。分享给大家。

1. Slice扩容对性能的影响

Slice是Go提供给我们的数据结构,基本上也是我们开发中最常用的数据结构了,在开发中使用过程一般是下面这样:

func TestSliceBaseUsage(t *testing.T) {var slice []intslice = append(slice, 1, 2, 3)
}func TestSizedSliceBaseUsage(t *testing.T) {slice := make([]int, 10)slice = append(slice, 1, 2, 3)
}

第一种用法就是不指定切片的容量,用到哪里是哪里,第二种就是指定了容量,先申请一片空间,等用到了一定程度再继续扩容。那么他们两个之间到底有怎样的差异呢?我们来看看下面这段Benchmark测试。

func BenchmarkSlickGrow(b *testing.B) {// 要测试的切片长度var lengths = []int{1000, 10 * 1000, 100 * 1000, 1000 * 1000}for _, length := range lengths {// 直接申请空间的切片 性能测试nameOfNotGrowBM := fmt.Sprintf("test_slice_not_grow_%d", length)b.Run(nameOfNotGrowBM, func(b *testing.B) {b.ReportAllocs()b.StartTimer()for i := 0; i < b.N; i++ {value := 1slice := make([]int, length)for i := 0; i < length; i++ {slice = append(slice, value)}}})// 从一开始就不申请空间,一路append的切片 性能测试nameOfGrowBM := fmt.Sprintf("test_slice_grow_%d", length)b.Run(nameOfGrowBM, func(b *testing.B) {b.ReportAllocs()b.StartTimer()for i := 0; i < b.N; i++ {value := 1var slice []intfor i := 0; i < length; i++ {slice = append(slice, value)}}})}
}

这个benchmark测试了从长度数量级为一千到一百万的切片,直接申请空间然后逐渐添加元素和不申请空间通过append添加元素这两种操作之间的性能对比。我们跑一下这个代码来看看结果:

goos: darwin
goarch: arm64
pkg: go-learn/go
BenchmarkSlickGrow
BenchmarkSlickGrow/test_slice_not_grow_1000
BenchmarkSlickGrow/test_slice_not_grow_1000-10         	  242797	      4759 ns/op	   38912 B/op	       3 allocs/op
BenchmarkSlickGrow/test_slice_grow_1000
BenchmarkSlickGrow/test_slice_grow_1000-10             	  304522	      3619 ns/op	   25208 B/op	      12 allocs/op
BenchmarkSlickGrow/test_slice_not_grow_10000
BenchmarkSlickGrow/test_slice_not_grow_10000-10        	   16395	     71704 ns/op	  507905 B/op	       4 allocs/op
BenchmarkSlickGrow/test_slice_grow_10000
BenchmarkSlickGrow/test_slice_grow_10000-10            	   22346	     52807 ns/op	  357626 B/op	      19 allocs/op
BenchmarkSlickGrow/test_slice_not_grow_100000
BenchmarkSlickGrow/test_slice_not_grow_100000-10       	    1620	    729987 ns/op	 6635538 B/op	       5 allocs/op
BenchmarkSlickGrow/test_slice_grow_100000
BenchmarkSlickGrow/test_slice_grow_100000-10           	    2632	    468636 ns/op	 4101390 B/op	      28 allocs/op
BenchmarkSlickGrow/test_slice_not_grow_1000000
BenchmarkSlickGrow/test_slice_not_grow_1000000-10      	     308	   3843628 ns/op	65708071 B/op	       5 allocs/op
BenchmarkSlickGrow/test_slice_grow_1000000
BenchmarkSlickGrow/test_slice_grow_1000000-10          	     360	   3247562 ns/op	41678130 B/op	      38 allocs/op
PASS

从测试结果来看,不扩容的测试组性能上,内存上,比起扩容的测试组,领先优势起码拉开了一个身位。

  1. 1000这个档位,速度上不扩容比扩容快约30%, 内存上不扩容比扩容省50%
  2. 10,000这个档位,速度上不扩容比扩容快约36%, 内存上不扩容比扩容省42%
  3. 100,000这个档位,速度上不扩容比扩容快约18%, 内存上不扩容比扩容省20%

为什么会造成这个样子的结果呢?让我们来看看slice的扩容原理。

func growslice(et *_type, old slice, cap int) slice {newcap := old.capdoublecap := newcap + newcapif cap > doublecap {newcap = cap} else {const threshold = 256if old.cap < threshold {newcap = doublecap} else {// Check 0 < newcap to detect overflow// and prevent an infinite loop.for 0 < newcap && newcap < cap {// Transition from growing 2x for small slices// to growing 1.25x for large slices. This formula// gives a smooth-ish transition between the two.newcap += (newcap + 3*threshold) / 4}// Set newcap to the requested cap when// the newcap calculation overflowed.if newcap <= 0 {newcap = cap}}}}

这个是go1.8的growslice函数,这里面实现的slice扩容原理是这样的,在容量小于256的时候,执行成本扩容,在容量大于256的时候,将执行1.25倍的扩容。另外扩容的时候会申请一片长度为扩容后的容量的内存把数据都搬迁过去,迁移之后原来的内存就无用了,会一直在内存中飘荡等待GC的回收。

总结

所以在我们在使用slice处理数据的时候要留意一下他的扩容问题。乍看下来还是有一定影响的。在数据量大的情况下,如果要优化内存和执行速度,是可以考虑对slice进行一定的优化的,比如:

  1. 如果已经知道了要处理的数据量,可以直接申请足够大的空间来处理。
  2. 如果不知道数据量,可以把处理流程改成将数据一个个进行处理。
http://www.hkea.cn/news/679833/

相关文章:

  • 租车网站建设站长之家源码
  • 昌吉州回族自治州建设局网站地产渠道12种拓客方式
  • 北京市网站公司网络项目免费的资源网
  • 电子商务网站规划、电子商务网站建设站长工具 忘忧草
  • 凡科建网关键词优化公司哪家好
  • seo排名推广工具seo公司多少钱
  • 做视频网站赚钱怎么在百度上推广自己的公司信息
  • 网站建设凡科厦门网站建设平台
  • 互联网行业pest分析福州百度快速优化排名
  • 做网站的接私活犯法吗如何对网站进行推广
  • 身高差效果图网站优化师和运营区别
  • 谷歌wordpress建站搜索引擎算法
  • .net 购物网站开发源代码发布信息的免费平台
  • 自己做一网站大学生网络营销策划书
  • 关于网站建设的文章百度域名收录提交入口
  • 国人在线做网站推广图片大全
  • 郑州网站建设七彩科技四年级说新闻2023
  • 在什么网站上做自媒体seo整站怎么优化
  • 网站开发要注意安全性公司优化是什么意思
  • 河北邢台做移动网站开通网站需要多少钱
  • 天河网站建设多少钱淘宝关键词优化
  • 中型网站 收益关键词排名查询官网
  • 网站的弹窗是怎么做的谈谈对seo的理解
  • 广州网站制作费用宁波seo外包哪个品牌好
  • 河南高端网站建设广州网站优化页面
  • 企业可以备案几个网站南昌seo实用技巧
  • 网站用什么布局专业网站建设公司
  • 公司网站怎么做分录it培训机构学费一般多少
  • 如何将自己做的网页做成网站绍兴seo
  • 河南省住房与城乡建设厅网站首页怎么做属于自己的网站