【问题标题】:Choosing a type for search results in C#在 C# 中选择搜索结果的类型
【发布时间】:2011-02-23 22:31:38
【问题描述】:

我有一个永远不会超过 500 的结果集;从网络服务返回的结果被分配给一个搜索结果对象。

来自webservice的数据大约2mb;我想使用的位大约是每条记录的三分之一,所以这让我可以缓存并快速操作它。

我希望能够以最少的开销和尽可能快的速度对结果进行排序和过滤,因此我使用了 VCSKICKS 计时类来衡量它们的性能

              Average        Total (10,000)
Type       Create  Sort      Create  Sort
HashSet    0.1579  0.0003    1579    3
IList      0.0633  0.0002    633     2
IQueryable 0.0072  0.0432    72      432

以秒为单位,使用http://www.vcskicks.com/algorithm-performance.php

我通过 Web 服务响应的 for 循环创建了哈希集(添加到哈希集)。

List 和 IQueryable 是使用 LINQ 创建的。

问题 我可以理解为什么 HashSet 需要更长的时间来创建(foreach 循环与 linq);但是为什么 IQueryable 比其他两个需要更长的时间来排序?最后有没有更好的方法来分配 HashSet。

谢谢

实际程序

public class Program
{
    private static AuthenticationHeader _authHeader;
    private static OPSoapClient _opSession;
    private static AccommodationSearchResponse _searchResults;

    private static HashSet<SearchResults> _myHash;
    private static IList<SearchResults> _myList;
    private static IQueryable<SearchResults> _myIQuery;

    static void Main(string[] args)
    {
        #region Setup WebService
        _authHeader = new AuthenticationHeader { UserName = "xx", Password = "xx" };
        _opSession = new OPSoapClient();


        #region Setup Search Results

        _searchResults = _opgSession.SearchCR(_authHeader, "ENG", "GBP", "GBR");

        #endregion Setup Search Results

        #endregion Setup WebService


        // HASHSET
        SpeedTester hashTest = new SpeedTester(TestHashSet);
        hashTest.RunTest();
        Console.WriteLine("- Hash Test \nAverage Running Time: {0}; Total Time: {1}", 
            hashTest.AverageRunningTime, 
            hashTest.TotalRunningTime);

        SpeedTester hashSortTest = new SpeedTester(TestSortingHashSet);
        hashSortTest.RunTest();
        Console.WriteLine("- Hash Sort Test \nAverage Running Time: {0}; Total Time: {1}",
            hashSortTest.AverageRunningTime,
            hashSortTest.TotalRunningTime);

        // ILIST
        SpeedTester listTest = new SpeedTester(TestList);
        listTest.RunTest();
        Console.WriteLine("- List Test \nAverage Running Time: {0}; Total Time: {1}",
            listTest.AverageRunningTime,
            listTest.TotalRunningTime);

        SpeedTester listSortTest = new SpeedTester(TestSortingList);
        listSortTest.RunTest();
        Console.WriteLine("- List Sort Test \nAverage Running Time: {0}; Total Time: {1}",
            listSortTest.AverageRunningTime,
            listSortTest.TotalRunningTime);

        // IQUERIABLE
        SpeedTester iqueryTest = new SpeedTester(TestIQueriable);
        iqueryTest.RunTest();
        Console.WriteLine("- iquery Test \nAverage Running Time: {0}; Total Time: {1}",
            iqueryTest.AverageRunningTime,
            iqueryTest.TotalRunningTime);

        SpeedTester iquerySortTest = new SpeedTester(TestSortableIQueriable);
        iquerySortTest.RunTest();
        Console.WriteLine("- iquery Sort Test \nAverage Running Time: {0}; Total Time: {1}",
            iquerySortTest.AverageRunningTime,
            iquerySortTest.TotalRunningTime);
    }

    static void TestHashSet()
    {
        var test = _searchResults.Items;

        _myHash = new HashSet<SearchResults>();

        foreach(var x in test)
        {
            _myHash.Add(new SearchResults
                                     {
                                         Ref = x.Ref,
                                         Price = x.StandardPrice
                                     });
        }

    }

    static void TestSortingHashSet()
    {
        var sorted = _myHash.OrderBy(s => s.Price);
    }



    static void TestList()
    {
        var test = _searchResults.Items;

        _myList = (from x in test
                   select new SearchResults
                              {
                                  Ref = x.Ref,
                                  Price = x.StandardPrice
                              }).ToList();
    }

    static void TestSortingList()
    {
        var sorted = _myList.OrderBy(s => s.Price);
    }

    static void TestIQueriable()
    {
        var test = _searchResults.Items;

        _myIQuery = (from x in test
                     select new SearchResults
                                {
                                    Ref = x.Ref,
                                    Price = x.StandardPrice
                                }).AsQueryable();

    }

    static void TestSortableIQueriable()
    {
        var sorted = _myIQuery.OrderBy(s => s.Price);
    }

}

=== 从控制台直接输出 ===

- Hash Test
Average Running Time: 0.154; Total Time: 1540
- Hash Sort Test
Average Running Time: 0.0003; Total Time: 3
- List Test
Average Running Time: 0.0601; Total Time: 601
- List Sort Test
Average Running Time: 0.0002; Total Time: 2
- iquery Test
Average Running Time: 0.0003; Total Time: 3
- iquery Sort Test
Average Running Time: 0.0399; Total Time: 399
- IEnum Test
Average Running Time: 0.0002; Total Time: 2
- IEnum Sort Test
Average Running Time: 0.0001; Total Time: 1
Press any key to continue . . .

显然,时间会根据我的机器当时在做什么而有所不同,您通常可以根据差异的大小做出一些判断,但正如“答案”所说,以同样的方式判断 IQueryable 是不公平的。

【问题讨论】:

  • 看看IEnumerableIList 上的表现会很有趣

标签: c# .net c#-3.0 types type-conversion


【解决方案1】:

我认为 IQueryable 已将创建推迟到执行排序之前,IList 预先创建然后对其执行排序。

就像 IList 一样,HashSet 的创建没有延迟,因此前期成本很高。

因此,必须先创建 HashSetIList,这需要您记录的时间。然后你记录它们的排序,这可能可以忽略不计。 IQueryable 将创建时间推迟到您进行排序,因此创建和排序都在排序时间内发生。对于IQueryable,这种排序并没有真正花费更长的时间,它看起来就像是因为创建是在您的测试中同时发生的。我怀疑所有 3 种排序的时间差异都可以忽略不计。

我认为在IQueryable 的情况下,根据您希望如何使用或扩展输出,无论哪种方式都可以使用它们中的任何一种。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-19
  • 1970-01-01
  • 2018-11-02
  • 2013-04-02
  • 2020-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多