2016-02-18 27 views
0

當我訪問一個文件,以獲取已保存的對象我目前經過這條路:有沒有辦法將本地數組轉換爲託管數據而不復制數據?

  1. 讀取序列化流進本地緩衝
  2. 複製本地緩存到託管緩存
  3. 反序列化(我使用netserializer)

複製不是一個大問題,但它似乎沒有必要,所以我想消除它,如果可能的話。

我想我發現了一個聰明的方式通過具有該流讀取功能接受字符*(* allocFunc)(ItemLengthType)的函數指針,然後直接將數據讀入所述釘扎管理的陣列,這樣做:

array<Byte>^ serBuf; 
    itemStream->ReadItem(i, [=](uint32_t len){ 
     serBuf = gcnew array<Byte>(len); 
     pin_ptr<Byte> pData = &serBuf[0]; 
     return reinterpret_cast<char*>(pData); 
    }); 

但史詩般的失敗,無法捕捉到lambda函數中的託管對象,甚至無法在託管類中創建lambda函數。

唯一的其他替代我看是把我流類爲管理一個並讓它產生一個管理陣列,但這個類是從其他項目,我在許多其他非CLR相關的解決方案使用。我也不打算創建該項目的半管理分支,太費心了。

有沒有其他辦法,我避免了複製步驟?

回答

2

有沒有辦法把一個本地緩存到託管數組,但你仍然可以消除副本的一步。

使用此流量代替:

  1. 引腳一個管理緩衝液(array<Byte>),導致char*
  2. 讀序列化流入char*就好像它是一個本地緩衝區。
  3. 脫出該管理緩衝區。
  4. 反序列化

要執行步驟1中,僅分配管理的字節數組,並使用pin_ptr獲得純char*。將數據讀入該數據,然後取消固定數組。然後,像正常一樣將託管陣列傳遞給解串器。

請注意,固定數組應該是很短的時間:只要有東西被固定,這對於垃圾收集器來說是額外的工作,因爲在想要重新排列的大塊內存中間,有這個你告訴它不要移動的陣列。

我也建議您分析您的應用程序,看看有多少性能從本地緩存命中額外拷貝到管理的陣列。它可能比你想象的要少得多,在這種情況下,我希望清楚易懂的代碼&。

相關問題