C語言的sprintf和snprintf將變量格式化輸出到內(nèi)存buffer,其功能強(qiáng)大,用起來很方便。但sprintf系列函數(shù)的運(yùn)行效率低下,主要包括四方面的原因:格式字符串解析、變參處理、locale(本地化)支持和通用(如對齊、填充、精度、寬度等)導(dǎo)致的復(fù)雜性。
在FastDFS和FastCFS開源項(xiàng)目中,我們將低效的sprintf和snprintf改造為高效的字符串拼接方式。因?yàn)镃標(biāo)準(zhǔn)庫沒有提供itoa(整數(shù)轉(zhuǎn)換為字符串)和ftoa(浮點(diǎn)數(shù)轉(zhuǎn)換為字符串)這樣的轉(zhuǎn)換函數(shù),我們在基礎(chǔ)庫libfastcommon中實(shí)現(xiàn)了fc_itoa、fc_ftoa和fc_ltostr_ex、int2hex和int2HEX等函數(shù),這些函數(shù)均返回轉(zhuǎn)換后的字符串長度。其中fc_itoa和fc_ftoa轉(zhuǎn)換后的字符串不以'\0'結(jié)尾,而fc_ltostr_ex是fc_itoa的加強(qiáng)版,支持以'0'補(bǔ)齊長度,且轉(zhuǎn)換后的字符串以'\0'結(jié)尾。
fc_itoa根據(jù)傳入的整數(shù)大小折半查找確認(rèn)輸出的字符串長度,因此不需要傳統(tǒng)的字符串逆轉(zhuǎn)操作。經(jīng)實(shí)測,性能大約是sprintf的6倍。
fc_ftoa支持小數(shù)點(diǎn)后的保留位數(shù),和sprintf一樣采用四舍五入的做法。經(jīng)實(shí)測,fc_ftoa性能大約是sprintf的25倍。
int2hex轉(zhuǎn)換為小寫字母的十六進(jìn)制字符串,而int2HEX轉(zhuǎn)換為大寫字母的十六進(jìn)制字符串。int2hex系列函數(shù)支持前導(dǎo)'0'補(bǔ)齊,對應(yīng)sprintf的格式修飾符為%0#x,其中#為對齊位數(shù),比如 %08x。經(jīng)實(shí)測,int2hex性能大約是sprintf的7倍。
為了提高替換sprintf和snprintf的代碼改造效率,libfastcommon中還封裝了如下函數(shù):fc_combine_two_strings、fc_get_full_filename、fc_get_one_subdir_full_filename和fc_get_two_subdirs_full_filename等,歡迎大家觀摩。
fc_itoa、fc_ftoa、fc_ltostr_ex和int2hex等轉(zhuǎn)換函數(shù)在shared_func.h和shared_func.c中實(shí)現(xiàn)。fc_itoa、fc_ftoa、int2hex和sprintf的性能對比測試源碼為 libfastcommon/src/tests/test_fast_buffer.c,感興趣的朋友可以把玩一下。