c#中用于高速应用程序的内存管理
本文关键字:内存 管理 应用程序 高速 用于 | 更新日期: 2023-09-27 18:10:12
我正在构建一个应用程序,该应用程序处理来自文件或缓冲区的传入图像,并以固定大小的数组或双精度对象的形式输出结果。应用程序需要相对快速。我遇到了一个循环时间的问题。我在处理一张图像时开始记录循环时间,它从最小的65ms开始逐渐增加到500ms,这实在是太慢了。果然,我检查了内存使用情况,它也在稳步增长。
我在每个周期后运行GC,并尽可能多地转储未使用的变量。我不在处理循环中创建新对象。图像处理在它自己的线程上完成,因此所有的资源都被转储。似乎大部分周期时间增加发生在我从文件中提取图像时。我还能错过什么呢?
这里是粗略的代码,完整的东西相当大。主要功能>
public void Vision()
{
Stopwatch sw = new Stopwatch();
sw.Start();
try
{
AlignmentParams.ApproximateNumberToFind = 1;
AlignmentParams.SearchRegionMode = 0;
AlignmentResult = AlignmentPat.Execute(cogDisplay1.Image as CogImage8Grey, null , AlignmentParams);
Fixture.InputImage = cogDisplay1.Image;
Fixture.RunParams.UnfixturedFromFixturedTransform = AlignmentResult[0].GetPose();
Fixture.Run();
AlignmentResult = null;
#region FindLineTools
#endregion
#region FindEllipse
#endregion
sw.Stop();
SetText("V" + sw.ElapsedMilliseconds.ToString() + Environment.NewLine);
}
catch (Exception err)
{
SetText(Environment.NewLine + "***********Error***********" + Environment.NewLine);
SetText(err.ToString() + Environment.NewLine);
SetText("***************************" + Environment.NewLine);
}
}
首先,我建议发布一个干净的代码,以获得更好的可读性(删除所有注释掉的东西)。其次,只关注最重要的部分,即:您的问题是由于繁重的图像处理导致的内存过度使用/泄漏(如果错误,请纠正)。因此,在名为Vision
的线程中,在处理完成后立即取消对图像对象的引用并将其设置为null(如上所述,GC在您的情况下没有多大帮助)。下面的代码片段简要地演示了这个概念:
public void Vision()
{
Stopwatch sw = new Stopwatch();
sw.Start();
try
{
AlignmentParams.ApproximateNumberToFind = 1;
AlignmentParams.SearchRegionMode = 0;
AlignmentResult = AlignmentPat.Execute(cogDisplay1.Image as CogImage8Grey, null , AlignmentParams);
Fixture.InputImage = cogDisplay1.Image;
Fixture.RunParams.UnfixturedFromFixturedTransform = AlignmentResult[0].GetPose();
Fixture.Run();
AlignmentResult = null;
// your coding stuff
sw.Stop();
SetText("V" + sw.ElapsedMilliseconds.ToString() + Environment.NewLine);
}
catch (Exception err)
{
SetText(Environment.NewLine + "***********Error***********" + Environment.NewLine);
SetText(err.ToString() + Environment.NewLine);
SetText("***************************" + Environment.NewLine);
}
finally{Fixture.InputImage=null}
不要调用GC.Collect。让虚拟机决定什么时候内存不足,什么时候必须进行收集。您通常不能很好地决定GC的最佳时间。收集,除非您正在运行其他心跳或空闲的监视线程。
其次,确保您从方法调用中接收到的任何资源都被dispose了。将变量设置为NULL不会这样做,你应该显式地调用Dispose或Using块:
using(SomeResource resource = Class.GiveMeResource("image.png"))
{
int width = resource.Width;
int height = resource.Height;
Console.Write("that image has {0} pixels", width*height);
} //implicitly calls IDisposable.Dispose() here.
您还需要做一些内存和调用分析来检测哪里(如果有的话)存在泄漏