c - 即使我將輸出重定向到/ dev/null,printf仍會有成本嗎?




linux performance (4)

我們有一個包含大量打印消息的守護進程。 由於我們正在開發具有弱CPU和其他約束硬件的嵌入式設備,因此我們希望在最終版本中最小化printf消息的任何類型的成本(IO,CPU等)。 (用戶沒有控制台)

我的隊友和我有分歧。 他認為我們可以將所有內容重定向到/ dev / null。 它不會花費任何IO,所以感情將是最小的。 但我認為它仍將花費CPU,我們最好為printf定義一個宏,這樣我們就可以重寫“printf”(也許只是返回)。

所以我需要一些關於誰是對的意見。 Linux是否足夠聰明以優化printf? 我真的很懷疑。


一般而言,如果實現不影響程序的可觀察(功能)輸出,則允許執行此類優化。 在 printf() 的情況下,這意味著如果程序不使用返回值,並且如果沒有 %n 轉換,那麼實現將被允許不執行任何操作。

在實踐中,我不知道Linux上當前(2019年初)執行這樣的優化的任何實現 - 我熟悉的編譯器和庫將格式化輸出並將結果寫入空設備,依賴於內核'忽略它。

如果您確實需要在未使用輸出時節省格式化成本,您可能希望編寫自己的轉發函數 - 您希望它返回 void ,並且您應該檢查 %n 的格式字符串。 (如果你需要那些副作用,你可以使用帶有 NULL0 緩衝區的 snprintf ,但節省的費用不太可能用於償還投入的努力)。


使用printf()源作為指導來編寫自己的包裝printf(),如果設置了noprint標誌,則立即返回。 這樣做的缺點是,實際打印時會因為必須解析格式字符串兩次而消耗更多資源。 但是在不打印時它使用的資源可以忽略不計。 不能簡單地替換printf(),因為printf()中的底層調用可以使用較新版本的stdio庫進行更改。

void printf2(const char * formatstring,...);


printf 函數 寫入 stdout 。 它不符合 /dev/null 優化。 因此,您將有解析格式字符串和評估任何必要參數的開銷,並且您將至少有一個系統調用,並且您將緩衝區復製到內核地址空間(與系統調用的成本相比,這是可忽略的) 。

這個答案基於POSIX的具體文檔。

系統接口
dprintf,fprintf,printf,snprintf,sprintf - 打印格式化輸出

fprintf()函數應將輸出放在命名輸出流上。 printf()函數應將輸出放在標準輸出流stdout上。 sprintf()函數應將輸出後跟空字節'\ 0'放在從* s開始的連續字節中; 用戶有責任確保有足夠的空間。

基礎定義

對於符合POSIX.1-2017的實現,描述了必需的功能或行為。 應用程序可以依賴於特徵或行為的存在。


printf 函數寫入 stdout 。 如果連接到 stdout 文件描述符被重定向到 /dev/null 則不會在任何地方寫入任何輸出(但它仍將被寫入),但是對 printf 本身的調用及其執行的格式化仍將發生。







dev-null