2

我决定在 C# 和 C++ 中对读取图像进行基准测试,以决定在我正在考虑为自己制作的项目中使用哪种语言。
我预计基准测试将与 C++ 非常接近,可能会稍微向前推进。

C# 代码每次运行大约需要 300 毫秒(我每个测试运行 100 次),而 C++ 代码大约需要 1.5 毫秒。

那么我的 C# 代码错了吗?我是否对它进行了糟糕的基准测试?还是真的就这么慢?

这是我使用的 c# 代码:

Stopwatch watch = new Stopwatch();

watch.Start();
Image image = Image.FromFile(imagePath);
watch.Stop();

Console.WriteLine("DEBUG: {0}", watch.ElapsedMilliseconds);

C ++代码几乎可以归结为:

QueryPerformanceCounter(&start);
Image * img = Image::FromFile(imagePath);
QueryPerformanceCounter(&stop);
delete img;
return (stop.QuadPart - start.QuadPart) * 1000.0 / freq.QuadPart;

无论哪种语言,它们都需要以 Image 对象结尾,因为它提供了我需要的功能。

==================================================== ======================

正如 xanatos 在评论中指出的那样, Image.FromFile 确实进行了检查。

更具体地说,这是:

num = SafeNativeMethods.Gdip.GdipImageForceValidation(new HandleRef(null, zero));
if (num != 0)
{
    SafeNativeMethods.Gdip.GdipDisposeImage(new HandleRef(null, zero));
    throw SafeNativeMethods.Gdip.StatusException(num);
}

改用 Image.FromStream() 可以避免这种情况。

我想知道的是,如果您确实避免这种情况并尝试加载无效的图像文件,则会引发 OutOfMemory 异常。
而在 C++ 中,您不会进行这样的检查。那么这个检查有多重要呢?谁能给我一个避免这种情况不好的情况?

4

2 回答 2

7

是的,你的基准是有缺陷的。问题是您忘记对位图进行实际操作。喜欢画它。

GDI+ 极大地优化了图像的加载。非常类似于 .NET 优化加载程序集的方式。它只做必要的事情,它读取文件的标题以检索基本属性。格式、宽度、高度、Dpi。然后它创建一个内存映射文件以创建到文件中像素数据的映射。但实际上并没有读取像素数据。

现在差异开始发挥作用。System.Drawing.Image 接下来实际读取像素数据。这会导致页面错误,操作系统现在读取文件并将像素数据复制到 RAM 中。非常可取的是,如果文件有任何问题,那么您将在 FromFile() 调用时收到异常,而不是稍后,通常是当您的程序绘制图像并埋在您没有编写的框架代码中时。您的 C# 代码基准乘以 mmf 的创建加上像素数据的读取。

C++ 程序也总是需要为读取像素数据付费。但是您没有衡量这一点,您只衡量了创建 MMF 的成本。

于 2012-07-18T17:56:38.413 回答
-2

我知道的几点

有一种东西叫做CLR。如果上述c++框架(好像是Qt)使用了不依赖.net框架的系统调用,那么显然它会运行得很快。

关于 c# => 可以在代码中调用它之前加载该程序集。如果你这样做,那么你会发现它的牢度很好。

如果你使用windows平台,那么除非有必要,否则MS不会降低自己语言的执行速度。

于 2014-03-12T08:29:03.713 回答