我在CodeFluent中遇到了内存泄漏问题,因为对象的ListCollections的事件处理程序维护了对我不再需要的对象的引用。解决方案是将实体的收集类型更改为List而不是ListCollection。这就解决了内存泄漏的问题。
但是,现在我注意到List比ListCollection慢得多。每次Codefluent检查对象是否已在列表中时,都将其添加到列表中。这将在对象中触发BaseContains方法。91%的CPU花费在这里(使用ANTS进行性能分析)。我已经用CPU百分比标记了热路径。
函数LoadByMainCwEntity包含以下代码块:
for (readerRead = reader.Read(); ((readerRead == true)
&& ((count < this.MaxCount)
&& (count < pageSize))); readerRead = reader.Read())
{
readCount = (readCount + 1);
if ((CodeFluent.Runtime.CodeFluentPersistence.CanAddEntity(pageIndex, pageSize, pageOptions, readCount) == true))
{
Runtime.CwObject cwObject = new Runtime.CwObject();
((CodeFluent.Runtime.ICodeFluentEntity)(cwObject)).ReadRecord(reader);
91% CPU >> if ((this.BaseContains(cwObject) == false))
{
this.BaseAdd(cwObject);
count = (count + 1);
}
cwObject.EntityState = CodeFluent.Runtime.CodeFluentEntityState.Unchanged;
}
}
哪个叫:
protected virtual bool BaseContains(Runtime.CwObject cwObject)
{
if ((cwObject == null))
{
return false;
}
91% CPU >> bool localContains = this.BaseList.Contains(cwObject);
return localContains;
}
哪个叫:
public virtual bool Equals(Runtime.CwObject cwObject)
{
if ((cwObject == null))
{
return false;
}
29% CPU >> if ((this.Guid.Equals(CodeFluentPersistence.DefaultGuidValue) == true))
{
return base.Equals(cwObject);
}
45% CPU >> return (this.Guid.Equals(cwObject.Guid) == true);
}
所有方法似乎都很简单。我认为问题出在人数上。如果我有100.000个对象的列表,并且Codefluent添加了100.001的数字,它将检查所有其他100.000个对象以找到匹配项。不断增长的集合将成倍地减慢.Add方法的速度。
在Codefluent的正常“加载”操作中检查对象是否已在集合中似乎有些奇怪。有什么解决方法,还是我应该只接受Codefluent中的大型列表速度真的很慢的事实?
SoftFluent通过消除一些检查和通用性,创建了一个可以提高所生成代码性能的方面:博客文章,GitHub上的代码。在Frans Bouma提供的基准测试中,使用此方面,在手动编码查询之后,CodeFluent实体排名第二。
如果仅确定了少数在应用程序上下文中缓慢的加载方法,则可以创建自定义C#方法,这些方法使用生成的代码返回自定义集合。例如,您可以创建一个返回IEnumerable<T>
而不是生成的集合的方法:
static IEnumerable<Order> LoadOrders()
{
using (IDataReader reader = OrderCollection.PageDataLoadAll(null))
{
while (reader.Read())
{
Order o = new Order();
o.RaisePropertyChangedEvents = false;
((ICodeFluentEntity)o).ReadRecord(reader);
yield return o;
}
CodeFluentPersistence.CompleteCommand(Constants.NorthwindStoreName);
}
}
更新
该fastReader
当您选择表面上的财产属性,应当在属性网格可见。您必须选择“方面和生产者属性”选项卡:
<cf:descriptor name="fastReader" targets="Property" defaultValue="false" displayName="Enable Fast Reader" typeName="boolean" description="Determines if the fast reder is enabled for collection loading." category="Faster Reader Aspect" />
该方面将删除自动转换(CodeFluentPersistence.GetReaderValue
),并期望存储过程返回所有列。在某些情况下,它可能不起作用。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句