女人荫蒂被添全过程13种图片,亚洲+欧美+在线,欧洲精品无码一区二区三区 ,在厨房拨开内裤进入毛片

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

C++異步日志實(shí)踐

科技綠洲 ? 來源:Linux開發(fā)架構(gòu)之路 ? 作者:Linux開發(fā)架構(gòu)之路 ? 2023-11-09 10:29 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

一個(gè)高效可拓展的異步C++日志庫(kù):RING LOG,本文分享了了其設(shè)計(jì)方案與技術(shù)原理等內(nèi)容

導(dǎo)論

同步日志與缺點(diǎn)

傳統(tǒng)的日志也叫同步日志,每次調(diào)用一次打印日志API就對(duì)應(yīng)一次系統(tǒng)調(diào)用write寫日志文件,在日志產(chǎn)生不頻繁的場(chǎng)景下沒什么問題

可是,如果日志打印很頻繁,同步日志有什么問題?

  • 一方面,大量的日志打印陷入等量的write系統(tǒng)調(diào)用,有一定系統(tǒng)開銷
  • 另一方面,使得打印日志的進(jìn)程附帶了大量同步的磁盤IO,影響性能

那么,如何解決如上的問題?就是

異步日志與隊(duì)列實(shí)現(xiàn)的缺點(diǎn)

異步日志,按我的理解就是主線程的日志打印接口僅負(fù)責(zé)生產(chǎn)日志數(shù)據(jù)(作為日志的生產(chǎn)者),而日志的落地操作留給另一個(gè)后臺(tái)線程去完成(作為日志的消費(fèi)者),這是一個(gè)典型的生產(chǎn)-消費(fèi)問題,如此一來會(huì)使得:

主線程調(diào)用日志打印接口成為非阻塞操作,同步的磁盤IO從主線程中剝離出來,有助于提高性能

對(duì)于異步日志,我們很容易借助隊(duì)列來一個(gè)實(shí)現(xiàn)方式:主線程寫日志到隊(duì)列,隊(duì)列本身使用條件變量、或者管道、eventfd等通知機(jī)制,當(dāng)有數(shù)據(jù)入隊(duì)列就通知消費(fèi)者線程去消費(fèi)日志

但是,這樣的異步隊(duì)列也有一定的問題:

  • 生產(chǎn)者線程產(chǎn)生N個(gè)日志,對(duì)應(yīng)后臺(tái)線程就會(huì)被通知N次,頻繁日志寫入會(huì)造成一定性能開銷
  • 不同隊(duì)列實(shí)現(xiàn)方式也各有缺點(diǎn):
  • 用數(shù)組實(shí)現(xiàn):空間不足時(shí),隊(duì)列內(nèi)存不易拓展
  • 用鏈表實(shí)現(xiàn):每條消息的生產(chǎn)消費(fèi)都對(duì)應(yīng)內(nèi)存的創(chuàng)建銷毀,有一定開銷

好了,可以開始正文了

簡(jiǎn)介

RING LOG是一個(gè)適用于C++的異步日志, 其特點(diǎn)是效率高(實(shí)測(cè)每秒支持125+萬日志寫入)、易拓展,尤其適用于頻繁寫日志的場(chǎng)景

一句話介紹原理:

使用多個(gè)大數(shù)組緩沖區(qū)作為日志緩沖區(qū),多個(gè)大數(shù)組緩沖區(qū)以雙循環(huán)鏈表方式連接,并使用兩個(gè)指針p1和p2指向鏈表兩個(gè)節(jié)點(diǎn),分別用以生成數(shù)據(jù)、與消費(fèi)數(shù)據(jù)

生產(chǎn)者可以是多線程,共同持有p1來生產(chǎn)數(shù)據(jù),消費(fèi)者是一個(gè)后臺(tái)線程,持有p2去消費(fèi)數(shù)據(jù)

大數(shù)組緩沖區(qū) + 雙循環(huán)鏈表的設(shè)計(jì),使得日志緩沖區(qū)相比于隊(duì)列有更強(qiáng)大的拓展能力、且避免了大量?jī)?nèi)存申請(qǐng)釋放,提高了異步日志在海量日志生成下的性能表現(xiàn)

此外,RING LOG還優(yōu)化了每條日志的UTC格式時(shí)間的生成,明顯提高日志性能

具體工作原理

數(shù)據(jù)結(jié)構(gòu)

Ring Log的緩沖區(qū)是若干個(gè)cell_buffer以雙向、循環(huán)的鏈表組成

cell_buffer是簡(jiǎn)單的一段緩沖區(qū),日志追加于此,帶狀態(tài):

  • FREE:表示還有空間可追加日志
  • FULL:表示暫時(shí)無法追加日志,正在、或即將被持久化到磁盤;

Ring Log有兩個(gè)指針:

  • Producer Ptr:生產(chǎn)者產(chǎn)生的日志向這個(gè)指針指向的cell_buffer里追加,寫滿后指針向前移動(dòng),指向下一個(gè)cell_buffer;Producer Ptr永遠(yuǎn)表示當(dāng)前日志寫入哪個(gè)cell_buffer,被多個(gè)生產(chǎn)者線程共同持有
  • Consumer Ptr:消費(fèi)者把這個(gè)指針指向的cell_buffer里的日志持久化到磁盤,完成后執(zhí)行向前移動(dòng),指向下一個(gè)cell_buffer;Consumer Ptr永遠(yuǎn)表示哪個(gè)cell_buffer正要被持久化,僅被一個(gè)后臺(tái)消費(fèi)者線程持有

圖片

起始時(shí)刻,每個(gè)cell_buffer狀態(tài)均為FREE Producer Ptr與Consumer Ptr指向同一個(gè)cell_buffer

整個(gè)Ring Log被一個(gè)互斥鎖mutex保護(hù)

大致原理

消費(fèi)者

后臺(tái)線程(消費(fèi)者)forever loop:

1.上鎖,檢查當(dāng)前Consumer Ptr:

  • 如果對(duì)應(yīng)cell_buffer狀態(tài)為FULL,釋放鎖,去STEP 4;
  • 否則,以1秒超時(shí)時(shí)間等待條件變量cond;

2.再次檢查當(dāng)前Consumer Ptr:

  • 若cell_buffer狀態(tài)為FULL,釋放鎖,去STEP 4;
  • 否則,如果cell_buffer無內(nèi)容,則釋放鎖,回到STEP 1;
  • 如果cell_buffer有內(nèi)容,將其標(biāo)記為FULL,同時(shí)Producer Ptr前進(jìn)一位;

3.釋放鎖

4.持久化cell_buffer

5.重新上鎖,將cell_buffer狀態(tài)標(biāo)記為FREE,并清空其內(nèi)容;Consumer Ptr前進(jìn)一位;

6.釋放鎖

生產(chǎn)者

1.上鎖,檢查當(dāng)前Producer Ptr對(duì)應(yīng)cell_buffer狀態(tài):

如果cell_buffer狀態(tài)為FREE,且生剩余空間足以寫入本次日志,則追加日志到cell_buffer,去STEP X;

2.如果cell_buffer狀態(tài)為FREE但是剩余空間不足了,標(biāo)記其狀態(tài)為FULL,然后進(jìn)一步探測(cè)下一位的next_cell_buffer:

  • 如果next_cell_buffer狀態(tài)為FREE,Producer Ptr前進(jìn)一位,去STEP X;
  • 如果next_cell_buffer狀態(tài)為FULL,說明Consumer Ptr = next_cell_buffer,Ring Log緩沖區(qū)使用完了;則我們繼續(xù)申請(qǐng)一個(gè)new_cell_buffer,將其插入到cell_buffer與next_cell_buffer之間,并使得Producer Ptr指向此new_cell_buffer,去STEP X;

3.如果cell_buffer狀態(tài)為FULL,說明此時(shí)Consumer Ptr = cell_buffer,丟棄日志;

4.釋放鎖,如果本線程將cell_buffer狀態(tài)改為FULL則通知條件變量cond

在大量日志產(chǎn)生的場(chǎng)景下,Ring Log有一定的內(nèi)存拓展能力;實(shí)際使用中,為防止Ring Log緩沖區(qū)無限拓展,會(huì)限制內(nèi)存總大小,當(dāng)超過此內(nèi)存限制時(shí)不再申請(qǐng)新cell_buffer而是丟棄日志

圖解各場(chǎng)景

初始時(shí)候,Consumer Ptr與Producer Ptr均指向同一個(gè)空閑cell_buffer1

圖片

然后生產(chǎn)者在1s內(nèi)寫滿了cell_buffer1,Producer Ptr前進(jìn),通知后臺(tái)消費(fèi)者線程持久化

圖片

消費(fèi)者持久化完成,重置cell_buffer1,Consumer Ptr前進(jìn)一位,發(fā)現(xiàn)指向的cell_buffer2未滿,等待

圖片

超過一秒后cell_buffer2雖有日志,但依然未滿:消費(fèi)者將此cell_buffer2標(biāo)記為FULL強(qiáng)行持久化,并將Producer Ptr前進(jìn)一位到cell_buffer3

圖片

消費(fèi)者在cell_buffer2的持久化上延遲過大,結(jié)果生產(chǎn)者都寫滿cell_buffer3456,已經(jīng)正在寫cell_buffer1了

圖片

生產(chǎn)者寫滿寫cell_buffer1,發(fā)現(xiàn)下一位cell_buffer2是FULL,則拓展換沖區(qū),新增new_cell_buffer

圖片

UTC時(shí)間優(yōu)化

每條日志往往都需要UTC時(shí)間:yyyy-mm-dd hh:mm:ss(PS:Ring Log提供了毫秒級(jí)別的精度)

Linux系統(tǒng)下本地UTC時(shí)間的獲取需要調(diào)用localtime函數(shù)獲取年月日時(shí)分秒

在localtime調(diào)用次數(shù)較少時(shí)不會(huì)出現(xiàn)什么性能問題,但是寫日志是一個(gè)大批量的工作,如果每條日志都調(diào)用localtime獲取UTC時(shí)間,性能無法接受

在實(shí)際測(cè)試中,對(duì)于1億條100字節(jié)日志的寫入,未優(yōu)化locatime函數(shù)時(shí) RingLog寫內(nèi)存耗時(shí)245.41s,僅比傳統(tǒng)日志寫磁盤耗時(shí)292.58s快將近一分鐘;而在優(yōu)化locatime函數(shù)后,RingLog寫內(nèi)存耗時(shí)79.39s,速度好幾倍提升

策略

為了減少對(duì)localtime的調(diào)用,使用以下策略

RingLog使用變量_sys_acc_sec記錄寫上一條日志時(shí),系統(tǒng)經(jīng)過的秒數(shù)(從1970年起算)、使用變量_sys_acc_min記錄寫上一條日志時(shí),系統(tǒng)經(jīng)過的分鐘數(shù),并緩存寫上一條日志時(shí)的年月日時(shí)分秒year、mon、day、hour、min、sec,并緩存UTC日志格式字符串

每當(dāng)準(zhǔn)備寫一條日志:

  1. 調(diào)用gettimeofday獲取系統(tǒng)經(jīng)過的秒tv.tv_sec,與_sys_acc_sec比較;
  2. 如果tv.tv_sec 與 _sys_acc_sec相等,說明此日志與上一條日志在同一秒內(nèi)產(chǎn)生,故年月日時(shí)分秒是一樣的,直接使用緩存即可;
  3. 否則,說明此日志與上一條日志不在同一秒內(nèi)產(chǎn)生,繼續(xù)檢查:tv.tv_sec/60即系統(tǒng)經(jīng)過的分鐘數(shù)與_sys_acc_min比較;
  4. 如果tv.tv_sec/60與_sys_acc_min相等,說明此日志與上一條日志在同一分鐘內(nèi)產(chǎn)生,故年月日時(shí)分是一樣的,年月日時(shí)分 使用緩存即可,而秒sec = tv.tv_sec%60,更新緩存的秒sec,重組UTC日志格式字符串的秒部分;
  5. 否則,說明此日志與上一條日志不在同一分鐘內(nèi)產(chǎn)生,調(diào)用localtime重新獲取UTC時(shí)間,并更新緩存的年月日時(shí)分秒,重組UTC日志格式字符串

小結(jié):如此一來,localtime一分鐘才會(huì)調(diào)用一次,頻繁寫日志幾乎不會(huì)有性能損耗

性能測(cè)試

對(duì)比傳統(tǒng)同步日志、與RingLog日志的效率(為了方便,傳統(tǒng)同步日志以sync log表示)

1. 單線程連續(xù)寫1億條日志的效率

分別使用Sync log與Ring log寫1億條日志(每條日志長(zhǎng)度為100字節(jié))測(cè)試調(diào)用總耗時(shí),測(cè)5次,結(jié)果如下:

圖片

單線程運(yùn)行下,Ring Log寫日志效率是傳統(tǒng)同步日志的近3.7倍,可以達(dá)到每秒127萬條長(zhǎng)為100字節(jié)的日志的寫入

2、多線程各寫1千萬條日志的效率

分別使用Sync log與Ring log開5個(gè)線程各寫1千萬條日志(每條日志長(zhǎng)度為100字節(jié))測(cè)試調(diào)用總耗時(shí),測(cè)5次,結(jié)果如下:

圖片

多線程(5線程)運(yùn)行下,Ring Log寫日志效率是傳統(tǒng)同步日志的近3.8倍,可以達(dá)到每秒135.5萬條長(zhǎng)為100字節(jié)的日志的寫入

2. 對(duì)server QPS的影響

現(xiàn)有一個(gè)Reactor模式實(shí)現(xiàn)的echo Server,其純凈的QPS大致為19.32萬/s

現(xiàn)在分別使用Sync Log、Ring Log來測(cè)試:echo Server在每收到一個(gè)數(shù)據(jù)就調(diào)用一次日志打印下的QPS表現(xiàn)

對(duì)于兩種方式,分別采集12次實(shí)時(shí)QPS,統(tǒng)計(jì)后大致結(jié)果如下:

圖片

傳統(tǒng)同步日志sync log使得echo Server QPS從19.32w萬/s降低至11.42萬/s,損失了40.89%RingLog使得echo Server QPS從19.32w萬/s降低至16.72萬/s,損失了13.46%

TODO

  • 日志本身緩存大小的配置
  • 程序正常退出、異常退出,此時(shí)在buffer中緩存的日志會(huì)丟失
  • 第N天23:59:59秒產(chǎn)生的日志有時(shí)會(huì)被刷寫到第N+1天的日志文件中
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • API
    API
    +關(guān)注

    關(guān)注

    2

    文章

    1567

    瀏覽量

    63726
  • 文件
    +關(guān)注

    關(guān)注

    1

    文章

    578

    瀏覽量

    25284
  • C++
    C++
    +關(guān)注

    關(guān)注

    22

    文章

    2118

    瀏覽量

    74968
  • 日志
    +關(guān)注

    關(guān)注

    0

    文章

    144

    瀏覽量

    10846
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    寫好C++代碼需要遵循的10個(gè)最佳實(shí)踐

    C++代碼提供了足夠的靈活性,因此對(duì)于大部分工程師來說都很難把握。本文介紹了寫好C++代碼需要遵循的10個(gè)最佳實(shí)踐,并在最后提供了一個(gè)工具可以幫助我們分析C++代碼的健壯度。
    發(fā)表于 09-19 09:30 ?878次閱讀

    現(xiàn)代C++項(xiàng)目的最佳實(shí)踐

    本系列是開源書C++ Best Practises[1]的中文版,全書從工具、代碼風(fēng)格、安全性、可維護(hù)性、可移植性、多線程、性能、正確性等角度全面介紹了現(xiàn)代C++項(xiàng)目的最佳實(shí)踐。本文是該系列的第三篇。
    發(fā)表于 09-29 11:32 ?1488次閱讀

    C++程序設(shè)計(jì)原理與實(shí)踐》(C++之父最新力作)

    `《C++程序設(shè)計(jì)原理與實(shí)踐》(C++之父最新力作)`
    發(fā)表于 08-19 16:30

    Visual C++小波變換技術(shù)與工程實(shí)踐

    本帖最后由 lee_st 于 2018-2-15 23:48 編輯 Visual C++小波變換技術(shù)與工程實(shí)踐
    發(fā)表于 02-15 18:27

    Visual C++ 串口通信技術(shù)與工程實(shí)踐

    Visual C++ 串口通信技術(shù)與工程實(shí)踐
    發(fā)表于 08-19 22:31

    Visual C++ 串口通信技術(shù)與工程實(shí)踐

    Visual C++ 串口通信技術(shù)與工程實(shí)踐
    發(fā)表于 12-30 15:19

    Visual C++ 串口通信技術(shù)與工程實(shí)踐

    Visual C++ 串口通信技術(shù)與工程實(shí)踐
    發(fā)表于 04-03 11:39

    Visual C++ 串口通信技術(shù)與工程實(shí)踐

    Visual C++ 串口通信技術(shù)與工程實(shí)踐
    發(fā)表于 04-13 12:07

    在NDK開發(fā)中C++的代碼中怎么實(shí)現(xiàn)日志輸出

    在NDK開發(fā)中C++的代碼中怎么實(shí)現(xiàn)日志輸出?實(shí)現(xiàn)方法是什么?
    發(fā)表于 09-30 07:04

    C++課件、習(xí)題及答案

    *1.1  從CC++*1.2  最簡(jiǎn)單的C++程序 1.3  C++程序的構(gòu)成和書寫形式 1.4 
    發(fā)表于 09-08 09:35 ?108次下載
    <b class='flag-5'>C++</b>課件、習(xí)題及答案

    Visual C++數(shù)字圖像模式識(shí)別技術(shù)及工程實(shí)踐

    Visual C++數(shù)字圖像模式識(shí)別技術(shù)及工程實(shí)踐
    發(fā)表于 11-06 10:08 ?3次下載

    C++程序設(shè)計(jì)原理與實(shí)踐

    C++程序設(shè)計(jì)原理與實(shí)踐
    發(fā)表于 02-28 23:01 ?0次下載

    《Visual C++編程基礎(chǔ)與實(shí)踐》中文電子教材詳細(xì)資料免費(fèi)下載

    本文檔的主要內(nèi)容介紹的是《Visual C++編程基礎(chǔ)與實(shí)踐》中文電子教材詳細(xì)資料免費(fèi)下載
    發(fā)表于 07-09 08:00 ?39次下載

    C++程序設(shè)計(jì)教程之C++的初步知識(shí)的詳細(xì)資料說明

    C++程序設(shè)計(jì)教程之C++的初步知識(shí)的詳細(xì)資料說明包括了:1. 從CC++,2 . 最簡(jiǎn)單的C++程序,3 .
    發(fā)表于 03-14 14:48 ?31次下載
    <b class='flag-5'>C++</b>程序設(shè)計(jì)教程之<b class='flag-5'>C++</b>的初步知識(shí)的詳細(xì)資料說明

    C++代碼需要遵循的10個(gè)最佳實(shí)踐

    C++代碼提供了足夠的靈活性,因此對(duì)于大部分工程師來說都很難把握。本文介紹了寫好C++代碼需要遵循的10個(gè)最佳實(shí)踐,并在最后提供了一個(gè)工具可以幫助我們分析C++代碼的健壯度。
    的頭像 發(fā)表于 10-18 15:20 ?1094次閱讀
    主站蜘蛛池模板: 时尚| 宜兴市| 宜良县| 聂荣县| 韩城市| 三门县| 宾阳县| 成武县| 延川县| 博客| 阿瓦提县| 原平市| 长岛县| 全州县| 淮南市| 招远市| 五寨县| 秦安县| 宜川县| 玉林市| 满洲里市| 余姚市| 舞钢市| 惠东县| 平武县| 汉川市| 湖南省| 金平| 台湾省| 卓尼县| 宜宾市| 望奎县| 棋牌| 凤翔县| 绵竹市| 库伦旗| 桓仁| 陆良县| 呼伦贝尔市| 永丰县| 潞城市|