本文告訴大家如何使用 marshal 做出可以快速釋放記憶體的大陣列。
最近在做 3d ,需要不斷申請一段大記憶體陣列,然後就釋放他,但是 c# 對於大記憶體不是立刻釋放,所以就存在一定的效能問題。
在看到了一位大神使用 marshal 做出快速申請的大陣列,於是我就學他的方法來弄乙個。本文告訴大家這個類是如何使用
在使用的時候,先來看下原來的 c# 的大陣列效能。可以看到在不停gc,效能不好
static void main(string args)
console.readkey();
}private static void foo()
在使用 marshal 之前需要知道這是什麼,其實 marshal 就是乙個提供 com 互操作的方法。
下面使用乙個快速申請 int 陣列來告訴大家如何使用。
是否還記得 c 的申請陣列?其實下面的方法和 c 的相同
int n = 100000;//長度
intptr buffer = marshal.allochglobal(sizeof(int) * n);
這時就可以使用 buffer 作為陣列
下面對他的第 k 個元素修改
intptr buffer = marshal.allochglobal(sizeof(int) * n);
int k = 2;
intptr t = buffer + k * sizeof(int);
var p = marshal.ptrtostructure(t);
console.writeline("p " + p); //196713 這時的值是不確定
p = 2;
marshal.structuretoptr(p,t,false);
p = marshal.ptrtostructure(t);
console.writeline("p " + p);//2
//遍歷
console.writeline("遍歷");
for (int i = 0; i < 10; i++)
遍歷:
43909312
4450214420
024
1357220181
196712
550912
543686656
可以從上面的**看到,主要使用的兩個方法是 structuretoptr 和 ptrtostructure ,而 structuretoptr 就是從指定型別寫到指標,希望大家還知道如何使用指標,ptrtostructure 就是從指標指向的地方開始讀資料,讀指定型別的資料。所以可以從 marshal 把乙個型別使用另乙個型別來讀取,但是一般需要讀取的型別都需要是確定型別大小的,如 char 可以、string 不可以。
反過來,structuretoptr 是對指定指標寫入指定的型別,同樣也是需要確定這個型別的大小,如可以寫入 char 但是不可以寫入 string。這就是對陣列讀寫的方法。
那麼遍歷的時候什麼輸出一些詭異的值,實際上因為沒有初始化,裡面的值是不確定的。我覺得用這個做隨機數也不錯。
使用 marshal 是比較安全,因為 ms 做了很多處理,但是也會讓程式閃退,如下面的**
private static void foo()
catch (exception e)
marshal.freehglobal(buffer);
}
會出現異常 system.accessviolationexception,這個異常是無法 catch 的,所以使用的時候最好封裝一下
「system.accessviolationexception」型別的未經處理的異常在 未知模組
嘗試讀取或寫入受保護的記憶體。這通常指示其他記憶體已損壞
<?xml version="1.0" encoding="utf-8" ?>
然後在 main 函式新增 handleprocesscorruptedstateexceptions ,請看**
[handleprocesscorruptedstateexceptions]
static void main(string args)
catch (exception e)
}console.writeline("完成");
console.readkey();
}
這時可以看到進入 unhandledexception ,但是無法接住,軟體還是會崩潰
那麼如何釋放記憶體?因為這個申請是沒有經過管理的,如果沒有手動釋放,那麼就出現記憶體洩露。
static void main(string args)
console.readkey();
}private static void foo()
上面的**很快就可以看到記憶體占用到2g,所以需要手動釋放
marshal.freehglobal(buffer);
原來的 byte 陣列需要使用 1g 記憶體,而且速度很慢,而現在使用這個方法只需要 7m 記憶體,速度很快
所以在需要進行大陣列申請的時候,需要不停釋放,就可以使用這個方法。
如果想使用封裝好的,請看下面的大神弄好的類
參見:c#+無unsafe的非託管大陣列(large unmanaged array in c# without 'unsafe' keyword) - bit祝威 -
實際在哪些地方使用?實際上因為很多時候都是使用例項化池,但是例項化池在進入遊戲的時候,可以讓gc不會讓程式暫停,但是會在遊戲進入下一關的時候,無法快速清理資料。所以這時就可以使用 marshal 做例項化池,瞬間就可以清空。
上面的方法暫時不告訴大家如何做,因為涉及到公司的使用。
C 快速釋放記憶體的大陣列
使用marshal快速申請釋放大陣列。使用allochglobal 函式開闢空間 static void main string args console.readkey private static void foo 使用marshal申請記憶體是沒有經過管理的,如果沒有手動釋放,那麼就出現記憶體...
C 如何快速釋放記憶體的大陣列詳解
本文告訴大家如何使用 marshal 做出可以快速釋放記憶體的大陣列。最近在做 3d 需要不斷申請一段大記憶體陣列,然後就釋放他,但是 c 對於大記憶體不是立刻釋放,所以就存在一定的效能問題。在部落格園看到了一位大神使用 marshal 做出快速申請的大陣列,於是我就學他的方法來弄乙個。本文程式設計...
C 物件陣列釋放造成記憶體洩漏
物件陣列在釋放的時候,經常會遇到兩種情況,可能會造成記憶體洩漏 例如,geopoint是乙個類 class geopoint geopoint double x,double y geopoint public void setx double x void sety double y double...