Skip to content

Map: comparer optimization - #10855

Closed
buybackoff wants to merge 13 commits into
dotnet:mainfrom
buybackoff:map_step3
Closed

Map: comparer optimization#10855
buybackoff wants to merge 13 commits into
dotnet:mainfrom
buybackoff:map_step3

Conversation

@buybackoff

@buybackoffbuybackoff commented Jan 8, 2021

Copy link
Copy Markdown
Contributor

Copied from comment #10845 (comment) to show the code and run CI

Map/Set always use the default comparison. It should be easy to optimize it... One may think... But I've seen #9348, #513, and related. Such a hopeless state to optimize (inline/devirtualize) the comparison :(

This implementation is probably not 100% compatible with the current behavior. It could be if we apply the logic from #9348 snippet, to exclude records & DUs, if that code is correct.

If we take the current NuGet 5.0 release without any changes to Map as a baseline, are we ready to (Ratio column)

  • [Improve the map performance with] primitive keys by 3.65x - getItem,
  • .. struct T : IComparable<T> by 4.14x - getItemIntLike,
  • .. struct records by 95% - getItemIntRecord
  • .. string by 52% - getItemString,
  • but lose 15% for reference types - getItemRefLike, 17% for reference type records - getItemIntRefRecord

?

I would say that everything could be wrapped by struct T : IComparable<T> + efficient logic there, and if someone uses ref-types as a key they do care about about performance by definition. But I do understand that regressing existing code by 15/17% may be too big. Yet the tradeoff is so great for primitive types.

What do you think? What's the most important use case for the map/set?

The types in the bench are:

 [<StructuralEquality;CustomComparison>]
type IntLike =
struct
val Value: int
new(v:int) = {Value = v}
member x.CompareTo(y:IntLike) = x.Value.CompareTo(y.Value)
end
interface IComparable<IntLike> with
member x.CompareTo(y) = x.CompareTo(y)
interface IComparable with
member x.CompareTo(y) = x.CompareTo(y :?> IntLike) type RefLike =
val Value: int
new(v:int) = {Value = v}
member x.CompareTo(y:RefLike) = x.Value.CompareTo(y.Value)
interface IComparable<RefLike> with
member x.CompareTo(y) = x.CompareTo(y)
interface IComparable with
member x.CompareTo(y) = x.CompareTo(y :?> RefLike)
[<Struct>]
type IntRecord =
{ Value1 : int
Value2 : int
}
type IntRefRecord =
{ Value1 : int
Value2 : int
}
MethodJobBuildConfigurationSizeMeanErrorStdDevRatioRatioSDRankGen 0Gen 1Gen 2Allocated
getItemAfterAfter10020.48 ns0.935 ns0.243 ns1.000.001----
getItemMain50Main5010029.40 ns0.728 ns0.189 ns1.440.022----
getItemNuGet50NuGet5010074.83 ns6.092 ns0.943 ns3.650.083----
getItemIntLikeAfterAfter10060.45 ns0.460 ns0.119 ns1.000.001----
getItemIntLikeMain50Main50100220.00 ns4.159 ns0.644 ns3.640.0220.0450--283 B
getItemIntLikeNuGet50NuGet50100250.34 ns9.453 ns1.463 ns4.140.0330.0449--283 B
getItemStringAfterAfter10076.03 ns1.027 ns0.267 ns1.000.002----
getItemStringMain50Main5010068.22 ns0.538 ns0.083 ns0.900.001----
getItemStringNuGet50NuGet50100115.77 ns0.626 ns0.162 ns1.520.013----
getItemRefLikeAfterAfter100278.41 ns3.569 ns0.927 ns1.000.003----
getItemRefLikeMain50Main50100200.05 ns6.346 ns1.648 ns0.720.011----
getItemRefLikeNuGet50NuGet50100236.40 ns3.194 ns0.494 ns0.850.002----
getItemIntRecordAfterAfter100113.75 ns5.312 ns1.380 ns1.000.001----
getItemIntRecordMain50Main50100200.78 ns1.451 ns0.224 ns1.770.0220.0449--283 B
getItemIntRecordNuGet50NuGet50100221.77 ns4.146 ns1.077 ns1.950.0330.0450--283 B
getItemIntRefRecordAfterAfter100255.08 ns5.493 ns1.427 ns1.000.003----
getItemIntRefRecordMain50Main50100173.02 ns3.398 ns0.883 ns0.680.011----
getItemIntRefRecordNuGet50NuGet50100211.41 ns2.625 ns0.406 ns0.830.012----

Store height in leaves. Compared to the old discussion, when Left/Right were proposed to be stored in a universal node,
this adds 4 bytes to leaves or 2 bytes per item on average (vs 16/8).
`Match` produces `sub 1` and `switch` instruction. Here, for any non-trivial count,
nodes are more frequent than leaves on the path, so branch prediction should be beneficial.
Comment threadsrc/fsharp/FSharp.Core/map.fs Outdated

@buybackoffbuybackoffJan 8, 2021

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

floats have non-standard treatment in F#, should remove these lines or replicate the behavior

@buybackoff

buybackoff commented Jan 9, 2021

Copy link
Copy Markdown
ContributorAuthor

This is what we could get if using:

  • static read-only field that indicates if a type implements IComparable<T>, like this
  • a custom IL that add .constained modified to callvirtCompareTo when the static field is true (not sure if that is verifiable), like this.
 type CompareHelper<'T when 'T : comparison>() =
static let c = LanguagePrimitives.FastGenericComparer
[<MethodImpl(MethodImplOptions.AggressiveInlining)>]
static member Compare(l:'T, r:'T):int =
if Spreads.KeyComparer<'T>.IsIComparable then // JIT-time constant
// add .constained before callvirt to IComparable.CompareTo
Spreads.Native.UnsafeEx.CompareToConstrained(&Unsafe.AsRef(&l),&Unsafe.AsRef(&r))
else
// with IsIComparable as constant all other cases use IComparer directly, as before
c.Compare(l, r)
MethodJobBuildConfigurationSizeMeanErrorStdDevRatioRatioSDRankGen 0Gen 1Gen 2Allocated
getItemAfterAfter10019.22 ns0.732 ns0.190 ns1.000.001----
getItemMain50Main5010028.86 ns0.168 ns0.026 ns1.500.022----
getItemNuGet50NuGet5010073.80 ns0.585 ns0.152 ns3.840.043----
getItemIntLikeAfterAfter10048.77 ns1.409 ns0.366 ns1.000.001----
getItemIntLikeMain50Main50100215.65 ns3.189 ns0.828 ns4.420.0420.0448--283 B
getItemIntLikeNuGet50NuGet50100248.46 ns3.763 ns0.582 ns5.090.0530.0445--283 B
getItemStringAfterAfter10077.26 ns0.935 ns0.243 ns1.000.002----
getItemStringMain50Main5010068.54 ns1.239 ns0.322 ns0.890.011----
getItemStringNuGet50NuGet50100114.88 ns1.200 ns0.312 ns1.490.003----
getItemRefLikeAfterAfter100132.77 ns1.419 ns0.369 ns1.000.001----
getItemRefLikeMain50Main50100200.83 ns4.727 ns1.228 ns1.510.012----
getItemRefLikeNuGet50NuGet50100236.52 ns7.414 ns1.147 ns1.780.013----
getItemIntRecordAfterAfter10093.29 ns0.634 ns0.098 ns1.000.001----
getItemIntRecordMain50Main50100199.74 ns8.888 ns1.375 ns2.140.0120.0444--283 B
getItemIntRecordNuGet50NuGet50100222.91 ns7.227 ns1.118 ns2.390.0130.0443--283 B
getItemIntRefRecordAfterAfter100137.51 ns1.681 ns0.436 ns1.000.001----
getItemIntRefRecordMain50Main50100176.34 ns7.543 ns1.167 ns1.280.012----
getItemIntRefRecordNuGet50NuGet50100211.85 ns2.063 ns0.319 ns1.540.013----

@buybackoff

Copy link
Copy Markdown
ContributorAuthor

Here are the numbers if we only use static readonly and a delegate from reflection.

 [<MethodImpl(MethodImplOptions.AggressiveInlining)>]
static member Compare(l:'T, r:'T):int =
if Spreads.KeyComparer<'T>.IsIComparable then
CompareHelper<'T>.CompareToDlg.Invoke(l,r)
else
c.Compare(l, r)

But this time delegates are used for ref-type IComparables

 static member val CompareToDlg : Func<'T,'T,int> =
let dlg =
try
if Spreads.KeyComparer<'T>.IsIComparable then // All types, not only structs
let dlg = ...
dlg
else
null
with _ -> null
dlg
with get

Both RefLike and normal record do implement IComparable, and they have significant improvement.

MethodJobBuildConfigurationSizeMeanErrorStdDevRatioRatioSDRankGen 0Gen 1Gen 2Allocated
getItemAfterAfter10019.19 ns0.900 ns0.234 ns1.000.001----
getItemMain50Main5010030.90 ns0.681 ns0.177 ns1.610.022----
getItemNuGet50NuGet5010074.52 ns2.275 ns0.591 ns3.880.033----
getItemIntLikeAfterAfter10075.48 ns0.582 ns0.090 ns1.000.001----
getItemIntLikeMain50Main50100212.54 ns2.125 ns0.552 ns2.820.0120.0448--283 B
getItemIntLikeNuGet50NuGet50100239.88 ns5.860 ns1.522 ns3.180.0330.0445--283 B
getItemStringAfterAfter10085.00 ns1.163 ns0.302 ns1.000.002----
getItemStringMain50Main5010064.90 ns1.165 ns0.302 ns0.760.011----
getItemStringNuGet50NuGet50100121.30 ns1.856 ns0.482 ns1.430.013----
getItemRefLikeAfterAfter100158.81 ns5.556 ns0.860 ns1.000.001----
getItemRefLikeMain50Main50100190.16 ns3.069 ns0.475 ns1.200.012----
getItemRefLikeNuGet50NuGet50100237.65 ns2.540 ns0.660 ns1.500.013----
getItemIntRecordAfterAfter100118.74 ns1.572 ns0.408 ns1.000.001----
getItemIntRecordMain50Main50100201.83 ns2.546 ns0.661 ns1.700.0120.0443--283 B
getItemIntRecordNuGet50NuGet50100223.86 ns4.687 ns0.725 ns1.880.0130.0448--283 B
getItemIntRefRecordAfterAfter100162.28 ns2.088 ns0.323 ns1.000.001----
getItemIntRefRecordMain50Main50100174.75 ns10.652 ns1.648 ns1.080.012----
getItemIntRefRecordNuGet50NuGet50100213.88 ns7.739 ns2.010 ns1.320.013----

@buybackoff

Copy link
Copy Markdown
ContributorAuthor

It works quite well now, without static readonly and custom IL.

Related to the changes is fsharp/fslang-suggestions#816. We use IComparable<T> if it is assignable from T, i.e. T implements it.

Strange thing happens with string vs the previous PR, but compared to the base line the improvement is still big.

Previous benchmarks were not correct for some cases in absolute terms (e.g. wrong number of OperationsPerInvoke), but relatively were OK. The updated Map benchmarks are here: https://github.com/buybackoff/fsharp-benchmarks

MethodJobBuildConfigurationSizeMeanErrorStdDevRatioRatioSDRankGen 0Gen 1Gen 2Allocated
getItemIntAfterAfter1012.82 ns0.269 ns0.070 ns1.000.001----
getItemIntMain50Main501018.22 ns1.041 ns0.270 ns1.420.022----
getItemIntNuGet50NuGet501037.81 ns0.398 ns0.103 ns2.950.023----
getItemIntLikeAfterAfter1031.17 ns0.388 ns0.060 ns1.000.001----
getItemIntLikeMain50Main5010125.00 ns6.831 ns1.774 ns4.030.0420.0267--168 B
getItemIntLikeNuGet50NuGet5010147.13 ns4.833 ns1.255 ns4.730.0330.0263--168 B
getItemStringAfterAfter1031.12 ns0.209 ns0.032 ns1.000.002----
getItemStringMain50Main501026.75 ns1.151 ns0.299 ns0.860.011----
getItemStringNuGet50NuGet501054.44 ns0.705 ns0.183 ns1.750.003----
getItemRefLikeAfterAfter1073.33 ns1.690 ns0.439 ns1.000.001----
getItemRefLikeMain50Main5010122.63 ns0.830 ns0.215 ns1.670.012----
getItemRefLikeNuGet50NuGet5010148.46 ns0.961 ns0.149 ns2.030.013----
getItemIntRecordAfterAfter1056.95 ns1.639 ns0.426 ns1.000.001----
getItemIntRecordMain50Main5010114.25 ns1.843 ns0.479 ns2.010.0120.0268--168 B
getItemIntRecordNuGet50NuGet5010134.20 ns1.453 ns0.225 ns2.360.0230.0263--168 B
getItemIntRefRecordAfterAfter1075.23 ns3.740 ns0.971 ns1.000.001----
getItemIntRefRecordMain50Main5010104.20 ns1.346 ns0.349 ns1.390.012----
getItemIntRefRecordNuGet50NuGet5010127.67 ns1.501 ns0.232 ns1.700.023----
getItemIntLikeNonGenCmpAfterAfter1047.39 ns2.249 ns0.584 ns1.000.0010.0133--84 B
getItemIntLikeNonGenCmpMain50Main5010122.17 ns1.105 ns0.171 ns2.570.0320.0263--168 B
getItemIntLikeNonGenCmpNuGet50NuGet5010142.20 ns2.236 ns0.581 ns3.000.0430.0262--168 B
getItemRefLikeNonGenCmpAfterAfter1097.35 ns2.416 ns0.628 ns1.000.001----
getItemRefLikeNonGenCmpMain50Main5010122.37 ns1.477 ns0.229 ns1.260.012----
getItemRefLikeNonGenCmpNuGet50NuGet5010147.73 ns2.022 ns0.313 ns1.520.013----
containsKeyIntAfterAfter1011.80 ns0.698 ns0.108 ns1.000.001----
containsKeyIntMain50Main501014.16 ns0.311 ns0.048 ns1.200.012----
containsKeyIntNuGet50NuGet501034.87 ns1.011 ns0.263 ns2.950.043----
containsKeyIntLikeAfterAfter1028.34 ns1.342 ns0.208 ns1.000.001----
containsKeyIntLikeMain50Main5010114.22 ns2.457 ns0.638 ns4.030.0120.0266--168 B
containsKeyIntLikeNuGet50NuGet5010144.45 ns5.236 ns1.360 ns5.090.0730.0265--168 B
containsKeyStringAfterAfter1030.09 ns1.165 ns0.180 ns1.000.002----
containsKeyStringMain50Main501024.20 ns0.670 ns0.174 ns0.800.011----
containsKeyStringNuGet50NuGet501049.48 ns1.291 ns0.335 ns1.650.003----
containsKeyRefLikeAfterAfter1074.45 ns4.001 ns1.039 ns1.000.001----
containsKeyRefLikeMain50Main5010117.72 ns2.011 ns0.311 ns1.580.022----
containsKeyRefLikeNuGet50NuGet5010150.47 ns2.439 ns0.377 ns2.020.033----
containsKeyIntRecordAfterAfter1054.18 ns0.445 ns0.069 ns1.000.001----
containsKeyIntRecordMain50Main5010109.51 ns1.518 ns0.394 ns2.020.0120.0267--168 B
containsKeyIntRecordNuGet50NuGet5010127.24 ns2.166 ns0.562 ns2.350.0130.0267--168 B
containsKeyIntRefRecordAfterAfter1075.88 ns1.335 ns0.207 ns1.000.001----
containsKeyIntRefRecordMain50Main5010100.98 ns1.748 ns0.454 ns1.330.012----
containsKeyIntRefRecordNuGet50NuGet5010126.92 ns4.102 ns1.065 ns1.670.013----
containsKeyIntLikeNonGenCmpAfterAfter1043.01 ns1.490 ns0.231 ns1.000.0010.0133--84 B
containsKeyIntLikeNonGenCmpMain50Main5010117.52 ns2.215 ns0.343 ns2.730.0120.0264--168 B
containsKeyIntLikeNonGenCmpNuGet50NuGet5010143.99 ns4.625 ns0.716 ns3.350.0230.0267--168 B
containsKeyRefLikeNonGenCmpAfterAfter1091.62 ns2.524 ns0.655 ns1.000.001----
containsKeyRefLikeNonGenCmpMain50Main5010117.78 ns4.052 ns1.052 ns1.290.012----
containsKeyRefLikeNonGenCmpNuGet50NuGet5010148.57 ns0.909 ns0.141 ns1.620.013----
itemCountIntAfterAfter1024.64 ns0.530 ns0.138 ns1.000.002----
itemCountIntMain50Main501021.32 ns0.547 ns0.142 ns0.870.011----
itemCountIntNuGet50NuGet501066.16 ns0.502 ns0.078 ns2.680.013----
itemCountIntLikeAfterAfter1024.60 ns0.361 ns0.094 ns1.000.002----
itemCountIntLikeMain50Main501021.28 ns0.140 ns0.036 ns0.870.001----
itemCountIntLikeNuGet50NuGet501065.35 ns1.491 ns0.387 ns2.660.023----
itemCountStringAfterAfter1029.24 ns1.547 ns0.402 ns1.000.001----
itemCountStringMain50Main501032.80 ns1.913 ns0.497 ns1.120.022----
itemCountStringNuGet50NuGet501094.59 ns1.625 ns0.251 ns3.230.043----
itemCountRefLikeAfterAfter1022.83 ns0.516 ns0.080 ns1.000.001----
itemCountRefLikeMain50Main501029.12 ns0.257 ns0.040 ns1.280.002----
itemCountRefLikeNuGet50NuGet501072.46 ns2.806 ns0.729 ns3.170.033----
itemCountIntRecordAfterAfter1024.84 ns0.903 ns0.235 ns1.000.002----
itemCountIntRecordMain50Main501021.27 ns0.481 ns0.074 ns0.860.011----
itemCountIntRecordNuGet50NuGet501065.32 ns1.707 ns0.443 ns2.630.043----
itemCountIntRefRecordAfterAfter1022.86 ns0.512 ns0.133 ns1.000.001----
itemCountIntRefRecordMain50Main501029.15 ns0.289 ns0.075 ns1.280.012----
itemCountIntRefRecordNuGet50NuGet501072.75 ns2.803 ns0.434 ns3.190.013----
itemCountIntLikeNonGenCmpAfterAfter1024.68 ns0.488 ns0.127 ns1.000.002----
itemCountIntLikeNonGenCmpMain50Main501021.37 ns0.245 ns0.038 ns0.870.001----
itemCountIntLikeNonGenCmpNuGet50NuGet501064.76 ns0.779 ns0.121 ns2.620.013----
itemCountRefLikeNonGenCmpAfterAfter1023.11 ns0.667 ns0.173 ns1.000.001----
itemCountRefLikeNonGenCmpMain50Main501029.25 ns0.700 ns0.182 ns1.270.012----
itemCountRefLikeNonGenCmpNuGet50NuGet501072.74 ns3.487 ns0.540 ns3.150.013----
iterForeachIntAfterAfter10340.84 ns3.626 ns0.561 ns1.000.0010.1200--760 B
iterForeachIntMain50Main5010345.94 ns13.114 ns3.406 ns1.020.0110.1204--760 B
iterForeachIntNuGet50NuGet5010408.34 ns7.207 ns1.872 ns1.200.0120.1143--720 B
iterForeachIntLikeAfterAfter10341.02 ns7.056 ns1.832 ns1.000.0010.1206--760 B
iterForeachIntLikeMain50Main5010343.78 ns4.780 ns1.241 ns1.010.0110.1198--760 B
iterForeachIntLikeNuGet50NuGet5010415.43 ns20.087 ns5.216 ns1.220.0120.1197--760 B
iterForeachStringAfterAfter10483.92 ns31.066 ns8.068 ns1.000.0010.1401--888 B
iterForeachStringMain50Main5010474.50 ns16.711 ns4.340 ns0.980.0110.1401--888 B
iterForeachStringNuGet50NuGet5010662.15 ns26.546 ns6.894 ns1.370.0220.1414--888 B
iterForeachRefLikeAfterAfter10433.02 ns4.705 ns1.222 ns1.000.0010.1191--760 B
iterForeachRefLikeMain50Main5010439.69 ns12.488 ns1.933 ns1.020.0020.1193--760 B
iterForeachRefLikeNuGet50NuGet5010603.15 ns16.566 ns4.302 ns1.390.0130.1192--760 B
iterForeachIntRecordAfterAfter10347.01 ns20.020 ns5.199 ns1.000.0010.1197--760 B
iterForeachIntRecordMain50Main5010341.07 ns4.461 ns0.690 ns0.980.0110.1195--760 B
iterForeachIntRecordNuGet50NuGet5010424.27 ns6.502 ns1.689 ns1.220.0220.1210--760 B
iterForeachIntRefRecordAfterAfter10444.85 ns9.004 ns1.393 ns1.000.0010.1211--760 B
iterForeachIntRefRecordMain50Main5010447.96 ns94.596 ns24.566 ns1.020.0610.1198--760 B
iterForeachIntRefRecordNuGet50NuGet5010615.27 ns41.290 ns10.723 ns1.380.0320.1205--760 B
iterForeachIntLikeNonGenCmpAfterAfter10336.76 ns7.874 ns2.045 ns1.000.0010.1200--760 B
iterForeachIntLikeNonGenCmpMain50Main5010345.60 ns2.811 ns0.435 ns1.020.0120.1198--760 B
iterForeachIntLikeNonGenCmpNuGet50NuGet5010406.77 ns6.882 ns1.065 ns1.210.0130.1193--760 B
iterForeachRefLikeNonGenCmpAfterAfter10426.80 ns12.058 ns3.131 ns1.000.0010.1208--760 B
iterForeachRefLikeNonGenCmpMain50Main5010436.47 ns15.438 ns4.009 ns1.020.0120.1194--760 B
iterForeachRefLikeNonGenCmpNuGet50NuGet5010601.39 ns20.317 ns5.276 ns1.410.0130.1205--760 B
addItemIntAfterAfter1072.52 ns1.264 ns0.328 ns1.000.0010.0308--194 B
addItemIntMain50Main501086.28 ns8.566 ns2.225 ns1.190.0320.0321--202 B
addItemIntNuGet50NuGet5010156.38 ns3.177 ns0.492 ns2.150.0130.0315--198 B
addItemIntLikeAfterAfter1089.76 ns0.966 ns0.150 ns1.000.0010.0306--194 B
addItemIntLikeMain50Main5010185.77 ns10.286 ns1.592 ns2.070.0220.0586--370 B
addItemIntLikeNuGet50NuGet5010272.67 ns6.496 ns1.687 ns3.040.0130.0581--370 B
addItemStringAfterAfter10100.96 ns1.229 ns0.319 ns1.000.0020.0302--190 B
addItemStringMain50Main501098.17 ns3.380 ns0.878 ns0.970.0110.0317--199 B
addItemStringNuGet50NuGet5010208.42 ns8.470 ns2.200 ns2.060.0230.0314--199 B
addItemRefLikeAfterAfter10146.04 ns4.998 ns1.298 ns1.000.0010.0306--194 B
addItemRefLikeMain50Main5010200.82 ns9.222 ns1.427 ns1.370.0120.0318--202 B
addItemRefLikeNuGet50NuGet5010328.08 ns16.192 ns4.205 ns2.250.0330.0321--202 B
addItemIntRecordAfterAfter10122.37 ns4.959 ns0.767 ns1.000.0010.0304--194 B
addItemIntRecordMain50Main5010178.96 ns2.040 ns0.316 ns1.460.0120.0585--370 B
addItemIntRecordNuGet50NuGet5010257.64 ns6.461 ns1.000 ns2.110.0130.0584--370 B
addItemIntRefRecordAfterAfter10147.27 ns8.818 ns2.290 ns1.000.0010.0308--194 B
addItemIntRefRecordMain50Main5010178.74 ns4.237 ns0.656 ns1.210.0220.0322--202 B
addItemIntRefRecordNuGet50NuGet5010295.57 ns4.790 ns0.741 ns2.000.0430.0313--202 B
addItemIntLikeNonGenCmpAfterAfter10108.42 ns1.574 ns0.244 ns1.000.0010.0441--278 B
addItemIntLikeNonGenCmpMain50Main5010184.77 ns3.463 ns0.899 ns1.710.0020.0584--370 B
addItemIntLikeNonGenCmpNuGet50NuGet5010273.93 ns4.158 ns1.080 ns2.530.0130.0577--370 B
addItemRefLikeNonGenCmpAfterAfter10167.32 ns2.057 ns0.534 ns1.000.0010.0308--194 B
addItemRefLikeNonGenCmpMain50Main5010199.51 ns4.683 ns0.725 ns1.190.0120.0318--202 B
addItemRefLikeNonGenCmpNuGet50NuGet5010320.73 ns5.032 ns1.307 ns1.920.0130.0321--202 B
removeItemIntAfterAfter1011.87 ns0.668 ns0.173 ns1.000.0010.0056--35 B
removeItemIntMain50Main501013.39 ns0.242 ns0.063 ns1.130.0220.0070--44 B
removeItemIntNuGet50NuGet501016.93 ns0.890 ns0.231 ns1.430.0430.0070--44 B
removeItemIntLikeAfterAfter1011.88 ns0.189 ns0.049 ns1.000.0010.0056--35 B
removeItemIntLikeMain50Main501015.17 ns0.241 ns0.063 ns1.280.0120.0069--44 B
removeItemIntLikeNuGet50NuGet501018.37 ns0.556 ns0.144 ns1.550.0130.0070--44 B
removeItemStringAfterAfter1012.20 ns0.206 ns0.053 ns1.000.0010.0056--35 B
removeItemStringMain50Main501014.81 ns0.308 ns0.080 ns1.210.0120.0070--44 B
removeItemStringNuGet50NuGet501021.20 ns0.403 ns0.105 ns1.740.0130.0070--44 B
removeItemRefLikeAfterAfter1012.17 ns0.302 ns0.078 ns1.000.0010.0056--35 B
removeItemRefLikeMain50Main501014.27 ns0.567 ns0.147 ns1.170.0220.0070--44 B
removeItemRefLikeNuGet50NuGet501020.95 ns0.278 ns0.072 ns1.720.0130.0070--44 B
removeItemIntRecordAfterAfter1013.16 ns0.193 ns0.050 ns1.000.0010.0056--35 B
removeItemIntRecordMain50Main501015.32 ns0.558 ns0.145 ns1.160.0120.0070--44 B
removeItemIntRecordNuGet50NuGet501019.50 ns0.592 ns0.154 ns1.480.0230.0070--44 B
removeItemIntRefRecordAfterAfter1012.07 ns0.155 ns0.040 ns1.000.0010.0056--35 B
removeItemIntRefRecordMain50Main501014.46 ns0.470 ns0.122 ns1.200.0120.0070--44 B
removeItemIntRefRecordNuGet50NuGet501020.97 ns0.257 ns0.067 ns1.740.0030.0070--44 B
removeItemIntLikeNonGenCmpAfterAfter1012.08 ns0.939 ns0.244 ns1.000.0010.0056--35 B
removeItemIntLikeNonGenCmpMain50Main501015.07 ns0.670 ns0.174 ns1.250.0420.0070--44 B
removeItemIntLikeNonGenCmpNuGet50NuGet501018.33 ns1.013 ns0.157 ns1.520.0330.0069--44 B
removeItemRefLikeNonGenCmpAfterAfter1012.13 ns0.455 ns0.118 ns1.000.0010.0056--35 B
removeItemRefLikeNonGenCmpMain50Main501014.47 ns0.613 ns0.159 ns1.190.0220.0070--44 B
removeItemRefLikeNonGenCmpNuGet50NuGet501020.94 ns0.375 ns0.058 ns1.720.0130.0069--44 B
getItemIntAfterAfter10018.97 ns1.405 ns0.365 ns1.000.001----
getItemIntMain50Main5010031.79 ns1.192 ns0.310 ns1.680.042----
getItemIntNuGet50NuGet5010072.33 ns0.624 ns0.097 ns3.810.083----
getItemIntLikeAfterAfter10066.84 ns1.111 ns0.172 ns1.000.001----
getItemIntLikeMain50Main50100246.56 ns3.648 ns0.947 ns3.690.0220.0524--331 B
getItemIntLikeNuGet50NuGet50100269.86 ns9.044 ns2.349 ns4.020.0230.0526--331 B
getItemStringAfterAfter10053.10 ns0.925 ns0.240 ns1.000.002----
getItemStringMain50Main5010046.17 ns1.272 ns0.197 ns0.870.001----
getItemStringNuGet50NuGet5010094.81 ns5.599 ns1.454 ns1.790.033----
getItemRefLikeAfterAfter100144.73 ns1.508 ns0.392 ns1.000.001----
getItemRefLikeMain50Main50100228.45 ns1.093 ns0.284 ns1.580.002----
getItemRefLikeNuGet50NuGet50100275.51 ns16.036 ns4.165 ns1.900.033----
getItemIntRecordAfterAfter100112.28 ns0.595 ns0.155 ns1.000.001----
getItemIntRecordMain50Main50100221.25 ns6.780 ns1.049 ns1.970.0120.0519--331 B
getItemIntRecordNuGet50NuGet50100253.14 ns1.861 ns0.288 ns2.250.0030.0520--331 B
getItemIntRefRecordAfterAfter100148.41 ns6.694 ns1.738 ns1.000.001----
getItemIntRefRecordMain50Main50100198.03 ns5.669 ns1.472 ns1.330.012----
getItemIntRefRecordNuGet50NuGet50100230.73 ns8.749 ns2.272 ns1.550.013----
getItemIntLikeNonGenCmpAfterAfter10099.52 ns2.670 ns0.693 ns1.000.0010.0259--166 B
getItemIntLikeNonGenCmpMain50Main50100230.76 ns5.653 ns0.875 ns2.320.0220.0528--331 B
getItemIntLikeNonGenCmpNuGet50NuGet50100267.13 ns8.118 ns2.108 ns2.680.0230.0520--331 B
getItemRefLikeNonGenCmpAfterAfter100184.42 ns11.382 ns2.956 ns1.000.001----
getItemRefLikeNonGenCmpMain50Main50100228.82 ns2.496 ns0.648 ns1.240.022----
getItemRefLikeNonGenCmpNuGet50NuGet50100269.54 ns2.950 ns0.457 ns1.460.033----
containsKeyIntAfterAfter10020.13 ns0.737 ns0.191 ns1.000.001----
containsKeyIntMain50Main5010026.04 ns1.071 ns0.278 ns1.290.012----
containsKeyIntNuGet50NuGet5010068.27 ns1.918 ns0.498 ns3.390.053----
containsKeyIntLikeAfterAfter10057.12 ns1.138 ns0.296 ns1.000.001----
containsKeyIntLikeMain50Main50100239.60 ns4.630 ns0.717 ns4.190.0320.0526--331 B
containsKeyIntLikeNuGet50NuGet50100273.49 ns4.715 ns1.224 ns4.790.0430.0515--331 B
containsKeyStringAfterAfter10052.79 ns3.496 ns0.541 ns1.000.002----
containsKeyStringMain50Main5010041.96 ns1.304 ns0.202 ns0.790.011----
containsKeyStringNuGet50NuGet5010085.71 ns2.955 ns0.767 ns1.620.013----
containsKeyRefLikeAfterAfter100148.24 ns1.592 ns0.246 ns1.000.001----
containsKeyRefLikeMain50Main50100234.13 ns3.836 ns0.594 ns1.580.002----
containsKeyRefLikeNuGet50NuGet50100277.66 ns7.306 ns1.131 ns1.870.013----
containsKeyIntRecordAfterAfter100100.83 ns3.616 ns0.939 ns1.000.001----
containsKeyIntRecordMain50Main50100229.00 ns5.064 ns1.315 ns2.270.0220.0520--331 B
containsKeyIntRecordNuGet50NuGet50100253.70 ns16.919 ns4.394 ns2.520.0630.0524--331 B
containsKeyIntRefRecordAfterAfter100152.22 ns3.240 ns0.841 ns1.000.001----
containsKeyIntRefRecordMain50Main50100199.06 ns1.979 ns0.514 ns1.310.012----
containsKeyIntRefRecordNuGet50NuGet50100238.39 ns6.600 ns1.714 ns1.570.013----
containsKeyIntLikeNonGenCmpAfterAfter10092.18 ns2.185 ns0.567 ns1.000.0010.0259--166 B
containsKeyIntLikeNonGenCmpMain50Main50100227.40 ns2.670 ns0.413 ns2.470.0220.0521--331 B
containsKeyIntLikeNonGenCmpNuGet50NuGet50100266.46 ns7.369 ns1.140 ns2.890.0230.0525--331 B
containsKeyRefLikeNonGenCmpAfterAfter100189.16 ns8.976 ns1.389 ns1.000.001----
containsKeyRefLikeNonGenCmpMain50Main50100228.42 ns4.952 ns1.286 ns1.210.012----
containsKeyRefLikeNonGenCmpNuGet50NuGet50100277.98 ns17.608 ns2.725 ns1.470.023----
itemCountIntAfterAfter100220.44 ns10.117 ns1.566 ns1.000.002----
itemCountIntMain50Main50100199.87 ns13.089 ns3.399 ns0.910.021----
itemCountIntNuGet50NuGet50100642.65 ns33.597 ns8.725 ns2.920.053----
itemCountIntLikeAfterAfter100219.28 ns5.408 ns1.404 ns1.000.002----
itemCountIntLikeMain50Main50100199.12 ns8.339 ns2.166 ns0.910.011----
itemCountIntLikeNuGet50NuGet50100638.60 ns21.622 ns5.615 ns2.910.023----
itemCountStringAfterAfter100210.41 ns22.729 ns5.903 ns1.000.001----
itemCountStringMain50Main50100270.53 ns20.309 ns5.274 ns1.290.042----
itemCountStringNuGet50NuGet50100808.91 ns37.733 ns9.799 ns3.850.083----
itemCountRefLikeAfterAfter100236.75 ns44.960 ns11.676 ns1.000.001----
itemCountRefLikeMain50Main50100302.45 ns37.958 ns5.874 ns1.300.032----
itemCountRefLikeNuGet50NuGet50100767.23 ns78.398 ns20.360 ns3.240.133----
itemCountIntRecordAfterAfter100224.46 ns9.359 ns2.430 ns1.000.002----
itemCountIntRecordMain50Main50100199.73 ns12.131 ns1.877 ns0.890.021----
itemCountIntRecordNuGet50NuGet50100643.28 ns24.220 ns3.748 ns2.870.033----
itemCountIntRefRecordAfterAfter100226.96 ns56.269 ns8.708 ns1.000.001----
itemCountIntRefRecordMain50Main50100290.03 ns17.004 ns2.631 ns1.280.052----
itemCountIntRefRecordNuGet50NuGet50100765.14 ns24.892 ns6.464 ns3.380.123----
itemCountIntLikeNonGenCmpAfterAfter100222.73 ns10.156 ns2.637 ns1.000.002----
itemCountIntLikeNonGenCmpMain50Main50100198.28 ns7.031 ns1.826 ns0.890.011----
itemCountIntLikeNonGenCmpNuGet50NuGet50100643.04 ns13.256 ns3.442 ns2.890.043----
itemCountRefLikeNonGenCmpAfterAfter100225.86 ns10.792 ns1.670 ns1.000.001----
itemCountRefLikeNonGenCmpMain50Main50100293.91 ns27.602 ns7.168 ns1.310.032----
itemCountRefLikeNonGenCmpNuGet50NuGet50100750.74 ns6.918 ns1.071 ns3.320.033----
iterForeachIntAfterAfter1003,184.55 ns15.290 ns2.366 ns1.000.0021.0300--6520 B
iterForeachIntMain50Main501003,143.18 ns52.629 ns8.144 ns0.990.0011.0388--6520 B
iterForeachIntNuGet50NuGet501003,799.58 ns416.457 ns108.153 ns1.180.0330.9650--6120 B
iterForeachIntLikeAfterAfter1003,150.37 ns57.264 ns14.871 ns1.000.0011.0321--6520 B
iterForeachIntLikeMain50Main501003,234.08 ns270.363 ns41.839 ns1.030.0111.0338--6520 B
iterForeachIntLikeNuGet50NuGet501003,735.78 ns54.658 ns8.458 ns1.190.0121.0304--6520 B
iterForeachStringAfterAfter1003,967.17 ns77.569 ns20.145 ns1.000.0011.0543--6648 B
iterForeachStringMain50Main501004,008.56 ns298.115 ns77.420 ns1.010.0211.0440--6648 B
iterForeachStringNuGet50NuGet501005,457.60 ns145.137 ns37.692 ns1.380.0121.0326--6648 B
iterForeachRefLikeAfterAfter1003,832.74 ns30.726 ns7.980 ns1.000.0011.0365--6520 B
iterForeachRefLikeMain50Main501003,848.77 ns69.727 ns10.790 ns1.000.0011.0331--6520 B
iterForeachRefLikeNuGet50NuGet501005,614.49 ns355.689 ns92.371 ns1.460.0221.0326--6520 B
iterForeachIntRecordAfterAfter1003,159.59 ns56.652 ns14.712 ns1.000.0011.0267--6520 B
iterForeachIntRecordMain50Main501003,151.96 ns240.842 ns62.546 ns1.000.0211.0310--6520 B
iterForeachIntRecordNuGet50NuGet501003,918.45 ns35.634 ns9.254 ns1.240.0021.0210--6520 B
iterForeachIntRefRecordAfterAfter1003,779.77 ns14.858 ns2.299 ns1.000.0011.0376--6520 B
iterForeachIntRefRecordMain50Main501004,095.19 ns774.857 ns201.228 ns1.070.0621.0285--6520 B
iterForeachIntRefRecordNuGet50NuGet501005,452.34 ns92.963 ns14.386 ns1.440.0031.0326--6520 B
iterForeachIntLikeNonGenCmpAfterAfter1003,141.00 ns48.912 ns12.702 ns1.000.0011.0243--6520 B
iterForeachIntLikeNonGenCmpMain50Main501003,148.50 ns77.225 ns11.951 ns1.000.0011.0300--6520 B
iterForeachIntLikeNonGenCmpNuGet50NuGet501003,727.12 ns67.235 ns10.405 ns1.190.0021.0346--6520 B
iterForeachRefLikeNonGenCmpAfterAfter1003,776.05 ns100.223 ns26.028 ns1.000.0011.0323--6520 B
iterForeachRefLikeNonGenCmpMain50Main501003,895.12 ns79.005 ns20.517 ns1.030.0121.0230--6520 B
iterForeachRefLikeNonGenCmpNuGet50NuGet501005,475.10 ns126.439 ns32.836 ns1.450.0131.0308--6520 B
addItemIntAfterAfter100149.46 ns1.576 ns0.409 ns1.000.0010.0566--357 B
addItemIntMain50Main50100158.51 ns1.524 ns0.236 ns1.060.0020.0578--366 B
addItemIntNuGet50NuGet50100357.40 ns3.389 ns0.524 ns2.390.0030.0568--361 B
addItemIntLikeAfterAfter100184.74 ns3.445 ns0.533 ns1.000.0010.0563--357 B
addItemIntLikeMain50Main50100375.63 ns12.012 ns1.859 ns2.030.0120.1103--697 B
addItemIntLikeNuGet50NuGet50100588.16 ns3.557 ns0.550 ns3.180.0130.1088--697 B
addItemStringAfterAfter100176.26 ns3.440 ns0.893 ns1.000.0010.0468--298 B
addItemStringMain50Main50100173.71 ns15.523 ns4.031 ns0.990.0210.0487--306 B
addItemStringNuGet50NuGet50100376.89 ns5.216 ns0.807 ns2.140.0120.0471--306 B
addItemRefLikeAfterAfter100296.47 ns2.760 ns0.717 ns1.000.0010.0560--357 B
addItemRefLikeMain50Main50100384.48 ns16.062 ns2.486 ns1.300.0120.0574--366 B
addItemRefLikeNuGet50NuGet50100678.90 ns10.881 ns1.684 ns2.290.0130.0576--366 B
addItemIntRecordAfterAfter100248.07 ns4.178 ns1.085 ns1.000.0010.0557--357 B
addItemIntRecordMain50Main50100366.16 ns28.587 ns7.424 ns1.480.0320.1102--697 B
addItemIntRecordNuGet50NuGet50100560.83 ns10.335 ns1.599 ns2.260.0130.1092--697 B
addItemIntRefRecordAfterAfter100296.26 ns6.037 ns1.568 ns1.000.0010.0557--357 B
addItemIntRefRecordMain50Main50100359.93 ns39.231 ns10.188 ns1.210.0320.0581--366 B
addItemIntRefRecordNuGet50NuGet50100626.88 ns8.513 ns1.317 ns2.120.0130.0559--366 B
addItemIntLikeNonGenCmpAfterAfter100222.56 ns7.935 ns2.061 ns1.000.0010.0829--522 B
addItemIntLikeNonGenCmpMain50Main50100369.14 ns4.631 ns0.717 ns1.660.0220.1104--697 B
addItemIntLikeNonGenCmpNuGet50NuGet50100592.62 ns6.368 ns1.654 ns2.660.0330.1095--697 B
addItemRefLikeNonGenCmpAfterAfter100338.14 ns5.822 ns1.512 ns1.000.0010.0556--357 B
addItemRefLikeNonGenCmpMain50Main50100381.96 ns6.078 ns0.941 ns1.130.0120.0569--366 B
addItemRefLikeNonGenCmpNuGet50NuGet50100689.68 ns10.552 ns2.740 ns2.040.0130.0549--366 B
removeItemIntAfterAfter100100.60 ns1.375 ns0.357 ns1.000.0010.0392--246 B
removeItemIntMain50Main50100107.81 ns8.196 ns2.129 ns1.070.0220.0406--255 B
removeItemIntNuGet50NuGet50100253.37 ns2.330 ns0.361 ns2.520.0130.0401--255 B
removeItemIntLikeAfterAfter100124.58 ns1.924 ns0.500 ns1.000.0010.0389--246 B
removeItemIntLikeMain50Main50100240.29 ns19.539 ns5.074 ns1.930.0420.0741--466 B
removeItemIntLikeNuGet50NuGet50100388.22 ns3.008 ns0.781 ns3.120.0130.0737--466 B
removeItemStringAfterAfter100202.76 ns4.735 ns1.230 ns1.000.0020.0493--314 B
removeItemStringMain50Main50100194.10 ns7.282 ns1.127 ns0.960.0110.0511--322 B
removeItemStringNuGet50NuGet50100465.08 ns4.439 ns1.153 ns2.290.0130.0491--322 B
removeItemRefLikeAfterAfter100185.09 ns5.629 ns0.871 ns1.000.0010.0388--246 B
removeItemRefLikeMain50Main50100251.99 ns29.504 ns7.662 ns1.370.0520.0404--255 B
removeItemRefLikeNuGet50NuGet50100484.94 ns2.478 ns0.644 ns2.620.0130.0387--255 B
removeItemIntRecordAfterAfter100148.08 ns1.551 ns0.403 ns1.000.0010.0393--246 B
removeItemIntRecordMain50Main50100224.98 ns10.822 ns2.810 ns1.520.0220.0743--466 B
removeItemIntRecordNuGet50NuGet50100387.87 ns2.351 ns0.611 ns2.620.0130.0739--466 B
removeItemIntRefRecordAfterAfter100192.79 ns2.909 ns0.450 ns1.000.0010.0389--246 B
removeItemIntRefRecordMain50Main50100223.71 ns5.286 ns1.373 ns1.160.0120.0399--255 B
removeItemIntRefRecordNuGet50NuGet50100466.15 ns3.277 ns0.507 ns2.420.0030.0395--255 B
removeItemIntLikeNonGenCmpAfterAfter100135.38 ns1.913 ns0.497 ns1.000.0010.0561--352 B
removeItemIntLikeNonGenCmpMain50Main50100240.62 ns7.711 ns1.193 ns1.780.0120.0742--466 B
removeItemIntLikeNonGenCmpNuGet50NuGet50100398.46 ns4.807 ns1.248 ns2.940.0130.0736--466 B
removeItemRefLikeNonGenCmpAfterAfter100210.35 ns3.156 ns0.488 ns1.000.0010.0392--246 B
removeItemRefLikeNonGenCmpMain50Main50100246.89 ns19.505 ns5.065 ns1.160.0220.0401--255 B
removeItemRefLikeNonGenCmpNuGet50NuGet50100487.36 ns6.175 ns1.604 ns2.320.0130.0389--255 B
getItemIntAfterAfter100025.02 ns0.827 ns0.128 ns1.000.001----
getItemIntMain50Main50100048.14 ns0.952 ns0.247 ns1.920.012----
getItemIntNuGet50NuGet501000108.20 ns0.849 ns0.221 ns4.320.023----
getItemIntLikeAfterAfter100094.32 ns1.025 ns0.159 ns1.000.001----
getItemIntLikeMain50Main501000352.89 ns12.728 ns3.306 ns3.730.0420.0770--490 B
getItemIntLikeNuGet50NuGet501000388.50 ns4.462 ns1.159 ns4.120.0130.0776--490 B
getItemStringAfterAfter100096.66 ns3.952 ns0.612 ns1.000.002----
getItemStringMain50Main50100077.31 ns0.980 ns0.152 ns0.800.001----
getItemStringNuGet50NuGet501000156.42 ns4.430 ns1.151 ns1.610.023----
getItemRefLikeAfterAfter1000202.58 ns2.227 ns0.578 ns1.000.001----
getItemRefLikeMain50Main501000319.66 ns5.877 ns0.910 ns1.580.002----
getItemRefLikeNuGet50NuGet501000384.77 ns9.908 ns1.533 ns1.900.013----
getItemIntRecordAfterAfter1000157.66 ns0.780 ns0.202 ns1.000.001----
getItemIntRecordMain50Main501000314.41 ns7.215 ns1.874 ns1.990.0120.0770--490 B
getItemIntRecordNuGet50NuGet501000356.50 ns8.239 ns2.140 ns2.260.0130.0775--490 B
getItemIntRefRecordAfterAfter1000205.85 ns1.482 ns0.385 ns1.000.001----
getItemIntRefRecordMain50Main501000264.93 ns4.938 ns1.282 ns1.290.012----
getItemIntRefRecordNuGet50NuGet501000320.31 ns7.575 ns1.967 ns1.560.013----
getItemIntLikeNonGenCmpAfterAfter1000149.52 ns12.115 ns1.875 ns1.000.0010.0389--245 B
getItemIntLikeNonGenCmpMain50Main501000329.73 ns3.041 ns0.471 ns2.210.0320.0773--490 B
getItemIntLikeNonGenCmpNuGet50NuGet501000389.06 ns25.240 ns6.555 ns2.610.0330.0762--490 B
getItemRefLikeNonGenCmpAfterAfter1000250.07 ns4.115 ns0.637 ns1.000.001----
getItemRefLikeNonGenCmpMain50Main501000321.05 ns1.900 ns0.493 ns1.280.012----
getItemRefLikeNonGenCmpNuGet50NuGet501000386.16 ns8.447 ns2.194 ns1.540.013----
containsKeyIntAfterAfter100028.67 ns0.341 ns0.089 ns1.000.001----
containsKeyIntMain50Main50100037.03 ns1.107 ns0.287 ns1.290.012----
containsKeyIntNuGet50NuGet501000101.60 ns1.478 ns0.384 ns3.540.013----
containsKeyIntLikeAfterAfter100094.45 ns1.779 ns0.462 ns1.000.001----
containsKeyIntLikeMain50Main501000341.01 ns19.770 ns5.134 ns3.610.0520.0775--490 B
containsKeyIntLikeNuGet50NuGet501000385.47 ns4.900 ns1.272 ns4.080.0330.0767--490 B
containsKeyStringAfterAfter100096.93 ns4.180 ns0.647 ns1.000.002----
containsKeyStringMain50Main50100071.39 ns2.019 ns0.524 ns0.730.011----
containsKeyStringNuGet50NuGet501000146.28 ns6.038 ns0.934 ns1.510.023----
containsKeyRefLikeAfterAfter1000205.47 ns10.856 ns2.819 ns1.000.001----
containsKeyRefLikeMain50Main501000322.46 ns1.045 ns0.272 ns1.570.022----
containsKeyRefLikeNuGet50NuGet501000394.52 ns2.167 ns0.335 ns1.920.033----
containsKeyIntRecordAfterAfter1000156.54 ns1.374 ns0.357 ns1.000.001----
containsKeyIntRecordMain50Main501000307.61 ns14.769 ns2.286 ns1.960.0120.0780--490 B
containsKeyIntRecordNuGet50NuGet501000355.10 ns21.796 ns5.660 ns2.270.0430.0778--490 B
containsKeyIntRefRecordAfterAfter1000211.84 ns3.127 ns0.484 ns1.000.001----
containsKeyIntRefRecordMain50Main501000267.75 ns1.141 ns0.177 ns1.260.002----
containsKeyIntRefRecordNuGet50NuGet501000332.18 ns1.878 ns0.291 ns1.570.003----
containsKeyIntLikeNonGenCmpAfterAfter1000147.87 ns2.210 ns0.574 ns1.000.0010.0384--245 B
containsKeyIntLikeNonGenCmpMain50Main501000326.15 ns4.386 ns0.679 ns2.210.0120.0780--490 B
containsKeyIntLikeNonGenCmpNuGet50NuGet501000386.89 ns21.193 ns5.504 ns2.620.0430.0766--490 B
containsKeyRefLikeNonGenCmpAfterAfter1000249.97 ns3.375 ns0.876 ns1.000.001----
containsKeyRefLikeNonGenCmpMain50Main501000319.27 ns8.171 ns1.264 ns1.280.012----
containsKeyRefLikeNonGenCmpNuGet50NuGet501000395.52 ns11.528 ns1.784 ns1.580.013----
itemCountIntAfterAfter10003,055.82 ns201.240 ns52.261 ns1.000.002----
itemCountIntMain50Main5010002,826.45 ns235.528 ns61.166 ns0.930.021----
itemCountIntNuGet50NuGet5010007,030.40 ns217.806 ns56.563 ns2.300.053----
itemCountIntLikeAfterAfter10003,061.21 ns239.546 ns62.209 ns1.000.002----
itemCountIntLikeMain50Main5010002,779.95 ns76.816 ns19.949 ns0.910.011----
itemCountIntLikeNuGet50NuGet5010007,142.48 ns108.106 ns28.075 ns2.330.043----
itemCountStringAfterAfter10003,406.13 ns236.256 ns36.561 ns1.000.001----
itemCountStringMain50Main5010003,566.58 ns113.958 ns29.595 ns1.050.002----
itemCountStringNuGet50NuGet5010008,920.93 ns116.982 ns18.103 ns2.620.033----
itemCountRefLikeAfterAfter10003,298.94 ns170.981 ns26.459 ns1.000.001----
itemCountRefLikeMain50Main5010003,479.42 ns179.309 ns46.566 ns1.050.012----
itemCountRefLikeNuGet50NuGet5010008,546.53 ns216.172 ns33.453 ns2.590.033----
itemCountIntRecordAfterAfter10003,034.17 ns101.451 ns26.347 ns1.000.002----
itemCountIntRecordMain50Main5010002,846.96 ns272.815 ns70.849 ns0.940.021----
itemCountIntRecordNuGet50NuGet5010007,088.36 ns189.757 ns49.279 ns2.340.023----
itemCountIntRefRecordAfterAfter10003,351.18 ns172.547 ns44.810 ns1.000.001----
itemCountIntRefRecordMain50Main5010003,491.27 ns41.517 ns6.425 ns1.040.022----
itemCountIntRefRecordNuGet50NuGet5010008,556.55 ns66.093 ns17.164 ns2.550.043----
itemCountIntLikeNonGenCmpAfterAfter10003,075.82 ns103.606 ns26.906 ns1.000.002----
itemCountIntLikeNonGenCmpMain50Main5010002,830.64 ns195.015 ns50.645 ns0.920.021----
itemCountIntLikeNonGenCmpNuGet50NuGet5010007,074.52 ns226.681 ns58.868 ns2.300.033----
itemCountRefLikeNonGenCmpAfterAfter10003,258.14 ns160.712 ns41.736 ns1.000.001----
itemCountRefLikeNonGenCmpMain50Main5010003,512.67 ns88.312 ns22.934 ns1.080.012----
itemCountRefLikeNonGenCmpNuGet50NuGet5010008,525.15 ns76.360 ns19.830 ns2.620.033----
iterForeachIntAfterAfter100033,235.90 ns1,256.411 ns326.286 ns1.000.00110.1974--64120 B
iterForeachIntMain50Main50100033,450.22 ns846.144 ns219.741 ns1.010.01110.1396--64120 B
iterForeachIntNuGet50NuGet50100039,009.83 ns601.700 ns93.114 ns1.180.0129.5405--60120 B
iterForeachIntLikeAfterAfter100033,313.42 ns680.245 ns176.657 ns1.000.00110.2212--64120 B
iterForeachIntLikeMain50Main50100033,004.49 ns405.091 ns105.201 ns0.990.01110.1127--64120 B
iterForeachIntLikeNuGet50NuGet50100039,379.16 ns1,016.077 ns263.872 ns1.180.01210.1881--64120 B
iterForeachStringAfterAfter100042,224.61 ns829.107 ns215.317 ns1.000.00110.9536--68728 B
iterForeachStringMain50Main50100042,272.99 ns1,669.605 ns433.591 ns1.000.01110.8696--68728 B
iterForeachStringNuGet50NuGet50100057,869.96 ns478.920 ns124.374 ns1.370.01210.6635--68728 B
iterForeachRefLikeAfterAfter100041,250.21 ns3,390.599 ns880.528 ns1.000.00110.1010--64120 B
iterForeachRefLikeMain50Main50100040,761.32 ns904.343 ns139.948 ns1.000.01110.0334--64120 B
iterForeachRefLikeNuGet50NuGet50100057,284.45 ns772.117 ns119.486 ns1.400.02210.0446--64120 B
iterForeachIntRecordAfterAfter100033,679.78 ns1,635.842 ns424.823 ns1.000.00110.0860--64120 B
iterForeachIntRecordMain50Main50100033,052.35 ns567.626 ns147.411 ns0.980.01110.1127--64120 B
iterForeachIntRecordNuGet50NuGet50100041,185.73 ns1,424.841 ns370.027 ns1.220.02210.0410--64120 B
iterForeachIntRefRecordAfterAfter100041,717.10 ns885.258 ns229.899 ns1.000.00210.0599--64120 B
iterForeachIntRefRecordMain50Main50100039,929.41 ns2,542.898 ns393.516 ns0.960.01110.1837--64120 B
iterForeachIntRefRecordNuGet50NuGet50100056,990.85 ns1,988.155 ns516.318 ns1.370.01310.0897--64120 B
iterForeachIntLikeNonGenCmpAfterAfter100033,414.51 ns2,153.555 ns559.271 ns1.000.00110.1396--64120 B
iterForeachIntLikeNonGenCmpMain50Main50100033,154.32 ns823.731 ns127.473 ns0.990.02110.1127--64120 B
iterForeachIntLikeNonGenCmpNuGet50NuGet50100039,843.78 ns2,070.478 ns537.697 ns1.190.03210.2201--64120 B
iterForeachRefLikeNonGenCmpAfterAfter100040,992.92 ns1,572.246 ns408.307 ns1.000.00110.2163--64120 B
iterForeachRefLikeNonGenCmpMain50Main50100040,656.75 ns3,498.869 ns541.454 ns0.990.01110.1513--64120 B
iterForeachRefLikeNonGenCmpNuGet50NuGet50100057,462.64 ns2,372.846 ns616.221 ns1.400.02210.0806--64120 B
addItemIntAfterAfter1000241.67 ns13.794 ns3.582 ns1.000.0010.0816--515 B
addItemIntMain50Main501000238.33 ns31.165 ns8.093 ns0.990.0410.0829--524 B
addItemIntNuGet50NuGet501000542.05 ns2.944 ns0.765 ns2.240.0320.0813--519 B
addItemIntLikeAfterAfter1000287.60 ns10.849 ns2.817 ns1.000.0010.0816--515 B
addItemIntLikeMain50Main501000576.99 ns79.313 ns20.597 ns2.010.0820.1598--1014 B
addItemIntLikeNuGet50NuGet501000871.13 ns15.566 ns4.043 ns3.030.0330.1572--1014 B
addItemStringAfterAfter1000311.91 ns28.343 ns4.386 ns1.000.0020.0731--466 B
addItemStringMain50Main501000291.01 ns12.160 ns3.158 ns0.940.0210.0743--474 B
addItemStringNuGet50NuGet501000677.33 ns2.210 ns0.342 ns2.170.0330.0744--474 B
addItemRefLikeAfterAfter1000444.25 ns18.302 ns2.832 ns1.000.0010.0805--515 B
addItemRefLikeMain50Main501000580.43 ns63.247 ns9.788 ns1.310.0220.0810--524 B
addItemRefLikeNuGet50NuGet501000993.81 ns3.105 ns0.806 ns2.240.0130.0799--524 B
addItemIntRecordAfterAfter1000380.90 ns8.203 ns1.269 ns1.000.0010.0815--515 B
addItemIntRecordMain50Main501000524.61 ns7.189 ns1.112 ns1.380.0020.1591--1014 B
addItemIntRecordNuGet50NuGet501000810.34 ns10.017 ns2.602 ns2.130.0030.1576--1014 B
addItemIntRefRecordAfterAfter1000443.09 ns19.383 ns5.034 ns1.000.0010.0813--515 B
addItemIntRefRecordMain50Main501000516.02 ns14.630 ns2.264 ns1.170.0220.0818--524 B
addItemIntRefRecordNuGet50NuGet501000928.03 ns8.637 ns2.243 ns2.090.0230.0833--524 B
addItemIntLikeNonGenCmpAfterAfter1000339.04 ns2.564 ns0.397 ns1.000.0010.1207--760 B
addItemIntLikeNonGenCmpMain50Main501000554.66 ns15.236 ns2.358 ns1.640.0120.1613--1014 B
addItemIntLikeNonGenCmpNuGet50NuGet501000882.71 ns30.659 ns7.962 ns2.610.0230.1580--1014 B
addItemRefLikeNonGenCmpAfterAfter1000493.60 ns4.568 ns1.186 ns1.000.0010.0816--515 B
addItemRefLikeNonGenCmpMain50Main501000553.96 ns24.781 ns6.435 ns1.120.0120.0821--524 B
addItemRefLikeNonGenCmpNuGet50NuGet501000985.67 ns15.301 ns2.368 ns2.000.0130.0788--524 B
removeItemIntAfterAfter1000165.01 ns2.059 ns0.319 ns1.000.0010.0643--405 B
removeItemIntMain50Main501000176.17 ns18.137 ns4.710 ns1.060.0320.0658--414 B
removeItemIntNuGet50NuGet501000441.60 ns4.653 ns1.208 ns2.680.0130.0639--414 B
removeItemIntLikeAfterAfter1000206.84 ns5.278 ns0.817 ns1.000.0010.0638--405 B
removeItemIntLikeMain50Main501000406.19 ns29.419 ns7.640 ns1.960.0420.1231--783 B
removeItemIntLikeNuGet50NuGet501000683.79 ns10.607 ns2.754 ns3.310.0230.1230--783 B
removeItemStringAfterAfter1000350.06 ns5.199 ns1.350 ns1.000.0010.0802--510 B
removeItemStringMain50Main501000334.93 ns42.534 ns11.046 ns0.960.0310.0819--519 B
removeItemStringNuGet50NuGet501000832.71 ns22.998 ns5.973 ns2.380.0120.0826--519 B
removeItemRefLikeAfterAfter1000343.39 ns3.726 ns0.968 ns1.000.0010.0638--405 B
removeItemRefLikeMain50Main501000418.47 ns6.834 ns1.775 ns1.220.0120.0648--414 B
removeItemRefLikeNuGet50NuGet501000807.87 ns10.423 ns2.707 ns2.350.0030.0649--414 B
removeItemIntRecordAfterAfter1000267.43 ns2.223 ns0.577 ns1.000.0010.0637--405 B
removeItemIntRecordMain50Main501000379.65 ns4.758 ns1.236 ns1.420.0020.1239--783 B
removeItemIntRecordNuGet50NuGet501000662.82 ns7.469 ns1.156 ns2.480.0130.1233--783 B
removeItemIntRefRecordAfterAfter1000338.94 ns4.317 ns0.668 ns1.000.0010.0644--405 B
removeItemIntRefRecordMain50Main501000399.10 ns27.237 ns7.073 ns1.180.0220.0655--414 B
removeItemIntRefRecordNuGet50NuGet501000788.90 ns36.366 ns9.444 ns2.330.0330.0658--414 B
removeItemIntLikeNonGenCmpAfterAfter1000229.83 ns3.315 ns0.513 ns1.000.0010.0935--590 B
removeItemIntLikeNonGenCmpMain50Main501000403.62 ns10.840 ns1.678 ns1.760.0120.1228--783 B
removeItemIntLikeNonGenCmpNuGet50NuGet501000680.05 ns20.804 ns5.403 ns2.960.0330.1242--783 B
removeItemRefLikeNonGenCmpAfterAfter1000377.34 ns4.709 ns1.223 ns1.000.0010.0627--405 B
removeItemRefLikeNonGenCmpMain50Main501000424.20 ns7.660 ns1.185 ns1.120.0120.0650--414 B
removeItemRefLikeNonGenCmpNuGet50NuGet501000804.00 ns8.058 ns2.093 ns2.130.0130.0642--414 B

Inline primitive comparison, keep the rest the same. See Comparison/cmp comments on how and why this works.
Arrays and structural comparison may cause problems
Maybe should just copy the snippet from dotnet#9348
…ilable
It's unambiguous. If it does something different than other ways to compare then it's very weird.
F# records implement IComparable<T> that works as expected.
buybackoff added a commit to buybackoff/fsharp that referenced this pull request Jan 10, 2021
@cartermp

Copy link
Copy Markdown
Contributor

Hmmmm. The regression for reflikes in your testing is troublesome. I can't speak towards overall usage, but within the compiler we definitely make heavy use of reference types and this would negatively affect that.

@buybackoff

Copy link
Copy Markdown
ContributorAuthor

Hmmmm. The regression for reflikes in your testing is troublesome. I can't speak towards overall usage, but within the compiler we definitely make heavy use of reference types and this would negatively affect that.

Yes, when I was writing "<5% mostly edge cases" of course I was biased towards my own usage patterns...

Overall, these things look too complicated. I opened the draft PRs mostly for CI and to show the magnitude of possible improvements. I'm glad that I was able to split the whole Map/Set story into independent steps. If you close these 2 comparer PRs I'm fine with it. A was aware of the comparer inefficiency for a long time. But I'm rather out of the loop these days and when I've learned all the complexity and history of the comparison vs Comparer<T>.Default issue I realized it's too much to push forward with this. It's a much bigger issue than just Map/Set.

@cartermp

Copy link
Copy Markdown
Contributor

Okay, makes sense. Thanks for the explanation! And for all of the enhancement so far :)

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@buybackoff@cartermp