高频率地创建类的短期新实例是否效率低下?

我有一个C#程序跟踪玩家在游戏中的位置。 在这个程序中,我有一个名为Waypoint(X,Y,Z)的类,它代表游戏地图上的一个位置。 在我产生的其中一个线程中,我一直在检查玩家与某个目标Waypoint的距离,在while(true)循环中相互之后非常快。 在Waypoint类中有一个名为public double Distance(Waypoint wp)的方法,它计算从当前航点到作为参数传递的航点的距离。

问题:每次我想检查玩家到目标航路点的距离时,是否可以为玩家的位置创建一个新的Waypoint? 然后程序可能会在一段时间(真实)循环中反复创建此玩家Waypoint,仅用于计算距离。

PS:我的程序可能需要巧妙地使用资源,因为它运行多个线程,连续的while循环执行各种工作,例如将玩家的X,Y,Z位置发布到UI。

非常感谢!

实际创建一个寿命很短的对象是微不足道的。 创建一个新对象几乎只涉及通过对象的大小增加堆指针并将这些位清零。 这不会成为问题。

至于这些对象的实际集合,当垃圾收集器执行集合时,它会使所有对象仍处于活动状态并复制它们。 此处GC不会触及任何“活动”的对象,因此它们不会向集合添加工作。 如果您创建的对象从未或非常非常罕见,在GC集合期间仍处于活动状态,那么它们就不会增加任何成本。

他们可以做的一件事是减少当前可用内存的数量,这样GC需要比其他情况更频繁地执行收集。 当GC需要更多内存时,它会实际执行一个集合。 如果你经常使用所有可用内存创建这些短期对象,那么你可以提高程序中的集合率。

当然,实际上会对集合发生的频率产生有意义的影响需要很多对象。 如果你担心,你应该花一些时间来衡量你的程序在有和没有这段代码的情况下执行集合的频率,看看它有什么影响。 如果你真的导致集合发生的频率比其他情况要高得多,并且你注意到性能问题,那么考虑尝试解决这个问题。

如果您发现集合数量有了可测量的增长,那么解决这个问题有两种途径可以解决。 您可以研究使用值类型而不是引用类型的可能性。 这在概念上可能对您有意义,也可能没有意义,它可能会或可能不会真正帮助解决问题。 它在很大程度上取决于未提及的具体细节,但至少要考虑一下。 另一种可能性是尝试积极地缓存对象,以便可以随着时间的推移重新使用它们。 这也需要仔细研究,因为它可能会大大增加程序的复杂性,使编写正确,可维护且易于推理的程序变得更加困难,但它可以成为重新引入内存的有效工具。使用正确。

其他答案所说的是:
– 也许你应该制作堆栈本地实例,因为它不应该花费太多,并且
– 也许你不应该这样做,因为内存分配可能代价高昂。
这些是猜测 – 有根据的猜测 – 但仍然是猜测。

你是唯一能够回答这个问题的人,通过实际发现(而不是猜测)这些新闻是否占据了足够多的挂钟时间值得担心。

我(以及许多其他人)依赖于回答这类问题的方法是随机暂停

这个想法很简单。 假设这些新闻,如果以某种方式被淘汰,将会节省 – 选择一个百分比,如20% – 的时间。 这意味着如果你只是点击暂停按钮并显示调用堆栈,你至少有20%的机会在行动中捕获它。 因此,如果你这样做20次,你会看到它大约做了4次,给予或接受。

如果你这样做,你会看到什么是时间的。
– 如果是新闻,你会看到它。
– 如果它是其他东西,你会看到它。
你不会确切知道它的成本,但你不需要知道。
你需要知道的是问题是什么,这就是它告诉你的。


补充:如果你能帮我解释一下这种性能调整是如何进行的,这里是一个假设情况的例证:
在此处输入图像描述
当您采用堆栈样本时,您可能会发现许多可以改进的事情,其中​​一个可能是内存分配,甚至可能不是很大,因为在这种情况下它是(C)只占14% 。 它告诉你其他东西需要花费更多时间,即(A)。

因此,如果您修复(A),您将获得1.67x的加速因子。 不错。

现在,如果你重复这个过程,它会告诉你(B)会节省你很多时间。 所以你修复它并(在这个例子中)获得另一个1.67x,总体加速为2.78x。

现在你再次这样做,你会发现你怀疑的原始内存,内存分配确实是很大一部分时间。 所以你修复它并(在这个例子中)获得另一个1.67x,总体加速为4.63x。 现在这是一个严重的加速。

所以重点是1)保持开放的思路,加快速度 – 让诊断告诉你要解决的问题,2)重复这个过程,进行多次加速。 这就是你如何获得真正的加速,因为当你修剪掉其他东西时,开始时很小的东西会变得更加重要。