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