欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

三種Golang數(shù)組拷貝方式及性能分析詳解

 更新時(shí)間:2022年08月24日 10:13:47   作者:jiaxwu  
在Go語(yǔ)言中,我們可以使用for、append()和copy()進(jìn)行數(shù)組拷貝。這篇文章主要為大家詳細(xì)介紹一下這三種方式的具體實(shí)現(xiàn)與性能分析,需要的可以參考一下

在Go語(yǔ)言中,我們可以使用forappend()copy()進(jìn)行數(shù)組拷貝,對(duì)于某些對(duì)性能比較敏感且數(shù)組拷貝比較多的場(chǎng)景,我們可以會(huì)對(duì)拷貝性能比較關(guān)注,這篇文件主要是對(duì)比一下這三種方式的性能。

測(cè)試

測(cè)試條件是把一個(gè)64KB的字節(jié)數(shù)組分為64個(gè)塊進(jìn)行復(fù)制。

測(cè)試代碼

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 < b.N; n++ {
		for i := 0; i < blocks; i++ {
			for j := 0; j < blockSize; j++ {
				a[i*blockSize+j] = block[j]
			}
		}
	}
}

func BenchmarkAppend(b *testing.B) {
	a := make([]byte, 0, blocks*blockSize)
	for n := 0; n < b.N; n++ {
		a = a[:0]
		for i := 0; i < blocks; i++ {
			a = append(a, block...)
		}
	}
}

func BenchmarkCopy(b *testing.B) {
	a := make([]byte, blocks*blockSize)
	for n := 0; n < b.N; n++ {
		for i := 0; i < blocks; i++ {
			copy(a[i*blockSize:], block)
		}
	}
}

測(cè)試結(jié)果

可以看到copy的性能是最好的,當(dāng)然append的性能也接近c(diǎn)opy,for性能較差。

BenchmarkFori-8            19831             52749 ns/op
BenchmarkAppend-8         775945              1478 ns/op
BenchmarkCopy-8           815556              1473 ns/op

原理分析

我們簡(jiǎn)單分析copy和append的原理。

copy

代碼

可以看到最終都會(huì)調(diào)用memmove()整塊拷貝內(nèi)存,而且是用匯編實(shí)現(xiàn)的,因此性能是最好的。

// 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 < n {
		n = toLen
	}

	if width == 0 {
		return n
	}

	size := uintptr(n) * width
	if raceenabled {
		callerpc := getcallerpc()
		pc := funcPC(slicecopy)
		racereadrangepc(fromPtr, size, callerpc, pc)
		racewriterangepc(toPtr, size, callerpc, pc)
	}
	if msanenabled {
		msanread(fromPtr, size)
		msanwrite(toPtr, size)
	}

	if size == 1 { // common case worth about 2x to do here
		// TODO: is this still worth it with new memmove impl?
		*(*byte)(toPtr) = *(*byte)(fromPtr) // known to be a byte pointer
	} else {
		memmove(toPtr, fromPtr, size)
	}
	return n
}

append

代碼

append最終會(huì)被編譯期轉(zhuǎn)換成以下代碼,也是調(diào)用了memmove()整塊拷貝內(nèi)存,因此其實(shí)性能是和copy差不多的。

	  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))

總結(jié)

拷貝方式性能適合場(chǎng)景
for較差無(wú)法使用append和copy的場(chǎng)景,比如類型不同,需要更加復(fù)雜的判斷等
copy適合提前已經(jīng)分配數(shù)組容量,且不是尾部追加的方式
append適合大多數(shù)情況,尾部追加

大部分情況下還是建議使用append,不僅性能好,動(dòng)態(tài)擴(kuò)展容量,而且代碼看起來(lái)更加清晰!

到此這篇關(guān)于三種Golang數(shù)組拷貝方式及性能分析詳解的文章就介紹到這了,更多相關(guān)Golang數(shù)組拷貝內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語(yǔ)言讀取文件的四種方式

    Go語(yǔ)言讀取文件的四種方式

    本文主要介紹了Go語(yǔ)言讀取文件的四種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 一百行Golang代碼實(shí)現(xiàn)簡(jiǎn)單并發(fā)聊天室

    一百行Golang代碼實(shí)現(xiàn)簡(jiǎn)單并發(fā)聊天室

    這篇文章主要為大家詳細(xì)介紹了一百行Golang代碼如何實(shí)現(xiàn)簡(jiǎn)單并發(fā)聊天室,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • Go語(yǔ)言中的通道channel詳情

    Go語(yǔ)言中的通道channel詳情

    這篇文章主要介紹了Go語(yǔ)言中的通道channel,在Go語(yǔ)言中管道類似于一個(gè)數(shù)據(jù)流,每次放入或者取出一部分?jǐn)?shù)據(jù),數(shù)據(jù)取出后原通道內(nèi)的數(shù)據(jù)就刪除掉,在linux操作系統(tǒng)中管道會(huì)將函數(shù)的返回結(jié)果作為下一個(gè)函數(shù)的參數(shù),下文詳細(xì)內(nèi)容需要的朋友可以參考下
    2022-02-02
  • 協(xié)同開發(fā)巧用gitignore中間件避免網(wǎng)絡(luò)請(qǐng)求攜帶登錄信息

    協(xié)同開發(fā)巧用gitignore中間件避免網(wǎng)絡(luò)請(qǐng)求攜帶登錄信息

    這篇文章主要為大家介紹了協(xié)同開發(fā)巧用gitignore中間件避免網(wǎng)絡(luò)請(qǐng)求攜帶登錄信息
    2022-06-06
  • 解決GO編譯時(shí)避免引入外部動(dòng)態(tài)庫(kù)的問(wèn)題

    解決GO編譯時(shí)避免引入外部動(dòng)態(tài)庫(kù)的問(wèn)題

    最近碰到一個(gè)問(wèn)題,有一個(gè)流量采集的組件中使用到了github.com/google/gopacket 這個(gè)庫(kù),這個(gè)庫(kù)使用一切正常,但是唯獨(dú)有一個(gè)缺點(diǎn),編譯后的二進(jìn)制文件依賴于libpcap.so的動(dòng)態(tài)庫(kù),這篇文章主要介紹了GO編譯時(shí)避免引入外部動(dòng)態(tài)庫(kù)的解決方法,需要的朋友可以參考下
    2022-10-10
  • 基于Go語(yǔ)言實(shí)現(xiàn)插入排序算法及優(yōu)化

    基于Go語(yǔ)言實(shí)現(xiàn)插入排序算法及優(yōu)化

    插入排序是一種簡(jiǎn)單的排序算法。這篇文章將利用Go語(yǔ)言實(shí)現(xiàn)冒泡排序算法,文中的示例代碼講解詳細(xì),對(duì)學(xué)習(xí)Go語(yǔ)言有一定的幫助,需要的可以參考一下
    2022-12-12
  • go-zero 應(yīng)對(duì)海量定時(shí)/延遲任務(wù)的技巧

    go-zero 應(yīng)對(duì)海量定時(shí)/延遲任務(wù)的技巧

    這篇文章主要介紹了go-zero 如何應(yīng)對(duì)海量定時(shí)/延遲任務(wù),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Go語(yǔ)言學(xué)習(xí)otns示例分析

    Go語(yǔ)言學(xué)習(xí)otns示例分析

    這篇文章主要為大家介紹了Go語(yǔ)言學(xué)習(xí)otns示例分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • Go uuid庫(kù)的具體使用

    Go uuid庫(kù)的具體使用

    在現(xiàn)代軟件開發(fā)中,全球唯一標(biāo)識(shí)符(UUID)在許多場(chǎng)景中發(fā)揮著重要的作用,本文主要介紹了Go uuid庫(kù)的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • 十個(gè)Go map面試常考問(wèn)題合集

    十個(gè)Go map面試??紗?wèn)題合集

    go面試中,map相關(guān)知識(shí)點(diǎn)問(wèn)的比較多,這篇文章主要為大家整理歸納了10個(gè)??嫉膯?wèn)題,文中的示例代碼講解詳細(xì),希望對(duì)大家有一定的幫助
    2023-07-07

最新評(píng)論