[{"data":1,"prerenderedAt":228},["ShallowReactive",2],{"content:\u002F2022\u002Fstruct_perf_boost_15_percent":3,"surround:\u002F2022\u002Fstruct_perf_boost_15_percent":217},{"id":4,"title":5,"body":6,"categories":171,"date":173,"description":174,"draft":175,"extension":176,"image":177,"meta":178,"navigation":203,"path":204,"permalink":177,"published":177,"readingTime":205,"recommend":177,"references":177,"seo":210,"sitemap":211,"stem":212,"tags":213,"type":215,"updated":177,"__hash__":216},"content\u002Fposts\u002F2022\u002Fstruct_perf_boost_15_percent.md","0 秒改 struct 性能直接提升 15%，产品姐姐都夸我好棒",{"type":7,"value":8,"toc":168},"minimark",[9,13,24,35,43,46,49,52,61,68,78,81,87,93,96,99,105,114,117,128,134,142,145,148,156,162],[10,11,12],"p",{},"让我们先来看一个例子。如下。",[14,15,21],"pre",{"className":16,"code":18,"language":19,"meta":20},[17],"language-go","type BadStruct struct {\n    age          uint8\n    IdCardNumber uint64\n    DateOfBirth  uint16\n}\n\ntype GoodStruct struct {\n    age          uint8\n    DateOfBirth  uint16\n    IdCardNumber uint64\n}\n","go","",[22,23,18],"code",{"__ignoreMap":20},[10,25,26,27,34],{},"在上面的例子中，我们定义了两个具有相同字段的结构体。接下来让我们编写一个简单的程序来输出他们的内存使用情况。点击",[28,29,33],"a",{"href":30,"rel":31},"https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002FDekLCtTGo6v",[32],"nofollow","此处","您可以获取测试代码。",[14,36,41],{"className":37,"code":39,"language":40},[38],"language-text","Bad struct is 24 bytes long\nGood struct is 16 bytes long\n","text",[22,42,39],{"__ignoreMap":20},[10,44,45],{},"如您所见，它们占用的内存不同。",[10,47,48],{},"到底发生了什么，导致两个字段相同的结构体消耗不同的字节？",[10,50,51],{},"答案是数据在操作系统中的内存排列方式。换句话说，数据结构对齐。",[10,53,54,57,58,60],{},[22,55,56],{"code":56},"CPU"," 以字长的方式读取数据，而不是通过字节大小。64 位操作系统中一个字长为 8 个字节，而 32 位操作系统中一个字长为 4 个字节。换句话说，",[22,59,56],{"code":56}," 以字长的倍数读取地址。",[10,62,63],{},[64,65],"img",{"alt":66,"src":67},"糟糕的结构体-01","https:\u002F\u002Fpic2.fukit.cn\u002Fautoupload\u002FZ3wg1auvHGH_fxQcOFgj2SfNcKcqEnRmcljopnyJoMs\u002F20260123\u002FXAeT\u002F1974X437\u002FBadStruct-01.png\u002Fwebp",[10,69,70,71,74,75,77],{},"在 64 位操作系统中，为了获取变量 ",[22,72,73],{"code":73},"IdCardNumber","，我们的 ",[22,76,56],{"code":56}," 需要两个周期来访问数据，而不是一个周期。",[10,79,80],{},"第一个周期将获取到 0 到 7 的内存，其余周期获取其余部分。",[10,82,83,84,86],{},"把它想象成一个笔记本，每页只能存储一个字大小的数据，此时是 8 个字节。如果 ",[22,85,73],{"code":73}," 分散在两个页面上，则需要翻页两次才能检索完整的数据。",[10,88,89],{},[90,91,92],"strong",{},"这是低效的。",[10,94,95],{},"因此我们需要对齐数据结构，即将数据存储在一个地址等于数据大小的倍数的位置。",[10,97,98],{},"例如，一个 2 字节的数据可以存储在内存 0、2 或 4 中，而一个 4 字节的数据可以存储在内存 0、4 或 8 中。",[10,100,101],{},[64,102],{"alt":103,"src":104},"糟糕的结构体-02","https:\u002F\u002Fpic2.fukit.cn\u002Fautoupload\u002FZ3wg1auvHGH_fxQcOFgj2SfNcKcqEnRmcljopnyJoMs\u002F20260123\u002FC5Ll\u002F1968X597\u002FBadStruct-02.png\u002Fwebp",[10,106,107,108,110,111,113],{},"通过简单的对齐数据，确保 ",[22,109,73],{"code":73}," 可以在同一个 ",[22,112,56],{"code":56}," 周期内检索到变量。",[10,115,116],{},"填充是实现数据对齐的关键。操作系统在数据结构之间用额外的字节填充数据以对齐它们。这就是额外内存的来源！",[10,118,119,120,123,124,127],{},"让我们再来看一看 ",[22,121,122],{"code":122},"BadStruct"," 和 ",[22,125,126],{"code":126},"GoodStruct","。",[10,129,130],{},[64,131],{"alt":132,"src":133},"修改结构体后的对比","https:\u002F\u002Fpic2.fukit.cn\u002Fautoupload\u002FZ3wg1auvHGH_fxQcOFgj2SfNcKcqEnRmcljopnyJoMs\u002F20260123\u002Fpcnx\u002F1808X1024\u002FGoodStruct-01.png\u002Fwebp",[10,135,136,138,139,141],{},[22,137,126],{"code":126}," 消耗更少的内存，仅仅是因为它比 ",[22,140,122],{"code":122}," 有更好的结构体字段顺序。",[10,143,144],{},"由于填充，两个数据结构分别变成了 16 字节和 24 字节。",[10,146,147],{},"所以，您只需重新排序结构体中的字段，就可以节省额外的内存！",[10,149,150,151,155],{},"最后，让我们来做一个简单你的基准测试来证明它在速度和内存的区别，结果如下。点击",[28,152,33],{"href":153,"rel":154},"https:\u002F\u002Fgo.dev\u002Fplay\u002Fp\u002Fi6F3VRFY61n",[32],"您可以获取可运行的代码。",[10,157,158],{},[64,159],{"alt":160,"src":161},"基准测试结果","https:\u002F\u002Fxland.eu.org\u002Fautoupload\u002FZ3wg1auvHGH_fxQcOFgj2SfNcKcqEnRmcljopnyJoMs\u002F20251110\u002Fw6n2\u002F1065X390\u002FResult.png",[10,163,164,165,167],{},"从结果您可以看出，遍历 ",[22,166,126],{"code":126}," 花费的时间确实更少。重新排序结构体字段可以提高程序的内存使用率和速度。",{"title":20,"searchDepth":169,"depth":169,"links":170},4,[],[172],"技术","2022-08-18 19:53:37","简单地重新排序结构体中的字段，提高了 Go 程序的速度和内存使用率。",false,"md",null,{"slots":179,"excerpt":180},{},{"type":7,"value":181},[182,184,189,194,199,201],[10,183,12],{},[14,185,187],{"className":186,"code":18,"language":19,"meta":20},[17],[22,188,18],{"__ignoreMap":20},[10,190,26,191,34],{},[28,192,33],{"href":30,"rel":193},[32],[14,195,197],{"className":196,"code":39,"language":40},[38],[22,198,39],{"__ignoreMap":20},[10,200,45],{},[10,202,48],{},true,"\u002F2022\u002Fstruct_perf_boost_15_percent",{"text":206,"minutes":207,"time":208,"words":209},"4 min read",3.44,206400,688,{"title":5,"description":174},{"loc":204},"posts\u002F2022\u002Fstruct_perf_boost_15_percent",[214],"内存对齐","story","_RY3YkcMJuzh2E3zulKJaIEzK2o3zIANRZo6NtE_ki4",[218,223],{"title":219,"path":220,"stem":221,"date":222,"type":215,"children":-1},"为什么抽不到 SSR，原来是这段代码在作祟","\u002F2022\u002Fweight-random","posts\u002F2022\u002Fweight-random","2022-02-16 18:34:07",{"title":224,"path":225,"stem":226,"date":227,"type":215,"children":-1},"游戏帧同步","\u002F2023\u002Fmultiplayer_frame_sync_strategies","posts\u002F2023\u002Fmultiplayer_frame_sync_strategies","2023-09-11 18:34:07",1781779103066]