Golang高效地拷貝big.Int

錯誤的方式

試圖通過拷貝*big.Int指針所指的結(jié)構(gòu):

a := big.NewInt(10)
b := new(big.Int)
*b = *a

這種方式是錯誤的,因為big.Int結(jié)構(gòu)內(nèi)部有slice,拷貝結(jié)構(gòu)的話內(nèi)部的slice仍然是共享內(nèi)存。

點擊運行測試

正確的方式

1.拷貝Bytes

思想:

序列化成[]bytes,然后拷貝

func BenchmarkBigIntCopyBytes(b *testing.B) {
    b.ReportAllocs()

    old, _ := new(big.Int).SetString("100000000222222222222222222220000000000000000000", 10)
    new := new(big.Int)
    for i := 0; i < b.N; i++ {
        new.SetBytes(old.Bytes())
    }
}

2.反射賦值

思想:

通過反射賦值

func BenchmarkBigIntCopier(b *testing.B) {
    b.ReportAllocs()

    old, _ := new(big.Int).SetString("100000000222222222222222222220000000000000000000", 10)
    new := new(big.Int)
    for i := 0; i < b.N; i++ {
        // "github.com/jinzhu/copier"
        copier.Copy(new, old)
    }

}

copier內(nèi)部實現(xiàn)使用了reflect

3. +0

思想

new = old = old + 0

func TestCopyByAdd(t *testing.T) {
    old, _ := new(big.Int).SetString("100000000222222222222222222220000000000000000000", 10)

    new := new(big.Int)
    // new = old = old + 0
    new.Add(old, new)
    if old.Cmp(new) != 0 {
        t.FailNow()
    }

    new.Add(new, big.NewInt(1))
    t.Logf("old:%v,new:%v", old, new)
    if old.Cmp(new) >= 0 {
        t.FailNow()
    }
}

Benchmark測試

func BenchmarkBigIntCopyByAdd(b *testing.B) {
    b.ReportAllocs()

    old, _ := new(big.Int).SetString("100000000222222222222222222220000000000000000000", 10)
    new := new(big.Int)
    for i := 0; i < b.N; i++ {
        // new = old = old + 0
        new.Add(old, new)
    }
}

性能對比

big.Int = 10

BenchmarkBigIntCopier-8     30000000            62.5 ns/op         0 B/op          0 allocs/op
BenchmarkBigIntCopyBytes-8      30000000            46.7 ns/op         8 B/op          1 allocs/op
BenchmarkBigIntCopyByAdd-8      100000000           20.8 ns/op         0 B/op          0 allocs/op

big.Int = 100000000222222222222222222220000000000000000000

BenchmarkBigIntCopier-8     30000000            60.8 ns/op         0 B/op          0 allocs/op
BenchmarkBigIntCopyBytes-8      20000000            69.1 ns/op        32 B/op          1 allocs/op
BenchmarkBigIntCopyByAdd-8      100000000           22.1 ns/op         0 B/op          0 allocs/op

比較兩次運行的結(jié)果,發(fā)現(xiàn):

  • BenchmarkBigIntCopyBytes有額外的內(nèi)存分配,其它兩個方法則沒有
  • 當(dāng)big.Int值變大時,BenchmarkBigIntCopyBytes分配的內(nèi)存增加,性能變差,結(jié)果BenchmarkBigIntCopier接近,甚至還差一點
  • BenchmarkBigIntCopyByAdd是性能最好的,沒有額外的內(nèi)存分配,且耗時穩(wěn)定

結(jié)論

+ 0 是最好的選擇

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載自:https://halfrost.com/go_map_chapter_one/ https://half...
    HuJay閱讀 6,484評論 1 5
  • 從三月份找實習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時芥藍閱讀 42,895評論 11 349
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,666評論 30 472
  • 故鄉(xiāng)的小河 是記憶中轉(zhuǎn)動的風(fēng)車 洋溢著歡樂 這洋溢著歡樂的小河 故鄉(xiāng)的小河 是泥巴捏成的信鴿 傳遞著思念 這傳遞著...
    喜禾丹閱讀 308評論 5 3
  • 關(guān)于人際邊界的感悟,實在是很多很多,于是乎整理出來,發(fā)表出來,大約會有不少于六篇。有興趣的朋友可以持續(xù)關(guān)注頭條號“...
    黃衣心理王靜閱讀 1,374評論 0 3

友情鏈接更多精彩內(nèi)容