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

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

内容简介: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产生的结果会比较不整齐,统计出来的时间起伏较大

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


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

查看所有标签

猜你喜欢:

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

交互设计

交互设计

. / 刘晓晖、张景 / 电子工业出版社 / 2003-6 / 39.00元

一起来看看 《交互设计》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具