【问题标题】:Two Lists containing an interface versus one List containing a struct with two interfaces包含一个接口的两个列表与一个包含具有两个接口的结构的列表
【发布时间】:2016-03-20 00:55:24
【问题描述】:

我有两个接口。 ICacheHolder 将由一个实现游戏对象逻辑的类和 IVisualizer 实现,该类将成为视觉表示。

public interface ICacheHolder
{
    void updateCacheWithCurrentState(int chachFrame);

    void resizeCache(int newSize);

    T getCacheFrame<T>(int cacheIndex, float interpolationToNext) where T : struct;
}

public interface IVisualizer
{
    void updateVisualization(ICacheHolder cacheHolder, int cacheIndex, float interpolation);
}

每个 ICacheHolder 都连接到一个 IVisualizer 对象,关系是 1 对 1。 我正在尝试确定将它们存储在两个单独的列表中还是作为结构存储在一个列表中是否更好(性能/内存方面)。会有很大的不同吗?如果我使用 struct 版本会发生拳击吗?我估计列表的大小将从 100 到 1000。

版本 1:

public class CacheFramework
{
private List<ICacheHolder> cacheHolders = new List<ICacheHolder>();
private List<IVisualizer> visualizers = new List<IVisualizer>();
...
}

版本 2:

struct SimulationObject
{
    public ICacheHolder CacheHolder;
    public IVisualizer Visualizer;
}
public class CacheFramework
{
private List<SimulationObject> cacheHolder = new List<SimulationObject>();
...
}

添加和删除之类的操作不会很频繁地进行。只有在游戏开始时,可​​能会有很多添加调用。

版本 1:

private bool AddSimulationObject(ICacheHolder cacheHolder, IVisualizer visualizer)
{
    if (!cacheHolders.Contains(cacheHolder) && !visualizers.Contains(visualizer))
    {
        cacheHolders.Add(cacheHolder);
        visualizers.Add(visualizer);
        return true;
    }
    return false;
}

版本 2:

private bool AddSimulationObject(ICacheHolder cacheHolder, IVisualizer visualizer)
{
    int index = simulationObjects.FindIndex(
        delegate (SimulationObject simulationObject)
        {
            return simulationObject.CacheHolder == cacheHolder || simulationObject.Visualizer == visualizer;
        }
        );

    if (index >= 0 )
    {
        SimulationObject newObject;
        newObject.CacheHolder = cacheHolder;
        newObject.Visualizer = visualizer;
        return true;
    }
    return false;
}

列表将至少被访问 每一帧都通过它的索引。

附加信息: 每个使用 ICacheHolder 的类都将包含一个List&lt;struct&gt;,其中包含位置、旋转或健康等数据。每个列表元素都将是时间的快照。目标是来回穿越时间。

编辑 1:

修正了 AddSimulationObject 版本 2 中的错误。

正如所指出的 AddSimulationObject 版本 2 可能是:

private bool AddSimulationObject(ICacheHolder cacheHolder, IVisualizer visualizer)
{
    SimulationObject newObject = new SimulationObject { CacheHolder = cacheHolder, Visualizer = visualizer };
    if (simulationObjects.Contains(newObject))
    {
        simulationObjects.Add(newObject);
        return true;
    }
    return false;
}

但在这种情况下,我需要确保 cacheHolder 和可视化工具不会出现在任何其他组合中。

编辑 2:

我正在使用主要支持 NET 的 Unity3D。 3.5

正如所指出的,使用查找速度比 List 更快的 .NET 集合可能会更好。或者,如果列表是可排序的,请使用 List.BinarySearch。

编辑 3:

我将使用结构版本。我不确定会有多少查找。如果它会成为问题,我可能会更改为另一个 .NET 集合。

【问题讨论】:

  • 每当我看到性能问题时,我都会链接这个:ericlippert.com/2012/12/17/performance-rant
  • 您将两个版本都显示为代码。那么您使用该代码测量的时间/内存值在哪里?如果您已对其进行测量,则可以根据您的标准判断出哪个版本符合您的要求。
  • 仅供参考 - 您不需要您的 FindIndex 与代表。与相同字段比较时,结构将返回 true。即:new SimulationObject { CacheHolder = ch, Visualizer = v }.Equals(new SimulationObject { CacheHolder = ch, Visualizer = v }) 将返回 true。你可以简单地使用var exists = simulationObjects.Contains(new SimulationObject { CacheHolder = cacheHolder, Visualizer = visualizer });
  • 任何性能问题都应首先通过 DotTrace 等性能分析工具进行测量。
  • @Rob 他不是在检查所有字段是否相等,而是在检查是否有任何字段相等,所以它不能被简单的包含替换

标签: c#


【解决方案1】:

Eric Lippert 的评论非常真实。 在这种情况下,甚至无需尝试比较性能差异,因为集合非常小,因此无需担心 CPU 时间。

内存方面...列表结构使用连续的内存块,只有当它们真的很大时才会成为内存问题。 (我的意思是数百万。)

只有其他建议: 如果您要在这些列表中执行每个游戏周期的搜索,您可以简单地选择另一种针对查找进行优化的结构。字典在检索项目时更有效,因为 find 从索引中进行查找,而列表将执行项目的遍历。

【讨论】:

    【解决方案2】:

    您正在谈论参考列表,您的任何一种解决方案都可以。 但是如果你的两个接口是成对的,你可以使用 List&lt;Tuple&lt;ICacheHolder, IVisualizer&gt;&gt;

    【讨论】:

    • 感谢您的提示。刚刚测试过。我正在使用 Unity3D Tuple 是 .NET Framework 4,不幸的是不受支持。 Unity / Mono 主要还是在 NET 上。 3.5.
    • @Markus:值得更新您的问题以指定您正在使用 Unity3D。鉴于 .NET 4 现在已经超过 5 年了,任何时候你提出一个问题并且不能使用它,你应该解释为什么会这样。
    【解决方案3】:

    我建议您使用 struct 方法,原因有两个:

    • 在 .NET 中,结构泛型类型参数被特殊处理,no boxing will occur
    • 这种方法将通过结构确保您有匹配的元素在一起。对我来说,这感觉更容易推理。

    所以,当谈到是使用 list of structs 还是 struct of lists 的问题时,我当然更喜欢使用结构列表,即使它会导致性能下降很小。在您的情况下,我预计 structs 版本列表会表现得更好,但我不能保证。您可以随时运行分析。但有一点是肯定的:性能差异远小于AddSimulationObject 中线性搜索的成本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-15
      相关资源
      最近更新 更多