将資料按照指定format輸出到buffer中,往往會用snprintf/sprintf(推薦前者)。但各個場景都習慣性的用snprintf/sprintf卻并不是什麼好事。
在分析團隊項目性能時候,發現将大量資料以文本text方式傳回給用戶端時,耗時非常多,且和類型有關,datetime > int > varchar。perf圖分析後發現,snprintf占用了很多時間。因為datetime調用4次,int調用1次,varchar 0次。datetime和int類型調用都主要是将int轉換為text文本方式。
對于int值列印,寫ltoa函數和snprintf做性能對比。
o2編譯執行,實驗結果如下,ltoa性能是snprintf的1倍以上:
對于datetime類型,其實隻是需要輸出xxxx-mm-dd hh-mm--ss.uuuuuu格式的資料。要輸出的位數已經确定,可以使用更簡單的方式例如兩位的moth/day,或者可能3位的數字:
上面的方式還需要做計算,如果使用200位元組的字元串記錄0~99的對應字元,那麼對于2位數字的轉換就可以直接用int64_t的指派操作,性能對比代碼如下:
得到性能結果,直接指派的性能達到之前計算每個字元方式的4倍:
即用下面代碼做替換可以得到更好的性能。
一個底層to_hex_str函數将輸入指定data_length的in_data按位元組轉換為hex值,在下面的代碼中檢查buff_size至少是data_length的2倍,但是sprintf會在末尾補'0',會導緻記憶體寫越界。
一個類似to_hex_str的代碼,使用如下方式列印。
這裡就出現一個錯誤,in_buf是char,是有符号的,在使用%02x列印的時候,按整數方式列印,char的範圍是[-128,127),但2個16進制僅能表示[0,255]。下面的例子中,buff中得到的就是ffffffff。其内容顯然不是希望的。
這裡如果使用snprintf,應該将char*轉換為unsinged char* 。
實際上,每個位元組列印16進制方式可以用如下代碼:
snprintf/sprintf雖然用起來友善,但一定要分析好使用場景和功能,防止出現性能問題或者正确性問題。