<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      thrift之TTransport層的緩存?zhèn)鬏旑怲BufferedTransport和緩沖基類TBufferBase

      本節(jié)主要介紹緩沖相關(guān)的傳輸類,緩存的作用就是為了提高讀寫的效率。Thrift在實現(xiàn)緩存?zhèn)鬏數(shù)臅r候首先建立一個緩存的基類,然后需要實現(xiàn)緩存功能的類都可以直接從這個基類繼承。下面就詳細(xì)分析這個基類以及一個具體的實現(xiàn)類。
        緩存基類TBufferBase
        緩存基類就是讓傳輸類所有的讀寫函數(shù)都提供緩存來提高性能。它在通常情況下采用memcpy來設(shè)計和實現(xiàn)快路徑的讀寫訪問操作,這些操作函數(shù)通常都是小、非虛擬和內(nèi)聯(lián)函數(shù)。TBufferBase是一個抽象的基類,子類必須實現(xiàn)慢路徑的讀寫函數(shù)等操作,慢路徑的讀寫等操作主要是為了在緩存已經(jīng)滿或空的情況下執(zhí)行。首先看看緩存基類的定義,代碼如下:

        class TBufferBase : public TVirtualTransport<TBufferBase> {
         public:
          uint32_t read(uint8_t* buf, uint32_t len) {//讀函數(shù)
            uint8_t* new_rBase = rBase_ + len;//得到需要讀到的緩存邊界
            if (TDB_LIKELY(new_rBase <= rBound_)) {//判斷緩存是否有足夠的數(shù)據(jù)可讀,采用了分支預(yù)測技術(shù)
              std::memcpy(buf, rBase_, len);//直接內(nèi)存拷貝
              rBase_ = new_rBase;//更新新的緩存讀基地址
              return len;//返回讀取的長度
            }
            return readSlow(buf, len);//如果緩存已經(jīng)不能夠滿足讀取長度需要就執(zhí)行慢讀
          }
          uint32_t readAll(uint8_t* buf, uint32_t len) {
            uint8_t* new_rBase = rBase_ + len;//同read函數(shù)
            if (TDB_LIKELY(new_rBase <= rBound_)) {
              std::memcpy(buf, rBase_, len);
              rBase_ = new_rBase;
              return len;
            }
            return apache::thrift::transport::readAll(*this, buf, len);//調(diào)用父類的
          }
          void write(const uint8_t* buf, uint32_t len) {//快速寫函數(shù)
            uint8_t* new_wBase = wBase_ + len;//寫入后的新緩存基地址
            if (TDB_LIKELY(new_wBase <= wBound_)) {//判斷緩存是否有足夠的空間可以寫入
              std::memcpy(wBase_, buf, len);//內(nèi)存拷貝
              wBase_ = new_wBase;//更新基地址
              return;
            }
            writeSlow(buf, len);//緩存空間不足就調(diào)用慢寫函數(shù)
          }
          const uint8_t* borrow(uint8_t* buf, uint32_t* len) {//快速路徑借
            if (TDB_LIKELY(static_cast<ptrdiff_t>(*len) <= rBound_ - rBase_)) {//判斷是否足夠借的長度
              *len = static_cast<uint32_t>(rBound_ - rBase_);
              return rBase_;//返回借的基地址
            }
            return borrowSlow(buf, len);//不足就采用慢路徑借
          }
          void consume(uint32_t len) {//消費函數(shù)
            if (TDB_LIKELY(static_cast<ptrdiff_t>(len) <= rBound_ - rBase_)) {//判斷緩存是否夠消費
              rBase_ += len;//更新已經(jīng)消耗的長度
            } else {
              throw TTransportException(TTransportException::BAD_ARGS,
                                        "consume did not follow a borrow.");//不足拋異常
            }
          }
         protected:
          virtual uint32_t readSlow(uint8_t* buf, uint32_t len) = 0;//慢函數(shù)
          virtual void writeSlow(const uint8_t* buf, uint32_t len) = 0;
          virtual const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len) = 0;
          TBufferBase()
            : rBase_(NULL)
            , rBound_(NULL)
            , wBase_(NULL)
            , wBound_(NULL)
          {}//構(gòu)造函數(shù),把所有的緩存空間設(shè)置為NULL
          void setReadBuffer(uint8_t* buf, uint32_t len) {//設(shè)置讀緩存空間地址
            rBase_ = buf;//讀緩存開始地址
            rBound_ = buf+len;//讀緩存地址界限
          }
          void setWriteBuffer(uint8_t* buf, uint32_t len) {//設(shè)置寫緩存地址空間
            wBase_ = buf;//
            wBound_ = buf+len;//邊界
          }
          virtual ~TBufferBase() {}
          uint8_t* rBase_;//讀從這兒開始
          uint8_t* rBound_;//讀界限
          uint8_t* wBase_;//寫開始地址
          uint8_t* wBound_;//寫界限
        };

        從TBufferBase定義可以看出,它也是從虛擬類繼承,主要采用了memcpy函數(shù)來實現(xiàn)緩存的快速讀取,在判斷是否有足夠的緩存空間可以操作時采用了分支預(yù)測技術(shù)來提供代碼的執(zhí)行效率,且所有快路徑函數(shù)都是非虛擬的、內(nèi)聯(lián)的小代碼量函數(shù)。下面繼續(xù)看看一個具體實現(xiàn)緩存基類的一個子類的情況!
        TBufferedTransport
        緩存?zhèn)鬏旑愂菑木彺婊惱^承而來,它對于讀:實際讀數(shù)據(jù)的大小比實際請求的大很多,多余的數(shù)據(jù)將為將來超過本地緩存的數(shù)據(jù)服務(wù);對于寫:數(shù)據(jù)在它被發(fā)送出去以前將被先寫入內(nèi)存緩存。
        緩存的大小默認(rèn)是512字節(jié)(代碼:static const int DEFAULT_BUFFER_SIZE = 512;),提供多個構(gòu)造函數(shù),可以只指定一個傳輸類(另一層次的)、也可以指定讀寫緩存公用的大小或者分別指定。因為它是一個可以實際使用的緩存類,所以需要實現(xiàn)慢讀和慢寫功能的函數(shù)。它還實現(xiàn)了打開函數(shù)open、關(guān)閉函數(shù)close、刷新函數(shù)flush等,判斷是否有數(shù)據(jù)處于未決狀態(tài)函數(shù)peek定義和實現(xiàn)如下:

          bool peek() {
            if (rBase_ == rBound_) {//判斷讀的基地址與讀邊界是否重合了,也就是已經(jīng)讀取完畢
              setReadBuffer(rBuf_.get(), transport_->read(rBuf_.get(), rBufSize_));//是:重新讀取底層來的數(shù)據(jù)
            }
            return (rBound_ > rBase_);//邊界大于基地址就是有未決狀態(tài)數(shù)據(jù)
          }
        下面繼續(xù)看看慢讀函數(shù)和慢寫函數(shù)的實現(xiàn)細(xì)節(jié)(快讀和快寫繼承基類的:也就是默認(rèn)的讀寫都是直接從緩存中讀取,所謂的快讀和快寫)。慢讀函數(shù)實現(xiàn)如下(詳細(xì)注釋):
        uint32_t TBufferedTransport::readSlow(uint8_t* buf, uint32_t len) {
          uint32_t have = rBound_ - rBase_;//計算還有多少數(shù)據(jù)在緩存中
        
          // 如果讀取緩存中已經(jīng)存在的數(shù)據(jù)不能滿足我們,
          // 我們(也僅僅在這種情況下)應(yīng)該才從慢路徑讀數(shù)據(jù)。
          assert(have < len);
        
          // 如果我們有一些數(shù)據(jù)在緩存,拷貝出來并返回它
          // 我們不得不返回它而去嘗試讀更多的數(shù)據(jù),因為我們不能保證
          // 下層傳輸實際有更多的數(shù)據(jù), 因此嘗試阻塞式讀取它。
          if (have > 0) {
            memcpy(buf, rBase_, have);//拷貝數(shù)據(jù)
            setReadBuffer(rBuf_.get(), 0);//設(shè)置讀緩存,基類實現(xiàn)該函數(shù)
            return have;//返回緩存中已經(jīng)存在的不完整數(shù)據(jù)
          }
        
          // 在我們的緩存中沒有更多的數(shù)據(jù)可用。從下層傳輸?shù)玫礁嘁赃_(dá)到buffer的大小。
          // 注意如果len小于rBufSize_可能會產(chǎn)生多種場景否則幾乎是沒有意義的。
          setReadBuffer(rBuf_.get(), transport_->read(rBuf_.get(), rBufSize_));//讀取數(shù)據(jù)并設(shè)置讀緩存
        
          // 處理我們已有的數(shù)據(jù)
          uint32_t give = std::min(len, static_cast<uint32_t>(rBound_ - rBase_));
          memcpy(buf, rBase_, give);
          rBase_ += give;
        
          return give;
        }

        慢讀函數(shù)主要考慮的問題就是緩存中還有一部分?jǐn)?shù)據(jù),但是不夠我們需要讀取的長度;還有比較麻煩的情況是雖然現(xiàn)在緩存中沒有數(shù)據(jù),但是我們從下層傳輸去讀,讀取的長度可能大于、小于或等于我們需要讀取的長度,所以需要考慮各種情況。下面繼續(xù)分析慢寫函數(shù)實現(xiàn)細(xì)節(jié):

        void TBufferedTransport::writeSlow(const uint8_t* buf, uint32_t len) {
          uint32_t have_bytes = wBase_ - wBuf_.get();//計算寫緩存區(qū)中已有的字節(jié)數(shù)
          uint32_t space = wBound_ - wBase_;//計算剩余寫緩存空間
          // 如果在緩存區(qū)的空閑空間不能容納我們的數(shù)據(jù),我們采用慢路徑寫(僅僅)
          assert(wBound_ - wBase_ < static_cast<ptrdiff_t>(len));
        
             //已有數(shù)據(jù)加上需要寫入的數(shù)據(jù)是否大于2倍寫緩存區(qū)或者緩存區(qū)為空
          if ((have_bytes + len >= 2*wBufSize_) || (have_bytes == 0)) {
            if (have_bytes > 0) {//緩存大于0且加上需要再寫入數(shù)據(jù)的長度大于2倍緩存區(qū)
              transport_->write(wBuf_.get(), have_bytes);//先將已有數(shù)據(jù)寫入下層傳輸
            }
            transport_->write(buf, len);//寫入這次的len長度的數(shù)據(jù)
            wBase_ = wBuf_.get();//重新得到寫緩存的基地址
            return;
          }
        
          memcpy(wBase_, buf, space);//填充我們的內(nèi)部緩存區(qū)為了寫
          buf += space;
          len -= space;
          transport_->write(wBuf_.get(), wBufSize_);//寫入下層傳輸
        
          assert(len < wBufSize_);
          memcpy(wBuf_.get(), buf, len);//拷貝剩余的數(shù)據(jù)到我們的緩存
          wBase_ = wBuf_.get() + len;//重新得到寫緩存基地址
          return;
        }

        慢寫函數(shù)也有棘手的問題,就是我們應(yīng)該拷貝我們的數(shù)據(jù)到我們的內(nèi)部緩存并且從那兒發(fā)送出去,或者我們應(yīng)該僅僅用一次系統(tǒng)調(diào)用把當(dāng)前內(nèi)部寫緩存區(qū)的內(nèi)容寫出去,然后再用一次系統(tǒng)調(diào)用把我們當(dāng)前需要寫入長度為len的數(shù)據(jù)再次寫入出去。如果當(dāng)前緩存區(qū)的數(shù)據(jù)加上我們這次需要寫入數(shù)據(jù)的長度至少是我們緩存區(qū)長度的兩倍,我們將不得不至少調(diào)用兩次系統(tǒng)調(diào)用(緩存區(qū)為空時有可能例外),那么我們就不拷貝了。否則我們就是按順序遞加的。具體實現(xiàn)分情況處理,最后我們在看看慢借函數(shù)的實現(xiàn),借相關(guān)函數(shù)主要是為了實現(xiàn)可變長度編碼。慢借函數(shù)實現(xiàn)細(xì)節(jié)如下:

        const uint8_t* TBufferedTransport::borrowSlow(uint8_t* buf, uint32_t* len) {
          (void) buf;
          (void) len;
          return NULL;//默認(rèn)返回空
        }

        在這個類我們可以看出,它什么也沒有做,只是簡單的返回NULL,所以需要阻塞去借。按照官方的說法,下面兩種行為應(yīng)該當(dāng)前的版本中實現(xiàn),在將來的版本可能會發(fā)生改變:
        如果需要借的長度最多為緩存區(qū)的長度,那么永遠(yuǎn)不會返回NULL。依賴底層傳輸,它應(yīng)該拋出一個異常或者永遠(yuǎn)不會掛掉;
        一些借用請求可能內(nèi)部字節(jié)拷貝,如果借用的長度最多是緩存區(qū)的一半,那么不去內(nèi)部拷貝。為了優(yōu)化性能保存這個限制。

      posted @ 2013-07-26 00:39  薔薇理想人生  閱讀(3237)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 绝顶丰满少妇av无码| 2019亚洲午夜无码天堂| 国产欧美日韩视频怡春院| caoporn成人免费公开| 99久久无码一区人妻a黑| 好姑娘高清影视在线观看| 亚洲人成网网址在线看| 国产美女遭强高潮免费| 国产精品福利中文字幕| 日日碰狠狠躁久久躁综合小说 | 色综合 图片区 小说区| 中国熟妇毛多多裸交视频| 欧美激情一区二区三区成人| 人成午夜免费视频无码| 亚洲精品~无码抽插| 少妇精品视频一码二码三| 国产一区在线播放av| 亚洲国产日韩一区三区| 亚洲人成电影网站 久久影视| 日本一区二区久久人妻高清| 国产精品亚洲片夜色在线| 亚洲日韩中文字幕在线播放| 亚洲老熟女一区二区三区| 亚洲欧美在线观看品| 波多野结衣久久一区二区| 九九热在线免费视频观看| 国产日韩一区二区三区在线观看 | 日本不卡一区二区三区在线| 亚洲AV无码东方伊甸园| 国产成人啪精品午夜网站| 五月丁香综合缴情六月小说| 夜夜影院未满十八勿进| 91久久夜色精品国产网站| 国产熟女丝袜av一二区| 十八禁午夜福利免费网站| 在线免费成人亚洲av| 男女啪啪免费观看网站| 国产精品推荐手机在线| 色综合天天综合天天综| 日韩理伦片一区二区三区| 亚洲免费网站观看视频|