青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Fork me on GitHub
隨筆 - 215  文章 - 13  trackbacks - 0
<2016年3月>
282912345
6789101112
13141516171819
20212223242526
272829303112
3456789


專注即時通訊及網游服務端編程
------------------------------------
Openresty 官方模塊
Openresty 標準模塊(Opm)
Openresty 三方模塊
------------------------------------
本博收藏大部分文章為轉載,并在文章開頭給出了原文出處,如有再轉,敬請保留相關信息,這是大家對原創作者勞動成果的自覺尊重!!如為您帶來不便,請于本博下留言,謝謝配合。

常用鏈接

留言簿(1)

隨筆分類

隨筆檔案

相冊

Awesome

Blog

Book

GitHub

Link

搜索

  •  

積分與排名

  • 積分 - 220943
  • 排名 - 117

最新評論

閱讀排行榜

http://wqtn22.iteye.com/blog/1820587

1. 進程標志設置:

       消息和binary內存:erlang:process_flag(min_bin_vheap_size, 1024*1024),減少大量消息到達或處理過程中產生大量binary時的gc次數

       堆內存:erlang:process_flag(min_heap_size, 1024*1024),減少處理過程中產生大量term,尤其是list時的gc次數

       進程優先級:erlang:process_flag(priority, high),防止特殊進程被其它常見進程強制執行reductions

       進程調度器綁定:erlang:process_flag(scheduler, 1),當進程使用了port時,還需要port綁定支持,防止進程在不同調度器間遷移引起性能損失,如cache、跨numa node拷貝等,當進程使用了port時,主要是套接字,若進程與port不在一個scheduler上,可能會引發嚴重的epoll fd鎖競爭及跨numa node拷貝,導致性能嚴重下降

  2. 虛擬機參數:

     +S X:X :啟用調度器數量,多個調度器使用多線程,有大量鎖爭用

     -smp disable :取消smp,僅使用單線程,16個-smp_disabled虛擬機性能高于+S 16:16

     +sbt db :將scheduler綁定到具體的cpu核心上,再配合erlang進程和port綁定,可以顯著提升性能,但是如果綁定錯誤,反而會有反效果

  3. 消息隊列:

     消息隊列長度對性能的影響主要體現在以下兩個方面:進程binary堆的gc和進程內消息匹配,前者可以通過放大堆內存來減少gc影響,后者需要謹慎處理。

     若進程在處理消息時是通過消息匹配方式取得消息,同時又允許其它進程無限制投遞消息到本進程,此時會引發災難,匹配方式取得消息會引發遍歷進程消息隊列,如果此時仍然有其它進程投遞消息,會導致進程消息隊列暴漲,遍歷過程也將增大代價,引發惡性循環。已知模式有:在gen_server中使用file:write(raw模式)或gen_tcp:send等,這些操作都是erlang虛擬機內部通過port driver實現的,均有內部receive匹配接收,對于這些操作,最好的辦法是將其改寫為nif,直接走進程堆進行操作,次之為將file:write或gen_tcp:send改寫為兩階段,第一階段為port_command,第二階段由gen_server接收返回結果,這種異步化可能有些正確性問題,對于gen_tcp:send影響不大,因為網絡請求本身要么同步化要么異步化,都需要內部的確認機制;對于file:write影響較大,file:write的錯誤通常為目錄不存在或磁盤空間不足,確保這兩個錯誤不造成影響即可,同時如果進程的其它部分需要使用file的其它操作,必須首先清空之前file:write產生的所有file的port消息,否則有可能產生消息序列紊亂的問題。

     對于套接字的接口調用,可以參考rabbitmq的兩階段套接字發送方法,而對于文件接口調用,可以參考riak的bitcask引擎將文件讀寫封裝為nif的方法

  4. 內存及ets表:

     ets表可以用于進程間交換大數據,或充當緩存,以及復雜匹配代理等,其性能頗高,并發讀寫可達千萬級qps,并有兩個并發選項,在建立表時設置,分別是{write_concurrency, true} | {read_concurrency, true},以允許ets的并發讀寫

     使用ets表可以繞過進程消息機制,從而在一定程度上提高性能,并將編程模式從面向消息模式變為面向共享內存模式

  5. CPU密集型操作:

     erlang執行流程的問題:

       1. 其指令都是由其虛擬機執行的,一條指令可能需要cpu執行3-4條指令,一些大規模的匹配或遍歷操作會嚴重影響性能;

       2. 其bif調用執行過程類似于操作系統的系統調用,需要對傳入參數進行轉換,在大量小操作時損失性能較為嚴重

       3. 其port driver流程較為繁冗復雜,需要經歷大量的回調等,一般的小功能操作,不要通過port driver實現

     建議:

       字符串匹配不要通過list進行,最好通過binary;單字節匹配,尤其是語法解析,如xmerl、mochijson2、lexx等,盡管使用binary,但是它們是一個字節一個字節匹配的,性能會退化到list的水平,應該盡量將其nif化;

       對于一些小操作,反而應該去bif化、去nif化、去port driver化,因為進入erlang內部函數的執行代價也不小;

       已知的性能瓶頸:re、xmerl、mochijson2、lexx、erlang:now、calendar:local_time_to_universal_time_dst等

  6. 數據結構:

     減少遍歷,盡量使用API提供的操作

     由于各種類型的變量實際可以當做c的指針,因此erlang語言級的操作并不會有太大代價

     lists:reverse為c代碼實現,性能較高,依賴于該接口實現的lists API性能都不差,避免list遍歷,[||]和foreach性能是foldl的2倍,不在非必要的時候遍歷list

     dict:find為微秒級操作,內部通過動態hash實現,數據結構先有若干槽位,后根據數據規模變大而逐步增加槽位,fold遍歷性能低下

     gb_trees:lookup為微秒級操作,內部通過一個大的元組實現,iterator+next遍歷性能低下,比list的foldl還要低2個數量級

     其它常用結構:queue,set,graph等

  7. 計時器:

     erlang的計時器timer是通過一個唯一的timer進程實現的,該進程是一個gen_server,用戶通過timer:send_after和timer:apply_after在指定時間間隔后收到指定消息或執行某個函數,每個用戶的計時器都是一條記錄,保存在timer的ets表timer_tab中,timer的時序驅動通過gen_server的超時機制實現。若同時使用timer的用戶過多,則tiemr將響應不過來,成為瓶頸。

     更好的方法是使用erlang的原生計時器erlang:send_after和erlang:start_timer,它們把計時器附著在進程自己身上。

  8. 尾調用和尾遞歸:

     尾調用和尾遞歸是erlang函數式語言最強大的優化,盡量保持函數尾部有尾調用或尾遞歸

  9. 文件預讀,批量寫,緩存:

     這些方式都是局部性的體現:

     預讀:讀空間局部性,文件提供了read_ahead選項

     批量寫:寫空間局部性

       對于文件寫或套接字發送,存在若干級別的批量寫:

         1. erlang進程級:進程內部通過list緩存數據

         2. erlang虛擬機:不管是efile還是inet的driver,都提供了批量寫的選項delayed_write|delay_send,

            它們對大量的異步寫性能提升很有效

         3. 操作系統級:操作系統內部有文件寫緩沖及套接字寫緩沖

         4. 硬件級:cache等

     緩存:讀寫時間局部性,讀寫空間局部性,主要通過操作系統系統,erlang虛擬機沒有內部的緩存

 10.套接字標志設置:

     延遲發送:{delay_send, true},聚合若干小消息為一個大消息,性能提升顯著

     發送高低水位:{high_watermark, 128 * 1024} | {low_watermark, 64 * 1024},輔助delay_send使用,delay_send的聚合緩沖區大小為high_watermark,數據緩存到high_watermark后,將阻塞port_command,使用send發送數據,直到緩沖區大小降低到low_watermark后,解除阻塞,通常這些值越大越好,但erlang虛擬機允許設置的最大值不超過128K

     發送緩沖大小:{sndbuf, 16 * 1024},操作系統對套接字的發送緩沖大小,在延遲發送時有效,越大越好,但有極值

     接收緩沖大小:{recbuf, 16 * 1024},操作系統對套接字的接收緩沖大小

 11. 序列化/反序列化:

     通常情況下,為了簡化實現,一般將erlang的term序列化為binary,傳遞到目的地后,在將binary反序列化為term,這通常涉及到兩個操作:

     term_to_binary及binary_to_term,這兩個操作性能消耗極為嚴重,應至多只做一次,減少甚至消除它們是最正確的,例如直接構造binary進行跨虛擬機數據交換;

     但對比與其它的序列化和反序列化方式,如利用protobuf等,term_to_binary和binary_to_term的性能是高于這些方式的,畢竟是erlang原生格式,對于力求簡單的應用,其序列化和反序列化方式推薦term_to_binary和binary_to_term

 12. 并發化

     在一些場景下,如web請求、數據庫請求、分布式文件系統等,單個接入接口已經不能滿足性能需求,需要有多個接入接口,多個數據通道,等等,這要求所有請求處理過程必須是無狀態的,或者狀態更改同步進入一個公共存儲,而公共存儲也必須是支持并發處理的,如并發數據庫、類hdfs、類dynamo存儲等,若一致性要求較高,最好選用并發數據庫,如mysql等,若在此基礎上還要求高可用,最好選擇同步多結點存儲,

     mnesia、zk都是這方面的典型;若不需要較高的一致性,類hdfs、類dynamo這類no sql存儲即可滿足

 13. hipe

     將erlang匯編翻譯成機器碼,減少一條erlang指令對應的cpu指令數

http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=429659&id=5205993

本人主要從事游戲后端開發,所以本文只從游戲開發角度分析Erlang使用中應注意的問題和優化點。

  1.  單節點還是多節點

Erlang節點之間的通信是透明的,節點內部和外部之間的調用一致。基于這樣的特性,很多人會選用多節點,把各子系統(登陸節點,玩家節點,地圖節點,全局節點等)分配到不同的節點中,以支持更多的在線玩家。這樣做的出發點是好點是好的,但會引起一列表的問題:登陸、轉場邏輯復雜,節點間的消息廣播頻繁,玩家數據同步、一致問題,內存消耗,運維復雜化等。相比之下,單節點就簡單多了,不用考慮節點通信,玩家數據保證一致,運維方便,一機多服。在開啟SMP的情間下,單節點的性能已經很好。對頁游的業務,同時在線達到5000人已經非常少見,即使達到也是首服當天才會出現,單節點完全可以應付這樣的情況,所以沒必要用多節點,增加系統復雜性。

2. 消息廣播

消息廣播是游戲中的性能消耗大頭,主要包括地圖的行走、PK廣播,世界聊天廣播。世界聊天廣播可以通過CD等策劃手段限制,行走和PK包的廣播實時性高,只能通過技術手段解決。地圖中的廣播包,只需發給視野內的玩家就可以,不用全地圖廣播。視野內的玩家可以通過九宮格劃分,以 X,Y為主鍵,映射到對應的玩家數據。以九宮格方式查找玩家非常高效,我第一個游戲,地圖中的玩家起初是保存在一個列表中,每次廣播時都要遍歷列表,找出同屏玩家,消息廣播非常低效,特別是在PK時,CPU占用高。用九宮格優化后,一切問題都解決了。還有一個優化廣播問題的方法是數據包緩存。

3. 緩存-數據庫,網絡

緩存是用空間換時間,它是性能優化中常用的方法。數據庫緩存,開服時把玩家的必要數據加載到內存中,可以減少玩家的登陸延時,應對玩家并發登陸,刷新也很有效。同時玩家數據沒必要實現存庫,對于坐標,經驗,金錢等變化頻繁的值,如果實時存在,會很容易壓跨數據庫或對存庫進程造成消息阻塞。玩家改變的數據可以緩在內存中,定時存庫,或下線時再存庫。網絡中的消息包也可以在應用層給緩存起來,達到一定長度或延時一定時間后再發出去。雖然虛擬機和TCP層會做緩存,最好還是在應用層做一次緩存。

4. 進程-每玩家應該有幾個進程

其實每玩家一個進程已經足夠,代碼簡單,方便維護,性能開銷小。沒必要為每個玩家開啟了網絡,物品、任務等進程,多個進程不但造成進程間通信開銷,還不好維護。

5. 善用進程字典

Erlang中是不建議用進程字典的,但進程字典是數據存取最快的方式,對于游戲這種高性能要求的應用,進程字典是不二的選擇。使用進程字典時要切記在對應的進程中操作,最好按功能把put,get操作封裝到模塊接口中,避免誤用。

6. 代碼規范

a. 代碼應該簡單,邏輯清晰,把功能細分到函數中。函數一般不多于30行,每個模塊不多于1000行。

b. 寫尾遞歸函數一定要有清淅的退出條件,不要在函數中改變退出條件。一個退出條件不明確的尾遞歸,是造成消息阻塞,內存耗盡的主要原因之一。


  1. %% 一個明確的尾遞歸函數:
  2. loop([H |T]) ->
  3.     do_something,
  4.     loop(T);
  5. loop([]) ->
  6.     ok.

  7. %% 存在錯誤風險的寫法
  8. %% NewLiist不可預期,存在死循環風險
  9. loop([H | T]) ->
  10.     NewList = do_something(H,T),
  11.     loop(NewList);
  12. loop([]) ->
  13.     ok.

c.  不要相信客戶端,上行的數據都需要驗證,前端的請求都要做合法性判斷,防止出現外掛、刷錢刷物品、刷金幣的情況。

d 不要寫過多的case ,if嵌套,最好不要大于3個嵌套,通過 try catch 方法寫扁平化的代碼。

7. 自動化工具

自動化工具可以避免出錯,還把開發人員解放出來,提高生產效率。對于重復性,有規律的代碼(如數據存取,通信協議),可以分離出來,讓工具自動生成。有了生成工具后,修改協議,新加字段等操作,簡單方便,不用為增加數據表中一個字段,而改十多個函數接口的修改;也不用擔心前后端協議不一致的問題。

8. 監控系統

通過erlang:system_monitor/2,監控系統long_gc,large_heap等情況。

9. 性能分析工具

準備好top memory,top message_queue等查看系統屬性的工具,出問題時可以隨時查看。

本文鏈接:http://www.kongqingquan.com/archives/221 

 

這幾天在弄個ERLANG的長連接測試程序,主要是要在一個服務器上建20萬條長連接.

于是找到了以下內容.

---------------------------------------------

前些天給echo_server寫了個非常簡單的連接壓力測試程序,

代碼:
  1. -module(stress_test).
  2.   
  3. -export([start/0, tests/1]).
  4.   
  5. start() ->
  6.     tests(12345).
  7.   
  8. tests(Port) ->
  9.     io:format("starting~n"),
  10.     spawn(fun() -> test(Port) end),
  11.     spawn(fun() -> test(Port) end),
  12.     spawn(fun() -> test(Port) end),
  13.     spawn(fun() -> test(Port) end).
  14.   
  15. test(Port) ->
  16.      case gen_tcp:connect("192.168.0.217", Port, [binary,{packet, 0}]) of
  17.     {ok, _} ->
  18.             test(Port);
  19.     _ ->
  20.         test(Port)
  21.     end.
 
一開始我的這個stress_test客戶端運行在windows上面, echo_server服務器端運行在linux上面。 結果接受了1016個連接就停止了. 于是我用ulimit -n 改了服務器端的文件描述符數量為10240. 接著還是如此,折騰了幾天,最終還是沒有搞明白。

于是就求助于公司的linux編程牛人,結果讓我一倒...  客戶端沒有修改文件描述符個數. windows上得在注冊表里面改.
牛人開始對這東西的性能感興趣了,剛好我摸了一陣子erlang的文檔,于是我倆就走向了erlang網絡連接的性能調優之旅啦~~過程真是讓人興奮。 我們很快通過了1024這一關~~到了4999個連接,很興奮.

但為什么4999個連接呢, 檢查一下代碼終于發現echo_server.erl定義了一個宏, 最大連接數為5000. 我又倒~~
修改編譯之后, 連接數跑到101xx多了, 太哈皮了!
再測102400個連接時,到32767個連接數erl掛了~說是進程開得太多了. 好在記得這個erl的參數+P,可以定義erlang能生成的進程數. 默認是32768. 改了!

后面不知怎么著,在81231個連接停止了. 新的性能瓶頸又卡了我們.  好在牛人對linux熟, 用strace(這東西會莫名地退出), stap查出一些苗頭.   我也想到在otp文檔好像提過另一個limit,那就是端口數...在此同時我們發現erlang在linux上是用的傳統poll模型. 但查erlang的源代碼發現是支持epoll的. 在網上搜了半天,終于搜到了個maillist的帖子.
代碼
  1. $./configure --enable-kernel-poll  

由于我們的測試服務器是雙核的,我們在配置的時候也打開了smp支持.  歡快的make  & make install之后....
把 /proc/sys/net/ipv4/ip_local_port_range 的內容改成了1024到65535.  最多也也能改成65535 :)

代碼
  1. $echo 1024 65535 > ip_local_port_range  

另外再添加一個erl的環境變量

代碼
  1. $export ERL_MAX_PORTS=102400  

于是開始跑了,不過這次跑不一樣了

echo_server
  1. $erl -noshell  +P 102400 +K true +S 2 -smp -s echo_server start  
stress_test
  1. $erl -noshell  +P 102400 +K true +S 2 -smp -s stress_test start  

這里的+K true,表示使用內核poll,+S 2 表示兩個核. 這樣可歡快啦~~~ 10w大關過咯! 而且比剛才沒用epoll的速度快暴多~~
于是我們又開始了204800個連接發測試了~~~

用top一看cpu占用率極低,服務器只在5%左右。 內存也不是很大~~

來源:  http://www.lupaworld.com/tutorial-view-aid-10191.html


posted on 2016-03-28 08:21 思月行云 閱讀(3576) 評論(0)  編輯 收藏 引用 所屬分類: Erlang
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            中文国产成人精品| 亚洲视频999| 欧美日韩国产成人在线91| 欧美一区视频在线| 亚洲免费视频在线观看| 欧美一区三区三区高中清蜜桃| 亚洲一区二区三区精品在线 | 欧美不卡高清| 欧美激情国产日韩精品一区18| 亚洲国产精品123| 亚洲第一精品福利| 夜夜嗨av色一区二区不卡| 99在线|亚洲一区二区| 中文在线资源观看网站视频免费不卡 | 欧美日韩国产一中文字不卡| 欧美日韩第一页| 国产农村妇女精品一区二区| 在线免费观看日本一区| 一本色道久久加勒比精品| 久久aⅴ国产欧美74aaa| 欧美成年人视频网站| 一区二区日韩| 久久夜色精品国产欧美乱| 欧美日韩国产小视频| 国产日韩欧美不卡| 99热在线精品观看| 久久黄色网页| 99精品国产一区二区青青牛奶| 欧美与黑人午夜性猛交久久久| 欧美高清在线视频观看不卡| 国产精品任我爽爆在线播放| 亚洲高清资源| 欧美在线一级视频| 一本色道久久综合亚洲精品不卡| 老牛嫩草一区二区三区日本| 国产精品亚洲а∨天堂免在线| 亚洲精品乱码久久久久| 久久久亚洲综合| 亚洲影院高清在线| 欧美色综合网| 日韩亚洲国产精品| 久久综合五月| 久久精品国语| 国产午夜精品一区理论片飘花| 在线中文字幕日韩| 欧美亚洲一区在线| 欧美高清视频一二三区| 亚洲欧美一区二区原创| 欧美日本韩国一区| 亚洲人体一区| 欧美激情女人20p| 久久婷婷色综合| 国产日韩精品一区| 午夜精品久久久久久久男人的天堂| 亚洲国产欧美精品| 欧美成人在线免费观看| 亚洲国产精品女人久久久| 久久综合狠狠综合久久激情| 午夜精品久久久久久久99樱桃| 国产精品大全| 免费观看国产成人| 国模大胆一区二区三区| 欧美一区二区性| 亚洲免费视频在线观看| 国产精品丝袜白浆摸在线| 中日韩在线视频| 亚洲色在线视频| 国产日韩精品在线| 久久久九九九九| 久久夜色精品一区| 日韩午夜av电影| 99精品视频免费| 国产精品一区二区三区成人| 久久大逼视频| 久久久久久久网| 亚洲精品一区二区三区在线观看| 最新69国产成人精品视频免费| 欧美激情按摩| 亚洲一区二区三区午夜| 亚洲欧美综合一区| 悠悠资源网久久精品| 亚洲福利国产精品| 国产精品美女久久久| 性做久久久久久免费观看欧美 | 99成人在线| 国产日韩精品一区| 欧美黄色大片网站| 国产精品久久999| 美日韩精品免费观看视频| 免费日韩成人| 亚洲免费网站| 久热精品视频在线| 亚洲尤物视频网| 久久噜噜噜精品国产亚洲综合| 亚洲福利小视频| 亚洲色图综合久久| 在线观看中文字幕不卡| 亚洲久久在线| 国产亚洲激情视频在线| 亚洲精品偷拍| 在线成人免费视频| 亚洲自拍偷拍色片视频| 91久久久亚洲精品| 性欧美大战久久久久久久免费观看 | 久久成人精品无人区| 久久久久久久999| 亚洲一区二区欧美日韩| 久久久久久高潮国产精品视| 中文在线资源观看网站视频免费不卡 | 久久久久久久网站| 欧美一区永久视频免费观看| 免费看亚洲片| 久久精品一区中文字幕| 欧美久久久久久| 久久亚洲色图| 国产精品一区免费在线观看| 亚洲国产精品国自产拍av秋霞 | 欧美黄免费看| 久久国产精品久久久久久久久久| 欧美激情一区二区三区成人| 久久精品女人的天堂av| 国产精品天天看| 亚洲伦理在线免费看| 亚洲国产精品成人综合色在线婷婷| 亚洲欧美日韩精品在线| 亚洲综合精品四区| 欧美午夜一区二区三区免费大片 | 香蕉久久夜色| 久久成年人视频| 国产精品综合视频| 亚洲自拍偷拍麻豆| 欧美自拍偷拍| 国产在线国偷精品产拍免费yy| 亚洲男人第一网站| 欧美一区二区三区视频免费| 国产精品你懂的| 亚洲中午字幕| 久久精品在线播放| 激情懂色av一区av二区av| 久久激情网站| 欧美成人精品福利| 亚洲精品日本| 欧美日韩三级| 亚洲免费视频观看| 久久亚洲不卡| 亚洲人成在线免费观看| 欧美日韩国产麻豆| 亚洲伊人一本大道中文字幕| 欧美在线观看一区| 狠狠色综合网站久久久久久久| 欧美一区二区视频观看视频| 久久久亚洲高清| 亚洲高清不卡| 欧美日韩一区视频| 午夜精品美女自拍福到在线 | 激情久久五月| 欧美激情久久久久| 亚洲一区精品在线| 久久久久久久一区| 亚洲日本一区二区| 国产精品久久亚洲7777| 欧美中文字幕在线播放| 校园春色国产精品| 艳女tv在线观看国产一区| 欧美日韩理论| 欧美一区二区三区播放老司机| 久久精品官网| 日韩一级成人av| 国产精品日韩在线| 久久噜噜噜精品国产亚洲综合| 亚洲激情网址| 久久精品免费看| 一区二区高清| 国产亚洲精品资源在线26u| 欧美高清影院| 欧美在线精品免播放器视频| 亚洲激情另类| 久久婷婷国产综合精品青草| 一本色道久久综合一区 | 久久亚洲图片| 中文久久乱码一区二区| 欧美 亚欧 日韩视频在线| 亚洲欧美日韩在线观看a三区| 好吊日精品视频| 欧美日韩亚洲一区三区 | 国产一区二区日韩| 欧美另类视频| 六月婷婷一区| 校园春色综合网| 一本色道久久综合亚洲精品高清| 蜜桃久久av| 久久www成人_看片免费不卡| 日韩午夜中文字幕| 亚洲国产综合视频在线观看| 国产精品综合色区在线观看| 欧美精品91| 欧美国产综合视频| 美日韩精品视频免费看| 久久精品人人做人人爽| 亚洲私拍自拍|