鑑於替代這樣的做法是有大量的構建,每個與它是這樣的:
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
所需的頁面可能會被換出。
如果文件非常大,加載消息文件應該只是一個很大的開銷,但是如果磁盤沒有旋轉,並且文件沒有被緩存,那麼會有幾秒的開銷。再次,如何量化。文件的大小顯然與翻譯(或母語)消息的實際大小成正比。
關於第2點:
據我所知,在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 =1
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更快 - 只是「運氣不好」(I有一些其他的代碼變體,並且它們在第一次調用sprintf
時差異很大,稍後調用時變化較小。可能有些設置(可能緩存[printf導致緩存被其他垃圾覆蓋很可能],分支預測等),需要額外的時間...
現在,這顯然不能回答您關於尋呼的問題等等。而且我沒有嘗試對我的「Hello,World」消息做一個瑞典語,葡萄牙語或德語翻譯。我仍然相信這並不是很大,除非你確實每秒鐘運行100個應用程序的實例,並且該應用程序除了在進行一些簡單的計算之後將消息打印到屏幕上之外沒有其他更多的工作,當然,這可能是重要的。
唯一真正的方法是找出它與#define _(x) x
而不是#define _(x) gettext(x)
相同的應用程序,看看你是否有任何區別。
我仍然認爲「翻頁」是一個紅色的鯡魚。如果機器處於高內存壓力下,那麼無論如何,它都會運行緩慢(如果我在機器上寫了一段代碼分配16GB [我機器上有16GB內存],除了鍵盤本身外幾乎所有內容(可以閃爍數字鎖定LED)並且鼠標指針本身(可以在屏幕上移動鼠標指針)無響應)。
@JamesKanze該程序可能會產生較長的報告,或者它可能會發送個性化的羣發電子郵件,或...輸出是人類可讀的意味着周圍有一個人,並且該程序可以停止,直到他/她讀完輸出爲止。 – Chris
@James:即使只有一個導致頁面錯誤的單個丟失字節也會導致延遲,即使是由人類引起的延遲也是如此。在極端情況下,如果硬盤必須旋轉,可能會延遲數秒。也有相當多的命令行程序是從腳本啓動的,這可能意味着程序幾千次啓動/停止。但真正的一點是,「這是可以忽略的」並不是對這些問題的回答,因爲在某些情況下它只是可忽略不計的。 – Robby75