C#静态类成员和System.Windows.Controls.Image性能问题
我目前正在调查一个应用程序中的性能问题,并强调了以下几点: 我有一节课-C#静态类成员和System.Windows.Controls.Image性能问题,c#,performance,static-members,C#,Performance,Static Members,我目前正在调查一个应用程序中的性能问题,并强调了以下几点: 我有一节课- public static class CommonIcons { ... public static readonly System.Windows.Media.ImageSource Attributes = typeof(CommonIcons).Assembly.GetImageFromResourcePath("Resources/attributes.png"); ... } 作为一个
public static class CommonIcons
{
...
public static readonly System.Windows.Media.ImageSource Attributes = typeof(CommonIcons).Assembly.GetImageFromResourcePath("Resources/attributes.png");
...
}
作为一个测试线束,我有以下代码使用这个类来显示问题-
for (int loop = 0; loop < 20000; loop++)
{
// store time before call
System.Windows.Controls.Image image = new System.Windows.Controls.Image
{
Source = CommonIcons.Attributes,
Width = 16,
Height = 16,
VerticalAlignment = VerticalAlignment.Center,
SnapsToDevicePixels = true
};
// store time after call
// log time between before and after
for(int-loop=0;loop<20000;loop++)
{
//通话前储存时间
System.Windows.Controls.Image=新建System.Windows.Controls.Image
{
Source=CommonIcons.Attributes,
宽度=16,
高度=16,
垂直对齐=垂直对齐。中心,
SnapsToDevicePixels=true
};
//通话后存储时间
//记录之前和之后之间的时间
}
在循环开始时,时间差小于0.001秒,但在20000次循环后,时间差增加到0.015秒
如果我不使用静态成员并直接引用我的图标,那么我就没有性能命中,即
for (int loop = 0; loop < 20000; loop++)
{
// store time before call
System.Windows.Controls.Image image = new System.Windows.Controls.Image
{
Source = typeof(CommonIcons).Assembly.GetImageFromResourcePath("Resources/attributes.png"),
Width = 16,
Height = 16,
VerticalAlignment = VerticalAlignment.Center,
SnapsToDevicePixels = true
};
// store time after call
// log time between before and after
for(int-loop=0;loop<20000;loop++)
{
//通话前储存时间
System.Windows.Controls.Image=新建System.Windows.Controls.Image
{
Source=typeof(CommonIcons.Assembly.GetImageFromResourcePath(“Resources/attributes.png”),
宽度=16,
高度=16,
垂直对齐=垂直对齐。中心,
SnapsToDevicePixels=true
};
//通话后存储时间
//记录之前和之后之间的时间
}
但是在我的真实程序中,我不想在每次调用时都创建imagesource(在垃圾收集之前增加内存),因此使用静态成员。然而,我也无法忍受这场演出的冲击
有人能解释一下为什么原始代码会产生这种性能冲击吗?还有一个更好的解决方案,我想做什么
谢谢闻起来像是垃圾收集的味道。我想知道
图像源
和图像
之间是否存在某种耦合,这在您的第一个案例中会导致问题。您是否查看了测试线束在每种情况下的内存使用情况
出于兴趣,如果在每次迭代结束时将
源设置为null,会发生什么?我知道这有点傻,但这是一个测试工具的自然推论:)这可能进一步表明它是源和图像之间的链接…你能在CommonIcons类中只存储像“Resources/attributes.png”这样的常量字符串吗?区别不在于静态成员与否,但在第一个版本中,您创建了20000个图像,所有图像都具有相同的图像源。我不知道到底发生了什么,但在引擎盖下可能会自动创建代理来处理imagesource和image之间的通信,每次imagesource中发生事件时,都需要通知20000个客户端,因此这是一个巨大的性能损失
在第二个版本中,20000个创建的图像中的每一个都有自己的图像源,因此您不会遇到这种开销
注意您应该始终使用其dispose()
-方法处理图像等图形对象。处理完这些对象后,这将稍微加快应用程序的速度,并降低一般内存使用率。只是出于兴趣,如果您在发布模式下运行代码或打开优化,使用静态版本会发生什么?在发布模式下运行会显示同样的情况。发布可以在我们的机器上运行的代码。至少缺少扩展方法。我已经更新了上面的名称空间,这足以让您运行吗?对于第一种情况,内存使用增加。在结束时强制垃圾收集不会释放内存。对于第二种情况,内存使用量增加得更多,但在最后强制执行垃圾回收会释放内存备份。我在测试工具中采纳了您的建议,并在每次迭代结束时将源代码设置为null,这样就可以在不再影响性能的情况下工作。为什么会这样?谢谢:)@TheBlackKnight:嗯,大概ImageSource
以某种方式创建了一个图像列表。这可以防止图像被垃圾收集,所以在第一种情况下,GC压力是恒定的。解决方法:不要这样做:)在处理完图像后清除图像源。谢谢你的回答。System.Windows.Controls.Image没有dispose方法(System.Drawing.Image有)。