fork download
  1. // Program.cs
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.Linq;
  6.  
  7. namespace WhereSelectDemo
  8. {
  9. class Branch
  10. {
  11. public Guid CompanyId { get; set; }
  12. public int BranchCode { get; set; }
  13. // (you could add more props if needed)
  14. }
  15.  
  16. class Program
  17. {
  18. static void Main()
  19. {
  20. try
  21. {
  22. const int NumItems = 200_000; // adjust if your IDE/machine can't handle this (try 200_000)
  23. Console.WriteLine($"Creating {NumItems:N0} Branch items...");
  24.  
  25. var targetCompanyId = Guid.NewGuid();
  26. var otherCompanyId = Guid.NewGuid();
  27.  
  28. // Create list with ~25% matches to targetCompanyId
  29. var branches = new List<Branch>(NumItems);
  30. for (int i = 0; i < NumItems; i++)
  31. {
  32. branches.Add(new Branch
  33. {
  34. CompanyId = (i % 4 == 0) ? targetCompanyId : otherCompanyId, // ~25% matches
  35. BranchCode = i % 1000
  36. });
  37. }
  38.  
  39. Console.WriteLine($"Target CompanyId: {targetCompanyId}");
  40. Console.WriteLine("Running Where -> Select ...");
  41.  
  42. var sw = Stopwatch.StartNew();
  43. long hitCount1 = 0;
  44.  
  45. // Filter first, then project - selector runs only for filtered items
  46. var result1 = branches
  47. .Where(b =>
  48. {
  49. hitCount1++; // counting the predicate calls
  50. return b.CompanyId == targetCompanyId;
  51. })
  52. .Select(b =>
  53. {
  54. hitCount1++; // counting the selector calls (only for matching items)
  55. return new { b.CompanyId, b.BranchCode };
  56. })
  57. .ToArray(); // force evaluation
  58. sw.Stop();
  59.  
  60. Console.WriteLine($"Where -> Select: {sw.ElapsedMilliseconds} ms, hitCount = {hitCount1:N0}, result count = {result1.Length:N0}");
  61.  
  62. // ---- second experiment ----
  63. Console.WriteLine("Running Select -> Where ...");
  64. sw.Restart();
  65. long hitCount2 = 0;
  66.  
  67. // Project first, then filter - projector runs for all items, then predicate runs for all projected items
  68. var result2 = branches
  69. .Select(b =>
  70. {
  71. hitCount2++; // projector called for every element
  72. return new { b.CompanyId, b.BranchCode };
  73. })
  74. .Where(x =>
  75. {
  76. hitCount2++; // predicate called for every element of the projection
  77. return x.CompanyId == targetCompanyId;
  78. })
  79. .ToArray(); // force evaluation
  80. sw.Stop();
  81.  
  82. Console.WriteLine($"Select -> Where: {sw.ElapsedMilliseconds} ms, hitCount = {hitCount2:N0}, result count = {result2.Length:N0}");
  83. }
  84. catch (Exception ex)
  85. {
  86. Console.WriteLine("Error: " + ex);
  87. }
  88.  
  89. Console.WriteLine("Done. Press any key to exit.");
  90. Console.ReadKey();
  91. }
  92. }
  93. }
  94.  
Success #stdin #stdout 0.57s 184180KB
stdin
100
stdout
Creating 2,000,000 Branch items...
Target CompanyId: 9831b8fa-0f64-4e84-86ce-fa01ef5e0a2e
Running Where -> Select ...
Where -> Select: 128 ms, hitCount = 2,500,000, result count = 500,000
Running Select -> Where ...
Select -> Where: 178 ms, hitCount = 4,000,000, result count = 500,000
Done. Press any key to exit.