大家好,我是Oleksandr Karpov,这个是我第一次发表文章,希望大家喜欢。
在这我将为大家展示和介绍怎么样在C#和.NET下使用汇编秒速拷贝数据,在我是实例里面我用了一运用程序创建了一段视频,里面包含图片,视频和声音。
当然如果你也需要在C#使用汇编的情况,这方法给你提供一个快速简单的解决途径。
背景
理解本文的内容, 最好具备以下知识: 汇编语言, 内存对齐, c#, windows 和 .net 高级技巧(advanced techniques).
要提高数据复制(copy-past )的速度, 我们需要将内存地址按 16 个字节对齐. 否则, 速度不会有明显的改变. (我的例子大概快 1.02 倍 )
Pentium III+ (KNI/MMX2) 和 AMD Athlon (AMD EMMX) 这两种处理器都支持本文代码用到 SSE 指令集.
我用配置为: Pentium Dual-Core E5800 3.2GHz, 4GB RAM 双通道内存的计算机做测试, 16 个字节内存对齐的速度要比标准方式快 1.5 倍, 而非内存对齐方式的速度几乎没有变化(1.02倍).
使用代码这是一个完整的演示测试,向你展示了性能测试以及如何使用。
FastMemCopy 类包含了用于快速内存拷贝逻辑的所有内容。
首先你需要创建一个默认的Windows Forms应用程序工程,在窗体上放两个按钮,一个PictureBox 控件,因为我们将用图片来测试。
声明几个字段先:
string bitmapPath;
Bitmap bmp, bmp2;
BitmapData bmpd, bmpd2;
byte[] buffer = null;
现在创建两个方法用来处理按钮的点击事件。
标准方法如下:
private void btnStandard_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog())
{
if (ofd.ShowDialog() != System.Windows.Forms.DialogResult.OK)
return;
bitmapPath = ofd.FileName;
}
//open a selected image and create an empty image with the same size
OpenImage();
//unlock for read and write images
UnlockBitmap();
//copy data from one image to another by standard method
CopyImage();
//lock images to be able to see them
LockBitmap();
//lets see what we have
pictureBox1.Image = bmp2;
}
快速方法如下:
private void btnFast_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog())
{
if (ofd.ShowDialog() != System.Windows.Forms.DialogResult.OK)
return;
bitmapPath = ofd.FileName;
}
//open a selected image and create an empty image with the same size
OpenImage();
//unlock for read and write images
UnlockBitmap();
//copy data from one image to another with our fast method
FastCopyImage();
//lock images to be able to see them
LockBitmap();
//lets see what we have
pictureBox1.Image = bmp2;
}
好的,现在我们有按钮并且也有了事件处理,下面来实现打开图片、锁定、解锁它们的方法,以及标准拷贝方法:
打开一个图片:
void OpenImage()
{
pictureBox1.Image = null;
buffer = null;
if (bmp != null)
{
bmp.Dispose();
bmp = null;
}
if (bmp2 != null)
{
bmp2.Dispose();
bmp2 = null;
}
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
bmp = (Bitmap)Bitmap.FromFile(bitmapPath);
buffer = new byte[bmp.Width * 4 * bmp.Height];
bmp2 = new Bitmap(bmp.Width, bmp.Height, bmp.Width * 4, PixelFormat.Format32bppArgb,
Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0));
}
锁定和解锁位图:
void UnlockBitmap()
{
bmpd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite,
PixelFormat.Format32bppArgb);
bmpd2 = bmp2.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite,
PixelFormat.Format32bppArgb);
}
void LockBitmap()
{
bmp.UnlockBits(bmpd);
bmp2.UnlockBits(bmpd2);
}
从一个图片拷贝数据到另一个图片,并且显示测得的时间: