• <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>

            sherrylso

            C++博客 首頁 新隨筆 聯(lián)系 聚合 管理
              18 Posts :: 0 Stories :: 124 Comments :: 0 Trackbacks

                    一般來講, 在服務(wù)器上,如果有足夠的資源,Winsock server,理論上可以支持成千的并發(fā)連接。而現(xiàn)實(shí)是,我們沒有足夠的資源可供使用,分配。本文主要來討論一下內(nèi)存資源之于Winsock server開發(fā)的重要性。
            一)基本概念。
            -> Pages,Locked Pages.
                    在現(xiàn)代操作系統(tǒng)中,內(nèi)存管理會把主存(RAM)分成Pages來管理。 Paging(或者swapping)指的是主存與外存之間以Page為單位進(jìn)行數(shù)據(jù)的交換。Locked Pages指的是被鎖定在主存中的內(nèi)存頁,以保證一些內(nèi)核組件,driver可以訪問到它們。windows一定會保證一定數(shù)量的可交換的內(nèi)存空間,防止一些非法程序鎖定所有的物理內(nèi)存,而致使系統(tǒng)崩潰。在windows NT, windows 2000上,可鎖定的內(nèi)存總的大小上限大概是物理內(nèi)存的1/8(當(dāng)然對于程序的開發(fā)人員,不應(yīng)該對這個值進(jìn)行任何的假設(shè),這個值可能會隨著操作系統(tǒng)本版的變化而變化)。在Winsock應(yīng)用開發(fā)過程中,以overlapped方式讀寫IO操作,將會導(dǎo)致內(nèi)存被鎖定。
            -> working set
                    在程序開始運(yùn)行,并達(dá)到其穩(wěn)定的運(yùn)行狀態(tài)(主要指的是其對內(nèi)存的使用),在這個狀態(tài)下,程序使用內(nèi)存的數(shù)量一般小于其需要使用內(nèi)存的總量。這樣一個穩(wěn)定的運(yùn)行狀態(tài),我們可以稱為working set: 被該程序頻繁訪問的內(nèi)存頁的集合。在windows上,你可以使用SetWorkingSetSize Win32 API來增加程序使用物理內(nèi)存的數(shù)量。
            -> non-paged pool
                   不可交換的內(nèi)存。這主要指以non-paged的方式分配的內(nèi)存,這些內(nèi)存就像locked pages一樣,是從來不會被交換出去的,用來存放一些由內(nèi)核組件,driver訪問的信息。 在Winsock應(yīng)用開發(fā)過程中,以下的操作可能導(dǎo)致分配non-paged內(nèi)存。
            1) 調(diào)用系統(tǒng)一些系統(tǒng)的API,例如打開文件,create socket,等,都會導(dǎo)致從non-paged pool分配內(nèi)存。
            2) 一些driver可以顯式地從該區(qū)域分配內(nèi)存。
            二) Winsock server上Locked Pages使用。
                    我們提到過,任何的overlapped IO操作,都會導(dǎo)致鎖定內(nèi)存頁。這些內(nèi)存頁一旦被locked,就不會被交換出去。我們知道,windows操作系統(tǒng)對最大的可鎖定內(nèi)存頁做了一個上限,如果超出這個上限,overlapped IO調(diào)用將會導(dǎo)致WSAENOBUFS錯誤。
                    考慮下面的情況,如果server在每個連接上會發(fā)出很多的overlapped receives操作,那么,隨著連接數(shù)目的增多,很明顯,被鎖定的內(nèi)存數(shù)量很有可能達(dá)到上限而導(dǎo)致WSAENOBUFS錯誤。在這種情況下,如果服務(wù)器預(yù)期會處理大數(shù)量的客戶端連接,則需要服務(wù)器在每個連接上發(fā)出zero-byte buffer的overlapped接收請求(這種情況下,因?yàn)閠he size of buffer is zero,所以沒有任何內(nèi)存被鎖定),一旦overlapped接收操作完成,server可以以non-blocking方式執(zhí)行receive操作,以取得所有緩存在so_rcvbuf中的數(shù)據(jù),直到返回WSAEWOULDBLOCK為止。
                    另外需要注意的是,windows在page的邊界上對內(nèi)存進(jìn)行鎖定,在x86平臺上,它是4kb的整數(shù)倍。所以,假如你post了一個1 KB buffer,而系統(tǒng)真實(shí)鎖定的是4 KB 的大小,為了避免這樣的浪費(fèi),盡量用4kb的整數(shù)做overlapped  IO操作。
            三) Winsock server上non-paged pool使用。
                    同Locked Pages限制一樣,windows對non-paged pool也有一個最大的限制。并且,當(dāng)你的應(yīng)用出現(xiàn)這個問題的時候,超出它的最大限制數(shù),情況要遠(yuǎn)比Locked Pages復(fù)雜。這種情況下,后果是不確定的,有可能你的Winsock調(diào)用返回WSAENOBUFS錯誤,也有可能,在系統(tǒng)中,一個和你的應(yīng)用毫無關(guān)聯(lián)的driver由于申請不到non-paged內(nèi)存而致使system crash。而這樣的災(zāi)難,是沒法恢復(fù)的。
                    考慮一個具體的例子:我們假設(shè)在windows2000上,系統(tǒng)有1 GB內(nèi)存。這樣的配置下,windows大概會預(yù)留1/4的空間用作non-paged pool(同樣,對于程序的開發(fā)人員,不應(yīng)該對這個值進(jìn)行任何的假設(shè)),即:256MB。這樣的配置下,保守估計(jì),我們的Winsock server能夠處理到大概50,000連接,或者更多。(每個accepted socket大概消耗1.5kb,每個連接上post一個overlapped操作,分配一個IRP,大概需要500 byte, 總計(jì):(1500+500)*50,000 = 100 Mb) 。
                   無論是對于Locked Pages,還是對于non-paged pool使用,一旦超出了上限,Winsock調(diào)用僅僅會返回一般的WSAENOBUFS 或者ERROR_INSUFFICIENT_RESOURCES錯誤。為了處理這些錯誤,你可以試試以下的方法:
            1) 需要首先調(diào)用SetWorkingSetSize,增加應(yīng)用的可支配資源數(shù),看能否解決。
            2)     確信你的應(yīng)用沒有做出太多的overlapped  IO操作。
            3) 關(guān)閉一些連接數(shù)。
            四) SOCKET的緩沖區(qū)設(shè)置問題。

                     Winsock在默認(rèn)的情況下,每個socket都會與一個send和receive buffer相關(guān)聯(lián)。你可以通過調(diào)用setsockopt來設(shè)置buffer的大小。
                    在緩沖區(qū)沒有被關(guān)閉的情況下,我們看看overlapped send和revc是怎么工作的。
                    當(dāng)上層的應(yīng)用做出了send調(diào)用,而這時如果send buffer還有剩余的空間,那么數(shù)據(jù)將會從用戶提交的buffer復(fù)制到send buffer中,然后調(diào)用返回成功。否則,假如這時send buffer已滿,用戶提交的buffer將會被鎖定,并且調(diào)用返回WSA_IO_PENDING。當(dāng)send buffer的數(shù)據(jù)被下層的tcp處理完成,winsock將直接處理用戶提交的buffer里的數(shù)據(jù),而不需要再復(fù)制。
                    同樣,對于recv操作,如果數(shù)據(jù)已經(jīng)被緩存在socket的receive buffer里,當(dāng)發(fā)生recv調(diào)用的時候,數(shù)據(jù)將直接從socket的receive buffer復(fù)制到用戶的buffer里,recv調(diào)用返回成功。否則,假如發(fā)生調(diào)用時receive buffer里沒有數(shù)據(jù),用戶提交的buffer將會被鎖定,recv調(diào)用返回WSA_IO_PENDING。當(dāng)數(shù)據(jù)到達(dá)當(dāng)前連接,將會被直接復(fù)制到用戶提交的buffer里。
                    一個應(yīng)用程序通過設(shè)定send buffer為0,把緩沖區(qū)關(guān)閉,然后發(fā)出一個阻塞send()調(diào)用。在這樣的情況下,系統(tǒng)內(nèi)核會把應(yīng)用程序的緩沖區(qū)鎖定,直到接收方確認(rèn)收到了整個緩沖區(qū)后send()調(diào)用才返回。似乎這是一種判定你的數(shù)據(jù)是否已經(jīng)為對方全部收到的簡潔的方法,實(shí)際上卻并非如此。想想看,即使遠(yuǎn)端tcp通知數(shù)據(jù)已經(jīng)收到,其實(shí)也根本不代表數(shù)據(jù)已經(jīng)成功送給客戶端應(yīng)用程序,比如對方可能發(fā)生資源不足的情況,導(dǎo)致afd.sys不能把數(shù)據(jù)拷貝給應(yīng)用程序。另一個更要緊的問題是,在每個線程中每次只能進(jìn)行一次發(fā)送調(diào)用,效率極其低下。
                    另外,希望通過關(guān)閉Winsock緩沖區(qū),從而避免數(shù)據(jù)復(fù)制,達(dá)到優(yōu)化性能的目的,也是不可取的。從上面,我們看到:只要應(yīng)用保證適量的,足夠的send, recv調(diào)用,這樣的復(fù)制是完全可以避免的。
                    高性能的服務(wù)器應(yīng)用程序可以關(guān)閉發(fā)送緩沖區(qū),同時不會損失性能。不過,這樣的應(yīng)用程序必須十分小心,保證它總是發(fā)出多個重疊發(fā)送調(diào)用,而不是等待某個重疊發(fā)送結(jié)束了才發(fā)出下一個。如果應(yīng)用程序是按一個發(fā)完再發(fā)下一個的順序來操作,那浪費(fèi)掉兩次發(fā)送中間的空檔時間,總之是要保證傳輸驅(qū)動程序在發(fā)送完一個緩沖區(qū)后,立刻可以轉(zhuǎn)向另一個緩沖區(qū)。
                    如果關(guān)閉了recv buffer,在你的應(yīng)用沒有保證足夠的recv操作前提下,任何進(jìn)來數(shù)據(jù),必須在TCP層進(jìn)行緩存,最大緩存的數(shù)量將取決于tcp windows的大小(17Kb)。而最為嚴(yán)重的是這些緩存是從non-paged pool分配而來。如上所述,non-paged pool是非常珍貴,稀缺的內(nèi)存。所以,從這個意義上來講,關(guān)閉了recv buffer操作是不可取的。
                這是2007年最后一篇帖子,最后祝大家新年快樂,過個好年!!!

            posted on 2008-02-03 15:18 愛上龍卷風(fēng) 閱讀(3091) 評論(2)  編輯 收藏 引用

            Feedback

            # re: Winsock服務(wù)器內(nèi)存資源管理[未登錄] 2008-02-03 16:01 汪江濤
            好帖!頂!  回復(fù)  更多評論
              

            # re: Winsock服務(wù)器內(nèi)存資源管理 2008-02-16 10:04 追夢時代
            好帖!  回復(fù)  更多評論
              


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            高清免费久久午夜精品| 亚洲日韩欧美一区久久久久我| 久久亚洲中文字幕精品一区| 国产亚洲精品久久久久秋霞| 伊人久久大香线蕉综合影院首页| 久久精品www人人爽人人| 久久国产影院| 亚洲精品白浆高清久久久久久| .精品久久久麻豆国产精品 | 精品人妻伦九区久久AAA片69| 人妻精品久久无码区| 91精品国产91久久久久久青草| 超级97碰碰碰碰久久久久最新| 色综合久久88色综合天天| 久久久国产视频| 精品熟女少妇av免费久久| 国产精品久久久久久久久软件| 成人精品一区二区久久久| 久久人人爽爽爽人久久久| 欧美丰满熟妇BBB久久久| 青青草国产精品久久| 国产精品久久久久久久| 91精品国产综合久久精品| 国产精品免费久久久久久久久| 久久婷婷五月综合国产尤物app| 污污内射久久一区二区欧美日韩 | 久久精品国产99久久久香蕉| 国产精品18久久久久久vr| 成人午夜精品无码区久久| 久久久女人与动物群交毛片| 久久精品国产亚洲综合色| 日韩AV毛片精品久久久| 久久久久久亚洲精品成人| 国产—久久香蕉国产线看观看| 亚洲日本va午夜中文字幕久久| 久久久久亚洲AV无码专区体验| 九九热久久免费视频| 久久精品午夜一区二区福利| 久久精品人妻中文系列| 亚洲欧洲中文日韩久久AV乱码| 久久美女人爽女人爽|