.Net Framework 性能分析——小对象分配

一、实验背景

C++一直有一个被人诟病的问题,就是在大量分配(new&delete)小对象时,性能会有很大的下降。因此,Andrei Alexandrescu 的书中给出了一种快速的小对象分配解决方案。这种方案能比较好的解决小对象分配问题。而C#中,在“Writing Faster Managed Code: Know What Things Cost”一文中作者提到“The amortized cost of creating and later automatically reclaiming an object is sufficiently low that you can create many tens of millions of small objects per second”,于是我就设计了一个实验来比较C++/C#在小对象分配上的速度差异,同时我这个实验也比较了.Net Framework 1.1与.Net Framework 2.0的区别。

二、实验设计

我设计的实验主要验证小对象分配,而且一般情况下小对象分配必然和存储结合的,单纯的new和delete有可能会被编译器优化掉,或者因为系统中的cache原因会影响实验的可靠性。因此在代码中我使用了固定长度的数组作为存储这些小对象指针的地方,以模拟一个分配——储存的过程。

实验中使用的小对象从4字节到1024字节,一共9种不同的小对象大小。以观察不同大小的对象是否有被优化。

实验的计时使用了TickCount,虽然不太准确,但是用于对比已经足够了。

下面先给出C++代码,其中用到简单的template,我机器上的RAND_MAX=0x7fff

template < int  nsize >
struct  smalldata
{
    
int d[nsize];
}
;
struct  smallobj 
{
    
void* data;
}
;
FILE 
* f;
smallobj g_p[RAND_MAX];

template
< int  nsize >
void  test()
{
    memset(g_p,
0,sizeof(g_p));
    DWORD c
=0;
    DWORD a;
    DWORD bt
=GetTickCount();
    
while (c++<10000000)
    
{
        a
=rand();
        
if (g_p[a].data){
            delete g_p[a].data;
            g_p[a].data
=0;
        }

        g_p[a].data
=new smalldata<nsize>;
    }

    DWORD et
=GetTickCount();
    fprintf(f,
"objsize=%d, time=%f ",nsize,(et-bt)/1000.0f);
}

int  _tmain( int  argc, _TCHAR *  argv[])
{
    memset(g_p,
0,sizeof(g_p));
    f
=fopen("a.txt","w+");
    srand( (unsigned)time( NULL ) );
    
    test
<1>();
    test
<2>();
    test
<4>();
    test
<8>();
    test
<16>();
    test
<32>();
    test
<64>();
    test
<128>();
    test
<256>();

    fclose(f);
    
return 0;
}

下面是C#代码,

class  Class1
{
    
public static ArrayList arr;
    
public static Random rand;
    
public static void test(int nsize)
    
{
        
int c=0;
        
int a;
        
int bt=Environment.TickCount;
        
while(c++<10000000)
        
{
            a
=rand.Next(0x7fff);
            arr[a]
=new int[nsize];
        }

        
int et=Environment.TickCount;
        sw.WriteLine(
"objsize={0}, time={1}",nsize,(et-bt)/1000.0);
    }

    
public static StreamWriter sw;


    
/// <summary>
    
/// The main entry point for the application.
    
/// </summary>

    [STAThread]
    
static void Main(string[] args)
    
{
        
//
        
// TODO: Add code to start application here
        
//
        arr=new ArrayList(0x7fff);
        
for (int a=0;a<0x7fff;a++)
        
{
            arr.Add(
null);
        }

        rand
=new Random();
        sw
= new StreamWriter("a.txt");
        test(
1);
        test(
2);
        test(
4);
        test(
8);
        test(
16);
        test(
32);
        test(
64);
        test(
128);
        test(
256);
        sw.Close();
    }

}

三、实验结果

这里我就不给出我机器的具体配置,因为这是一个对比实验,具体数值会因为机器不同而有很大变化的。

 首先是C++程序结果,第一列是实验对象的大小,后面是几次实验的时间(s)

大小(byte)
4             8.359          8.375       8.500        8.359          8.437
8             8.672          8.453       8.421        8.516          8.453
16           8.765          8.672       8.704        8.875          8.657
32           9.204          9.234       9.328        9.265          9.218
64          10.453        10.516     10.593      10.516       10.453
128        12.078        11.984     12.000      12.047       11.969
256        15.281        15.328     15.329      15.234       15.281
512        18.313        18.500     18.187      18.203       18.188
1024      24.094        24.141     24.047      23.828       23.797

 然后是C#的结果,其中结果中前3列是.Net Framework 1.1编译的,后3列是Framework 2.0编译的

4             1.453           1.484        1.468     |    1.297          1.313         1.36
8             1.656           1.672        1.656     |    1.469          1.5              1.515
16           1.969           2.062        1.969     |    1.813          1.812         1.86
32           2.843           3.047        2.796     |    2.609          2.578         2.64
64           4.5                4.531        4.454     |    4.203          4.219         4.219
128         8.282           8.266        8.218     |    7.594          7.594         7.672
256         14.531         14.625     14.828   |    14.844        14.672       14.75
512         29.109         29.141     28.875   |    25.89          25.593       25.609
1024       51.594         51.875     51.11     |    45.281        45.813       45.391

可以看出,在256bytes以下的对象分配上,C#比C++有较大的优势,我觉得这个优势是来自于C#本身对小对象分配的优化以及其GC不是立即释放内存上,这就提供了某些被分配的内存不需要象C++那样先释放再分配,而是可以直接重用。

但是,在256bytes以上时,C#的速度却大大降低,在1024byte上更是只有C++一半的速度。同时我们看到,Framework 2.0在这方面有一点改善,虽然速度提高比例并不多。我觉得这其中有boxing和unboxing的原因,同时也有GC的原因。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值