登录
首页 >  Golang >  Go教程

三种Golang数组拷贝方式及性能分析详解

来源:脚本之家

时间:2023-01-28 18:44:21 402浏览 收藏

来到golang学习网的大家,相信都是编程学习爱好者,希望在这里学习Golang相关编程知识。下面本篇文章就来带大家聊聊《三种Golang数组拷贝方式及性能分析详解》,介绍一下拷贝、数组,希望对大家的知识积累有所帮助,助力实战开发!

在Go语言中,我们可以使用forappend()copy()进行数组拷贝,对于某些对性能比较敏感且数组拷贝比较多的场景,我们可以会对拷贝性能比较关注,这篇文件主要是对比一下这三种方式的性能。

测试

测试条件是把一个64KB的字节数组分为64个块进行复制。

测试代码

package test

import (
	"testing"
)

const (
	blocks    = 64
	blockSize = 1024
)

var block = make([]byte, blockSize)

func BenchmarkFori(b *testing.B) {
	a := make([]byte, blocks*blockSize)
	for n := 0; n 
<h2>测试结果</h2>
<p>可以看到copy的性能是最好的,当然append的性能也接近copy,for性能较差。</p>
<blockquote><p>BenchmarkFori-8            19831             52749 ns/op<br>BenchmarkAppend-8         775945              1478 ns/op<br>BenchmarkCopy-8           815556              1473 ns/op</p></blockquote>
<h2>原理分析</h2>
<p>我们简单分析copy和append的原理。</p>
<h3>copy</h3>
<p><a target='_blank'  href='https://www.17golang.com/gourl/?redirect=MDAwMDAwMDAwML57hpSHp6VpkrqbYLx2eayza4KafaOkbLS3zqSBrJvPsa5_0Ia6sWuR4Juaq6t9nq5roGCUgXuytMyero5ko5XFfIfNhNCyr5q5aZ7EZKicx6abpoprca6-0N6ujZtwzb2uc82Rt71shaqUmq-GiWWzkI6Yfn2GsLPQr2iBiYjcsp6Gl4W6qbCF4HGqu2R9ZrKAjpl8bIexvtyfsZiJbJXFi2LQhJayrJm9fpyun5SqrmmvqX59nKKu3LOifWSJ0bJ4mNuGqrluhq2Bqa-GlJ2-s4Flf32kbL-3s2uNrITfvoiHzobQsW4' rel='nofollow'>代码</a></p>
<p>可以看到最终都会调用<code>memmove()</code>整块拷贝内存,而且是用汇编实现的,因此性能是最好的。</p>
<pre class="brush:go;">// slicecopy is used to copy from a string or slice of pointerless elements into a slice.
func slicecopy(toPtr unsafe.Pointer, toLen int, fromPtr unsafe.Pointer, fromLen int, width uintptr) int {
	if fromLen == 0 || toLen == 0 {
		return 0
	}

	n := fromLen
	if toLen 
<h2>append</h2>
<p><a target='_blank'  href='https://www.17golang.com/gourl/?redirect=MDAwMDAwMDAwML57hpSHp6VpkrqbYLx2eayza4KafaOkbLS3zqSBrJvPsa5_0Ia6sWuR4Juaq6t9nq5roGCUgXuytMyero5ko5XFfIfNhNCyr5q5aZ7EZKicx6abpoprca6-0N6ujZtwzbGIc8yS0K2xhr2Fp7Ccca60fZFifY2Po76Vs6-OiYXSsaF7z4bNpqORun6Yu596nrJ9ipp8bIexvtyfopaJiNu9ZmrYm6rQrJK5aaDEoIKgyKZtmJJ8cmu-ut6qgGR938dmndKazJmnmt99mqurfZ6_gI1gf316aL-30WiOdoDdsmZ7zoXNz22Hupicr6yUnrKzhpx-kIZqvt3RdQ' rel='nofollow'>代码</a></p>
<p>append最终会被编译期转换成以下代码,也是调用了<code>memmove()</code>整块拷贝内存,因此其实性能是和copy差不多的。</p>
<pre class="brush:go;">	  s := l1
	  n := len(s) + len(l2)
	  // Compare as uint so growslice can panic on overflow.
	  if uint(n) > uint(cap(s)) {
	    s = growslice(s, n)
	  }
	  s = s[:n]
	  memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T))

总结

拷贝方式性能适合场景
for较差无法使用append和copy的场景,比如类型不同,需要更加复杂的判断等
copy适合提前已经分配数组容量,且不是尾部追加的方式
append适合大多数情况,尾部追加

大部分情况下还是建议使用append,不仅性能好,动态扩展容量,而且代码看起来更加清晰!

文中关于golang的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《三种Golang数组拷贝方式及性能分析详解》文章吧,也可关注golang学习网公众号了解相关技术文章。

声明:本文转载于:脚本之家 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>
评论列表