Lambda使用Array.Contains的性能改进?

时间:2017-05-05 21:07:56

标签: c# linq lambda

我有这个功能,我想提高性能。当创建选择时,瓶颈就在最后,并且可能与Contains()函数有关。我不知道更有效的方法来做这个选择:

public static Dictionary<string, SubItem> SubItemCache = new Dictionary<string, SubItem>();
public static Dictionary<string, Item> ItemCache = new Dictionary<string, Item>();

private static IEnumerable<Item> GetSimilarItems(int days, string type, 
    float counterOne, float counterTwo)
{
    string[] similarSubItems;

    if (days > 180)
    {
        similarSubItems = SubItemCache.Values
            .Where(p => p.CounterOne >= counterOne * 0.9 
                && p.CounterOne <= counterOne * 1.1)
            .Select(o => o.ID).ToArray();
    }
    else
    {
        similarSubItems = SubItemCache.Values
            .Where(p => p.CounterTwo >= counterTwo * 0.9 
                && p.CounterTwo <= counterTwo * 1.1)
            .Select(o => o.ID).ToArray();
    }

    var selection = ItemCache.Values.Where(p => p.days >= days - 5 && p.days <= days + 5
                                          && p.Type == type
                                          && similarSubItems.Contains(p.Key));

    return selection;
}

有没有办法明智地提高功能性能?

2 个答案:

答案 0 :(得分:2)

根据其大小,使用string[]替换HashSet<string>并使用.Contains方法。它的查找时间会明显加快。

上次我测试时,我发现如果您将直接查找与构建哈希集+查找的开销进行比较,那么集合中的大约15个项目就是您使用哈希集的查找时间更快。

public static Dictionary<string, SubItem> SubItemCache = new Dictionary<string, SubItem>();
public static Dictionary<string, Item> ItemCache = new Dictionary<string, Item>();

private static IEnumerable<Item> GetSimilarItems(int days, string type, 
    float counterOne, float counterTwo)
{
    HashSet<string> similarSubItems;

    if (days > 180)
    {
        similarSubItems = new HashSet<string>(SubItemCache.Values
            .Where(p => p.CounterOne >= counterOne * 0.9 
                && p.CounterOne <= counterOne * 1.1)
            .Select(o => o.ID));
    }
    else
    {
        similarSubItems = new HashSet<string>(SubItemCache.Values
            .Where(p => p.CounterTwo >= counterTwo * 0.9 
                && p.CounterTwo <= counterTwo * 1.1)
            .Select(o => o.ID));
    }

    var selection = ItemCache.Values.Where(p => p.days >= days - 5 && p.days <= days + 5
                                          && p.Type == type
                                          && similarSubItems.Contains(p.Key));

    return selection;
}

答案 1 :(得分:0)

我无法想到任何简单的事情,但作为最后的手段,你应该能够通过避免LINQ和lambda开销来节省另外20%左右:

print str(os.path.getmtime(fullname))
print str(time.mktime(t.timetuple()))