美文网首页
Golang高效地拷贝big.Int

Golang高效地拷贝big.Int

作者: 幸运排骨虾 | 来源:发表于2018-09-18 16:23 被阅读0次

错误的方式

试图通过拷贝*big.Int指针所指的结构:

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

这种方式是错误的,因为big.Int结构内部有slice,拷贝结构的话内部的slice仍然是共享内存。

点击运行测试

正确的方式

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内部实现使用了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

比较两次运行的结果,发现:

  • BenchmarkBigIntCopyBytes有额外的内存分配,其它两个方法则没有
  • big.Int值变大时,BenchmarkBigIntCopyBytes分配的内存增加,性能变差,结果BenchmarkBigIntCopier接近,甚至还差一点
  • BenchmarkBigIntCopyByAdd是性能最好的,没有额外的内存分配,且耗时稳定

结论

+ 0 是最好的选择

相关文章

  • Golang高效地拷贝big.Int

    错误的方式 试图通过拷贝*big.Int指针所指的结构: 这种方式是错误的,因为big.Int结构内部有slice...

  • golang小知识

    golang这门语言中没有深拷贝。浅拷贝是拷贝值以及值中直接包含的东西。深拷贝是连同结构一块拷贝。 通道是将gor...

  • 后端研发体系

    记录自己为了面试发现的文章 golang golang中都是值传递,没有引用传递,哪怕是指针,也是指针的值拷贝。 ...

  • golang copy

    golang copy函数用于在两个slice之间进行拷贝数据,其拷贝数据的长度为 len(dst)与len(sr...

  • golang开发环境搭建

    1. 操作系统以及golang安装 使用操作系统redhat7.2 x86_64为,将golang解压后拷贝到/u...

  • golang 16进制转换10进制

    float64 convert to string string hex convert to big.Int ...

  • golang结构体拷贝

    实现了类似Spring中BeanUtils中的对象复制功能,支持过滤字段,支持时间和字符字段的转换

  • 如何手动使用ccenv image编译golang的chainc

    准备golang chaincode源文件 本地创建目录: 把chaincode所有源文件拷贝到chaincode...

  • golang 从 map 获取值时的值拷贝问题

    实际场景 我们知道 golang 中,slice, map, channel 是引用类型,函数之间传递都是以值拷贝...

  • 深拷贝和常见一些坑

    golang 完全是按值传递,所以正常的赋值都是值拷贝,当然如果类型里面嵌套的有指针,也是指针值的拷贝,此时就会出...

网友评论

      本文标题:Golang高效地拷贝big.Int

      本文链接:https://www.haomeiwen.com/subject/ecmpnftx.html