問題來源
最近在做服務器壓力以及並發測試,因為是C/S模型,所以需要自己模擬客戶端,需要運行大量的線程模擬並發,於是就碰到這個問題了。
另一個原因是,我在服務器中創建了一個線程池,我很想知道線程池的個數上限,從而更好的制定線程池動態增減的方法,所以也做了同樣的測試。
首先分析32位linux系統
對32位系統來說,理論上的尋址范圍是4G(2^32),但實際系統還要預留系統空間用於自身管理,一般來說真正的最大尋址范圍都要小於4G。對於Linux來說,一個進程擁有的用戶空間為0~0xBFFFFFFF,共3G,另外1G是內核空間;Windows的到0x7FFFFFFF,只有2G。(32位系統的尋址范圍還可以擴大,應用某些擴展標准,例如PAE,最多能支持到16G到64G不等。但這個情況不在我的討論范圍)。
一個LInux進程在用戶態最多訪問3G內存,每個線程必須占用特定大小的堆棧空間(stack size),這個因素使32位系統創建的線程數不可能超過n=3G/StackSize
注:Stack Size可以用ulimit -s查看,單位是k,同時這個size是可以設定的。
我的系統是ubuntu12.04,這個size是8192k
所以大致上一個用戶進程最對創建360左右的線程數。
Create thread 303
can't create thread: Cannot allocate memory
然后考慮64位系統
因為64位系統,沒有尋址范圍的限制,所以理論上,可以創建的線程數應該是幾乎無限的,除非其他條件限制。
但是,我在實際測試中,當創建線程數達到7500左右的時候,出現錯誤。但是原因一直沒能找到。
Create thread 7545
can't create thread: Resource temporarily unavailable
如何更改線程棧的大小
1.使用ulimit -s size命令,將線程棧大小臨時設置成size,單位是k
2.使用pthread_attr_setstacksize在程序中改變線程棧大小,單位是byte
3.運行程序的時候,是否以root運行,可以避免被限制資源
在64位linux下,增加線程數的方法試驗
1.使用ulimit -s,將線程棧大小改為1024k,最大創建線程數仍為7500,沒有改變,說明64位系統棧空間大小已經不再是限制了。
2.以root權限運行程序,發現線程可以運行數目達到1.5w級別,確實權限高,受限小一些,但是有風險。
3.使用ulimit -s改變線程棧大小,然后再以root權限運行,結果與2一樣,說明線程棧空間不是限制因素。
服務器並發的測試方法
1.首先編寫了客戶端程序,並進行單個測試,ok!
2.將客戶端程序改寫成多線程的,一個客戶端運行100個線程(線程是1中的程序改裝)
3.shell腳本並行運行2中的客戶端100次,那么就可以創造100*100的並發了。
4.一台機子可開啟的線程數受限,考慮N台同時運行,那么並發測試就可以N*100*100了。
5.如果客戶程序非長連接,還可以讓客戶端線程反復跑起來!