深度拷贝 pcopy,性能升级版本来了 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
guonaihong
V2EX    Go 编程语言

深度拷贝 pcopy,性能升级版本来了

  •  1
     
  •   guonaihong
    guonaihong 2023 年 5 月 18 日 3333 次点击
    这是一个创建于 1055 天前的主题,其中的信息可能已经有所发展或是发生改变。

    地址

    https://github.com/antlabs/pcopy

    作用

    Go codecov

    pcopy.Copy主要用于两个类型间的深度拷贝, 前身是 deepcopy

    新加预热函数。Copy 时打开加速开关,达到性能提升 4-10 倍的效果。

    警告:

    高性能的同时可能会有些 bug, 如果发现 bug 可以去掉pcopy.WithUsePreheat()试下, 结果不一致,可以提 issue 。

    feature

    • 高性能, 相对第一个版本提升 4-10 倍的性能
    • 支持异构结构体拷贝, dst 和 src 可以是不同的类型,会拷贝 dst 和 src 交集的部分
    • 多类型支持 struct/map/slice/array/int...int64/uint...uint64/ 等等

    内容

    Installation

    go get github.com/antlabs/pcopy 

    Quick start

    package main import ( "fmt" "github.com/antlabs/pcopy" ) type dst struct { ID int Result string } type src struct{ ID int Text string } func main() { d, s := dst{}, src{ID:3} pcopy.Preheat(&dst{}, &src{}) // 一对类型只要预热一次 pcopy.Copy(&d, &s, pcopy.WithUsePreheat()) fmt.Printf("%#v\n", d) } 

    copy slice

    package main import ( "fmt" "github.com/antlabs/pcopy" ) func main() { i := []int{1, 2, 3, 4, 5, 6} var o []int pcopy.Preheat(&o, &i) pcopy.Copy(&o, &i, pcopy.WithUsePreheat()) fmt.Printf("%#v\n", o) } 

    copy map

    package main import ( "fmt" "github.com/antlabs/pcopy" ) func main() { i := map[string]int{ "cat": 100, "head": 10, "tr": 3, "tail": 44, } var o map[string]int pcopy.Preheat(&o, &i) pcopy.Copy(&o, &i, pcopy.WithUsePreheat()) fmt.Printf("%#v\n", o) } 

    simplify business code development

    经常看到,对同一个结构体的,有值更新操作,都是一堆手工 if 然后赋值的代码。不仅容易出错,还累。快使用 pcopy 解放双手。

    type option struct { Int int Float64 float64 S string } func main() { var a, b option if b.Int != 0 { a.Int = b.Int } if b.Float64 != 0.0 { a.Float64 = b.Float64 } if b.S != "" { a.S = b.S } pcopy.Preheat(&a, &b) //只要预热一次 //可以约化成 pcopy.Copy(&a, &b, pcopy.WithUsePreheat()) } 

    benchmark

    从零实现的 pcopy 相比 json 序列化与反序列化方式拥有更好的性能

    压测仓库位置

    goos: darwin goarch: arm64 pkg: benchmark Benchmark_Use_reflectValue_MiniCopy-8 334728 3575 ns/op Benchmark_Use_reflectValue_DeepCopy-8 595302 1956 ns/op Benchmark_Use_reflectValue_Copier-8 203574 5860 ns/op Benchmark_Use_Ptr_jsoniter-8 821113 1477 ns/op Benchmark_Use_Ptr_pcopy-8 3390382 354.0 ns/op Benchmark_Use_Ptr_coven-8 1414197 848.7 ns/op PASS ok benchmark 9.771s 

    本项目压测

    从下面的压测数据可以看到,基本提供了 4-10 倍的性能提升

    goos: darwin goarch: arm64 pkg: github.com/antlabs/pcopy Benchmark_BaseMap_Unsafe_Pcopy-8 529747 2343 ns/op Benchmark_BaseMap_miniCopy-8 62181 19212 ns/op Benchmark_BaseMap_Reflect-8 93810 12756 ns/op Benchmark_BaseSlice_Unsafe_Pcopy-8 2013764 595.1 ns/op Benchmark_BaseSlice_miniCopy-8 154918 7728 ns/op Benchmark_BaseSlice_Reflect-8 188720 6393 ns/op Benchmark_BaseType_Unsafe_Pcopy-8 4872112 243.8 ns/op Benchmark_BaseType_MiniCopy-8 517814 2278 ns/op Benchmark_BaseType_Pcopy-8 635156 1886 ns/op Benchmark_CompositeMap_Unsafe_Pcopy-8 486253 2409 ns/op Benchmark_CompositeMap_miniCopy-8 229674 5173 ns/op Benchmark_CompositeMap_Reflect-8 475243 2490 ns/op Benchmark_GetLikeFavorited_Unsafe_Pcopy2-8 446907 2662 ns/op Benchmark_GetLikeFavorited_Unsafe_Pcopy-8 470217 2572 ns/op Benchmark_GetLikeFavorited_MiniCopy-8 85674 13989 ns/op Benchmark_GetLikeFavorited_Reflect_Pcopy-8 121603 9856 ns/op Benchmark_GetRedPoint_Unsafe_Pcopy-8 1626688 736.1 ns/op Benchmark_GetRedPoint_MiniCopy-8 650004 1871 ns/op Benchmark_GetRedPoint_Reflect_Pcopy-8 1669778 722.0 ns/op Benchmark_Interface_Unsafe_Pcopy-8 2869022 421.3 ns/op Benchmark_Interface_MiniCopy-8 413936 2704 ns/op Benchmark_Interface_Pcopy-8 440250 2688 ns/op Benchmark_Interface_BaseSlice_Unsafe_Pcopy-8 1266501 947.4 ns/op Benchmark_Interface_BaseSlice_MiniCopy-8 141610 8422 ns/op Benchmark_Interface_BaseSlice_Pcopy-8 203906 5917 ns/op Benchmark_Ptr_BaseType1_Unsafe_Pcopy-8 910153 1310 ns/op Benchmark_Ptr_BaseType1_Reflect_Pcopy-8 391117 3026 ns/op Benchmark_Ptr_BaseSlice_Unsafe_Pcopy-8 698156 1704 ns/op Benchmark_Ptr_BaseSlice_Reflect_Pcopy-8 219999 5415 ns/op Benchmark_SliceWithStruct_Unsafe_Pcopy-8 1395982 860.3 ns/op Benchmark_SliceWithStruct_miniCopy-8 163154 7298 ns/op Benchmark_SliceWithStruct_Reflect_Pcopy-8 190728 6213 ns/op 
    13 条回复    2023-07-19 17:42:06 +08:00
    matrix1010
        1
    matrix1010  
       2023 年 5 月 18 日
    你这 codecov 42%有点难看啊, 我觉得低于 70%就别放了
    SingeeKing
        2
    SingeeKing  
    PRO
       2023 年 5 月 18 日
    感觉基于反射实现的一个最大的问题就是不支持私有字段,十分难受
    guonaihong
        3
    guonaihong  
    OP
       2023 年 5 月 18 日
    @matrix1010 后面再提高下,影响测试覆盖度的都是用 tmpl 生成的代码。
    shockerli
        4
    shockerli  
       2023 年 5 月 18 日
    一直在用 copier
    phithon
        5
    phithon  
       2023 年 5 月 18 日
    同用 copier
    bthulu
        6
    bthulu  
       2023 年 5 月 18 日
    能支持多语言吗?
    guonaihong
        7
    guonaihong  
    OP
       2023 年 5 月 18 日
    @shockerli @phithon copier 从压测数据来看不太快。pcony 运行时间是 copier 的 1/16.
    guonaihong
        8
    guonaihong  
    OP
       2023 年 5 月 18 日
    @bthulu 怎么理解?
    ToBeHacker
        9
    ToBeHacker  
       2023 年 5 月 19 日
    有必要这么搞么,使用大量的反射来进行 deep copy 还是太重了吧
    xuanbg
        10
    xuanbg  
       2023 年 5 月 19 日
    有和我一样直接序列化再反序列化完事的么……
    bv
        11
    bv  
       2023 年 5 月 19 日
    @xuanbg 那估计少有,哈哈
    guonaihong
        12
    guonaihong  
    OP
       2023 年 5 月 21 日
    @ToBeHacker 这么做只是为了可控性。能不停进行性能的提升。假如跳开这个库的话题,回到大家熟悉的服务端,我们可以用标准库快速一个 server 。如果要进行性能的提升,可能要进行一大量的定制开发(库作者的角度),比如 epoll+协程池+gc 优化。它背后的思路一样,开箱即用的东西,性能不好提升。
    guonaihong
        13
    guonaihong  
    OP
       2023 年 7 月 19 日
    @SingeeKing 要支持的话也很简单,拿到这个字段的指针地址,后面直接修改就行。但是 pcopy 不会支持修改私有字段的。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3424 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 10:57 PVG 18:57 LAX 03:57 JFK 06:57
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86