我已將原始問題簡化爲此測試。並行內部的處理比循環的常規要慢。爲什麼?
使用這個類:
public class Unmanaged : IDisposable
{
private IntPtr unmanagedResource;
public Unmanaged()
{
this.unmanagedResource = Marshal.AllocHGlobal(10 * 1024 * 1024);
}
public void DoSomethingWithThisClass()
{
Console.WriteLine($"{DateTime.Now} - {this.unmanagedResource.ToInt64()}");
}
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
Marshal.FreeHGlobal(unmanagedResource);
disposedValue = true;
}
}
~Unmanaged() {
Dispose(false);
}
void IDisposable.Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
我有這兩項測試:
public class UnitTest1
{
const int Runs = 100000;
[TestMethod]
public void UsingFor()
{
for (var i = 0; i <= Runs; i++)
{
using (var unman = new Unmanaged())
{
unman.DoSomethingWithThisClass();
}
}
}
[TestMethod]
public void UsingParallelFor()
{
Parallel.For(0, Runs, new ParallelOptions() { MaxDegreeOfParallelism = 10},
index => {
using (var unman = new Unmanaged())
{
unman.DoSomethingWithThisClass();
}
});
}
}
ParallelFor通常需要大約只要定期兩次。根據Profiler的說法,62%-65%的執行時間花在FreeHGlobal的ParallelFor中。 FreeHGlobal僅花費了52%-53%的費用。
我認爲與現代RAM系統,這不會有太大的區別。有沒有辦法在多個進程中處理大量未受管理的內存?有沒有一種方法可以改變它使其具有多線程?
如果我不處理每個進程中使用的RAM(糟糕的想法,但只是爲了測試),Parallel For是兩倍的速度,但然後我只能打開大約4-5個(它們是大量的的圖像數據)在應用程序崩潰之前(根據您的猜測,出現內存異常)。
爲什麼在單獨對象上執行多個Dispose動作會減慢速度?
我可以讓他們單線程,如果這是唯一的選擇,但我希望加快這一點。
謝謝。
如果您將'Unmanaged'作爲'sealed'類,那麼編寫'Dispose()'更容易,因爲不需要'virtual Dispose(bool)'。 –
AllocHGlobal()中內置了一個鎖,它使堆保持線程安全。所以你測量的是鎖持續了多長時間,不可避免地需要更長的時間,而另一個線程也忙於分配內存。 –
如果你正在處理大量的非託管資源('10 * 1024 * 1024'可能是代理),你可能會考慮C++/CLI而不是P/Invoke; C++也可以給你更多的工具來管理內存。 –