【发布时间】:2011-03-09 01:42:26
【问题描述】:
我经常看到以下模式:
b->last = ngx_cpymem(b->last, "</pre><hr>", sizeof("</pre><hr>") - 1);
请注意,文字字符串被使用了两次。提取物来自 nginx 源代码库。
当在编译单元中遇到这些文字时,编译器应该能够合并这些文字。
我的问题是:
- 商业级编译器(VC++、GCC、LLVM/Clang)在编译单元中遇到这种冗余时是否会删除?
- (静态)链接器在链接目标文件时是否会删除此类冗余。
- 如果应用 2,这种优化会在动态链接期间发生吗?
- 如果 1 和 2 适用,它们是否适用于所有文字。
这些问题很重要,因为它允许程序员在不损失效率的情况下变得冗长——例如,考虑将大量静态数据模型硬连接到程序中(例如,在某些低端中使用的决策支持系统的规则)水平场景)。
编辑
2 点/说明
上面的代码是由公认的“大师”程序员编写的。那家伙单枪匹马写了nginx。
我没有问过哪种可能的文字硬编码机制更好。所以不要跑题。
编辑 2
我最初的例子是相当做作和限制性的。下面的 sn-p 显示了嵌入到内部硬编码知识中的字符串文字的用法。第一个 sn-p 用于配置解析器,告诉它要为哪个字符串设置什么枚举值,第二个更普遍地用作程序中的字符串。只要编译器使用字符串文字的一份副本,我个人对此感到满意,并且由于元素是静态的,它们不会进入全局符号表。
static ngx_conf_bitmask_t ngx_http_gzip_proxied_mask[] = {
{ ngx_string("off"), NGX_HTTP_GZIP_PROXIED_OFF },
{ ngx_string("expired"), NGX_HTTP_GZIP_PROXIED_EXPIRED },
{ ngx_string("no-cache"), NGX_HTTP_GZIP_PROXIED_NO_CACHE },
{ ngx_string("no-store"), NGX_HTTP_GZIP_PROXIED_NO_STORE },
{ ngx_string("private"), NGX_HTTP_GZIP_PROXIED_PRIVATE },
{ ngx_string("no_last_modified"), NGX_HTTP_GZIP_PROXIED_NO_LM },
{ ngx_string("no_etag"), NGX_HTTP_GZIP_PROXIED_NO_ETAG },
{ ngx_string("auth"), NGX_HTTP_GZIP_PROXIED_AUTH },
{ ngx_string("any"), NGX_HTTP_GZIP_PROXIED_ANY },
{ ngx_null_string, 0 }
};
紧随其后:
static ngx_str_t ngx_http_gzip_no_cache = ngx_string("no-cache");
static ngx_str_t ngx_http_gzip_no_store = ngx_string("no-store");
static ngx_str_t ngx_http_gzip_private = ngx_string("private");
致那些一直关注主题的人,好样的!
【问题讨论】:
-
抱歉,但您担心高辛烷值燃油会使车开得更快,但不考虑道路上到处都是坑洞。通过将文字放在常量中来选择更好的道路。 (好吧,这不是最好的比喻,但它在一定程度上有效)
-
你为什么想要在你的代码中重复你自己?一个更好的问题是“我可以避免冗长而又不降低效率吗?”
-
虽然我必须同意 jalf (“主”程序员与否),但您的问题的答案是肯定的,所有体面的编译器不仅会在同一个翻译单元中合并重复的字符串文字,但链接器还将跨翻译单元合并重复项。即使对于像 CW 8 这样的过时编译器也是如此,它提供了这个作为链接器选项。当然,这显然不会在共享库/DLL 中发生。但是,如果您的代码依赖于重复的字符串文字来共享相同的地址,那么代码就是一场等待发生的灾难。
-
你不会通过某人喜欢的软件成为“大师”程序员。你可以通过编写好的代码来做到这一点。
标签: c++ c micro-optimization compiler-theory string-interning