好的,我想对我做以下似乎是一个好主意,所以如果没有办法做我要问的事情,我相信这是一个合理的选择。
无论如何,我有一个稀疏矩阵。它很大,大多是空的。我有一个名为MatrixNode的类,它基本上是矩阵中每个单元格的包装器。通过它,您可以获取并设置该单元格的值。它还具有Up,Down,Left和Right属性,返回指向相应单元格的新MatrixNode。
现在,由于矩阵基本上是空的,因此每个单元的实时节点(包括空单元)都是不可接受的内存开销。另一种解决方案是每次请求节点时创建MatrixNode的新实例。这将确保只有所需的节点保存在内存中,其余节点将被收集。我不喜欢的是每次都必须创建一个新对象。我很害怕它太慢了。
所以这就是我想出来的。有一个对节点的弱引用的字典。请求节点时,如果该节点不存在,则字典会创建该节点并将其存储为弱引用。如果节点已经存在(可能在某处引用),它只返回它。 然后,如果节点没有剩余任何实时引用,而不是收集它,我想将它存储在池中。稍后,当需要一个新节点时,我想首先检查该池是否为空,如果没有一个已经可用的节点可以只更换它,那么我只想创建一个新节点。
可以这样做吗? 一个更好的问题是,.NET已经为我做了这个吗?我是否正确地担心大量创建单一用途对象的性能?
答案 0 :(得分:1)
您应该进行性能测试,看看是否存在任何问题,而不是猜测。您可能会惊讶地发现,托管内存分配通常可以胜过显式分配,因为当您的数据超出范围时,您的代码不必为解除分配付费。
只有在频繁分配新对象以至于垃圾收集器无法收集它们时,性能才会成为问题。
也就是说,C#中已经存在稀疏数组实现,如Math.NET和MetaNumerics。这些库已针对性能进行了优化,可能会避免在从stratch开始实施时遇到的性能问题
c#和稀疏矩阵的SO search会返回许多相关问题,包括指向商业图书馆的答案,例如ILNumerics(有社区版),NMath和{{3}的库
答案 1 :(得分:1)
大多数稀疏矩阵实现使用一些众所周知的方案作为其数据;我通常建议使用CSR或CSC,因为它们对于常见操作非常有效。
如果这看起来太复杂,您可以开始使用COO。这在您的代码中意味着您不会为空成员存储任何内容;但是,每个非空的都有一个项目。一个简单的实现可能是:
public struct SparseMatrixItem
{
int Row;
int Col;
double Value;
}
你的矩阵通常是一个简单的容器:
public interface SparseMatrix
{
public IList<SparseMatrixItem> Items { get; }
}
您应该确保Items列表根据行和col索引保持排序,因为这样您就可以使用二进制搜索来快速找出某个项是否存在特定的(i,j)。
答案 2 :(得分:1)
拥有人们使用然后返回池的对象池的想法用于真正昂贵的对象。表示网络连接的对象,新线程等。听起来您的对象非常小且易于创建。鉴于此,你几乎肯定会损害它的性能;管理池的开销将大于每次创建新池的成本。
具有大量短暂的非常小的对象是GC 设计以便快速处理的确切情况。创建一个新对象很便宜;它只是向上移动一个指针并清除该对象的位。当一个新的垃圾收集发生时,对象的实际开销就会出现;为此,它需要找到所有“活着的”物体并移动它们,将所有“死”的物体留在原处。如果你的小对象没有通过单个集合,它几乎没有增加任何开销。将对象保持很长时间(例如,通过将它们合并以便您可以重用它们)意味着将它们复制到多个集合中,从而消耗相当多的资源。