2011-11-19 79 views
1

我在Netty的兩種情況,其中我試圖儘量減少內存拷貝和優化內存使用:正確的方式,以儘量減少內存使用了Netty

(1)閱讀一個非常大的幀(20個Megabites)。 (2)讀取大量非常少的幀(20兆字節,每幀50個叮),重建爲管道中更高級別的一條消息。

對於第一種情況,當我在幀的開始處獲得長度時,我擴展了FrameDecoder。不幸的是,由於我沒有看到如何將長度返回給Netty(我只是指出幀是否完整),我相信Netty正在經歷多個填充緩衝區,複製和重新分配循環,因此使用的內存超過了所需的內存。有什麼我在這裏失蹤?或者我應該完全避免FrameDecoder,如果我期待這種情況?

在第二種情況下,我正在創建一個鏈接列表,我使用ChannelBuffers.wrappedBuffer(然後可以包裝在一個ChannelBufferInputStream中)包裝所有小框架,但我再次使用的內存比我預期的要多得多(可能是因爲分配的ChannelBuffers有空餘空間?)。這是使用Netty ChannelBuffers的正確方法嗎?

回答

0

最後,它似乎是處理我的FrameDecoder問題的最好方法是在SimpleChannelUpstreamHandler之上編寫我自己的代碼。只要我確定了標題的長度,我就創建了大小與長度完全一致的ChannelBuffer。這(連同其他更改)顯着改善了我的應用程序的內存性能。

2
  1. 有一種稱爲LengthFieldBasedFrameDecoder的幀解碼器的專用版本。它的方便,當你有一個消息長度的標題。它甚至可以通過給出偏移量來從頭中提取消息長度。

  2. 實際上,ChannelBuffers.wrappedBuffer不會創建接收數據的副本,它會根據給定的緩衝區創建複合緩衝區,因此您的接收幀數據將不會被複制。如果您在代碼中持有複合緩衝區/您的自定義包裝並忘記取消,則可能發生內存泄漏。

這些做法我跟着,

  • 分配直接緩衝區爲長壽命的對象,切它上使用。

  • 當我想加入/編碼多個緩衝區到一個大緩衝區。我使用ChannelBuffers.wrappedBuffer

  • 如果我有一個緩衝,並希望/以用它做什麼呢一部分,我做它的一個切片通過調用通道緩衝例如片或片(0,..)

  • 如果我有一個通道緩衝,知道這是小數據的位置,我總是用getXXX方法

  • 如果我有通道緩衝器,它在很多地方用於化妝出來的東西吧,總使其可修改,在使用時進行分割。

注:channelbuffer.slice不會使數據的副本,它會創建新的讀者&寫索引通道緩衝器。

+0

我很欣賞這個迴應,但你幾乎可以說明我已經在做什麼。 LengthFieldBasedFrameDecoder,因爲它延伸幀解碼器,繼承它的問題(你不能避免填充緩衝區/ realloc和複製週期)。我知道wrappedBuffer不會創建副本,但我仍然使用比預期更多的內存(堆增加3-4倍的消息大小)。 – Gareth

+1

@Gareth沒有看到代碼,它很難說任何事情。我剛剛檢查了FrameDecoder,發現它使用DynamicChannel緩衝區女巫從256字節開始,所以我不確定它在接收時如何增長20MBs,我認爲,最好是用固定緩衝區編寫自己的FrameDecoder版本。 –