多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

C# 过滤数据的三种姿势:yield return、LINQ Where、ToList 全景性能对决

C# 过滤数据的三种姿势:yield return、LINQ Where、ToList 全景性能对决 测试代码[MemoryDiagnoser]publicclassYieldBenchmark{privatereadonlyConsumer_consumernewConsumer();[Params(100,10000,100000)]publicintN;privateint[]_intArray;privateMyClass[]_classArray;privateMyStruct[]_structArray;[GlobalSetup]publicvoidSetup(){_intArrayEnumerable.Range(0,N).ToArray();_classArrayEnumerable.Range(0,N).Select(inewMyClass{Valuei}).ToArray();_structArrayEnumerable.Range(0,N).Select(inewMyStruct{Valuei}).ToArray();}// int [Benchmark]publicvoidInt_Yield()YieldInt(_intArray).Consume(_consumer);[Benchmark]publicvoidInt_IfYield()IfYieldInt(_intArray).Consume(_consumer);[Benchmark]publicListintInt_ToList()YieldInt(_intArray).ToList();[Benchmark]publicint[]Int_ToArray()YieldInt(_intArray).ToArray();privatestaticIEnumerableintYieldInt(int[]source){returnsource.Where(xx%20);}privatestaticIEnumerableintIfYieldInt(int[]source){foreach(variteminsource)if(item%20)yieldreturnitem;}// class [Benchmark]publicvoidClass_Yield()YieldClass(_classArray).Consume(_consumer);[Benchmark]publicvoidClass_IfYield()IfYieldClass(_classArray).Consume(_consumer);[Benchmark]publicListMyClassClass_ToList()YieldClass(_classArray).ToList();[Benchmark]publicMyClass[]Class_ToArray()YieldClass(_classArray).ToArray();privatestaticIEnumerableMyClassYieldClass(MyClass[]source){returnsource.Where(xx.Value%20);}privatestaticIEnumerableMyClassIfYieldClass(MyClass[]source){foreach(variteminsource)if(item.Value%20)yieldreturnitem;}// struct [Benchmark]publicvoidStruct_Yield()YieldStruct(_structArray).Consume(_consumer);[Benchmark]publicvoidStruct_IfYield()IfYieldStruct(_structArray).Consume(_consumer);[Benchmark]publicListMyStructStruct_ToList()YieldStruct(_structArray).ToList();[Benchmark]publicMyStruct[]Struct_ToArray()YieldStruct(_structArray).ToArray();privatestaticIEnumerableMyStructYieldStruct(MyStruct[]source){returnsource.Where(xx.Value%20);}privatestaticIEnumerableMyStructIfYieldStruct(MyStruct[]source){foreach(variteminsource)if(item.Value%20)yieldreturnitem;}}publicclassMyClass{publicintValue;}publicstructMyStruct{publicintValue;}测试结果MethodNMeanErrorStdDevMedianGen0Gen1Gen2AllocatedInt_Yield100173.4 ns2.64 ns2.47 ns173.3 ns0.0076--48 BInt_IfYield100156.7 ns0.57 ns0.50 ns156.6 ns0.0088--56 BInt_ToList100258.2 ns4.85 ns4.77 ns257.4 ns0.1106--696 BInt_ToArray100277.2 ns5.26 ns5.16 ns278.3 ns0.1144--720 BClass_Yield100423.1 ns8.19 ns8.41 ns420.5 ns0.0076--48 BClass_IfYield100394.8 ns4.34 ns4.06 ns394.9 ns0.0100--64 BClass_ToList100410.5 ns5.47 ns5.11 ns408.9 ns0.18980.0005-1192 BClass_ToArray100492.8 ns2.29 ns1.79 ns492.7 ns0.1898--1192 BStruct_Yield100218.6 ns3.82 ns4.09 ns218.3 ns0.0076--48 BStruct_IfYield100190.5 ns1.33 ns1.04 ns190.9 ns0.0088--56 BStruct_ToList100263.2 ns6.99 ns20.60 ns274.4 ns0.1109--696 BStruct_ToArray100306.3 ns4.50 ns3.99 ns307.1 ns0.1144--720 BInt_Yield1000016,310.8 ns244.84 ns229.02 ns16,303.4 ns---48 BInt_IfYield1000014,991.2 ns278.83 ns273.85 ns15,040.4 ns---56 BInt_ToList1000021,684.4 ns419.96 ns483.63 ns21,635.4 ns10.46751.1597-65888 BInt_ToArray1000023,093.1 ns225.83 ns211.24 ns23,045.3 ns8.48390.5798-53440 BClass_Yield1000039,518.1 ns786.32 ns772.27 ns39,381.6 ns---48 BClass_IfYield1000038,522.0 ns246.33 ns230.41 ns38,476.6 ns---64 BClass_ToList1000032,900.5 ns645.10 ns904.35 ns32,591.2 ns20.81303.4180-131408 BClass_ToArray1000033,693.9 ns278.96 ns260.94 ns33,711.5 ns16.84571.5259-106224 BStruct_Yield1000019,381.9 ns319.79 ns299.13 ns19,403.8 ns---48 BStruct_IfYield1000014,652.0 ns16.89 ns14.10 ns14,653.5 ns---56 BStruct_ToList1000019,771.0 ns188.52 ns167.12 ns19,717.3 ns10.46751.1597-65888 BStruct_ToArray1000016,348.6 ns139.48 ns123.65 ns16,322.8 ns8.48390.5798-53440 BInt_Yield100000145,367.8 ns161.72 ns151.27 ns145,342.5 ns---48 BInt_IfYield100000134,651.7 ns1,063.77 ns995.06 ns134,108.5 ns---56 BInt_ToList100000182,513.1 ns571.52 ns534.60 ns182,429.3 ns98.632878.369177.3926525216 BInt_ToArray100000191,113.4 ns857.08 ns801.71 ns191,026.0 ns88.378970.800867.3828463287 BClass_Yield100000393,067.4 ns1,592.34 ns1,411.57 ns392,486.7 ns---48 BClass_IfYield100000386,997.1 ns1,470.07 ns1,375.11 ns386,845.2 ns---64 BClass_ToList100000595,860.0 ns5,105.46 ns4,775.65 ns596,887.2 ns183.5938163.0859162.10941050004 BClass_ToArray100000457,150.3 ns4,990.60 ns4,668.21 ns456,151.7 ns181.6406165.5273160.1563925998 BStruct_Yield100000186,671.9 ns1,434.43 ns1,197.81 ns186,435.3 ns---48 BStruct_IfYield100000172,955.8 ns2,730.39 ns2,554.01 ns172,108.0 ns---56 BStruct_ToList100000241,428.5 ns2,556.80 ns2,391.63 ns240,950.8 ns97.900477.880976.9043525206 BStruct_ToArray100000201,362.2 ns657.62 ns549.15 ns201,645.8 ns84.716867.138763.7207463252 B总结list通常比array更占内存使用LINQ Where会生成迭代器对象迭代器对象WhereArrayIterator产生48B内存手写循环yield return返回会生成一个状态机产生56B/64B(引用类型占8B)内存但平均比LINQ Where稍微快一点大数据量用IEnumerable可以减少内存分配
返回列表