我正在尝试使用Json.net来序列化和反序列化Windows通用项目中的对象。我需要在后台任务中使用这个库,并且因为后台任务的内存在Windows手机上非常有限,我需要确保我没有使用太多内存。
我遇到的问题是Json.net似乎使用了大量内存,似乎永远不会被释放。
为了证明这一点,我创建了一个小例子。创建一个新的通用应用程序并创建一个PageLoaded事件处理程序,如下所示(此示例在Windows应用程序中与在手机应用程序中相同,因此您使用哪个平台无关紧要):
private void Page_Loaded(object sender, RoutedEventArgs e)
{
List<string> testItems = new List<string>();
List<string> destinationItems;
testItems.Add("Test Item Number 001");
testItems.Add("Test Item Number 002");
testItems.Add("Test Item Number 003");
testItems.Add("Test Item Number 004");
testItems.Add("Test Item Number 005");
testItems.Add("Test Item Number 006");
testItems.Add("Test Item Number 007");
testItems.Add("Test Item Number 008");
testItems.Add("Test Item Number 009");
testItems.Add("Test Item Number 010");
testItems.Add("Test Item Number 011");
testItems.Add("Test Item Number 012");
testItems.Add("Test Item Number 013");
testItems.Add("Test Item Number 014");
testItems.Add("Test Item Number 015");
testItems.Add("Test Item Number 016");
testItems.Add("Test Item Number 017");
testItems.Add("Test Item Number 018");
testItems.Add("Test Item Number 019");
testItems.Add("Test Item Number 020");
testItems.Add("Test Item Number 021");
testItems.Add("Test Item Number 022");
testItems.Add("Test Item Number 023");
testItems.Add("Test Item Number 024");
testItems.Add("Test Item Number 025");
testItems.Add("Test Item Number 026");
testItems.Add("Test Item Number 027");
testItems.Add("Test Item Number 028");
testItems.Add("Test Item Number 029");
testItems.Add("Test Item Number 030");
testItems.Add("Test Item Number 031");
testItems.Add("Test Item Number 032");
testItems.Add("Test Item Number 033");
testItems.Add("Test Item Number 034");
testItems.Add("Test Item Number 035");
testItems.Add("Test Item Number 036");
testItems.Add("Test Item Number 037");
testItems.Add("Test Item Number 038");
testItems.Add("Test Item Number 039");
testItems.Add("Test Item Number 040");
testItems.Add("Test Item Number 041");
testItems.Add("Test Item Number 042");
testItems.Add("Test Item Number 043");
testItems.Add("Test Item Number 044");
testItems.Add("Test Item Number 045");
testItems.Add("Test Item Number 046");
testItems.Add("Test Item Number 047");
testItems.Add("Test Item Number 048");
testItems.Add("Test Item Number 049");
testItems.Add("Test Item Number 050");
testItems.Add("Test Item Number 051");
testItems.Add("Test Item Number 052");
testItems.Add("Test Item Number 053");
testItems.Add("Test Item Number 054");
testItems.Add("Test Item Number 055");
testItems.Add("Test Item Number 056");
testItems.Add("Test Item Number 057");
testItems.Add("Test Item Number 058");
testItems.Add("Test Item Number 059");
testItems.Add("Test Item Number 060");
testItems.Add("Test Item Number 061");
testItems.Add("Test Item Number 062");
testItems.Add("Test Item Number 063");
testItems.Add("Test Item Number 064");
testItems.Add("Test Item Number 065");
testItems.Add("Test Item Number 066");
testItems.Add("Test Item Number 067");
testItems.Add("Test Item Number 068");
testItems.Add("Test Item Number 069");
testItems.Add("Test Item Number 070");
testItems.Add("Test Item Number 071");
testItems.Add("Test Item Number 072");
testItems.Add("Test Item Number 073");
testItems.Add("Test Item Number 074");
testItems.Add("Test Item Number 075");
testItems.Add("Test Item Number 076");
testItems.Add("Test Item Number 077");
testItems.Add("Test Item Number 078");
testItems.Add("Test Item Number 079");
testItems.Add("Test Item Number 080");
testItems.Add("Test Item Number 081");
testItems.Add("Test Item Number 082");
testItems.Add("Test Item Number 083");
testItems.Add("Test Item Number 084");
testItems.Add("Test Item Number 085");
testItems.Add("Test Item Number 086");
testItems.Add("Test Item Number 087");
testItems.Add("Test Item Number 088");
testItems.Add("Test Item Number 089");
testItems.Add("Test Item Number 090");
testItems.Add("Test Item Number 091");
testItems.Add("Test Item Number 092");
testItems.Add("Test Item Number 093");
testItems.Add("Test Item Number 094");
testItems.Add("Test Item Number 095");
testItems.Add("Test Item Number 096");
testItems.Add("Test Item Number 097");
testItems.Add("Test Item Number 098");
testItems.Add("Test Item Number 099");
testItems.Add("Test Item Number 100");
Debug.WriteLine(GC.GetTotalMemory(true));
string saveStr = JsonConvert.SerializeObject(testItems);
Debug.WriteLine(GC.GetTotalMemory(true));
destinationItems = JsonConvert.DeserializeObject<List<string>>(saveStr);
Debug.WriteLine(GC.GetTotalMemory(true));
destinationItems = null;
Debug.WriteLine(GC.GetTotalMemory(true));
}
调试输出为:
40236
193084
199624
193472
我希望最后一个值与第一个值大致匹配,但似乎Json.net保留了大约150kb的内存。更重要的是,后续的序列化和反序列化指令似乎使情况变得更糟。
我没有在Windows桌面应用中试过这个,但我希望结果是一样的。
我的问题是: 有谁知道为什么会这样,以及如何释放这段记忆? 如果这是不可能的,有没有人知道另一个更好地管理内存的Json库?
编辑:经过一段时间的斗争,我意识到问题不是Json.net,而是WinRT中的流问题。
我在MSDN上提出了一个新问题(希望微软的某个人可以解释一下): WinRT Stream Memory Issue
答案 0 :(得分:3)
据我所知,当您调用GC.GetTotalMemory(true)时,无法保证GC实际上已经回收了所有未使用的对象。您需要使用更多数据对此进行更长时间的测试,以确保存在实际的内存泄漏。
我很确定JSON.NET会出于性能原因缓存生成的序列化器/反序列化器,并且在这种情况下不会回收它们。但是,在先前序列化/反序列化类型的连续序列化/反序列化期间,实际使用的内存量不应增加。