cocos转unity笔记(二)C#的ArrayList和List性能对比

栏目: 编程语言 · IOS · 发布时间: 9年前

内容简介:cocos转unity笔记(二)C#的ArrayList和List性能对比

接上篇,发现一个神奇的现象,List<object>的存储速度比List<T>的速度要快

性能测试准备

既然要做性能测试,那我们肯定需要一个 工具 来统计代码块运行时间。C#里有现成的时间函数供我们使用,一般都是这么写:

var time1 = System.DateTime.Now;
// 会花掉很多时间的代码
var time2 = System.DateTime.Now;
var diff = time2.Subtract(time1);
Console.WriteLine("Time Cost: {0}ms", diff.TotalMilliseconds);

有点儿麻烦,那我封装一下好了,成这样:

class TimeCount
{
    private DateTimem_startTime;
    private bool m_started;
 
    public TimeCount()
    {
        m_started = false;
        m_startTime = System.DateTime.Now;
    }
 
    public void start()
    {
        m_started = true;
        m_startTime = System.DateTime.Now;
    }
 
    public double stop()
    {
        if (!m_started)
        {
            return 0;
        }
        TimeSpandiff = System.DateTime.Now.Subtract(m_startTime);
        double ret = diff.TotalMilliseconds;
        return ret;
    }
};

直接调用Start和End就行

ArrayList和List<object>

现在网上所有的说法都不赞同使用ArrayList这个非泛型容器。理由是:

  1. 效率低下,涉及基本类型的保存时会产生装箱拆箱的操作,损失很大一部分性能
  2. 就算有时候我们有需要Listobject这样的容器,但是还是尽量写成Listobj,写成ArrayList会和其他List显得不整齐

是这样没错,尤其是第二条,所以我们直接抛弃掉ArrayList的写法实际上,ArrayList和Listobj的效率是一样的,用如下代码测试:

System.Collections.ArrayListl0 = new System.Collections.ArrayList();
tc.start();
for (var i = 0; i < 1000000; ++i)
{
    ClassDataitem = new ClassData();
    item.intValue = i;
    l0.Add(item);
}
Console.WriteLine("Time Cost: {0}ms -- create l0", tc.stop());
 
List<object> l1 = new List<object>();
tc.start();
for (var i = 0; i < 1000000; ++i)
{
    ClassDataitem = new ClassData();
    item.intValue = i;
    l1.Add(item);
}
Console.WriteLine("Time Cost: {0}ms -- create l1", tc.stop());

输出结果如下:

cocos转unity笔记(二)C#的ArrayList和List性能对比

于是我们就不再考虑ArrayList了

List<object>和List<T>

这里的T是我们自定义的一个结构体或类

至于这里到底是结构体还是类,测试结果相差很远。

结构体

先看结构体的情况:

struct StructData
{
    public int intValue;
};

接下来是测试代码:

List<int> l3 = new List<int>();
tc.start();
for (var i = 0; i < 1000000; ++i)
{
    l3.Add(i);
}
Console.WriteLine("Time Cost: {0}ms -- create l3", tc.stop());
 
List<object> l4 = new List<object>();
tc.start();
for (var i = 0; i < 1000000; ++i)
{
    l4.Add(i);
}
Console.WriteLine("Time Cost: {0}ms -- create l4", tc.stop());

多执行几次,运行结果如下:

cocos转unity笔记(二)C#的ArrayList和List性能对比

可以看到,当我们打算用List<T>存储结构体时,最好不要用List<object>,因为在存储的时候必须进行装箱的操作,也就是把存储于栈的结构体保存到堆中,这会极大地损耗性能

如果T不是结构体而是一个我们手动new出来的对象,那么理论上就不存在装箱和拆箱的操作了,然后再试试

// 类的声明
class ClassData
{
    public int intValue;
};
 
// 测试代码
List<object> l1 = new List<object>();
tc.start();
for (var i = 0; i < 1000000; ++i)
{
    ClassDataitem = new ClassData();
    item.intValue = i;
    l1.Add(item);
}
Console.WriteLine("Time Cost: {0}ms -- create l1", tc.stop());
 
List<ClassData> l2 = new List<ClassData>();
tc.start();
for (var i = 0; i < 1000000; ++i)
{
    ClassDataitem = new ClassData();
    item.intValue = i;
    l2.Add(item);
}
Console.WriteLine("Time Cost: {0}ms -- create l2", tc.stop());

同样多执行几次,运行结果如下:

cocos转unity笔记(二)C#的ArrayList和List性能对比

咦,List<MyClass>的速度居然还不如List<object>

我也不太清楚为啥会这样,估计是List<MyClass>存的时候需要进行类型检查,这一步消耗了一定的时间吧

其实这一篇也没啥实际意义,在实际的应用中还是尽量用List<MyClass>吧,既不用考虑装箱导致的性能损耗,又能保证类型安全,损失的部分性能也是可以接受的,除非某些对应能特别敏感的需求。

PS. 新的发现,在List<object>和List<T>的对比中,使用macOS下的monoDevelop产生的结果会比较整齐,在Windows10下使用VS2015产生的结果会比较不整齐,统计出来的时间起伏较大

下一篇开始正儿八经做游戏啦


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Code

Code

Charles Petzold / Microsoft Press / 2000-10-21 / USD 29.99

Paperback Edition What do flashlights, the British invasion, black cats, and seesaws have to do with computers? In CODE, they show us the ingenious ways we manipulate language and invent new means of ......一起来看看 《Code》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具