我目前正在调查应用程序中的性能问题,并强调了以下内容;
我有一个班级 -
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
}
在循环开始时,时差小于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
}
但在我的真实世界程序中,我不想在每次调用时创建imagesource(增加内存直到垃圾收集),因此使用静态成员的原因。但是我也无法忍受性能打击。
有人可以解释为什么原始代码会产生这种性能影响吗?还有一个更好的解决方案,我正在尝试做什么?
由于
答案 0 :(得分:1)
它闻起来与垃圾收集有关。我想知道ImageSource
和Image
之间是否存在某种耦合,这会导致第一种情况出现问题。您是否想过了解每种情况下测试工具的内存使用情况?
出于兴趣,如果在每次迭代结束时将Source
设置为null会发生什么?我知道这有点傻,但那是它作为测试工具的一个自然结果:)它可能进一步表明它是源和图像之间的链接......
答案 1 :(得分:0)
你能在CommonIcons类中只存储像“Resources / attributes.png”这样的常量字符串吗?
答案 2 :(得分:0)
区别在于静态成员与否之间,但在第一个版本中,您创建的20000个图像都具有相同的图像源。我不确切知道发生了什么,但是在幕后可能会有自动创建的委托来处理imagesource和image之间的通信,每次如果在imagesource中发生事件,就需要通知20000个客户端,所以这是一个很大的表现很受欢迎。
在第二个版本中,20000个创建的图像中的每一个都有自己的图像源,因此您不会遇到这种开销。
注意您应该在完成后使用Dispose()
- 方法处理图像等图形对象,这样可以加快应用程序的速度并降低一般内存使用量