c# - 如何提高 C# 中的 foreach 循环性能
问题描述
class Student
{
public int ID { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
class Program
{
private static object _lockObj = new object();
static void Main(string[] args)
{
List<int> collection = Enumerable.Range(1, 100000).ToList();
List<Student> students = new List<Student>(100000);
var options = new ParallelOptions()
{
MaxDegreeOfParallelism = 1
};
var sp = System.Diagnostics.Stopwatch.StartNew();
sp.Start();
Parallel.ForEach(collection, options, action =>
{
lock (_lockObj)
{
var dt = collection.FirstOrDefault(x => x == action);
if (dt > 0)
{
Student student = new Student();
student.ID = dt;
student.Name = "Zoyeb";
student.Email = "ShaikhZoyeb@Gmail.com";
students.Add(student);
Console.WriteLine(@"value of i = {0}, thread = {1}",
action,Thread.CurrentThread.ManagedThreadId);
}
}
});
sp.Stop();
double data = Convert.ToDouble(sp.ElapsedMilliseconds / 1000);
Console.WriteLine(data);
}
}
我想尽快循环遍历 100000 条记录我尝试了 foreach 循环,但是对于循环遍历 100000 条记录并不是很好,然后在我尝试实现 Parallel.ForEach() 提高了我的性能之后,在实际场景中我将收集Ids 和我需要查找集合是否 id 退出,如果退出然后添加。当我评论条件大约需要 3 秒来执行,而当我取消注释条件大约需要 24 秒,所以我的问题是有什么方法可以通过在集合中查找 id 来提高我的性能
//var dt = collection.FirstOrDefault(x => x == action);
//if (dt > 0)
//{
Student student = new Student();
student.ID = 1;
student.Name = "Zoyeb";
student.Email = "ShaikhZoyeb@Gmail.com";
students.Add(student);
Console.WriteLine(@"value of i = {0}, thread = {1}",
action,Thread.CurrentThread.ManagedThreadId);
//}
解决方案
您的原始代码正在执行 a lock
inside a Parallel.ForEach
。这本质上是采用并行代码并强制它串行运行。
在我的机器上需要 40 秒。
这实际上相当于这样做:
foreach (var action in collection)
{
var dt = collection.FirstOrDefault(x => x == action);
if (dt > 0)
{
Student student = new Student();
student.ID = dt;
student.Name = "Zoyeb";
student.Email = "ShaikhZoyeb@Gmail.com";
students.Add(student);
}
}
这也需要40秒。
但是,如果你这样做:
foreach (var action in collection)
{
Student student = new Student();
student.ID = action;
student.Name = "Zoyeb";
student.Email = "ShaikhZoyeb@Gmail.com";
students.Add(student);
}
运行需要 1毫秒。它大约快 40,000 倍。
在这种情况下,您可以通过一次迭代您的集合来获得更快的循环,而不是以嵌套方式并且不使用Parallel.ForEach
.
我很抱歉错过了关于 id 不存在的信息。
尝试这个:
HashSet<int> hashSet = new HashSet<int>(collection);
List<Student> students = new List<Student>(100000);
var sp = System.Diagnostics.Stopwatch.StartNew();
sp.Start();
foreach (var action in collection)
{
if (hashSet.Contains(action))
{
Student student = new Student();
student.ID = action;
student.Name = "Zoyeb";
student.Email = "ShaikhZoyeb@Gmail.com";
students.Add(student);
}
}
sp.Stop();
运行时间为 3 毫秒。
另一种方法是使用join
这样的:
foreach (var action in
from c in collection
join dt in collection on c equals dt
select dt)
{
Student student = new Student();
student.ID = action;
student.Name = "Zoyeb";
student.Email = "ShaikhZoyeb@Gmail.com";
students.Add(student);
}
运行时间为 25 毫秒。
推荐阅读
- recursion - 如何在 SML 中使用 map 函数来实现此代码?
- python - 确定最大 UDP 数据报大小的跨平台方法
- python - 根据列字典值过滤数据框
- wso2 - WSO2IS 5.10.0 - 通过 deployment.toml 配置 RootPartition
- tensorflow - 为什么从量化感知训练模型派生的 TFLite 模型与具有相同权重的正常模型不同?
- r - 奇怪的平淡奥特曼情节
- python - scipy中exp1的日志
- data-analysis - 从存储的文本字符串中识别可能的条形码符号的方法?
- python - 如何用例如使用字典的代码替换大型 if-elif 语句?
- reactjs - react docker项目的权限错误:EACCES:权限被拒绝,mkdir'/app/node_modules/.cache'