背景
近來在用 DotNetty 實現一個文件上傳下載的同步服務。
其中:客戶端下載服務端的文件,客戶端多次請求,從服務端將文件分片下載下來,追加到本地磁盤。
—— 非常簡單的代碼,都寫了幾十次了,駕輕就熟。
問題來了
可是:在進行壓力測試時,我這邊下載一個 Win10 的 ISO 鏡像,4個G。
我發現:客戶端內存不停增長,直到內存溢出 —— 我擦。
VS2015內存診斷
內存診斷,我們發現 有很多 16M(16777228字節) 的 byte[] 占據着內存。
而我請求服務端的 文件分片 只有 64K
—— 於是我肯定:這些 16M 的 byte[] 肯定是 DotNetty 創建的。
調試代碼
通過調試代碼,確實發現了 這些 16M 字節所在的位置:
((DotNetty.Buffers.PooledByteBufferAllocator)
((DotNetty.Transport.Channels.AbstractChannelHandlerContext)context)
.Allocator)
.directArenas
簡寫就是:
context.Allocator.directArenas
知道了 內存泄漏 的數據 存在哪里,剩下的就是 刪除這些數據。
因為
Allocator
和directArenas
都是不可訪問的(私有類型)我猜:按照微軟框架的習慣,肯定有 屬性 或 方法 能夠設置 這個東西。
—— 是我想太多,我找了好久 都找不到 相關方法。
萬能解法:反編譯
直到數據在哪里,肯定有修正這些數據的方法。
反射是萬能的 —— 但是我不想用。
於是,開始反編譯:查看這個 directArenas
字段在哪里 賦值、哪里添加數據。
問題解決
再次運行程序,內存穩定在 30M —— 內存泄漏問題解決。
這次修改BUG,最廢時間的 莫過於 DotNetty 毫無微軟風格。
微軟框架基本都有一個風格:底層一定提供了各種 函數、屬性 —— 默認會給你一個 最穩定的默認值。
尼瑪,這分明是 Java 的尿性:各種參數千奇百怪,不配參數還不能運行 —— 給我個默認參數 有那么難么~