System.Xml.Linq即使在應該釋放任何資源之后,這似乎也消耗了大量記憶體。一個簡單的演示
await using ( System.IO.FileStream stream = new ( xmlFilePath, System.IO.FileMode.Open) ) {
using ( System.Xml.XmlReader reader = System.Xml.XmlReader.Create( stream, new () { ConformanceLevel = System.Xml.ConformanceLevel.Fragment, Async = true } ) ) {
int i = 0;
while ( await reader.ReadAsync().ConfigureAwait( false ) ) {
while ( reader.NodeType != System.Xml.XmlNodeType.None ) {
if ( reader.NodeType == System.Xml.XmlNodeType.XmlDeclaration ) {
await reader.SkipAsync().ConfigureAwait( false );
continue;
}
if ( ct.IsCancellationRequested ) {
continue;
}
i ;
if ( i % 100000 == 0 ) {
Console.WriteLine( $"Processed {i}: {reader.ReadString()}" );
}
System.Xml.Linq.XNode node = await System.Xml.Linq.XNode.ReadFromAsync( reader, ct ).ConfigureAwait( false );
}
}
}
}
Console.WriteLine( $"\n---->Memory Use/false: {GC.GetTotalMemory(false):N0}");
Console.WriteLine( $"---->Memory Use : {GC.GetTotalMemory(true):N0}\n");
return;
輸出:
---->Memory Use/false: 402,639,448
---->Memory Use : 400,967,152
如果我更換XNode部分,
string xmlFilePath = "/home/eric/dev/src/github.com/erichiller/mkmrk-dotnet/src/Cli/dataset/cme/definition/2021/11/2021-11-05/20211104.061134-05_20211104.030927-05_cmeg.nymex.fut.prf.xml";
await using ( System.IO.FileStream stream = new ( xmlFilePath, System.IO.FileMode.Open) ) {
using ( System.Xml.XmlReader reader = System.Xml.XmlReader.Create( stream, new () { ConformanceLevel = System.Xml.ConformanceLevel.Fragment, Async = true } ) ) {
int i = 0;
while ( await reader.ReadAsync().ConfigureAwait( false ) ) {
while ( reader.NodeType != System.Xml.XmlNodeType.None ) {
if ( reader.NodeType == System.Xml.XmlNodeType.XmlDeclaration ) {
await reader.SkipAsync().ConfigureAwait( false );
continue;
}
if ( ct.IsCancellationRequested ) {
continue;
}
i ;
if ( i % 100000 == 0 ) {
Console.WriteLine( $"Processed {i}: {reader.ReadString()}" );
}
await reader.ReadAsync().ConfigureAwait( false );
}
}
}
}
Console.WriteLine( $"\n---->Memory Use/false: {GC.GetTotalMemory(false):N0}");
Console.WriteLine( $"---->Memory Use : {GC.GetTotalMemory(true):N0}\n");
return;
使用量大幅下降:
---->Memory Use/false: 11,048,992
---->Memory Use : 6,317,248
我在這里誤解了什么/做錯了什么?正在加載的檔案很大(~60MB),但即使 XNode 需要使用那么多記憶體,它不應該在Console.WriteLine到達時釋放嗎?
uj5u.com熱心網友回復:
Linq to XML 急切地將整個 XML 檔案加載到記憶體中,創建許多物件來表示它。您在閱讀時似乎在回圈中多次這樣做 - 沒有太多保護遞回遍歷。
但是,使用XmlReader, 允許手動控制并且它只讀取足夠的資訊并允許消費者決定如何處理它。
當塊關閉時,記憶體并不總是被釋放。堆上的東西會在某個時候被 GC 清理掉。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/393771.html
