当把一个类的成员重构成一个struct容器时,是否有性能方面的考虑?

问题描述 投票:2回答:1

假设我有几个这样的类。

class MyClassA {
    public List<string> UpData;
    public List<string> DownData;
    public List<string> LeftData;
    public List<string> RightData;
}

class MyClassB {
    public List<string> UpData;
    public List<string> DownData;
    public List<string> LeftData;
    public List<string> RightData;
}

我想重构它们,这样我就可以增加一些便利性(比如一个枚举器,或者有一些函数让我选择一个特定的成员)。

struct DirectionMap {
    public List<string> Up;
    public List<string> Down;
    public List<string> Left;
    public List<string> Right;
    //... various helper functions ...
}

class MyClassA {
    public DirectionMap Data;
}

class MyClassB {
    public DirectionMap Data;
}

然而,我的应用是非常耗费内存的,我有几百万个这样的实例,所以我需要考虑到内存的使用和垃圾回收。 我还必须尽可能频繁地突变这些对象,所以速度也很重要。 这样做有什么性能开销吗?

如果我的理解是正确的,如果 DirectionMap 是一个类,它会多用一点内存来存储指向它的指针,并多接触一次堆,对吗? 但是作为一个结构体,它是自由的吗?

我知道结构中的可变对象可能会导致错误,但我并不打算通过 Data 左右,只是它所包含的字符串列表,也就是引用值。

c# performance memory-management refactoring
1个回答
2
投票

谈论性能的第一条规则是对代码进行剖析,即使是有经验的开发人员也会对哪些事情需要花费时间感到惊讶。

如果你把东西放在结构中和直接放在类中,我希望内存使用和性能是一样的。内存布局应该是相似或相同的。

我不建议突变结构,除非你非常小心。例如,替换Up-list的内容会很好,但是用一个新的列表替换Up-list可能会引起问题。请看 为什么变异的结构是邪恶的.

如果你为你的结构实现了接口,你需要注意装箱。如果你实现了 IEnumerable<List<string>> 并使用任何linq方法,这将导致结构体被 盒装,性能不理想。这应该可以通过使用通用约束来避免。你可能还想使用一个可读结构和和 在参数修饰符 以避免复制。例如:

public static void MyMethod<T, U>(in T value) where T : struct, IEnumerable<U>
{
        // do something
}
© www.soinside.com 2019 - 2024. All rights reserved.