英文:
What is the best way to work around the overhead of reflection?
问题
我有一个程序,它从内存映射中读取173个(c)数据结构,需要将其转换为Go语言。这些结构中的类型值以字符串形式存储。这些结构每秒接收60次。
我目前使用反射(FieldByName
)来获取Go语言结构体字段的引用并设置接收到的数据。但由于字段很多(173个)且经常更新,这会增加很多开销,并且该函数调用是我程序中最慢的部分(使用go prof
进行分析)。
如何使这个过程更快?据我所见,我有三个选项:
- 在一个映射中缓存
reflect.Value
,并创建一个接收数据的函数,使用与缓存映射相关联的模板结构体,填充该结构体并返回该模板结构体的副本。 - 使用
go generate
生成所有的setter函数和一个巨大的switch语句,用于处理每个接收到的字段。 - 编写所有不同的setter函数。
哪个选项是“最佳”的?我是否忽略了其他选项?
英文:
I have a program that reads 173 (c) data structures from a memory map that need to be converted to Go. The value of the type is stored as a string in those structures. The structures are received 60 times per second.
I'm now using reflection (FieldByName
) to get a reference to the go struct field and set the received data. But because there a many fields (173) and they get updated a lot this ads a lot of overhead and that function call is the slowest part of my program (jay go prof
!).
What is the best way to make this faster? As far as I can see I have three options:
- cache the
reflect.Value
's in a map and make a function that receives data, use a template struct tied to the cache map, fill that struct and return a copy of that template-struct go generate
all the setters and a giant switch statement for each received field- Just code all the different setters
What would be the "best" option? Is there an option I'm overlooking?
答案1
得分: 4
使用#1的方法,为了保证并发安全性,你需要一个“模板结构体”的池,或者至少需要一个互斥锁来保护它。这会增加一些开销,并且可能很难调试。
#3是一个维护的噩梦。
我会选择#2。运行的代码将会快速、并发安全且易于调试。
一旦你的工具设置好了,只需要运行一个命令行就可以更新结构体的设置。
英文:
With #1, to be concurrency-safe you'd need a pool of those "template-struct" or at least a mutex protecting it. That adds some overhead and can be tricky to debug.
#3 is a nightmare to maintain.
I would go with #2. The running code will be fast, concurrency-safe and easy to debug.
Once your tool is setup, a change in your struct only requires running a command line to update the setters.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论