Dato che l'alternativa a questo approccio è quello di avere un gran numero di build, ognuno con qualcosa di simile in esso:
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;
}
invece otteniamo:
int main()
{
printf(gettext("Hello, World\n"));
}
che è facile da leggi e capisci.
Non conosco la struttura esatta dell'implementazione gettext, ma mi aspetto che sia una tabella hash una volta caricata. Forse un albero binario, ma il tavolo hash sembra più ragionevole.
Per quanto riguarda le spese generali esatte, è molto difficile mettere un numero su di esso - specialmente, come dici tu, se qualcosa viene scambiato su disco, e il disco si è fermato, ci vogliono 3-4 secondi per sollevare il disco accelerare. Quindi come lo si quantifica? Sì, è possibile che la pagina necessaria per gettext
venga sostituita se il sistema è occupato a fare qualcosa di intensivo della memoria.
Il caricamento del file di messaggi deve essere solo un grande sovraccarico se il file è molto grande, ma ancora, se il disco non gira e il file non viene memorizzato nella cache, ci sarà un sovraccarico di diversi secondi. Ancora una volta, come quantificarlo. La dimensione del file è chiaramente direttamente proporzionale alla dimensione effettiva dei messaggi tradotti (o madrelingua).
quanto riguarda il punto 2:
Per quanto ne so, sia in Linux e Windows, le pagine vengono scambiati su un "usato meno di recente" (o qualche altro uso statistico) Base, che non ha nulla a che fare con dove si trovano. Chiaramente i messaggi tradotti si trovano in un posto diverso dal codice reale - non c'è un elenco di 15 traduzioni diverse nel file sorgente, quindi le traduzioni vengono caricate in fase di runtime e si troveranno in un posto diverso dal codice stesso.Tuttavia, l'overhead di questo è simile alla differenza tra le spese generali:
static const char *msg = "Hello, World\n";
e
static const char *msg = strdup("Hello, World\n");
Dato che il testo-stringhe sono generalmente tenuti insieme nel binario di un programma in ogni caso, non lo faccio pensare che la loro "vicinanza" al codice in esecuzione sia significativamente diversa da un pezzo di memoria allocata dinamicamente da qualche parte nell'heap. Se chiami la funzione gettext
abbastanza spesso, quella memoria verrà mantenuta "corrente" e non sostituita. Se non chiami gettext
per un po 'di tempo, potrebbe essere scambiato. Ma questo vale per "nessuna delle stringhe memorizzate nell'eseguibile è stata usata di recente, quindi sono state scambiate".
3) Penso che l'inglese (o "nessuna lingua selezionata") sia trattato esattamente identico a qualsiasi altra variante linguistica.
avrò un po 'più di scavo in un po', hanno bisogno di colazione prima ...
molto poco scientifica:
#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);
}
dà i seguenti risultati:
$ 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
Il codice in dcigettext.c
utilizza una combinazione di ricerca binaria in una matrice di stringhe piatte e una funzione di hash che esegue l'hash della stringa su un hash PJW (vedere: http://www.cs.hmc.edu/~geoff/classes/hmc.cs070.200101/homework10/hashfuncs.html).
Quindi, il sovraccarico, una volta avviata l'applicazione, sembra essere "appena percettibile" (quando si contano i clock), ma non enorme.
Il tempo esatto necessario per eseguire il primo sprintf
varia leggermente in entrambi i casi, quindi non direi che "utilizzando gettext" rende sprintf più veloce alla prima chiamata - solo "sfortuna" in questa esecuzione (I disponeva di alcune altre varianti del codice e variava notevolmente durante la prima chiamata a sprintf
e meno per le chiamate successive). Probabilmente alcune impostazioni (possibilmente cache [printf che causa la sovrascrittura delle cache con altri rifiuti è molto probabile], previsione delle branche, ecc. Da qualche parte che richiede più tempo ...
Ora, questo chiaramente non risponde alle tue domande sul cercapersone fuori, ecc. E non ho provato a fare una traduzione svedese, portoghese o tedesca del mio messaggio "Hello, World". Continuo a credere che non sia enorme, a meno che non si eseguano effettivamente centinaia di istanze di un'applicazione al secondo, e che l'applicazione non faccia molto altro che stampare un messaggio sullo schermo dopo aver fatto alcuni semplici calcoli, certo, potrebbe essere importante .
L'unico vero modo per scoprire quanta differenza fa è compilare la stessa applicazione con #define _(x) x
anziché #define _(x) gettext(x)
e vedere se si nota alcuna differenza.
Continuo a pensare che "il paginato" sia un'aringa rossa. Se la macchina è sotto la pressione di memoria ALTA, allora sarà in esecuzione lenta, non importa cosa (Se scrivo un pezzo di codice che alloca 16 GB [Ho 16 GB di RAM nella macchina] sulla mia macchina, quasi tutto tranne la tastiera stessa (può lampeggiare il LED del blocco numerico) e il puntatore del mouse stesso (può spostare il puntatore del mouse sullo schermo) non risponde).
Un programma che utilizza 'gettext' sta generando output leggibile dall'uomo. Il sovraccarico è meno che ci vorrà l'umano a leggere il testo, quindi può essere considerato trascurabile. (Questo non è assolutamente vero, ma realisticamente, il sovraccarico non è un problema.) –
@JamesKanze il programma potrebbe anche generare rapporti di lunga durata, oppure inviare e-mail di massa personalizzate, oppure ... Che l'output sia leggibile dall'uomo non implica che ci sia un umano intorno e che il programma possa fermarsi fino a quando non ha finito di leggere l'output. – Chris
@James: anche un singolo byte mancante che causa un errore di pagina causerà un ritardo che è evidente anche da un essere umano. In casi estremi può causare un ritardo di alcuni secondi se il disco rigido deve essere attivato. Anche molti programmi da riga di comando vengono avviati da script che possono significare che un programma viene avviato/arrestato migliaia di volte. Ma il vero punto è che "è neglegabile" non è una risposta alle domande poiché in alcuni casi è solo neglegabile. – Robby75