免费模板简历网站,做关于家乡的网站,百度小程序入口官网,帝国cms是免费的吗概要
我们在开发过程中#xff0c;经常需要在一个很大的数组或集合中搜索元素#xff0c;以满足业务需求。
本文主要介绍通过使用yield return的方式#xff0c;避免将大量数据全部加载进入内存#xff0c;再进行处理。从而提高程序的性能。
设计和实现
基本业务场景经常需要在一个很大的数组或集合中搜索元素以满足业务需求。
本文主要介绍通过使用yield return的方式避免将大量数据全部加载进入内存再进行处理。从而提高程序的性能。
设计和实现
基本业务场景我们需要在10000台ATM的数据中找前100台品牌是BrandA的ATM机的数据。
我们不再使用传统的方式将10000台ATM机的数据全部载入内容再进行过滤查找。
我们通过yield return方式只返回一个迭代器代码如下
本例中存在BrandA和BrandB两个品牌在生成ATM的L集合序列时候每次都是随机生成ATM机的品牌。
public IEnumerableATM getATMListYield(){ListATM atms new ListATM();int count 0;for(var i0; i 10000; i){yield return new ATM (){Id i,Name Atm i,Brand getBrand()} ;}yield break;
}
private string getBrand(){Random rd new Random();int count rd.Next(100);if (count 50) return BrandA;return BrandB;
}调用getATMListYield进行过滤找到前100个BrandA的ATM机。完整代码请参考附录。 public void runGetList(){DataProvider dp new DataProvider();var lists dp.getATMList();var count 0;foreach(var atm in lists){if(atm.Brand BrandA) {Console.WriteLine(atm.Name ); count;}if (count 100){break;}}}在foreach循环中每次访问ATM的集合只将集合中的一个元素载入内存进行过滤和比较当找到100个BrandA的元素程序停止不再载入ATM数组的其它元素。
载入全部ATM数据再进行过滤的代码请见附录。
我们使用Benchmark对两种实现的性能进行测试测试结果如下 从测试结果中可以看出使用yield return方式运行时间几乎减少了一半。
由于不需要将全部ATM数据载入内容yield return方式的内存使用量仅仅相当于传统方法的2%左右。
附录
Programs.cs
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Net.Mail;
using System.ComponentModel.Design.Serialization;
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Collections.Generic;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;
namespace IQueryableIEnumerable
{[MemoryDiagnoser]public class Programs{[Benchmark]public void runGetList(){DataProvider dp new DataProvider();var lists dp.getATMList();var count 0;foreach(var atm in lists){if(atm.Brand BrandA) {Console.WriteLine(atm.Name ); count;}if (count 100){break;}}}[Benchmark]public void runGetListByYield(){DataProvider dp new DataProvider();var lists dp.getATMListYield();int count 0;foreach(var atm in lists){if(atm.Brand BrandA) {Console.WriteLine(atm.Name ); count;}if (count 100){break;}}}public static void Main(string[] args){var summary BenchmarkRunner.RunPrograms(); }}
}
DataProvider.cs
using System;
using System.Linq;
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;namespace IQueryableIEnumerable
{public class DataProvider {public IEnumerableATM getATMList(){ListATM atms new ListATM();for(var i0; i 10000; i){atms.Add(new ATM (){Id i,Name Atm i,Brand getBrand()});}return atms;}public IEnumerableATM getATMListYield(){ListATM atms new ListATM();int count 0;for(var i0; i 10000; i){yield return new ATM (){Id i,Name Atm i,Brand getBrand()} ;}yield break;}private string getBrand(){Random rd new Random();int count rd.Next(100);if (count 50) return BrandA;return BrandB;}}
}ATM.cs
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace IQueryableIEnumerable
{public class ATM {public int Id { get; set; }public string Name { get; set; }public string Brand {get;set;} }
}