1、乙個日誌庫大體可分為前端(frontend)與後端(backend)。前端是**用程式使用的介面(api),並生成日誌資訊;後端則是負責將日誌資訊寫到目的地。每個執行緒都有自己的前端,而整個程式共用乙個後端。對於生產者(前端)而言,要盡量做到低延遲、低cpu開銷、無阻塞;對消費者(後端)而言,要盡量做到足夠大的吞吐量,並占用較少的資源。
對c++程式而言,最好整個程式(包括主程式和程式庫)都使用相同的日誌庫,程式有乙個整體的日誌輸出,而不要每個元件都有各自的日誌輸出。從這個意義上講,日誌庫是個singleton。
非同步日誌:每個【程序】最好只寫乙個日誌檔案,這樣分析日誌檔案更容易,不必再多個檔案中跳來跳去。實現方法是,用乙個背景執行緒負責收集日誌訊息,並寫入日誌檔案,其他業務執行緒只管往這個「日誌執行緒」傳送日誌訊息,這稱為「非同步日誌」。
muduo日誌庫採用的是雙緩衝技術,基本思路是準備兩塊緩衝:a與b,前端負責往buffer a中填資料(日誌訊息),後端負責將buffer b中的資料寫入檔案。當buffer a寫滿之後,交換a與b,讓後端將buffer a中的資料寫入檔案,而前端負責往buffer b中填入新的日誌檔案。如此往復。用兩個buffer的好處是在新建日誌訊息的時候不必等待磁碟檔案操作,也避免每條訊息都觸發(喚醒)了後端日誌執行緒。換言之,前端不是將一條條訊息分別傳送給後端,而是將多個日誌訊息拼成乙個大的buffer傳送給後端,相當於批處理,減少了執行緒喚醒的頻率,降低了開銷。另外,為了及時將訊息寫入檔案,即使前端的buffer a未寫滿,日誌庫也會每三秒執行一次上述交換寫入操作。
【.h】
#ifndef muduo_base_asynclogging_h
#define muduo_base_asynclogging_h
#include #include #include #include #include #include #include #include namespace muduo
} void start()
void stop()
private:
void threadfunc();
typedef muduo::detail::fixedbufferbuffer;
typedef std::vector> buffervector;
typedef buffervector::value_type bufferptr;
const int flushinterval_;
std::atomicrunning_;
string basename_;
off_t rollsize_;
muduo::thread thread_;
muduo::countdownlatch latch_;
muduo::mutexlock mutex_;
muduo::condition cond_;
bufferptr currentbuffer_;
bufferptr nextbuffer_;
buffervector buffers_;};}
#endif // muduo_base_asynclogging_h
【.cpp】
#include #include #include #include using namespace muduo;
asynclogging::asynclogging(const string& basename,
off_t rollsize,
int flushinterval)
: flushinterval_(flushinterval),
running_(false),
basename_(basename),
rollsize_(rollsize),
thread_(std::bind(&asynclogging::threadfunc, this), "logging"),
latch_(1),
mutex_(),
cond_(mutex_),
currentbuffer_(new buffer),
nextbuffer_(new buffer),
buffers_()
else
else
cond_.notify();
}}void asynclogging::threadfunc()
buffers_.push_back(std::move(currentbuffer_));
currentbuffer_ = std::move(newbuffer1);
bufferstowrite.swap(buffers_);
if (!nextbuffer_)
}assert(!bufferstowrite.empty());
if (bufferstowrite.size() > 25)
for (size_t i = 0; i < bufferstowrite.size(); ++i)
if (bufferstowrite.size() > 2)
if (!newbuffer1)
if (!newbuffer2)
bufferstowrite.clear();
output.flush();
} output.flush();
}
在 陳碩所著《linux多執行緒服務端程式設計中》,第117~119頁,闡述了非同步日誌前端與後端互動的四種情形。在此不再詳述。 高效能非同步爬蟲
目的 在爬蟲中使用非同步實現高效能的資料爬取操作。非同步爬蟲的方式 多執行緒 多程序 不建議 弊端 無法無限制的開啟多執行緒或者多程序 執行緒池 程序池 適當的使用 好處 可以降低系統對程序或者執行緒建立和銷毀的乙個頻率,從而很好的降低系統的開銷 弊端 池中線程或程序的數量是有上限 from mul...
高效能非同步爬蟲概述
同步呼叫 即提交乙個任務後就在原地等待任務結束,等到拿到任務的結果後再繼續下一行 效率低下,呼叫乙個任務,就在原地等待任務結束拿到結果後才繼續往後執行。好處 在伺服器端使用多執行緒 或多程序 的目的是讓每個連線都擁有獨立的執行緒 或程序 這樣任何乙個連線的阻塞都不會影響其他的連線。缺點 在遇到要同時...
scrapy框架的日誌及提高效能
目錄實戰 使用scrapy crawl spiderfilename執行程式時,在終端裡列印輸出的就是scrapy的日誌資訊。日誌資訊的種類 error 一般錯誤 warning 警告 info 一般的資訊 debug 除錯資訊設定日誌資訊指定輸出 在settings.py配置檔案中,加入 log ...