我只是阅读了http://www.gnu.org/software/gettext/manual/gettext.html的文档,而根本没有关于性能开销的讨论。在互联网上,我只发现了针对其他语言(PHP和Java)的性能讨论,而没有针对C/C++的性能讨论。
因此,我的问题是:
非常感谢。
最佳答案
鉴于此方法的替代方案是拥有大量构建,每个构建中都包含以下内容:
int main()
{
printf(
#ifdef SWEDISH
"Hej världen\n"
#elsif ENGLISH
"Hello, World\n"
#elsif PORTUGUESE
"Olá, Mundo\n"
#else
#error Language not specified.
#endif
);
return 0l;
}
相反,我们得到:
int main()
{
printf(gettext("Hello, World\n"));
}
易于阅读和理解。
我不知道gettext实现的确切结构,但是我希望它一旦加载便是一个哈希表。可能是二叉树,但散列表似乎更明智。
至于确切的开销,很难在上面加上数字-尤其是,正如您所说,如果将某些内容交换到磁盘上,并且磁盘已停止,则需要3-4秒才能使磁盘达到最高速度。那么如何量化呢?是的,如果系统一直在忙于占用大量内存,那么
gettext
所需的页面可能会换出。仅当消息文件很大时,加载消息文件才需要很大的开销,但是,如果磁盘没有旋转并且文件没有被缓存,则加载消息文件的开销将为几秒钟。同样,如何量化。文件的大小显然与翻译的(或本地语言)消息的实际大小成正比。
关于第二点:
据我所知,在Linux和Windows中,页面都是根据“最近最少使用”(或其他使用情况统计信息)交换出来的,这与它们所在的位置无关。显然,翻译后的消息与实际代码位于不同的位置-源文件中没有15种不同翻译的列表,因此这些翻译在运行时加载,并且位于与代码本身不同的位置。但是,其开销类似于以下两者之间的开销差异:
static const char *msg = "Hello, World\n";
和
static const char *msg = strdup("Hello, World\n");
考虑到文本字符串通常总是放在程序的二进制文件中,因此我认为它们与执行代码的“近距离”与堆中某个位置的动态分配内存没有明显不同。如果您经常调用
gettext
函数,则该内存将保持为“当前”状态,而不被换出。如果一段时间没有调用gettext
,它可能会被换出。但这适用于“最近没有使用存储在可执行文件中的字符串,因此它们被换出了”。3)我认为英语(或“未选择任何语言”)与任何其他语言的变体完全一样。
我需要进一步挖掘,首先需要早餐...
非常不科学:
#include <libintl.h>
#include <cstdio>
#include <cstring>
static __inline__ unsigned long long rdtsc(void)
{
unsigned hi, lo;
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}
int main()
{
char str[10000] = {};
char *s = str;
unsigned long long time;
for(int i = 0; i < 10; i++)
{
time = rdtsc();
s += sprintf(s, "Hello, World %d", i);
time = rdtsc() - time;
printf("Time =%lld\n", time);
}
printf("s = %s\n", str);
s = str;
strcpy(s, "");
for(int i = 0; i < 10; i++)
{
time = rdtsc();
s += sprintf(s, gettext("Hello, World %d"), i);
time = rdtsc() - time;
printf("Time =%lld\n", time);
}
printf("s = %s\n", str);
}
得到以下结果:
$ g++ -Wall -O2 intl.cpp
$ ./a.out
Time =138647
Time =9528
Time =6710
Time =5537
Time =5785
Time =5427
Time =5406
Time =5453
Time =5644
Time =5431
s = Hello, World 0Hello, World 1Hello, World 2Hello, World 3Hello, World 4Hello, World 5Hello, World 6Hello, World 7Hello, World 8Hello, World 9
Time =85965
Time =11929
Time =10123
Time =10226
Time =10628
Time =9613
Time =9515
Time =9336
Time =9440
Time =9095
s = Hello, World 0Hello, World 1Hello, World 2Hello, World 3Hello, World 4Hello, World 5Hello, World 6Hello, World 7Hello, World 8Hello, World 9
dcigettext.c
中的代码混合使用二进制搜索(在平面字符串数组中)和将字符串哈希为PJW哈希的哈希函数(请参阅:http://www.cs.hmc.edu/~geoff/classes/hmc.cs070.200101/homework10/hashfuncs.html)。因此,一旦应用程序启动,开销似乎就在“仅可察觉的”范围内(在计算时钟周期时),但并不是很大。
在两种情况下,运行第一个
sprintf
所需的确切时间有所不同,因此我不会说“使用gettext”使sprintf在第一次调用时更快-这次运行只是“运气不好”(我还有其他一些运气)代码的变体,并且在第一次调用sprintf
时,它们的差异很大,而在以后的调用中,差异很小)。可能需要一些额外的时间(在某些地方进行设置(可能是缓存[printf导致缓存被其他垃圾覆盖的可能性],分支预测等),...现在,这显然不能回答您关于分页等问题。而且,我也没有尝试对“Hello,World”消息进行瑞典语,葡萄牙语或德语的翻译。我仍然相信它不是很大,除非您确实确实在每秒运行一个应用程序的实例化数百次,并且该应用程序除了做一些简单的计算后在屏幕上显示一条消息外,不做其他任何事情,当然,这可能很重要。
找出有什么不同的唯一真实方法是使用
#define _(x) x
而不是#define _(x) gettext(x)
编译相同的应用程序,并查看是否注意到任何区别。我仍然认为“分页”是一个红色的鲱鱼。如果计算机承受高内存压力,那么无论如何(如果我编写一段分配16GB [我的计算机中有16GB RAM]的代码,除了键盘本身,几乎所有东西都将运行缓慢)。可以使Num-lock LED闪烁),并且鼠标指针本身(可以在屏幕上四处移动鼠标指针)无响应)。
关于c++ - C/C++中的gettext国际化系统的性能开销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18268608/