英文:
Golang behaviour on map definition with static content (compile time construction?)
问题
让我们来看一下以下的 Golang 表达式:
type MyStruct struct {
foo int,
bar map[string]MyInterface
}
type MyInterface interface { /* ... */ }
func firstFunc() { /* ...*/ }
func secondFunc() { /* ...*/ }
以及以下的构建函数:
func NewMyStruct() *MyStruct {
// 由编译时已知的静态内容构建一个映射
// 将其赋值给一个局部变量
m := map[string]MyInterface {
"first": firstFunc,
"second": secondFunc,
}
/* ... */
return &MyStruct{
bar: m, // 将映射复制到结构体字段中
/* ... */
}
}
我遇到了这段代码,并决定尝试在内存管理和/或执行时间方面进行优化。
作为来自 C++ 世界的人,我习惯于 "静态 vs 动态分配" 的困境以及使用 constexpr
。我在这里尝试实现相同的目标:在语言允许的范围内避免过于频繁地构建/分配数据结构。
问题 1:在 NewMyStruct()
中,临时映射 实际上 每次调用都会被构建/分配吗?
问题 2:编译器能否检测到临时映射由静态内容构成,并为其构建一次以供所有调用使用?
我的另一个解决方案是使用全局定义的映射,并通过指针从 MyStruct
实例中引用它。
英文:
Lets take the following Golang expressions :
type MyStruct struct {
foo int,
bar map[string]MyInterface
}
type MyInterface interface { /* ... */ }
func firstFunc() { /* ...*/ }
func secondFunc() { /* ...*/ }
with the following builder function :
func NewMyStruct() *MyStruct {
// Building a map made of only static content, known at compile time
// Assigning it to a local variable
m := map[string]MyInterface {
"first": firstFunc,
"second": secondFunc,
}
/* ... */
return &MyStruct{
bar: m, // Copying the map into the struct field
/* ... */
}
}
I came across this code and decided to try optimizing it in terms of memory management and/or execution time.
Coming from the C++ world, I am used to the "static vs dynamic allocation" dilema and the use of constexpr
. I am trying to achieve the same goal here in Golang: avoid constructing/allocating a data structure too often in the limits of what the language permits.
Question 1: In NewMyStruct()
, is the temporary map effectively assigned to m
constructed/allocated at each call?
Question 2: Can the compiler detect that the temporary map is made of static content, and construct it once for all?
My other solution is to go for a globally defined map and refer to it from the MyStruct
instances using a pointer.
答案1
得分: 2
根据Volker的建议,这几乎可以确定是过早优化。然而,如果你已经发现在你的程序中这会带来一些显著的时间成本,并且只是在寻找选项,这个Playground链接展示了一种在程序启动时构建并共享map的方法。核心思想就是:
return &MyStruct{bar: sharedMap, /*...*/}
在这一点上,共享的map需要被创建。如果简单的静态初始化不可行,可以使用init函数,或者在第一次调用New
函数时添加sync.Once
来构建map。
英文:
As Volker suggests, this is almost certainly premature optimization. However, if you've already found that this has some significant time cost in your program and are just looking for options, this Playground link shows a way to construct a map at program startup time and share it. The essence is just:
return &MyStruct{bar: sharedMap, /*...*/}
The shared map needs to be created by this point. If a simple static init is not possible, use an init function, or add a sync.Once
to construct the map only once on the first call to your New
function.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论