• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            @阿凡
            Server S把Client A的NAT信息發給Client B,然后B直接給A的NAT發一條信息即可,具體原因可以再看一下文中對Cone NAT的介紹。
            說的不錯,pool的方式存在的問題是挺多。不過對于pool的效率高不到哪去的觀點我不敢認同,針對大量小數據的分配,有時候還必須得使用pool的方式,不然ptmalloc、tcmalloc、jemalloc等不會維護復雜的內存分配方式@chipset
            如果我沒記錯的話malloc自始至終都有自己的一套pool策略,所以我所說的malloc性能提升并非指的這個。
            不過第三方穩定高效的allocator實現可能是標準庫作者放棄pool的一個原因@egmkang
            re: 論epoll的使用[未登錄] peakflys 2014-08-06 18:53
            @呆賊
            “如果socket有寫事件,不要直接放入epoll中”?
            你的意思應該是epoll不監聽寫事件吧?
            如果是這個意思的話,你說的可以解決LT模式下CPU空轉的問題,不過會引入新的問題,也就是頻繁地修改epoll事件(剛開始EPOLL_OUT不監聽,后來send失敗后Add EPOLL_OUT事件,等監聽發送完畢,還要再Del掉EPOLL_OUT事件).
            已修正,謝謝@wencan
            @zdd 兩者沒有本質區別。
            *(Derive*)&b 先取地址,強轉地址類型,然后再取內容,同匯編實現基本是一一對應起來的;
            (Derive&)b是使用C式的強轉直接把內容轉成Derive的引用,編譯器幫你翻譯成的匯編代碼實現應該和上面的是一樣的。
            僅作例子講解@Richard Wei
            @zuhd
            如果使用成熟的網絡庫大可不必特別關注連接超時的問題,但是如果是自己按實際需要重新寫的網絡層,那么網絡層的容錯性和健壯性就需要通過很多指標來考核,前期連接超時如果很多的話,就需要排查一下雙方網絡層代碼是否有異常。
            最后一個例子不是什么坑,只不過是ISO未定義的情況,其實要實現基類指針正確找到派生類this偏移的方式很多種,記下大小,加上固定偏移就是一種方法,當然還有其他很多種方法,應該沒什么特別的復雜,這里頂多告誡大家要慎用,因為是標準未定義的行為,crash or not crash,compiler decides it。建議博主修改之。
            剛才構造了一個例子,如下:
            #include <cstdio>

            class Base
            {
            public:
            Base(const int a=10) : a(a)
            {
            printf("Base constructor,this addr: %p\n",this);
            }
            virtual ~Base()
            {
            printf("Base destructor, a=%d, this addr: %p\n",a,this);
            }
            int a;
            };
            class Derive : public Base
            {
            public:
            Derive(const int a=20,const int b=20) : Base(a),b(b)
            {
            printf("Derive constructor,this addr: %p\n",this);
            }
            virtual ~Derive()
            {
            printf("Derive destructor, b=%d, this addr: %p\n",b,this);
            }
            int b;
            };
            int main(int argc, char* argv[])
            {
            Base *pb = new Derive[3];
            delete [] pb;
            printf("over\n");
            return 0;
            }
            特意在基類和派生類里各加了一個成員變量,來增大兩者可能的指針偏移。
            結果證明 delete 多態的指針后,內存正常釋放,而每個派生類對象的this指針也均無差錯!
            編譯器:g++ (GCC) 4.4.6 20120305 (Red Hat 4.4.6-4)
            對于博主最后一個例子所說的“但是Base*類型的指針式不能正確計算出Derived數組的10個析構函數需要的this指針的位置的”,請問為什么不行呢?難點在哪?
            re: 關于hash_map的一點感悟 peakflys 2013-05-14 17:38
            呵呵,這種代碼大點的系統,很多都是存在的,而潛在的錯誤可能還沒爆發出來@egmkang
            @syd
            其實不然,編譯器產生的構造函數很多時候是nontrivial的,
            例如:成員變量是含有構造函數的類類型,含有virtual function等等
            @jxhgzs
            請提供你的編譯器版本,因為這是C++98標準規定的操作,如果你的編譯器產生的代碼行為同文中描述有出入,只能說明你的編譯器沒按照98標準來實現。
            @noname
            文中的結論是基于C++98標準的編譯器驗證結果,而VS2012是根據最新的C++11標準實現的,新標準對于這種情況的規定有沒有變動尚未驗證。
            PS:你提供的匯編代碼應該是和文中的結論吻合的吧?
            看多了就很自然了@zuhd
            @tangfu
            其實這個不是編譯器相關的,標準化委員會細化規則的程度大大超過你的想象。
            摘自:ISO/IEC 14882:2003(E) 5.3.4 - 15
            — If the new-initializer is omitted:
            — If T is a (possibly cv-qualified) non-POD class type (or array thereof), the object is default-initialized(8.5). If T is a const-qualified type, the underlying class type shall have a user-declared default constructor.
            — Otherwise, the object created has indeterminate value. If T is a const-qualified type, or a (possibly cv-qualified) POD class type (or array thereof) containing (directly or indirectly) a member of const-qualified type, the program is ill-formed;
            — If the new-initializer is of the form (), the item is value-initialized (8.5);
            恩,這個網站提供了很好的C++參考文檔@Wilbur
            其實現在國內很多公司的筆試題都很學究,真正考察在工程項目中使用的比較多的那些語法、算法或者一些編程技巧很少、很淺……@zgpxgame
            re: 論epoll的使用 peakflys 2013-02-26 16:28
            經過討論最終結論我認為:ET模式在網絡層方面的效率肯定比LT要高。
            主要表現在:
            1、網絡IO比較小時,send buffer表現為一直可寫,如果網絡主循環沒有延時操作的話,epoll_wait每次調用都會馬上有事件返回,導致不必要的CPU空耗,如果加入延時處理,對于一些實時性要求比較高的操作會受到影響,必須耗費額外的邏輯處理。
            2、在網絡IO比較大,尤其是連接數比較多的時候,每次epoll_wait調用時LT模式肯定比ET模式多,因為之后需要對ready list 進行遍歷處理,如果處理邏輯比較復雜,或者之前反饋的事件數LT比ET多很多的話,這時候效率差異就比較明顯了。

            ET模式在網絡主循環處理的效率肯定比LT模式要高,至于高多少,視具體應用和具體實現而定。當然ET模式的代價就是增加了網絡層的邏輯處理復雜度,必須手動維護fd當前的狀態,在數據發送時也不能像LT模式那樣直接丟到fd應用層的buffer中。當然武器是好武器,關鍵還是看用的人,如果非要把寶劍當菜刀使,那也只能沉默了……
            其實這個問題我之前在一篇blog里已經討論過(http://www.shnenglu.com/peakflys/archive/2012/08/26/188344.aspx)
            我現在的結論是:ET模式在網絡層方面的效率確實比LT要高。
            主要表現在:
            1、網絡IO比較小時,send buffer表現為一直可寫,如果網絡主循環沒有延時操作的話,epoll_wait每次調用都會馬上有事件返回,導致不必要的CPU空耗。
            2、在網絡IO比較大,尤其是連接數比較多的時候,每次epoll_wait調用時LT模式肯定比ET模式多,因為之后需要對ready list 進行遍歷處理,如果處理邏輯比較復雜,或者之前反饋的事件數LT比ET多很多的話,這時候效率差異就比較明顯了。

            還是那句話,ET模式在網絡主循環處理的效率肯定比LT模式要高,至于高多少,視具體應用和具體實現。當然ET模式的代價就是增加了網絡層的邏輯處理復雜度,必須保證時刻知道fd當前的狀態。
            re: Libjingle庫 綜述 peakflys 2013-01-31 11:21
            文章黑體字部分還有圖片來自Google的英文開發文檔,文檔首頁見:https://developers.google.com/talk/libjingle/index @免費空間
            re: 關于最優無限循環的考證 peakflys 2013-01-09 13:15
            恩?@花
            re: 關于最優無限循環的考證 peakflys 2013-01-06 14:07
            在硬件性能和編譯器優化能力不斷提升的今天,程序員的門檻一降再降,甚至出現了半月培訓即可入崗的事情,但是如果想要寫出優質高效的代碼,就一定要熟悉你所使用的編譯器,不能完全寄望于編譯器的優化,養成良好的書寫習慣才是王道。@zgpxgame
            re: 關于最優無限循環的考證 peakflys 2013-01-05 17:05
            上面的匯編代碼是建立在GCC編譯未加-O優化,VS用的也是debug版本,目的是為了說明 所謂廣為流傳的for(;;)比while(1)效率更好的說法是編譯器相關的,當然GCC和VS下編程同意網上說的無限循環優先選用for(;;),至于VS的release版本,還有其他編譯器平臺,有興趣的可以自己去驗證一下。@Lo
            其實這種情況實現的方法有很多,例如backtrace等等,但是這種情況在服務器上試問有什么意義?通過這種方法打出來的東西遠遠沒有OS dump出的程序core文件包含的信息多……
            PS,這種情況在C/S架構的C端才有相應的應用價值,通過網絡 把遠端客戶端dump出的信息傳送過來,便于客戶端查錯而已。
            ack是TCP機制提供的一種接收反饋,對端接收發送的數據包會自動反饋回一個ack,這個過程上層app是沒有參與的,所以單從一個ack來看是不知道對端app有沒有取到剛才傳送的數據,但是也有一個辦法可以大體上猜到對端的使用,就是根據多個ack反饋,由窗口大小的改變來揣測。舉個例子,對端窗口大小為65530個字節,我現在傳過去10個字節,對端回復一個ack,但是這個ack不代表剛才傳的10個字節對端app已經取到,但是如果我現在再傳10個字節,如果對端回復的ack中window大小是65520,這時我可以猜出剛才傳的數據已經被對端app取到了,這也就是原文中的意思:對端反饋回來ack,只代表對端接收到了數據,不代表上層應用程序取到了數據。@Sunny
            re: 未來軟件結構(討論帖) peakflys 2012-12-14 11:22
            對于嵌入式這一塊沒有特別關注,所以也就沒有說,不過據我了解,近一兩年隨著嵌入式硬件的性能提升,很多嵌入式程序都已經不用匯編或者C開發了,不過5年或者10年之內感覺嵌入式 應該沒有什么大的變化,個人意見……@haskell
            re: 未來軟件結構(討論帖) peakflys 2012-12-10 10:44
            LO說的沒錯,cpu連同GPU散熱導致的手機溫度升高,暫時是沒有什么好的解決辦法,不過相比于以Browser為軸心擴展各種軟件 為用戶帶來的便利性和傻瓜化的操作感而言,那個問題5年內應該會得以解決,辦法當然很多:摩爾效應繼續,器件能效比提高,新型移動散熱輔材的出現等等……@LO
            re: 未來軟件結構(討論帖) peakflys 2012-12-07 10:03
            貼中是我前天無聊時結合自己的想法寫出來的,大家可以提出自己未來的軟件結構,也歡迎大家拍磚
            re: 未來軟件結構(討論帖) peakflys 2012-12-07 10:01
            現在部分手機型號已經和平板無異,而平板和PC的區別,這個還真不好嚴格區別@alex
            re: 未來軟件結構(討論帖) peakflys 2012-12-07 09:58
            續航能力確實是現在移動設備的短板,這個我表示認同,但是這一兩年來手機電池電量從700mA/h一路飆升到3300mA/h(摩托刀鋒系列),未來5年這個還真不好說。退一步講,就算電池技術沒有什么突破,但是現在的ipad mini都可以達到12小時的連續使用,未來的手機完全可以做成折疊式的平板(折疊式屏幕已在三星Galaxy部分機型上使用),這樣功能即強勁,攜帶也便捷,電池電量也可通過擴大體積的形式規避@LO
            re: 未來軟件結構(討論帖) peakflys 2012-12-06 14:00
            “有”和“普及”相差很遠,上面我的5年后的猜想是B/S成為主流,依據有二:一則因為現在的電子設備不具有上網功能的基本可以直接判死刑,而聯網的話 瀏覽器可以說是必不可少的,移動設備的互聯互通,通過瀏覽器是最直接、最方便的;二則因為現在各種軟件的微型化,甚至可以作為一個插件來使用,這樣用戶操作也方便化,傻瓜化,符合軟件發展的方向,符合大眾使用的最終需求,而之所以說大概5年就可以實現,是因為現在很多廠商好像都有這樣的共識,例如Google,可以說google對chrome的期望很高的,無論是在平板還是手機或是PC,現在chrome的表現都還不錯,而chrome的設計就是為此而生的,它采用一標簽一進程的形式,一則可以加快網頁等的執行速度,二則可以方便插件化的程序高效、安全運行,當然這樣的代價自然是內存的極大占用很大,瀏覽器自帶進程管理器,可以隨時殺瀏覽器開啟的進程,儼然一個小生態系統 @bill gates
            呵呵,滑動窗口英文名稱是“sliding-window”是TCP協議的一部分,因其大小根據對方的ACK來動態調整,故稱之為滑動窗口,這個稱呼應該是很貼切很形象的,并且目前幾乎所有關于網絡的書籍都會翻譯成滑動窗口。recvbuf和sendbuf是為了說明程序中設置的buffer大小和滑動窗口的關系我特意加上去的,不然估計有不少人像我之前一個同事一樣只知道設置接收緩沖區和發送緩沖區,而不知道它們真正執行的過程 @kaka
            re: UDP,TCP打洞技術 peakflys 2012-11-27 12:35
            不錯,講的很詳細,但是如果是轉載的,希望博主能夠把轉載的源地址附上。
            24那個值看一下匯編 或者 info frame 看一下堆棧幀也可以看出來 但是你計算的不對,上面的編譯環境使用的寄存器是rbp、rsp、rip(從上面匯編也可以看出來) 這些都是64位的,24的具體計算過程是這樣的:a數據擴展成4個int是16個字節,然后加上test函數調用時壓進堆棧的rbp 8個字節,總共是24個字節,這個位置就是調用test函數后的返回地址,修改內容即可,具體可以用gdb調試看一下 @zuhd
            re: 論epoll的使用 peakflys 2012-09-02 11:36
            @zuhd
            移出的代價必然大于輪詢的代價,但是如果LT模式不做寫事件優化的話,是在一定程度上影響效率的(影響的程度和掛載的socket數量有關),這種影響首先表現在輪詢的次數上,其次(也應該說主要)是你的發送函數上調用上,因為不管有沒有消息需要發送,只要send buffer不滿,寫事件都會觸發,你所封裝的發送函數都會調用。
            re: 論epoll的使用 peakflys 2012-08-30 15:48
            恩,看來服務器性能還不錯,我們單網關設計是5K連接,不過使用的是線程池,單個線程掛512個socket,在加上網絡主循環有相應優化,所以LT模式影響不大,留給上層邏輯很大的擴展空間 @唐詩
            re: 論epoll的使用 peakflys 2012-08-30 14:11
            恩,唐詩兄在socket上加入標記位的辦法是可以很好解決ET模式的寫問題(上述代碼中唐詩兄應該加上write之后 0==n 的情況,及時斷掉正常中斷的socket,而不是認為寫正常,馬上調整發送緩存)
            謝謝唐詩兄的指教,不過如果使用LT模式,唐詩兄會發現更簡單,呵呵。不知道你們一個網絡主線程掛載多少socket? @唐詩
            re: 論epoll的使用 peakflys 2012-08-30 07:34
            謝謝唐詩的回復和指教,你指出的
            a問題:在文中寫ET模式時已經說了一部分,不過沒有說寫事件處理完之后,send buffer仍然可寫時怎么處理,因為這個本身就是我認為的ET模式弊端之一,因為挺麻煩也挺易出錯。
            b問題:當時寫這篇短文時確實沒有特別考慮,不過在評論里面 春秋十二月仁兄指出了這個問題,唐詩兄給出的方法是每次把數據寫完之后把它移出epoll監聽隊列,以后有新的寫數據時再加入寫事件到隊列,不過個人感覺這種方法不是很理想,除了自己寫著難受之外,因為從2.6.10內核之后 epoll內部隊列的數據結構變成了RB_TREE,游戲中寫數據很頻繁(尤其是大規模玩家在線時),這樣頻繁的調整RB_TREE,性能損耗應該會不小。我在給春秋十二月仁兄的回復中給出了我的大致解決方法(參看上面評論),有什么不完整或者不對的地方,還請唐詩兄指教或者郵件交流 peakflys@gmail.com
            至于唐詩兄說的et要比lt簡單,這個可能是用et用的多了,很多細節錯誤已經有了自己固定成熟的解決方案了才說出這樣的結論。ET如果保證每次觸發的事件都可以及時有效的處理完全(當然 個人認為不容易,有時候還要自己處理一些本該TCP處理的東西)ET模式還是可以作為首選的,否則會表現出通訊過程中應用上層各種詭異的問題…… @唐詩
            re: 論epoll的使用 peakflys 2012-08-28 10:51
            @春秋十二月
            謝謝春秋仁兄的指教,我是這么認為的。send buffer不滿時觸發的寫事件,應該不至于引起CPU的占用過高(OS里本身也有很多納秒級的死循環),如果過高說明輪詢時的處理函數太耗CPU了,應該是可以優化的,另外輪詢時間也可以設置的長一些,當然有些應用需要這么準確、及時。如果這樣的話,我認為可以這樣改進:在一次網絡主循環里調用兩次epoll_wait,第一次是及時的(例如1ms)用于處理讀和錯誤事件,第二次是稍微長的(例如30~50ms,視情況定)用于處理讀、寫等事件。為了達到這種效果,我們可以 封裝兩種send方式,一種是使用epoll觸發的寫,另外一種是緊急的立即寫(當然寫時可以調用poll等檢測一下是否可寫)。這樣效率應該跟得上了,復雜度和出錯成都也沒有ET模式高。
            re: 論大小端 peakflys 2012-08-20 09:56
            對的,那幾個函數就是為了在網絡字節序(也就是大端)和本地字節序間轉換的,不過它提供的只有32位和16位的數值轉換,實際項目中還會用到其他格式的數值類型,為了保證格式上的統一,一般都自己封裝轉換方法(其實那幾個函數的真實實現 也是用到上面的方法實現的)@時間矢
            re: 論大小端 peakflys 2012-08-20 09:48
            64位和32位道理一樣,挺好寫的,自己實現就okay了,呵呵 @zaccheo
            挺好的方法,無論是從空間上還是時間上 都是不錯的算法
            re: 編譯器背后的小故事 peakflys 2012-07-30 11:01
            @zgpxgame
            例一的結果自然是發生在隱式轉換之前的值溢出,但 關鍵應該是上面提到的GCC編譯器做運算時如果后面運算值沒有超過32位的,都會用32位寄存器做運算,只有你運算值本身有大于32位的或者程序中強制轉換成大于32位的(如例一后來改的那樣),編譯器才會有64位寄存器的參與。就如同如果上面是把兩個unsigned short的最大值,即65535+65535賦給一個unsigned int值,程序運行正常,不會發生溢出。
            PS string強轉去除const屬性,在實際應用中會出現,但是一般項目中都不會強制改變它的內容,上面例二僅僅是測試類常量和基本值常量直接些許的差別。
            re: 編譯器背后的小故事 peakflys 2012-07-30 10:48
            @ntest 而object需要占用內存空間???
            這位仁兄的意思是const int 沒有內存的占用,只有寄存器的占用?上面例二加上匯編碼是為了說明,const int入棧時 沒有從內存取值,應該是編譯器優化直接從類似的符號表(同C中的define一樣)里取出數值。
            re: 關于hash_map的一點感悟 peakflys 2012-07-24 18:29
            @likun原因很簡單,上面我也說過,operator++ 操作是從_M_cur開始,優先_M_cur->_M_next,為空時遍歷vector直至找到一個_M_cur不為空的節點,遍歷vector時需要取它對應的桶位置(參砍上面hash_map取值過程),_M_bkt_num_key(key)中key的值是修改后的值,假如你改的鍵值,通過此函數得到的桶位置在你當前元素之前,這樣就造成了死循環。
            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            導航

            統計

            公告

            人不淡定的時候,就愛表現出來,敲代碼如此,偶爾的靈感亦如此……

            常用鏈接

            留言簿(4)

            隨筆分類

            隨筆檔案

            文章檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            天天综合久久久网| 亚洲国产欧洲综合997久久| 亚洲AV日韩精品久久久久久 | 久久妇女高潮几次MBA| 国产精品99久久精品爆乳| 久久综合九色综合久99| 精品久久久无码人妻中文字幕豆芽| 国产精品乱码久久久久久软件| 久久亚洲国产成人精品无码区| 久久中文字幕无码专区| 久久久精品国产亚洲成人满18免费网站| 国产成人综合久久久久久| 91精品国产91久久久久久| 97超级碰碰碰碰久久久久| 色综合久久综精品| 久久性生大片免费观看性| 日韩十八禁一区二区久久 | 日本加勒比久久精品| 一个色综合久久| 久久亚洲国产成人精品性色| 97久久久精品综合88久久| 婷婷综合久久中文字幕| 人妻精品久久久久中文字幕| 久久SE精品一区二区| 免费观看久久精彩视频| 人妻系列无码专区久久五月天| 久久久久久精品无码人妻| 91精品国产综合久久婷婷| 欧美久久综合九色综合| 亚洲av日韩精品久久久久久a | 亚洲国产精品无码久久久秋霞2 | 久久婷婷色综合一区二区| 久久ZYZ资源站无码中文动漫| 国产精品成人99久久久久91gav| 综合久久精品色| 99精品久久久久中文字幕| 伊人热热久久原色播放www| 久久精品国产亚洲沈樵| 伊人色综合九久久天天蜜桃| 国内精品久久久久影院免费| 久久久久久久精品成人热色戒|