程序员羽化之路--假如需要一百万个对象
點擊上方藍字關注我們
菜菜哥,救命呀
又被產品經理砍了?
這次搞不好真要被砍了,線上一個用戶系統內存溢出了,占用內存太高了
用戶基數大,內存占用高正常
高的不太正常了,我覺得可能和我的設計有關
那說說你的用戶設計
設計背景
每個平臺都會有用戶這種基礎數據的設計,作為最基礎的用戶,每個用戶都有很多屬性,比如性別,姓名,手機號等,每個用戶還可以有類似經驗值這樣的榮譽系統,根據不同的經驗值來對應不同的等級,不同的等級對應不同的榮譽UI,比如一級用戶可能只顯示一個星星,二級用戶顯示兩顆星星,以此類推,類似于QQ等級的星星月亮太陽,這樣的榮譽系統隨著平臺的不斷壯大,可能會衍生出很多類型。那么問題來了,用戶登錄的時候就需要初始化用戶的這些榮譽值,以星星數為例,類似于以下代碼?
public?class?Star {//等級public?int?Level{get?;set?;}//對應的星星數目public?int?StarNumber{get?;set?;}//對應的星星顏色public?int?Color{get?;set?;}...?其他屬性 } //用戶信息 public?class?User{???public?Star?StarInfo{get?;set?;}//...用戶的其他屬性 }//初始化用戶信息 User?u=new?User(){?StarInfo=new?Star(){?Level=1,?StarNumber=1,Color=1}};每一個登錄用戶都會初始化一個Star屬性來表示當前用戶的Star信息,當有100萬用戶甚至更多用戶同時在線的時候,內存中就實例化了同樣數量的Star對象,以及其他類似的屬性對象。這么多重復的對象難道不能優化嗎?當然不是!!
問題分析
一個業務出現問題,首先要分析問題的所在。根據以上所說,問題的根本在于產生了大量的對象,首先每個用戶對象都有自己獨特的狀態,這個基本上不可能分解優化,但是類似Star這樣的屬性就有優化途徑了,這些榮譽屬性一個最大的共同點就是不可變,換句話說,等級1的用戶對應的Star信息是永遠不會變的,永遠是level=1,starnumber=1,color=1 等?;谶@個不變性,我們可以把這個Star抽離出來,供所有等級1的用戶使用,假設原來有10萬等級1的用戶,原來需要10萬個對象,現在只需要一個對象,這可是天壤之別。
解決問題
基于以上問題分析,我們需要做的是把對象重復使用,只要是對象重復問題,基本上可以利用一個對象出口來解決問題,類似于以下的對象初始化工廠,但是要注意線程安全問題,因為同時請求并初始化對象的線程會有多個。
public?class?UserStarFac{static?object?objLock?=?new?object();static?Dictionary<int,?Star>?UserStarMap?=?new?Dictionary<int,?Star>();public?static?Star?GetUserStar(int?level){//利用鎖來防止實例化多次,當然這里可以優化lock?(objLock){Star?info?=?null;?;if(!UserStarMap.TryGetValue(level,?out?info)){info?=?new?Star()?{?Color?=?1,?Level?=?1,?StarNumber?=?1?};UserStarMap.Add(level,info);}return?info;}}}編寫簡單測試程序
static?void?Main(string[]?args){int?i?=?0;List<User>?userList?=?new?List<User>();while?(i?<?100000){//?userList.Add(new?User()?{??StarInfo=new?Star()?{??Color=1,?Level=1,?StarNumber=1}?});userList.Add(new?User()?{??StarInfo=?UserStarFac?.GetUserStar(1)});i++;?}Console.WriteLine("初始化完成");Console.Read();}內存的測試結果:
不執行任何程序:占用內存:2.8 M ?
無優化初始化10萬對象:占用內存:11 M
優化之后初始化10萬對象:占用內存:7 M
居然一個小小的優化就減少了4M內存,不要小看這小小的4M,你要看的是比例,居然減少了將近 50%,真實業務中,可以進行這種優化的地方數不勝數,不知道你是否在乎呢?
這種大量重復對象的問題尤其是在游戲編程中經常存在,比如五子棋游戲,棋子的初始化,一個游戲大廳存在成千上百萬對局,如果每個局中的棋子都初始化一個對象,那內存使用是相當可怕的,這種需要把通用的對象屬性,不變的對象屬性抽離出來,做共享是有必要的。
據說這種優化有一個學名:享元模式,沒有必要記住名字,但需要記住原理和場景,必須要提一句:注意不變的對象才可以哦
完
●程序員過關斬將-- 噴一噴坑爹的面向UI編程
●程序員過關斬將--redis做消息隊列,香嗎?
●程序員修神之路--有了容器為什么kubernetes還需要Pod?
●程序員修神之路--為什么我會了SOA,你們還要逼我學微服務?
●程序員過關斬將--要想獲取我的用戶信息,就得按照規矩來
●程序員過關斬將--更加優雅的Token認證方式JWT
●程序員過關斬將--cookie和session的關系其實很簡單
●程序員修神之路--用NOSql給高并發系統加速
●程序員修神之路--高并發系統設計負載均衡架構
●程序員過關斬將--你為什么還在用存儲過程?
●程序員修神之路--問世間異步為何物?
●程序員修神之路--提高網站的吞吐
總結
以上是生活随笔為你收集整理的程序员羽化之路--假如需要一百万个对象的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: .NET 5 Preview 1的深度解
 - 下一篇: WTM 3.5发布,VUE来了!