【发布时间】:2011-08-19 22:09:17
【问题描述】:
我已经开始对我们的应用程序进行内存分析,因为我们最近收到了几份关于性能和内存不足异常的报告。该应用使用 C# .Net Winforms (.Net Framework 2.0)
开发当应用程序启动时,ANT 分析器显示第 2 代中存在 17.7 MB 对象。
当应用程序启动时,它会从磁盘上的 xml 序列化文件中读取 77000 多个邮政编码,并保存在 Hashtable 中。请看下面的示例代码
public Class ZipCodeItem
{
private string zipCode;
private string city;
private string state;
private string county;
private int tdhCode;
private string fipsCounty;
private string fipsCity;
Public ZipCodeItem()
{
// Constructor.. nothing interesting here
}
// Bunch of public getter/setter properties
}
这是从磁盘上的文件中读取序列化的 zip 数据并加载邮政编码的静态类。
internal sealed class ZipTypes
{
private static readonly Hashtable zipCodes = new Hashtable();
public static ArrayList LookupZipCodes(string zipCode)
{
if (zipCodes.Count == 0)
LoadZipCodes();
ArrayList arZips = new ArrayList();
// Search for given zip code and return the matched ZipCodeitem collection
if (zipCodes.ContainsKey(zipCode))
{
// Populate the array with the matched items
}
// Omitted the details to keep it simple
return arZips;
}
private static bool LoadZipCodes()
{
using (FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
// unzip it.. Omitted the details to keep it simple
// Read the zipcodes from the flat xml file on disk and load the local zipCodes HashTable
}
}
}
这个类和更正。整个应用程序都可以访问邮政编码。
在 17.7 meg 的 Gen 2 对象中,大约有 14 meg 是 zipCodeItems 或其子 String 类。
我想将我的代码更改为如何不将这些 77000 多个邮政编码项目对象保留在内存中(在哈希表中),而是在应用需要时提供映射的邮政编码项目。
任何建议如何解决这个问题?提前致谢。
【问题讨论】:
-
您认为 14MB 的 RAM 会导致 OOM 异常吗?它不是。有什么选择?每次需要邮政编码时从磁盘读取?不,根据我所见,将其存储在内存中没有任何问题。
-
顺便说一句,您为什么使用
ArrayList和Hashtable?这些类基本上已被弃用。首选System.Collections.Generic命名空间中的集合类,即List<T>和Dictionary<K,V>。 -
Erm,您可以进行的另一项改进是使用
TryGetValue而不是Contains,然后执行另一次查找。你做的工作量是你需要做的两倍。 -
是的,这很公平。但是,这 14MB 散列绝对不会导致 OOM 异常。您需要在代码/分析结果中查看其他地方。根据您告诉我们的内容,我可以向您保证,您走错了路。
-
14MB 是现代应用程序的噪音。真的,我可以 99% 肯定地说这不是你的问题,而且你说的是 OOM 异常,这似乎更重要。您是否已证明您存在由 GC 引起的性能问题?
标签: c# winforms memory-management memory-leaks garbage-collection