【问题标题】:Memory usage of an empty List or Dictionary?空列表或字典的内存使用情况?
【发布时间】:2013-04-21 13:31:01
【问题描述】:

一个空的 List 或 Dictionary 使用了多少内存?如:

List<double> list = new List<double>();

指针本身在 x86 和 x64 操作系统的 64 位上至少占用 32 位,但是列表本身呢?有 0 条记录。

问的原因是,你可以通过将列表设置为null来节省一些字节吗?

(假设您有一个包含一些 List&lt;T&gt; 的类,在某些情况下正在使用它,而在其他情况下则不是,在这种情况下有一个 booleanIsEmptynull 而不是空列表可能会节省一些操作内存。尤其是在操作内存中有数千个这样的类的情况下,每一位都很重要。)

【问题讨论】:

  • 我认为最好的办法是使用像 ANTS 这样的内存分析器并查找这些特定对象及其内存使用情况。
  • 我没有钱买蚂蚁和 ATM 我在 ubuntu 上
  • 我认为在几乎所有情况下,答案都是“很少,实际上并不重要”。
  • 内存对我来说总是很重要...如果不关心内存使用的程序员越少,现代程序的资源就不会那么昂贵...
  • @Petr 1. 你有多少个空列表?除非是数百万,否则这不会产生可衡量的差异。 2. 如果您想减少应用程序的内存消耗,您应该使用内存分析器来找出占用最多内存的内容。过早的优化(充其量)是浪费时间,这也适用于优化内存。

标签: c# memory


【解决方案1】:

dotPeek 反编译:

public class List<T> : IList<T>, ICollection<T>, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
{
    private T[] _items; //4 bytes for x86, 8 for x64
    private int _size; //4 bytes
    private int _version; //4 bytes
    [NonSerialized]
    private object _syncRoot; //4 bytes for x86, 8 for x64
    private static readonly T[] _emptyArray; //one per type
    private const int _defaultCapacity = 4; //one per type
    ...
}

x86 上总共有 20 个字节(List&lt;T&gt; 成员为 16 个,元数据引用开销为 4 个)和 x64 上为 32,包括对类型的引用对象,.net 中的每个对象都有。此计算大致完成,不包括对齐。


public class Dictionary<TKey, TValue> : ...
{
    private int[] buckets; //4 bytes for x86, 8 for x64
    private Dictionary<TKey, TValue>.Entry[] entries; //4 bytes for x86, 8 for x64
    private int count; //4 bytes
    private int version; //4 bytes
    private int freeList; //4 bytes
    private int freeCount; //4 bytes
    private IEqualityComparer<TKey> comparer; //4 bytes for x86, 8 for x64
    private Dictionary<TKey, TValue>.KeyCollection keys; //4 bytes for x86, 8 for x64
    private Dictionary<TKey, TValue>.ValueCollection values; //4 bytes for x86, 8 for x64
    private object _syncRoot; //4 bytes for x86, 8 for x64

    private const string VersionName = "Version"; //one per type
    private const string HashSizeName = "HashSize"; //one per type
    private const string KeyValuePairsName = "KeyValuePairs"; //one per type
    private const string ComparerName = "Comparer"; //one per type
}

44 用于 x86,72 用于 x64。再次粗略计算,因为需要不同对象的实例。

【讨论】:

  • 虚拟方法表呢?
  • @PieterGeerkens 不是为每种类型创建一个吗? List&lt;T&gt; 也有两个静态变量,不过我没算,因为它们不影响对象本身的大小。据我记得,.net 中的每个对象只有一个引用开销。
  • @svick 如 OP 所述:“有多少内存占用 empty 列表和字典?”。
  • @IlyaIvanov 是的,但你确定为空List 表示数组实际上没有分配?
  • @svick 有一个 static 空数组 T[0],由所有 T 类型的空列表共享。在默认构造函数中:_items = _emptyArray;.
【解决方案2】:

问的原因是,你可以通过将列表设置为null来节省一些字节吗?

作为一般规则(与任何规则一样,也有例外),您不应将托管对象设置为null 以释放内存。相反,将其留给垃圾收集器来检测对象何时不再可访问。事实上,设置对null 的引用可能会适得其反,因为它实际上可以slightly extend the lifetime of the object

一个例外可能是一个边缘情况,值得将一个大对象设置为null(例如,一个非常大的列表是另一个对象的属性,出于某种原因需要保持可访问),但这种情况很少见并且可能表示“代码味道”。

【讨论】:

    猜你喜欢
    • 2011-10-08
    • 1970-01-01
    • 2013-12-24
    • 1970-01-01
    • 2015-08-02
    • 2014-01-13
    • 1970-01-01
    • 1970-01-01
    • 2011-06-15
    相关资源
    最近更新 更多