為什麼多數遊戲服務端是用 C++ 來寫呢,是歷史原因還是性能方面的考慮?
遊戲也分不同領域,不同的遊戲之間業務邏輯和適用架構區別很大,並不能一概而論。
比如對於大部分手游、頁游來說,追求短平快的開發節奏也不要求太高的實時性和計算效率,C++在這些領域的使用屬於殺雞用牛刀。國內這些領域還採用 C++ 的團隊,要麼是技術決策者視野狹窄;要麼是大廠成熟團隊已有完善的遺留技術棧、工具鏈和人才儲備,遷移到其他語言的收益相對不高,或是怕擔轉型決策風險等等;再有就是從大廠出去創業順走了技術框架或迷信大廠經驗的團隊等。
題主特別提到 MMORPG ,此處就 MMORPG 這一領域為何普遍使用 C++ 進行簡單討論。
下文所說的 MMORPG,主要是指在地圖上實時戰鬥一類(比如 WOW、傳奇等),不包括回合制 MMORPG (神仙道、夢幻西遊等)。
常見 MMORPG 伺服器在技術層面的特性需求:
- 網路IO密集。高頻率的視野同步消息(一般在 10-60Hz 之間),與玩家數量的關係是 O(n^2) 的複雜度,對於一些側重國戰等玩法的 MMORPG 尤其壓力山大。通常都需要配合相關視野管理演算法來減少消息發包數量,甚至需要配合架構做廣播的負載分流。
- CPU密集。MMORPG 的玩法規則都需要伺服器做權威性的計算,簡單些的也需要大量怪物的 AI 和尋路計算,以及實時戰鬥的邏輯和技能運算等等;一些先進的 3D MMORPG 伺服器甚至整合了物理引擎,來做碰撞檢測和校驗。
- 實時性。此類遊戲側重實時戰鬥和交互體驗,能容忍的響應延遲通常在 200ms 以內,即使可以通過客戶端預演算進行緩和。考慮到網路延遲這個不能通過語言和架構來解決的要素,兩次遊戲邏輯更新發包的間隔最好控制在幾十毫秒這一量級。(所以一些 GC 不太注重實時性的語言,可能會有潛在的負面體驗影響)。
- 穩定性和容災。常 Crash 的伺服器,輕則影響玩家體驗,重則導致公司倒閉。
- 開發效率。這個方面除了受語言特性本身影響,還需要考量其它要素,比如生態圈豐富程度(需要的功能可以容易找到穩定好用的庫)、周邊工具鏈完善程度、人員補充難易程度(是否是學校培訓的主力語言、是否是領域比較主流的語言,或者是否足夠簡單好培訓)、現有遺留人力和技術資源的價值等等。
C++ 和其它候選語言的比較
C++:
- 網路 IO:歷史上這方面曾經是考量的主要因素,近年來幾乎所有主流後端語言都封裝有高效的網路 IO 庫,C++ 已不具備獨特優勢。
- CPU 利用率:C++ 在這方面的優勢不需要討論了吧...
- 實時性:無 GC,內存分配延遲可控(內存池、預分配等),毫秒級延遲需求的高頻交易都在用。
- 穩定性和容災:用 C++ 寫出長期穩定運行的伺服器程序,對開發團隊而言是件要求比較高的事情,尤其在邏輯複雜又變更頻繁的前提下。語言本身也不保證內存訪問的安全性,如果有內存寫越界導致的 Crash 也很難定位。國內某大廠採用了分離數據和邏輯進程,通過進程間共享內存來通信的方式,來實現邏輯進程崩潰重啟不丟失數據。不過這種做法有一定門檻,存在性能開銷,而且對開發效率和靈活性也有比較大的約束,也不易整合第三方庫,不能算是通用的最佳實踐。
- 開發效率:如果有良好的內力和 C++ 編程素養,並且配合現代 C++ 的一些語法(auto、lambda、智能指針等),開發效率尚可算是勉強及格,但相對以下討論的其他語言來說仍處於劣勢,然而達到上述水準的人力資源成本卻要比其它語言要高出不少(人員補充速度、培訓周期和薪資)。綜合而言,這方面可算 C++ 的一大短板。
那麼,假設不採用混合語言的方案(C++ 配合 Lua 或 Python,或者多服架構不同伺服器用不通語言 等),除了 C++ 之外還有哪些語言值得考慮?
考慮到 MMORPG 在 CPU 計算方面的壓力,解釋型語言暫且可以排除。
目前答主考察過的備選方案,主要有 Java、C#、Go、Rust。
Java:
優點:
- 生態圈成熟,庫豐富。
- Netty 網路庫性能強悍。
- 不爽語法還可以用 scala 和 kotlin...
缺點:
- 除了原始類型外,不支持自定義值類型。而且泛型是以類型擦除的方式實現。這樣的特性導致了:1.難以把數據連續緊湊地進行表示來優化演算法的緩存命中率,比如2D地圖的每個格子坐標都是個object,尋路演算法呵呵。3D 場景的碰撞體每個頂點都是個object,物理引擎呵呵。2.對原本對實時性不甚友好的 GC 造成了更大壓力。
- 成熟的 JVM 實現並不怎麼側重 GC 的實時性。如果觸發了百毫秒以上的世界凍結 GC 延遲,所有在線玩家都會受到影響。
- JIT 在預熱不足的情況下,偶爾會導致性能曲線不平滑,引入預料之外的響應延遲。
C#:
優點:
- 開發友好,語法糖甜。
- 有真正的泛型和值類型。特定演算法好優化。
缺點:
- 微軟家的。微軟家的。微軟家的。跑在 Windows Server 下沒什麼問題,然而拋開授權費不談,大部分主流的開源好物都是優先考慮 Unix / Linux,比如 Redis(長期沒有 Windows 版本的官方支持)、MongoDB(Windows 下性能要弱於 Linux 下),而且 Windows Server 的網路性能也要弱一些。除非解決方案都用微軟全家桶,不然部署和運維就需要同時維護兩個平台...至於 Mono,跟 JVM 比起來就像玩具。只能期待 Rosalyn 成熟了。
- GC 實時性類似 Java。
Go:
優點:
- 語法簡單易掌握。
- 開發體驗友好。
- 有值類型。
- 新版本的 Go,GC 實時性良好(1.8 號稱 STW 控制在 1ms 以內)。
缺點:
- 沒有范型,某些地方需要轉型成 interface{},不過編譯器會做逃逸分析,不必要的地方不會自動 boxing,影響不算太嚴重。
Rust:
優點:
- 運行效率比肩 C++。
- 語言特性優秀。
- 編譯期保證了內存安全,沒有 GC 開銷。
- 編譯期保證線程安全,可以放心大膽地並發,容易寫出高效的多線程代碼(不過死鎖是需要自己避免的)。
缺點:
- 上手曲線較陡。
- 太年輕,生態圈尚未成熟。
- 較小眾,人員補充困難。
綜述
大部分 MMORPG 主要採用 C++ 並不是沒有原因 ,雖然歷史原因的比重不小。然而如果要在什麼都沒有的情況下,從零開始開發 MMORPG 伺服器,採用 C++ 並無必要。拋開人才儲備的方面不談,Go 算是目前開發 MMORPG 伺服器各方面特性都比較匹配的選擇:無論開發效率還是運行效率,以及工具和人員培訓速度等等。如果是技術導向的團隊,可以試試 Rust。C# 和 Java 也是不錯的選擇,雖然有些特性不是很好滿足,但也足夠支撐一款遊戲成功了(如果不追求提供極致的平滑體驗的話)。
至於 C++,在具備一些前提條件的情況下可以考慮採用:已有成熟 C++ MMORPG 代碼框架;已有 C++ 寫得 666 的技術團隊;不差錢也不趕進度,就要質量稍高一些的流暢體驗;需要整合一些 C++ 庫等。不過即使如此,C++ 也推薦搭配其它語言使用(比如早幾年常見搭配 Lua,主要用來提高迭代速度和開發效率,並且一定程度上可以支持熱更)。
我來說兩句吧:目前幾乎沒有純粹的 C/C++開發遊戲服務端的。
早年開發遊戲必須用C++,這沒得說,2000-2004年,java還沒有nio,其他動態語言不抗重負,只能C/C++能開發出完整可用的遊戲服務端。直到2005年,韓國的遊戲很多都還是純C++寫服務端,金山之前也開發過很多純粹C++的遊戲服務端,後來大家都切了。
現代選擇有很多:java + javascript, c+python, c+lua, scala, go, erlang。我們面向性能的伺服器用 java,面向邏輯伺服器 python,面向高並發的會選擇 scala,次一級高並發或者性能測試程序(機器人)會選擇 gevent。那是不是我們就不用C++呢?我們用 C來做網路,不用C++,但是C的比例在所有代碼中佔比有限。
這是否意味我們可以放棄C/C++了?也不是:C語言是一把鋒利的匕首,而現代動態語言是一把長劍。平時匕首可以藏在身上,大部分時候用長劍披荊斬棘就夠了,但當你碰到堅硬的石頭,長劍不管用了,那麼拿出匕首來果斷的切碎他。
對於一個成熟領域而言,我的建議是盡量用更高級一點的開發語言,因為遊戲開發很多核心技術都有了較為妥當的解決方法。大量的服務端邏輯其實都是在等待,等待網路,等待資料庫,這種情況下用C得不償失。但是服務端有一些地方還是躲不開C/C++,比如當伺服器涉及到 3D計算的話(國內很多2D服務端,國外很多3D服務端),大量的矢量矩陣,除了用C++封裝出一套好用的數學庫外,即便直接用java寫,那也是很麻煩的。再比如現在快速動作越來越多,為了讓玩家操作更流暢,我需要基於 UDP快速可靠協議,協議開發用 java或者scala,性能上是沒辦法滿足要求的,況且協議實現後要和客戶端通信,你沒法讓所有客戶端跟著你一起用java/scala。再比如某些cpu密集的抽象度高的模塊,如 aoi或者 ai模塊。
對於一個新興領域而言,C/C++很多情況下是你別無選擇的東西。比如移動化浪潮剛起步的時候,還沒有啥 cocos或者 unity你真要開發遊戲,你必須迅速的使用起 OpenGL ES和 OpenSL,然後再疊加某一腳本,以快制勝,第一批移動浪潮上發財的就是這些遊戲。又或者,你可以根本躲開,先不介入,等到幾年後cocos和 unity成熟了,你在介入用lua / C#寫程序。再比如服務端你如果離開熟悉的遊戲和web,去開發一個陌生的領域,如流媒體服務,你會發現這怎麼和10年前的遊戲一樣呀,什麼高級工具都不給我用用,這時你可以再等個四五年應該高級工具會出現,異或你想領先別人時,你就果斷的拿出 C/C++來解決之,這就是C獨有的開拓新領域能力。
大部分答案都是非黑即白,非此即彼。不要只會C不會動態語言,避免成為一個傻逼;也不要只會動態語言不會C,避免離開熟悉的溫室就活不下去。對於一個新手而言,如果什麼都沒學過,我的建議是先用快速開發的東西,把項目弄起來再說,有精力有機會的情況下,也不能完全放棄一些基礎的東西,讓自己殘缺了。
PS:在相同架構下,就純粹性能而言,各種語言性能差距到底是多少呢?如果只開發回合制這些慢節奏遊戲,或者HTTP介面,大部分情況都在等待資料庫等待用戶消息的話,差別確實不大,的確可能5%都不到。如果cpu密集了,那麼可以參考下面的圖表,總體來說是10-50倍的性能差別:
有人問,說了半天,這個也不行,那個也不完美,而我時間有限,有沒有一個更經濟實惠的方法呀?如何才一次性達到彼岸呀?時間有限項目吃緊有沒有更好的選擇?我說有啊!那就是 java。
國內遊戲開發繞來繞去還是腳本+C+erlang+go,難道大家就不會其他東西了么?大部分可以的情況下,除了非用C/C++,我推薦各位認真考慮下 java,這個性能上最接近C的東西,能承當大部分cpu密集型事務,卻又不會象c那樣 crash了找都找不到問題在哪裡。同時面向高並發時基於原生jvm的 scala可以提供類似 erlang的簡單方式,函數式編程 大規模並發協程 actor;同時 java可以很方便的同 javascript結合,js的速度應該是動態語言裡面最快的吧。再者 java還有 groovy,可以提供 python/ruby的泛型編程,用超高的開發效率和 python/ruby媲美,同時還能和 scala 結合實現高並發。最重要的是寫 java好招聘,到處都是寫 java的工程師,大部分語言級的培訓都可以省略了。
國內遊戲開發者很多拒絕學習 java,因為很多開發者自己是碰都沒碰過。現在拒絕 java的人,大部分只是在遊戲圈子裡面打轉的人,偶爾開發下 web,缺乏其他行業和領域的經驗。看看除遊戲外,當今多少世界級的開源伺服器是用 java開發的?遊戲就真有那麼特殊么?我看不是,國外大把java開發的遊戲服務端,各位如果知道遊戲服務端領域有啥 java技術棧解決不了的事情,麻煩告訴我一聲。再看看java上下游的 scala, javascript, groovy這些東西。所以建議各位,有空有條件的情況下,認真考慮下 java技術棧,世界很大,不是只有遊戲;即便遊戲,現在的開發方法真的對嗎?
---------------------------------------------PS,剛才又了解了一下,原來國內最近這兩年用 java開發遊戲伺服器是越來越普遍了,比我之前想的還多,這是好事情呀。距這個問題提出已經有三年過去了,好像這個狀況還是沒什麼大變化,究其原因,無非是兩點,潮流和領域特點。
硬體水平是在不斷提高的,內存變得更大,IO設備的能力更強,CPU頻率好像快觸到天花板,可是已經到了一般的程序根本榨不幹的程度。於是各種設計開始消費硬體發展帶來的福利,代碼不用動,換個SSD,輕輕鬆鬆降低一倍延遲,那代碼上的優化為什麼還要做那麼好?
可是歷史從來是螺旋式的發展,硬體發展==&>應用消費==&>碰觸瓶頸==&>應用優化==&>碰觸硬體瓶頸==&>硬體發展。關於這點,看看上世紀那幾個設計超前的語言就知道了,現在很多新設計無非拾人牙慧。
c++也不是一成不變的。
大概三四年前我覺得boost::function這種東西好重啊,可是這兩年c++11開始普及,我立刻轉投c++11的懷抱,多一層封裝什麼的在編譯器優化面前不值一提。這幾年的c++開始變得越來越好用,開發效率也完全不是問題,除了反射之外,其他我開發中需要的feature幾乎都有了。
技術選型這件事,除了政治原因之外,幾乎是潮流決定的,潮流決定語言怎麼轉變,決定大家怎麼開發,遊戲的服務端一開始有很多人用c++編寫,那c++在這個領域的積澱也就深。再舉個例子,Python、Ruby這麼好用,這麼容易寫,門檻幾乎談不上,可是在運維這個領域,還是喜歡用shell,即便shell這種面向字元串編程的模式為很多運維人員所不齒,但是在浪潮興起的時候,這個領域積澱了太多shell相關的東西,想改,就不那麼容易了。
領域特點就更加明顯了,即便遊戲端也不是完全流行c++的,很多無關乎性能的地方,大家依然喜歡用各種腳本,shell、Python以及這些年流行起來的Lua等等。但是引擎部分,c++太過普遍,有出於性能上的考慮,也是因為歷史上這方面的積澱。
還有哪些領域在用c++呢?網路設備、資料庫、圖形引擎、實時系統等等。至於使用的原因呢,一是性能上的需要,一是在這個領域相應的基礎設施相對完善。各位在討論用Java開發遊戲伺服器的同時,也要看到有一些業務已經把協議棧搞到了網卡上,需求是選型的一大重要因素。
c++是個龐大而奇怪的語言,很多新領域會選擇這個語言是因為有性能上的需求,但是又拿不準瓶頸會出在哪裡,c++是一個什麼地方調優都很方便的語言。我以前經常噎那些喜歡過度優化的人說「你怎麼不寫彙編呢」,直到上個月,給程序調優的時候發現一個compare函數平均每秒會被調用500W次,我不得內聯了一個彙編來優化它。雖然不是什麼地方都需要面向性能編程的,但是發現瓶頸之後能不能方便的解決掉,是一個非常重要的問題。
經過近幾年發展,c++開發效率也不算低,雖然對新人依然不怎麼友好,但是從技術選型的角度來看依然是很多領域的不二之選。
我又是來講段子的,端游不熟,我說的是頁游手游,我們遇到其他團隊說自己伺服器負載能力不好,總開玩笑問,你們伺服器是java的吧。。。。。
然而。。。。
可悲的是,大部分這個語境下,對方回答,是的。。。。java並不一定註定慢,c不一定註定快,關鍵是程序員。。。。。。。
問題是太多java程序員半吊子還喜歡搞各種奇技淫巧的設計模式,c程序員玩奇技淫巧的相對少一點。。。。我自己更推崇混合編程,適合c的用c,適合腳本語言的用腳本。
感覺很多人對C++的看法根本是道聽途說或者想當然的啊……
也就是所謂的諸如
- c++開發效率低
- c++語言複雜臃腫- c++難以維護,容易出錯- c++只適合開發需要極端壓榨性能的程序,但是現在硬體性能溢出blahblah種種如此……
很多人根本不知道c++開發並不需要用到c++的所有特性,只需要根據情況運用其中的一小部分就好了
很多人根本不知道c++在有完整編譯環境支持下維護效率要比腳本類語言高到不知那裡去了
很多人根本不知道開發效率只和程序員的技術水平有關
很多人根本不知道現在硬體性能遠遠談不上溢出的程度,說句難聽的,家用PC連個4k VR都得頂級配置還帶著吃力,更別說伺服器端動輒上萬的並發
(原來反對的高贊已經看不到了。。)答案純屬鬼扯,不像是搞過遊戲服務端的。
為什麼都用C++做遊戲服務端?
因為用C++做遊戲服務端簡單。這裡說的簡單,並不是指C++這門語言簡單,而是說,對於遊戲服務端開發來說,你用C++來做,可以在領域知識積累的不夠多的情況下,也能做出一款在線數量能滿足上面要求的服務端框架。
十年前,遊戲剛成為朝陽產業的時候,網上流傳C++實現的遊戲服務端框架的趨勢逐漸蓋過老的mud遊戲用的那種單點lpc,大部分都是一個IO線程一個邏輯線程裸跑,客戶端直連各種GameServer/SceneServer/ZoneServer(都只是邏輯伺服器的代號而已),後端再接個。試想,如果你的程序員只會這樣一種簡單架構,那是不是唯一能往上跑性能的點只在這個語言的效率本身了?那為什麼不能用C++來寫遊戲服務端?先定義下什麼叫遊戲服務端。
網路IO層不應該算遊戲服務端。一般目前現存的、服務端代碼中有C++的團隊,所謂的用C++,用的最多的地方其實就是網路層。但是一個網路層用C++,其他的邏輯部分用C++去驅動腳本,這種算不算C++開發的遊戲服務端呢?我覺得不算,mono的網路層也用C++,但是我上層可以用C#,可以用F#。各種虛擬機的runtime裡面,網路層也都要麼是C要麼是C++,但是我上層用的是其他語言並不是C++。這樣來看,我用其他語言寫邏輯+C++寫網路層和部分底層,性能上跟專業團隊維護的runtime會有本質區別嗎?至少在性能上並不是數量級的區別。那用C++來寫服務端會有什麼弊端呢?
- 用C++寫邏輯簡直是反人類,實現同樣一個功能代碼量多N倍。
- C++邏輯出了bug就是能core掉你一組伺服器的bug。項目團隊大了+再牛逼的人也會有腦抽的時候,線上伺服器隨時都有core掉的風險。
- 早期端游沒多少的時候,是賣方市場,你的遊戲掛了我玩家就沒其他遊戲可玩了。後來端游是買方市場,你的遊戲掛了我只要付出成本沒多少我一個不爽就換另一款跟你品質差不多的遊戲去了。所以熱更新已經成為大廠端游標配。純C++服務端怎麼熱更新?所以你會聽說到/看到騰訊大批老的純C++寫服務端的頁游、端游熱更新的唯一辦法是快速重啟。
還有一點是高票答案比較扯淡的,所謂遊戲是極度壓榨硬體性能的。
這個對於端游來說,客戶端部分確實是,但服務端並不是。正是因為受限於客戶端,所以你服務端做單節點上萬人是沒有意義的,同屏了才有強交互的強烈需求,不同屏的話我幹嘛自己找罪受?
現在不是十年前了,分散式洗禮遊戲行業也已經不是一年兩年了。把時間花在節點拆分上的回報率遠高於花在單節點在線上。IO線程和邏輯線程的消息隊列整各種奇技淫巧的lock-free演算法?好吧你寫了個看起來沒bug的,單節點網路報吞吐量提高了5%。那我把AOI和AI拆成單獨的節點好了,整個集群的壓測數據提高了50%。那現在為啥還有團隊招C++程序員呢?
先看下傳統C++端游團隊的心路歷程:團隊擴張,要招點業務邏輯狗。C++邏輯程序太特么難招了,低薪程序員成天core,高薪程序員不願意做業務邏輯狗。怎麼辦?改改改。擔心性能?那我IO線程不改了,還用C++;AOI不改了,還用C++。邏輯線程主循環雖然跑的還是C++,但是python/lua各種侵佔的邏輯模塊越來越多,一開始可能只是小範圍嘗試,後來發現:咦?性能影響不是特別大嘛,慢慢的C++那塊代碼已經沒人敢動也沒人想動了。再不濟,招個大廠出身的、用過bigworld的來做「架構師」,借鑒點大廠泄露出來的ppt講座什麼的,也來搞一組可以熱擴展的gate,db前面也掛一組可以熱擴展的proxy,再配合一下分線,性能問題還算問題嗎?這就是目前國內大部分老的端游團隊,所以他們招人的時候為什麼喜歡問C++呢?因為他們以前搞C++的對C++熟,C++當面試題逼格高,C++當面試題對老C++程序員簡單,面試前一晚翻一本《Inside C++ Object Model》能問翻80%,再隨便看看C++新特性,能再問翻15%,剩下的5%是什麼?也只剩搞編譯器的了吧?咦說好的業務邏輯狗呢?
好吧,那究竟該用什麼語言寫遊戲服務端呢?
用你喜歡的語言就行。大概分下類:第一類。C++叉某種腳本。優點:一般是大廠職位,技術積累雄厚。缺點:底層部分碰不得。即使有代碼你也不敢改,很多都是線上跑過幾年的,即使發現有bug你敢改嗎?第二類。各種actor模型的服務端開發框架。比如直接Erlang,比如雲風的skynet。
優點:大部分搞遊戲服務端的程序員思維是比較傳統的,只認邏輯線程+IO線程的死理,他們雖然沒用過actor,但就是覺得MMO拆成actor不靠譜。但是程序員的初心應該就是學習新知識,所以你到這種團隊可以遠離沒初心的程序員接觸有初心的程序員。缺點:基本上是限定工作城市在廣州了。那現在還有純C++寫服務端的遊戲嗎?真的難找了。題主思考這樣幾個問題:廣州頁游圈多少Erlang的?skynet群里已經有多少實際使用並上線的遊戲?騰訊的TSF4G-tapp/SWIFT,還有幾個新項目是純用C++寫的so往上面掛?網易出來的團隊是不是除了C++叉lua就是C++叉python?先拋出C#開發組的dev manager當初在微軟內部一次講話時說的(大意):相信我,絕大部分C++開發人員花那麼幾小時或者一兩天弄出來的內存管理,除了針對某些特定問題,是無法和我們專門小組花幾年時間並根據現代軟體各種場景仔細設計後開發出來的管理機制相比的。
中國的開發人員其實很有兩面性,一方面他們什麼都喜歡去講「用效率最高的」「最強的」,他們認為「C++雖然難以精通,但是一旦精通就是大殺器「(雖然壓根就沒幾個搞懂了c++實現機制。。。),另一方面他們又要抱怨加班,抱怨需求經常變,抱怨不停改bug...
中國的程序員從來沒有去想過國外程序員經常考慮的一個問題:how to make your life easier?
他們覺得凡是把事情簡化的,都是loser,都是水平低才做的事情,高手就要用c++...
他們沒想過什麼叫scalability
沒想過什麼叫learning curve沒想過什麼叫testability老闆要他們加快進度,他們說老闆不懂技術,說別家用的是低能的php,或者稍微高一點但是還是很low的java,他們說老子用的是效率最強的c++,當然,時間也要多一點。。。
尼瑪開發時間和debug/fix時間不考慮在「效率」裡面?
你說他們勤快呢,似乎也是,願意用最難的工具去做無數簡單又無聊的事情(嗯嗯,比如非要用c++處理資料庫...)
但是他們嘴上說「核心功能一定要保證效率要C/C++",但是卻不願意去分析到底哪些核心達到了必須用C/C++的地步,結果卻變成所有東西都是c/c++
你處理個tcp連接真心需要c++?你以為java和C++在處理單個tcp handshake的時候有多大本質差別?
你存取個redis還一定要c++?何為膠水語言,何為glue language,他們似乎沒有概念。
伺服器後端本來就該是各種語言各種micro service的組合,他們也不理解。
之前有人問我我的遊戲伺服器後端是什麼實現,我說我很懶,就是node.js,他立刻拋出這個問題:為什麼不用c++呢,c++效率高多了。。。
我說為什麼你這麼覺得呢?他說他之前做個路由的實現,就是用c++額。。。我要說windows kernel裡面還有我的代碼是C做的呢,我也沒說要用C去寫服務端。。。不同環境不同需求就該用不同語言和工具,似乎很多人理解不了。。。但是我跟對方說用node.js比較快也容易修改,他就覺得你這是「水平低」的體現,老子就是要知難而上克服技術難關直攀科學高峰。。。額。。。好吧。。。我不會用javascript/html5去寫遊戲客戶端,因為我不敢保證其單機性能,但是後端的瓶頸是在scalability,如果受限於單機效率,那是架構出了問題,而不是用什麼語言。
我把這個問題總結為:很多人對C++的極端推崇,歸根到底是眼界不夠廣,也不知道不同場景該用什麼不同工具,更不知道國外不斷推出的python/ruby/node/go/scala 等等到底是為了解決什麼問題針對什麼場景,不會去選擇最合適的工具,只能用他們自己比較熟悉的c++,然後標榜「高效」。
其實這個跟政府採購設備反正往最貴的買不會有錯,總可以給上面交代,是同一種思維模式。
用C++很多時候是為了低延遲, 而不是低消耗。一般服務端架構都是按進程分類 , 需要優化的進程用c/c++寫好了。關鍵還是設計要好, 不然以後想重構都無處下手。某些回答給我的感覺就是認為寫C++的人就只會在意性能,不考慮可伸縮性,可維護性和可測試性等等。。
(誇大點說)C++這麼簡單的語言都學不會(畢竟大學有四年,難不成跟我一樣讀的三年?),我不知道你是怎麼去解決遊戲開發中的難點(需求)。
不要以為自己開發C++很痛苦就認為大家都跟你一樣。
我不知道什麼時候追求性能成為了貶義詞。只要你說追求性能,就覺得你只在意性能,就跳出來說你太土了,現在都什麼年代了,機器這麼牛逼,人力成本算個啥,語言執行效率早就不是瓶頸。。
無論如何,請保持謙遜不要以己度人。
說回題目,既有歷史(遺留)原因,又有性能原因,後者是最初的原因。
然後,遊戲分很多種類型,當然並非所有都必須得用C++,但這也並非是你拒絕和不用C++的理由。
在我看來,那些對性能要求不高的遊戲,用啥都差不多。 性能要求高的,你自己看看討論Go和Java如何減少gc的帖子,沒有銀彈,有時候用C++或許還少一些擔心(有人要反駁說段錯誤,溢出么?)。
另外用C++還可以用各種腳本,還有成熟的性能分析工具,還有VS(來噴我啊)。多爽。
最後,項目當然是多種語言結合,每個部分使用最合適的,你以為寫cpp的人什麼都不懂?不要因為存在極端cpper就以為所有人都如此,別自己給別人面前樹個靶子自己來打。。。
補充能分散式多機當然好,譬如Dota2,CS,守望等,但單機效率依然重要。代碼的易用性、傳承性、容易理解和上手,最關鍵是要於項目的需求相匹配,這方面要比代碼的性能更重要。
lua本來就是搭配c++使用的,不同項目比重不同而已,lua有自己的優勢,而且這些優勢在網路遊戲中越發重要。
erlang也是一個很不錯的服務端語言。
php/java等,由於題主問的是mmorpg,並不合適。參與過一個Minecraft大型伺服器的後台維護,然後發現好可怕的佔用啊,如果是C++肯定不會出現這麼恐怖的事情。
-------------------------------------------------------------------第一次這麼快的拿到2個贊,受寵若驚啊。其實用C++來寫服務端確實效率比較低,而且難度比較大,但是往往服務端最講究效率,像java這類的效率不夠的就先不予考慮了。(如果說錯了請輕拍)
我分割線上的既是玩笑也是真事,正是C++開發難度高,並且對於操作系統等要更加的了解。也就防止了很多水貨程序猿來做。就像我說的Minecraft一樣,有大把大把的插件和mod,但是由於java的門檻很低,有大把的初中生高中生開發一些東西,如果使用的話,很多情況下會造成卡服,大量資源佔用,甚至會崩服。這種事情已經遇到不止一兩次了,而且經常我看到好多源碼都是把功能全部寫在一個文件裡面的,由此可見一斑。雖然我用的語言也不多,但是感覺到如果涉及到比較大規模而且對於資源等利用要求很嚴格的時候,擁有手動內存管理的語言才是首選,每次在java裡面我new了一個我總是想去delete掉。更多的時候我們需要的並不是無比多的三方庫,而是對於系統資源利用和程序穩定性的儘可能的把握。這一點C++給於了很大的支持。至於趕不趕超一大截我還真沒做過基準測試,java很多時候甚至比C++更快,但是。。。java就是一個內存殺手啊你造嗎?----------------------------------------------------------------
一個晚上莫名其妙的多了幾十個贊,這個答案寫了有一年多了,解釋一下關於MC伺服器的情況。MC的官方原版伺服器是Java的,就是一個jar包,這個東西是創始人個人開發的,所以根本談不上這些亂七八糟的,他喜歡用/最熟悉java而已。然後後續有人反編譯反混淆了他的jar包導致了三方伺服器的出現,隨後出現了CraftBukkit,然後是Spigot。這些都是基於反編譯反混淆原來的官方代碼來的,而且最重要的一點是因為他們用了官方的源碼功能,導致了使用java是最快捷方便的途徑(我沒想到什麼比較簡便的C++反射java類的方法)。事實上,以性能著稱的Spigot自己官方文檔都說了,512M內存都只能跑5個人,也就是64G內存也就是500多人同時在線就是極限了,這麼算伺服器的配置,去現有的雲伺服器提供商那裡幾乎要1W一個月,這可玩不起。(自己搭伺服器會便宜很多,貴是因為「物業」)。當然這麼糟糕的性能指標肯定是有人看不下去的,感謝評論里@Yangff 提供的C++版伺服器,我下了一個win64的版本,跑起來用了70M內存,不知道加入玩家會是怎麼樣的,還待更多的嘗試和資料研究(在官方的社區和管理員以及幾位開發聊了聊,發現這個服務端代碼不太穩定,所以等以後嘗試吧。。。)--------------------------------------------------------------最近心血來潮研究了部分現有伺服器的代碼,這些伺服器並不是因為Java而低效,純粹的是因為官服的代碼低效。從跑起來幾百人的情況看,官服的代碼就是在一個線程上跑到死,2.4G主頻的cpu無論你的核心有多少,一個服務端只能撐大概100人保持10tps。相對cpu的瓶頸來說,內存反而不再是重要的的。而且由於數據恐怕是沒怎麼做壓縮處理,1000人保守估計要100Mbps的上行帶寬。當然更加深入的研究因為脫離了這個問題的主題,如果有誰感興趣可以單獨開問題我有階段性結論了回答。中文那麼難,怎麼還有這麼多人不去用簡單而又流行的英語啊。。。。
-----------------------------------------------------------------------------------------------------------------
說別的肯定都引來一波語言宗教的爭論,還是不說為妙。。
很多時候,遊戲伺服器的瓶頸通常不是在cpu,也不是在io,而是在內存。遊戲不同於網站伺服器,遊戲在線玩家數據都會放在內存,資料庫只是作為一個數據持久化的存在。所以限制遊戲伺服器同時在線人數的關鍵是內存的利用率。而對內存的利用上,還沒有一門語言能達到c/c++相同的級別。所以對於一些同時在線不多,交互少的遊戲,用什麼語言無所謂,但是單服同時在線人數過1000,強交互的遊戲基本都選擇c++。
客戶端可能會因為硬體性能提升而使用腳本語言,但伺服器卻無論硬體性能如何提升,都用效率較高的編程語言,為什麼呢?因為使用C++,同服對戰人數可以最大化,雖然可以使用分散式彌補腳本語言帶來的性能缺陷,但是必然會產生跨服對戰帶來的延遲問題。跨服對戰,由於網路延遲,會降低用戶體驗,尤其對於即時類遊戲。儘管硬體性能提升,然而遊戲廠商都願意把提升的硬體性能用於增加同服對戰人數進而提升用戶體驗,而非用於降低編程難度和增加開發效率,當然這其中也有歷史遺留問題的原因
其實用C++用的多是國內遊戲界,主要是端游界的常態。在國內的頁游手游界用的不多,主要是小團隊Hold不住。而國外我看到過大把用Java寫的,也有用C#的,總的來說沒有國內端游界這麼一枝獨秀的現象。分析原因可能是有以下幾個方面吧。從歷史原因來說,早期國內遊戲研發大公司基本都是用C++寫的遊戲引擎。可能原因是因為當時可能並沒有專業的伺服器端程序員,很多程序員都是客戶端伺服器端兩手一起抓。而寫客戶端基本上就是C++的天下了。所以用同一種語言比較順手,也不需要重新招聘,就直接用C++來寫伺服器了。其次可能是當時Java確實也不成熟,在業內沒有一個有說服力的案例。.net就更加了。端遊行業又是一個很看重成功案例的行業,前一個項目用C++效果不錯,可能後一個就繼續了。而且當時那一幫人出來創業的話,一定也會用自己熟悉的方案,所以C++就一直流傳下來了。從技術原因來看,C++確實是一個寫伺服器的好語言。範例多,庫多,各種底層API支持也好,學校學生學的也多。雖然邏輯寫不好容易crash,但是我們不是還有腳本么。而國內流行的Python和Lua嵌入到C++裡面又特別方便。而國內運營環境對熱更新的要求又特別高(雖然我覺得高強度的加班會顯著導致Bug的增加,同時反過來促進了熱更新的需求),所以C++做引擎加上腳本語言基本上就變成遊戲伺服器的王道了。讓我推薦語言的話,其實我覺得Java和C++都可以。畢竟現在都是分散式架構。C++的問題是如果要從頭寫網路框架會很累。Java則有netty和mina這種成熟的網路庫。如果要我推薦,我推薦可以嘗試一下http://vertx.io,感覺可以利用它和組件化編程方式來構建一個不錯的伺服器集群。不過好像沒有遊戲公司用這個。可以當一下小白鼠分享經驗。說幾句無關的,今天火氣甚旺,對家人說了幾句不得體的話,非常鬱悶,半夜懲罰自己坐在桌前回答這個我非常熟悉但是極不喜歡的話題,這也算一種怒答了吧,可惜沒有逼格更高的蟹妖,不免有些遺憾。
我嘗試著把這個(有些無聊的)問題分為兩部分,
1 C/C++歷史上為何成為主流;2 當今為何大多數遊戲後端不再採用C/C++,優劣如何考量。第一個問題:
在網路遊戲這個領域起步的十幾年前,CPU是什麼效率?——主頻大約500M/s。內存多大?——2G出頭(34位的16G內存略過不提)的奢侈空間。就是這樣。在這樣的條件下,伺服器跑的功能,傳奇wow/FO征途等,和現在的網路遊戲沒有太大的區別,排除掉工程師能力局限的損失之後,承載也在同一個量級,當你想省著點用硬體的時候,沒有比C/C++更快意的語言了,Cray與Google(言必稱Google是一種病,知乎上的高逼格工程師得治。總提微軟?別逗了,兄台有點專業精神可好?)在前,我不願討論是不是和為什麼這種話題,畢竟回答這個問題不是為了證明自己是一個「php是最好的語言」的逗逼。
C/C++與其他常用的高級語言相比,最為不同之處,在於它在沒有過多的假設了你如何操縱硬體的前提下,最大化的努力嘗試用(還不夠)精鍊準確的語法表達操縱硬體(也就是軟體行為、業務邏輯)的意圖。
——所有討論【C++(注意,這裡不是C/C++)如果支持這個,如果限制那個就好了】觀點的工程師,都應該認真讀一讀關於C++語言設計歷程與思想的著作,在表達與操控之間,C/C++有道邊境線,不放棄工程師對硬體的操控權。在親身經歷過觸摸硬體極限的工程,從而懂得這條價值之前,工程師們總是圍繞「表達」討論C++的設定,我跟你談操控,你跟我講GC,夏蟲語冰。以上這段算是附贈,也是順便噴吐一下這個歪門邪道的問題下我真正想說的東西。
2 在21世紀已經十五個年頭,筆記本都有八個核的今天,C/C++是否還有在遊戲後端的競爭力?
如果要做一個市面上99%的遊戲,那麼C/C++競爭力不強,只有希望後端表現遠超同類競品,產品人員有很特別(奇葩)想法的極限設定,或許才有不可替代的價值。前面說了,C/C++作為一個(儘力)優雅的彙編宏的語言定位,保留了對硬體的極佳操控性,那麼如果高級語言對硬體的操控原則已經足夠工程需要,並因此給出了更好的表達效率,例如GC,例如並發,例如魯棒,那作為一個追求開發結果過程性價比的投資人,我為何要選用開發費時費力的C++咧?只可能是我的主程對我說一萬個理由,但是背後的核心是「我擅長」,而已。
那麼滿足什麼條件,C/C++仍然是一個好的選擇?
1 有一支C/C++功夫過硬的團隊,不是一個主程就足夠,一個搞不清狀況的C/C++程序員足以讓整個項目死的很難看。2 你的遊戲主策劃希望追求一些腦洞更大玩法更創新,尤其是在社交與即時互動方面更瘋狂的追求。——通常而言,把這個主策劃開掉是比起用C/C++更好的選擇,這種想法一般不靠譜,看看近些年的網路遊戲,已經不需要後端工程師了。最後多嘴一句,目前市面上各種流行的高級語言都已經證明:在特定團隊手中,完成特定的項目,語言設計的實現功能是足夠勝任遊戲後端開發的,比如java,erlang,C+lua等。但是尚未有強大到成為行業標準的完善閉合的開發語言環境,就如Windows的窗口應用解決方案,.net的web解決方案,java的ERP解決方案等。希望這一天早日到來,我們可以用高級語言快速的開發繁重而複雜的遊戲後端,不必糾結於功能的豐富與C/C++的繁瑣之間。
胡說八道一陣果然舒服多了。感謝您的閱讀,以上。
「對開發人員的要求也高」 --- 對於一個小孩子而言,用鎚子比用數控機床簡單,但你若想加工一個精密零件,你必須得用數控機床。問題不在於「對開發人員的要求高」,而在於「你想做的事,對技術要求高」;「C++開發效率相對較低」 --- C++是一門真正的編程語言,因此她很難學,在未學會之前,你當然是覺得其開發效率低。事實上,大型遊戲之所以用C++編寫,就是因為在這種高複雜度的場合下,C++比其它任何語言的開發效率都高。「用C++寫出一個健壯的服務端確實比較難」 --- 真實的原因是,為了壓低成本,小公司一般喜歡挑最差的程序員,因為他們要求的薪水少。之所以他們要求的薪水少,是因為他們還沒真正學會C++;最後一個是『執行效率』,這一點也很重要。遊戲是極度壓榨硬體性能的,為了提供10%的性能,你在硬體上就可能需要投入2倍的錢。更多是情形是,你願意在硬體上花錢,也沒有這樣的硬體賣。就MMORPG來說,C++可以說是最好的選擇。因為前後端可以都用C++和lua去寫,極大降低了程序團隊之間的溝通成本。
更早一些的時候,伺服器和客戶端都是純C/C++代碼編寫,沒有protobuf,lua這些好用的工具,客戶端和伺服器之間的通信協議直接寫成struct,發送時直接把struct內存中的bytes發過去,這樣只能都使用struct才會比較方便,當然,擴展就很傷筋動骨。
那個時候,分散式,微服務等概念還沒普及,所有的邏輯,都跑在一個進程裡面,想通過擴展硬體增加增加伺服器負載根本行不通。既然如此,我們只有採用C++這種性能較高的語言開發伺服器,當時的java還沒有現在這麼快。
還有歷史包袱的問題,可能你們不信,我到今年(2017)還見過上面說的單進程架構方式的伺服器框架,只是加入了actor模型,這套東西依然有人喜歡並奉若珍寶,因為說句實在話,非同步編程,分散式是需要考慮很多問題的,需要大量實踐和學習才能夠掌握的,而如今,項目的成敗往往跟這些技術關係不大,況且,「經過上線檢測的穩定代碼怎麼能隨意拋棄呢?」
如果是現在這個時間點進行沒有「歷史包袱」的MMORPG開發,我建議使用開發效率更高的Java,C#,Go等語言。現在已經不是十五年以前,這些語言的運行效率也都很高,不僅如此,現代伺服器開發,離不開很多從IT行業的其他分支借鑒的開發方式。比如,現代遊戲伺服器比以前更加需要和第三方伺服器進行交互,普遍的方式是採用Http/Https等協議進行通信,而我上面提到的這些語言都有原生庫的支持。再者,現代遊戲伺服器,基本上都需要考慮利用機器多核心的優勢,這幾個語言都有各自的解決方式。除此之外,這些語言更加現代化,支持函數式編程,這對程序員來說是一種福音。簡悅雲風用的是lua+c,私以為比c++好。可以讀讀他的博文。
C++是一門很好的教學用語言,熟練掌握的話也很適用於個人項目;但是團隊協作。。sigh,挑選一個不帶模板不帶raw new的C++11的子集吧。我個人喜歡的子集叫做「C with destructors」。歷史原因罷了,端游年代起來的那一撥人從大學開始就都是用C++,到現在這麼多年過去了習慣性的路徑依賴而已。
至於各種推薦C++給大學畢業生用的回答實在只能呵呵了....現在這年頭服務端可選的語言非常多,Java/Go/Erlang...隨便哪個跟C++比優勢都很明顯。
至於執行效率....不談實際應用場景就得出C++效率高實在是耍流氓。樓上幾個回答Java效率差的,你們實際項目當中有用Java和C++在技術選型的時候做過對比么?有數據能拿出來給我們看看么?連LOL的服務端用的都是Java這種事情我會亂說么?
推薦閱讀:
※程序猿如何快速高效的改 bug?改bug都有哪些技巧?
※怎麼從編程語言的角度解釋kan extension?
※為什麼 2010 年前後誕生的語言(如 Golang, Rust, Swift)都是強類型 + 靜態?
※python3 為什麼取消了sort方法中的cmp參數?
※為什麼C++中會把文件操作抽象為fstream?