# 也谈谈性能：局部性与性能的实验观察

Bitmap
{
Width,Height;
Data;
}

for(int y = 0; y<xxx.Height; y++)
{
for(int x = 0; x < xxx.Width; x++)
{
Data[x,y] = ....
}
}

int width = xxx.Width;
int height = xxx.Height;
for(int y = 0; y<height ; y++)
{
for(int x = 0; x <width ; x++)
{
Data[x,y] = ....
}
}

====

public class Image
{
public int Width { get; set; }
public int Height { get; set; }
}

public class Bitmap : Image
{
public int[] Data;

public Bitmap(int width, int height)
{
this.Width = width;
this.Height = height;
Data = new int[width*height];
}

public void Fill(int value)
{
int height = Height;
int width = Width;

for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
Data[y * width + x] = value;
}
}
}

public void FillEx(int value)
{
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
Data[y * Width + x] = value;
}
}
}

public static void Test()
{
Bitmap img = new Bitmap(5000, 6000);
CodeTimer.Time("Fill", 1, () => { img.Fill(1); });
CodeTimer.Time("FillEx", 1, () => { img.FillEx(2); });
CodeTimer.Time("Fill", 1, () => { img.Fill(1); });
CodeTimer.Time("FillEx", 1, () => { img.FillEx(2); });
CodeTimer.Time("Fill", 1, () => { img.Fill(1); });
CodeTimer.Time("FillEx", 1, () => { img.FillEx(2); });
CodeTimer.Time("Fill", 1, () => { img.Fill(1); });
CodeTimer.Time("FillEx", 1, () => { img.FillEx(2); });
}
}

 1 2 3 4 Fill 126(82) 83 84 85 FillEx 100(141) 99 100 99

“1”列结果中括号数据是将Fill和FillEx执行顺序互换后的测试结果。可以发现，同一个类中，首次执行的方法吃点亏。对于这个测试来说，吃 40 ms 的亏。比较2，3，4可以看出，FillEx要比Fill慢一点。

====

public class UnmanagedBitmap : Image
{
public IntPtr Data;

public UnmanagedBitmap(int width, int height)
{
this.Width = width;
this.Height = height;
Data = Marshal.AllocHGlobal(sizeof(int) * width * height);
}

public unsafe void Fill(int value)
{
int height = Height;
int width = Width;
int* p = (int*)Data;

for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
*p = value;
p++;
}
}
}

public unsafe void FillEx(int value)
{
int* p = (int*)Data;
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
*p = value;
p++;
}
}
}

public static void Test()
{
UnmanagedBitmap img = new UnmanagedBitmap(5000, 6000);
CodeTimer.Time("Fill", 1, () => { img.Fill(1); });
CodeTimer.Time("FillEx", 1, () => { img.FillEx(2); });
CodeTimer.Time("Fill", 1, () => { img.Fill(1); });
CodeTimer.Time("FillEx", 1, () => { img.FillEx(2); });
CodeTimer.Time("Fill", 1, () => { img.Fill(1); });
CodeTimer.Time("FillEx", 1, () => { img.FillEx(2); });
CodeTimer.Time("Fill", 1, () => { img.Fill(1); });
CodeTimer.Time("FillEx", 1, () => { img.FillEx(2); });
}
}

 1 2 3 4 Fill 128(83) 93 84 84 FillEx 88(123) 90 84 84

====

for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
Data[y * Width + x] = value;
}
}

public unsafe void FillEx(int value)
{
int* p = (int*)Data;
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
*p = value;
p++;
}
}
}

====

public unsafe void ToBitmap(Bitmap map)
{
if (map == null) throw new ArgumentNullException("map");
if (map.Width != this.Width || map.Height != this.Height)
{
throw new ArgumentException("尺寸不匹配.");
}

if (map.PixelFormat != PixelFormat.Format32bppArgb)
{
throw new ArgumentException("只支持 Format32bppArgb 格式。 ");
}

Int32 step = SizeOfT();
Byte* t = (Byte*)StartIntPtr;

BitmapData data = map.LockBits(new Rectangle(0, 0, map.Width, map.Height), ImageLockMode.ReadWrite, map.PixelFormat);
try
{

int width = map.Width;
int height = map.Height;

Byte* line = (Byte*)data.Scan0;

for (int h = 0; h < height; h++)
{
Argb32* c = (Argb32*)line;
for (int w = 0; w < width; w++)
{
m_converter.Copy(t, c);
t += step;
c++;
}
line += data.Stride;
}
}
finally
{
map.UnlockBits(data);
}
}

public unsafe void ToBitmapEx(Bitmap map)
{
if (map == null) throw new ArgumentNullException("map");
if (map.Width != this.Width || map.Height != this.Height)
{
throw new ArgumentException("尺寸不匹配.");
}

if (map.PixelFormat != PixelFormat.Format32bppArgb)
{
throw new ArgumentException("只支持 Format32bppArgb 格式。 ");
}

Int32 step = SizeOfT();
Byte* t = (Byte*)StartIntPtr;

BitmapData data = map.LockBits(new Rectangle(0, 0, map.Width, map.Height), ImageLockMode.ReadWrite, map.PixelFormat);
try
{
Byte* line = (Byte*)data.Scan0;

for (int h = 0; h < map.Height; h++)
{
Argb32* c = (Argb32*)line;
for (int w = 0; w < map.Width; w++)
{
m_converter.Copy(t, c);
t += step;
c++;
}
line += data.Stride;
}
}
finally
{
map.UnlockBits(data);
}
}

public static void Test()
{
ImageArgb32 src = new ImageArgb32(5000, 6000);
System.Drawing.Bitmap dst = new System.Drawing.Bitmap(5000, 6000, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
CodeTimer.Time("ToBitmap",1,()=>{ src.ToBitmap(dst);});
CodeTimer.Time("ToBitmapEx", 1, () => { src.ToBitmapEx(dst); });
CodeTimer.Time("ToBitmap", 1, () => { src.ToBitmap(dst); });
CodeTimer.Time("ToBitmapEx", 1, () => { src.ToBitmapEx(dst); });
CodeTimer.Time("ToBitmap", 1, () => { src.ToBitmap(dst); });
CodeTimer.Time("ToBitmapEx", 1, () => { src.ToBitmapEx(dst); });
CodeTimer.Time("ToBitmap", 1, () => { src.ToBitmap(dst); });
CodeTimer.Time("ToBitmapEx", 1, () => { src.ToBitmapEx(dst); });
}

 1 2 3 4 ToBitmap 354 259 261 260 ToBitmapEx 7451 7441 7440 7445

public unsafe void ToBitmapEx(Bitmap map)
{
if (map == null) throw new ArgumentNullException("map");
if (map.Width != this.Width || map.Height != this.Height)
{
throw new ArgumentException("尺寸不匹配.");
}

if (map.PixelFormat != PixelFormat.Format32bppArgb)
{
throw new ArgumentException("只支持 Format32bppArgb 格式。 ");
}

Int32 step = SizeOfT();
Byte* t = (Byte*)StartIntPtr;

BitmapData data = map.LockBits(new Rectangle(0, 0, map.Width, map.Height), ImageLockMode.ReadWrite, map.PixelFormat);
try
{
Byte* line = (Byte*)data.Scan0;

int width = map.Width;
for (int h = 0; h < map.Height; h++)
{
Argb32* c = (Argb32*)line;
for (int w = 0; w < width; w++)
{
m_converter.Copy(t, c);
t += step;
c++;
}
line += data.Stride;
}
}
finally
{
map.UnlockBits(data);
}
}

 1 2 3 4 ToBitmap 313(263) 261 261 260 ToBitmapEx 268(313) 261 264 261

====

（1）部分情况（实验2），jit可以对程序的局部性做完全优化。

（2）部分情况（实验1），jit可以对程序的局部性做部分优化。

（3）部分情况（实验3），jit对程序的局部性不做优化。

for(int i=0; i< xxx.Width; i++)

{

xxx.Width = 3;

}

jit就不能简单优化成：

int w = xxx.Width;

for(int i=0; i< w; i++)

{

xxx.Width = 3;

}

====

《大唐双龙传》中，寇仲、徐子陵的井中月至境，师仙子的剑心通明，石之轩的入微，伏难陀的梵我不二（tmd黄易这个老小子竟然没给我家可爱的婠婠的天魔功十八层取一个类似井中月至境、剑心通明、入微、梵我不二这样响亮的名字！），都是相通的。

posted @ 2010-07-02 04:59  xiaotie  阅读(4481)  评论(17编辑  收藏