编程杂谈——std::vector与List<T>的性能比较
- 2019 年 10 月 17 日
- 筆記
昨天在比较完C++中std::vector的两个方法的性能差异并留下记录后——编程杂谈——使用emplace_back取代push_back,今日尝试在C#中测试对应功能的性能。
C#中对应std::vector的数据结构为List
std::vector – List
std::list – LinkedList
std::map – Dictionary<K, V>
std::set – HashSet
std::multimap – Dictionary<K, List>
C#的测试代码如下:
using System; using System.Collections.Generic; using System.Diagnostics; namespace ConsoleApp { class Item { public string Name { get; set; } } class Program { static void Main(string[] args) { var sw = new Stopwatch(); sw.Start(); var count = 100000; var l = new List<Item>(); for (int i = 0; i < count; i++) { l.Add(new Item { Name = "Test" }); } Console.WriteLine(sw.ElapsedMilliseconds / 1000.0); } } }
程序执行结果约为0.077(该值每次会发生少许变化)
而C++的测试代码的结果约是0.207。这就有违于我们一般的认知了,毕竟通常都觉得C++的性能要优于C#。
#include <iostream> #include <vector> #include <chrono> class Item { public: Item(std::string name):name(name){} private: std::string name; }; int main() { std::vector<Item> v; int count = 100000; v.reserve(count); clock_t begin_time = clock(); for (auto i = 0; i < count; i++) { v.emplace_back("Test"); } std::cout << float(clock() - begin_time) / CLOCKS_PER_SEC << std::endl; }
原来这里犯了个错误,如果要进行基准测试的话,必须要在Release模式下进行。
当改成Release模式后,C++的代码执行时间变成了0.003,而C#也下降到了0.061左右。
不过在上述C#代码中,缺少一点优化,var l = new List<Item>();
没有预设容量值,如果改成var l = new List<Item>(count);
,执行时间进一步下降至0.050左右。
然而C#代码还可以继续优化,将Item类改成结构体后,结果变成了0.006。
struct Item { public string Name { get; set; } }
如果把C++代码中也同样改成结构体,则几乎没有获得什么优化。
struct Item { public: Item(std::string name):name(name){} private: std::string name; };
最后将测试数据量从10W加至1000W后,C++代码的执行时间约是0.286,而C#的约为0.627。同样是2倍左右的差距。
值得注意的是,上述的C#代码是在.NET Core 3.0基础上测试,如果改成.NET Framwork 4.8,执行时间会降为0.536左右。由此可见,.NET Core应该还留有不少可以优化的地方,希望其在性能方面上能够进一步改善。