Skip to content

Improve searching for symbols when a name is known ahead of time. (And avoid O(n) enumerations)#26330

Merged
agocke merged 8 commits intodotnet:masterfrom
CyrusNajmabadi:symbolSearchO1
May 1, 2018
Merged

Improve searching for symbols when a name is known ahead of time. (And avoid O(n) enumerations)#26330
agocke merged 8 commits intodotnet:masterfrom
CyrusNajmabadi:symbolSearchO1

Conversation

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi commented Apr 23, 2018

Followup to #26325.

This also switches the backing store for the MemberNames collection to an ImmutableHashSet. That has two benefits. One, it fixes #26328 where the current system allows a client to potentially corrupt internal compiler state.

Second, it allows for O(log(n)) name lookups instead of O(n). this is because we use ImmutableHashSet which is an efficient AVL tree where the hashcode of the object is the key for the node**. This is an improvement on top of our own SmallDict ** , and means we can be immutable, have fast lookups, and not have much more overhead than an array/immutablearray.

--

** SmallDictionary is effectively the same, just with space for a 'value'. As we don't need that here, we save by just using ImmutableHashSet.

@CyrusNajmabadi CyrusNajmabadi requested a review from a team as a code owner April 23, 2018 00:55
@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

Tagging @dotnet/roslyn-ide @VSadov @jcouv

@jcouv jcouv added Area-Compilers Community The pull request was submitted by a contributor who is not a Microsoft employee. labels Apr 23, 2018
@gafter
Copy link
Copy Markdown
Member

gafter commented Apr 23, 2018

This appears to contain deltas from #26325. Can we wrap that one up before I review this?

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

@gafter Yup. As i mentioned:

Followup to #26325.

I'll ping you when that goes in and this is ready to review.

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

@gafter Dependent PR has been merged. This is ready for review now. Also @jcouv.

@jcouv
Copy link
Copy Markdown
Member

jcouv commented Apr 24, 2018

Yup. Removed "Blocked" tag. Will take a look tonight or tomorrow.

@jcouv jcouv added this to the 15.8 milestone Apr 24, 2018
@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

@gafter @jcouv can you take a peek plz? Thanks!

''' <see cref="CaseInsensitiveComparison.Comparer"/> so that name lookup happens in an
''' appropriate manner for VB identifiers. This allows fast member name O(log(n)) even if
''' the casing doesn't match.
''' </summary>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

note: we have lot of case sensitivty tests for VB (including directly in symbol search) to validate this behavior.

private static readonly ObjectPool<ImmutableHashSet<string>.Builder> s_memberNameBuilderPool =
new ObjectPool<ImmutableHashSet<string>.Builder>(() => ImmutableHashSet.CreateBuilder<string>());

private static ImmutableHashSet<string> ToImmutableAndFree(ImmutableHashSet<string>.Builder builder)
Copy link
Copy Markdown
Member

@jcouv jcouv Apr 27, 2018

Choose a reason for hiding this comment

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

If there is a chance that we'd want to use pooled ImmutableHashSet in other parts of the code, it may be good to pull into a dedicated type (like PooledHashSet).

Update: hum, I see that VB needs to use hash sets with a case-insensitive comparer... I see why you didn't factor this out. #Resolved

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yup yup :)

declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.HasAnyNontypeMembers;
}

// PERF: The member names collection tends to be long-lived. Use a string array since
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we have any idea if how much this change increases memory usage (versus decreases CPU usage by virtue of faster lookup)? @agocke @jaredpar do we have some sort of benchmark or perf leg we could trigger?

Copy link
Copy Markdown
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

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

The change looks good, but I'm not convinced that it helps for perf/allocation trade-off.
Getting some data point would help (maybe benchmark on compiling Roslyn?).

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

Compiling roslyn shows no change in perf for me. How do you guys normally validate compiler changes wrt perf yourself?

@jcouv
Copy link
Copy Markdown
Member

jcouv commented Apr 27, 2018

I'll let @agocke reply (he has some instructions on how to validate).

@agocke
Copy link
Copy Markdown
Member

agocke commented Apr 27, 2018

I wrote up a tool to help test perf changes here: https://github.com/dotnet/roslyn-tools/tree/master/src/CompilerPerfTests

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

Awesome. I'll try this out this weekend!

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

@agocke I tried this, but i got:

C:\GitHub\roslyn-internal\roslyn-tools\src\CompilerPerfTests [master ≡]> .\run-perf.ps1
The term 'Ensure-SdkInPath' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

@agocke
Copy link
Copy Markdown
Member

agocke commented May 1, 2018

@CyrusNajmabadi Fixed here: dotnet/roslyn-tools#248. Looks like some changes were made to Roslyn that needed to be reflected in the powershell script.

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

CyrusNajmabadi commented May 1, 2018

Thanks! Here are my results:

// * Summary *

BenchmarkDotNet=v0.10.9, OS=Windows 10.0.16299
Processor=Intel Core i7-7600U CPU 2.80GHz (Kaby Lake), ProcessorCount=4
Frequency=2835939 Hz, Resolution=352.6169 ns, Timer=TSC
.NET Core SDK=2.1.105
  [Host] : .NET Core 2.0.7 (Framework 4.6.26328.01), 64bit RyuJIT

Toolchain=Perf.ExternalProcessToolchain  LaunchCount=0  RunStrategy=Monitoring
TargetCount=25  WarmupCount=0

            Method | Commit |    Mean |    Error |   StdDev | Rank |
------------------ |------- |--------:|---------:|---------:|-----:|
 PlaceholderMethod |   HEAD | 4.801 s | 0.1239 s | 0.1654 s |    1 |
 PlaceholderMethod |  HEAD^ | 4.779 s | 0.1318 s | 0.1759 s |    1 |
Details // ***** BenchmarkRunner: Start ***** // Found benchmarks: // PlaceholderBenchmarkRunner.PlaceholderMethod: Job-EWQPHF(Toolchain=Perf.ExternalProcessToolchain, LaunchCount=0, RunStrategy=Monitoring, TargetCount=25, WarmupCount=0) [Commit=HEAD^] // PlaceholderBenchmarkRunner.PlaceholderMethod: Job-EWQPHF(Toolchain=Perf.ExternalProcessToolchain, LaunchCount=0, RunStrategy=Monitoring, TargetCount=25, WarmupCount=0) [Commit=HEAD]

// Validating benchmarks:
No exporters defined, results will not be persisted.
// **************************
// Benchmark: PlaceholderBenchmarkRunner.PlaceholderMethod: Job-EWQPHF(Toolchain=Perf.ExternalProcessToolchain, LaunchCount=0, RunStrategy=Monitoring, TargetCount=25, WarmupCount=0) [Commit=HEAD^]
// *** Generate ***
// Result = Success
// BinariesDirectoryPath =

// *** Build ***
Building commit: HEAD^

commit b6d9b18
Author: Cyrus Najmabadi cyrus.najmabadi@gmail.com

Add comments

Repo Dir C:\GitHub\roslyn-internal\roslyn
Binaries Dir C:\GitHub\roslyn-internal\roslyn\Binaries
Running restore
Restore using dotnet at C:\GitHub\roslyn-internal\roslyn\Binaries\Tools\dotnet\dotnet.exe
Restoring Roslyn Toolset
Restoring Roslyn
Microsoft (R) Build Engine version 15.7.66.2115 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

Restoring packages for C:\GitHub\roslyn-internal\roslyn\src\Compilers\Core\Portable\CodeAnalysis.csproj...
Restoring packages for C:\GitHub\roslyn-internal\roslyn\src\Compilers\CSharp\csc\csc.csproj...
Restore completed in 214.62 ms for C:\GitHub\roslyn-internal\roslyn\src\Compilers\Core\Portable\CodeAnalysis.csproj.
Restoring packages for C:\GitHub\roslyn-internal\roslyn\src\Compilers\CSharp\Portable\CSharpCodeAnalysis.csproj...
Restore completed in 50.01 ms for C:\GitHub\roslyn-internal\roslyn\src\Compilers\CSharp\Portable\CSharpCodeAnalysis.csproj.
Restore completed in 532.41 ms for C:\GitHub\roslyn-internal\roslyn\src\Compilers\CSharp\csc\csc.csproj.
CodeAnalysis -> C:\GitHub\roslyn-internal\roslyn\Binaries\Release\Dlls\CodeAnalysis\Microsoft.CodeAnalysis.dll
CSharpCodeAnalysis -> C:\GitHub\roslyn-internal\roslyn\Binaries\Release\Dlls\CSharpCodeAnalysis\Microsoft.CodeAnalysis.CSharp.dll
csc -> C:\GitHub\roslyn-internal\roslyn\Binaries\Release\Exes\csc\net46\csc.exe
csc -> C:\GitHub\roslyn-internal\roslyn\Binaries\Release\Exes\csc\netcoreapp2.0\csc.dll

Build succeeded.
0 Warning(s)
0 Error(s)

Time Elapsed 00:00:23.06
// Result = Success

// *** Execute ***
// Launch: 1 / 1
// Execute: dotnet "C:\GitHub\roslyn-internal\roslyn\Binaries/Release/Exes/csc/netcoreapp2.0/csc.dll" -noconfig @repro.rsp
Result 0: 1 op, 4627325552.49 ns, 4.6273 s/op
Result 1: 1 op, 4628823821.67 ns, 4.6288 s/op
Result 2: 1 op, 4694308304.94 ns, 4.6943 s/op
Result 3: 1 op, 4799332425.70 ns, 4.7993 s/op
Result 4: 1 op, 4699403971.67 ns, 4.6994 s/op
Result 5: 1 op, 5012073955.05 ns, 5.0121 s/op
Result 6: 1 op, 5269704672.77 ns, 5.2697 s/op
Result 7: 1 op, 4845931453.39 ns, 4.8459 s/op
Result 8: 1 op, 5031030991.85 ns, 5.0310 s/op
Result 9: 1 op, 4685931890.64 ns, 4.6859 s/op
Result 10: 1 op, 4665204364.41 ns, 4.6652 s/op
Result 11: 1 op, 4990832313.39 ns, 4.9908 s/op
Result 12: 1 op, 4817819071.57 ns, 4.8178 s/op
Result 13: 1 op, 4683325346.56 ns, 4.6833 s/op
Result 14: 1 op, 4524974267.78 ns, 4.5250 s/op
Result 15: 1 op, 4651704426.65 ns, 4.6517 s/op
Result 16: 1 op, 4618164212.98 ns, 4.6182 s/op
Result 17: 1 op, 4681305557.00 ns, 4.6813 s/op
Result 18: 1 op, 4713645110.14 ns, 4.7136 s/op
Result 19: 1 op, 4990797756.93 ns, 4.9908 s/op
Result 20: 1 op, 4730881376.50 ns, 4.7309 s/op
Result 21: 1 op, 4615948368.42 ns, 4.6159 s/op
Result 22: 1 op, 4875749795.75 ns, 4.8757 s/op
Result 23: 1 op, 4673418222.32 ns, 4.6734 s/op
Result 24: 1 op, 4947422000.26 ns, 4.9474 s/op

Mean = 4.7790 s, StdErr = 0.0352 s (0.74%); N = 25, StdDev = 0.1759 s
Min = 4.5250 s, Q1 = 4.6585 s, Median = 4.6994 s, Q3 = 4.9116 s, Max = 5.2697 s
IQR = 0.2531 s, LowerFence = 4.2788 s, UpperFence = 5.2913 s
ConfidenceInterval = [4.6472 s; 4.9108 s] (CI 99.9%), Margin = 0.1318 s (2.76% of Mean)
Skewness = 0.96, Kurtosis = 3.23

// **************************
// Benchmark: PlaceholderBenchmarkRunner.PlaceholderMethod: Job-EWQPHF(Toolchain=Perf.ExternalProcessToolchain, LaunchCount=0, RunStrategy=Monitoring, TargetCount=25, WarmupCount=0) [Commit=HEAD]
// *** Generate ***
// Result = Success
// BinariesDirectoryPath =

// *** Build ***
Building commit: HEAD

commit bbb77e5 (HEAD -> symbolSearchO1, CyrusNajmabadi/symbolSearchO1)
Merge: b6d9b18 d4c6589
Author: Cyrus Najmabadi cyrus.najmabadi@gmail.com

Merge remote-tracking branch 'upstream/master' into symbolSearchO1

Repo Dir C:\GitHub\roslyn-internal\roslyn
Binaries Dir C:\GitHub\roslyn-internal\roslyn\Binaries
Running restore
Restore using dotnet at C:\GitHub\roslyn-internal\roslyn\Binaries\Tools\dotnet\dotnet.exe
Restoring Roslyn Toolset
Restoring Roslyn
Microsoft (R) Build Engine version 15.7.66.2115 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

Restoring packages for C:\GitHub\roslyn-internal\roslyn\src\Compilers\CSharp\Portable\CSharpCodeAnalysis.csproj...
Restoring packages for C:\GitHub\roslyn-internal\roslyn\src\Compilers\Core\Portable\CodeAnalysis.csproj...
Restoring packages for C:\GitHub\roslyn-internal\roslyn\src\Compilers\CSharp\csc\csc.csproj...
Restore completed in 243.88 ms for C:\GitHub\roslyn-internal\roslyn\src\Compilers\Core\Portable\CodeAnalysis.csproj.
Restore completed in 243.88 ms for C:\GitHub\roslyn-internal\roslyn\src\Compilers\CSharp\Portable\CSharpCodeAnalysis.csproj.
Restore completed in 551.91 ms for C:\GitHub\roslyn-internal\roslyn\src\Compilers\CSharp\csc\csc.csproj.
CodeAnalysis -> C:\GitHub\roslyn-internal\roslyn\Binaries\Release\Dlls\CodeAnalysis\Microsoft.CodeAnalysis.dll
CSharpCodeAnalysis -> C:\GitHub\roslyn-internal\roslyn\Binaries\Release\Dlls\CSharpCodeAnalysis\Microsoft.CodeAnalysis.CSharp.dll
csc -> C:\GitHub\roslyn-internal\roslyn\Binaries\Release\Exes\csc\netcoreapp2.0\csc.dll
csc -> C:\GitHub\roslyn-internal\roslyn\Binaries\Release\Exes\csc\net46\csc.exe

Build succeeded.
0 Warning(s)
0 Error(s)

Time Elapsed 00:00:24.08
// Result = Success

// *** Execute ***
// Launch: 1 / 1
// Execute: dotnet "C:\GitHub\roslyn-internal\roslyn\Binaries/Release/Exes/csc/netcoreapp2.0/csc.dll" -noconfig @repro.rsp
Result 0: 1 op, 4787332872.82 ns, 4.7873 s/op
Result 1: 1 op, 4720957326.66 ns, 4.7210 s/op
Result 2: 1 op, 4700068301.89 ns, 4.7001 s/op
Result 3: 1 op, 4756243699.18 ns, 4.7562 s/op
Result 4: 1 op, 4592740887.59 ns, 4.5927 s/op
Result 5: 1 op, 4748217080.83 ns, 4.7482 s/op
Result 6: 1 op, 5040503339.46 ns, 5.0405 s/op
Result 7: 1 op, 4936436220.95 ns, 4.9364 s/op
Result 8: 1 op, 5329153765.30 ns, 5.3292 s/op
Result 9: 1 op, 4726247990.52 ns, 4.7262 s/op
Result 10: 1 op, 4772723954.92 ns, 4.7727 s/op
Result 11: 1 op, 4795551314.75 ns, 4.7956 s/op
Result 12: 1 op, 4818697087.63 ns, 4.8187 s/op
Result 13: 1 op, 4689932329.29 ns, 4.6899 s/op
Result 14: 1 op, 4631686365.61 ns, 4.6317 s/op
Result 15: 1 op, 4637369139.46 ns, 4.6374 s/op
Result 16: 1 op, 4602611692.28 ns, 4.6026 s/op
Result 17: 1 op, 4678998737.28 ns, 4.6790 s/op
Result 18: 1 op, 4732467094.67 ns, 4.7325 s/op
Result 19: 1 op, 4975978679.37 ns, 4.9760 s/op
Result 20: 1 op, 4857831215.69 ns, 4.8578 s/op
Result 21: 1 op, 5011682197.68 ns, 5.0117 s/op
Result 22: 1 op, 4922174983.31 ns, 4.9222 s/op
Result 23: 1 op, 4706059615.53 ns, 4.7061 s/op
Result 24: 1 op, 4844305184.28 ns, 4.8443 s/op

Mean = 4.8006 s, StdErr = 0.0331 s (0.69%); N = 25, StdDev = 0.1654 s
Min = 4.5927 s, Q1 = 4.6950 s, Median = 4.7562 s, Q3 = 4.8900 s, Max = 5.3292 s
IQR = 0.1950 s, LowerFence = 4.4025 s, UpperFence = 5.1825 s
ConfidenceInterval = [4.6767 s; 4.9246 s] (CI 99.9%), Margin = 0.1239 s (2.58% of Mean)
Skewness = 1.31, Kurtosis = 4.83

// ***** BenchmarkRunner: Finish *****

// * Export *

// * Detailed results *
PlaceholderBenchmarkRunner.PlaceholderMethod: Job-EWQPHF(Toolchain=Perf.ExternalProcessToolchain, LaunchCount=0, RunStrategy=Monitoring, TargetCount=25, WarmupCount=0) [Commit=HEAD^]
Runtime = ; GC =
Mean = 4.7790 s, StdErr = 0.0352 s (0.74%); N = 25, StdDev = 0.1759 s
Min = 4.5250 s, Q1 = 4.6585 s, Median = 4.6994 s, Q3 = 4.9116 s, Max = 5.2697 s
IQR = 0.2531 s, LowerFence = 4.2788 s, UpperFence = 5.2913 s
ConfidenceInterval = [4.6472 s; 4.9108 s] (CI 99.9%), Margin = 0.1318 s (2.76% of Mean)
Skewness = 0.96, Kurtosis = 3.23

PlaceholderBenchmarkRunner.PlaceholderMethod: Job-EWQPHF(Toolchain=Perf.ExternalProcessToolchain, LaunchCount=0, RunStrategy=Monitoring, TargetCount=25, WarmupCount=0) [Commit=HEAD]
Runtime = ; GC =
Mean = 4.8006 s, StdErr = 0.0331 s (0.69%); N = 25, StdDev = 0.1654 s
Min = 4.5927 s, Q1 = 4.6950 s, Median = 4.7562 s, Q3 = 4.8900 s, Max = 5.3292 s
IQR = 0.1950 s, LowerFence = 4.4025 s, UpperFence = 5.1825 s
ConfidenceInterval = [4.6767 s; 4.9246 s] (CI 99.9%), Margin = 0.1239 s (2.58% of Mean)
Skewness = 1.31, Kurtosis = 4.83

Total time: 00:05:26 (326.04 sec)

// * Summary *

BenchmarkDotNet=v0.10.9, OS=Windows 10.0.16299
Processor=Intel Core i7-7600U CPU 2.80GHz (Kaby Lake), ProcessorCount=4
Frequency=2835939 Hz, Resolution=352.6169 ns, Timer=TSC
.NET Core SDK=2.1.105
[Host] : .NET Core 2.0.7 (Framework 4.6.26328.01), 64bit RyuJIT

Toolchain=Perf.ExternalProcessToolchain LaunchCount=0 RunStrategy=Monitoring
TargetCount=25 WarmupCount=0

        Method | Commit |    Mean |    Error |   StdDev | Rank |

------------------ |------- |--------:|---------:|---------:|-----:|
PlaceholderMethod | HEAD | 4.801 s | 0.1239 s | 0.1654 s | 1 |
PlaceholderMethod | HEAD^ | 4.779 s | 0.1318 s | 0.1759 s | 1 |

// * Legends *
Commit : Value of the 'Commit' parameter
Mean : Arithmetic mean of all measurements
Error : Half of 99.9% confidence interval
StdDev : Standard deviation of all measurements
Rank : Relative position of current benchmark mean among all benchmarks (Arabic style)
1 s : 1 Second (1 sec)

// ***** BenchmarkRunner: End *****
// * Artifacts cleanup *

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

@agocke can you help interpret this? It looks like the diffs are well within the margin of error. yes?

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

@gafter can you take a look? The dependent PR has gone in now.

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

@agocke Can you confirm my reading that this means there is no appreciable perf impact to this change? @gafter @jcouv could you take a look at this rather simple change. Note: actually testing this on Roslyn brought down the time to test lookup from over 7 seconds to an almost 0.2 seconds. That's a big win! :) Hash lookups much better than a linear scan of every top level symbol name in the entire solution

Copy link
Copy Markdown
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

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

LGTM
Thanks for the perf analysis!

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

Note: this search function is used both by add-using and fully-qualify (though only for the direct project you start in, and not for searching other projects in the solution), as well as the public SymbolFinder.FindDeclarationsAsync entrypoint. So improvements here will def have a benefit.

It is not currently used by FindRefs, or goto-impl/override. Though it's possible searches could be sped up by using these helpers before having to build/examine our own IDE indexes here. Though investigations would hav eto be done to know for sure.

@agocke
Copy link
Copy Markdown
Member

agocke commented May 1, 2018

@CyrusNajmabadi The "rank" part of the output is the most important here. That both are rank "1" indicates that there was no statistically significant difference in end-to-end performance of the compiler between the two commits.

@agocke
Copy link
Copy Markdown
Member

agocke commented May 1, 2018

If you have other perf measurements I think you should also post those benchmarks. Without some definite perf improvement in a specific scenario, I wouldn't take this change.

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

@agocke i mentioned them above.

Note: i was the person who added this API in the early days of Roslyn precisely for speeding up add-using and for other IDE search tasks. It looks like it was changed at one point to not be a set, without understanding that scenario, and also making it so we expose mutable data.

To me, it was a mistake to have made that change, and this is simply rectifying things (both fixing the exposing of mutable data, and improving perf). I'm not sure hte best way for us to prevent these sorts of regressions in the future. At one point there was a roslyn perf harness, but i'm not sure the current state of it.

@agocke
Copy link
Copy Markdown
Member

agocke commented May 1, 2018

My work is kind of the replacement for that, but it only measures end-to-end perf, which this change is too small to affect. Could you post detailed results for a benchmark of the API change, then? Means, standard deviations, maybe a t-test for significance?

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

Do you have a good way to collect that data? All i did was make a scenairo and run it several hundred times. the results were consistent every time i tried to do this.

@agocke
Copy link
Copy Markdown
Member

agocke commented May 1, 2018

https://github.com/dotnet/BenchmarkDotNet can give you that information. They have pretty good documentation for writing tests, as well.

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

CyrusNajmabadi commented May 1, 2018

Ok. I had some trouble using htat directly. But just doing the benchmarking manually was no problem. Here are the results.

Before my change:

Raw run times. Note, these are in milliseconds.

Details ``` 11380 5980 5843 6852 5913 5896 6235 5914 5995 5879 6038 5905 5873 5869 5918 5870 6023 5883 5900 6597 6063 5874 5925 5899 5879 ```

This gives the following values:

avg(ms) stdev(ms) error(ms)
6,216.12 1101.545328 220.3090656

After my change:

Details ``` 679 917 1070 835 981 729 402 403 400 386 392 390 408 398 394 389 391 402 397 380 409 377 420 452 492 ```
avg(ms) stdev(ms) error(ms)
515.72 214.8205685 42.96411371

This is roughly a 12x improvement.

computation of average, stddev and error was done with =average, =stdev and =stdev/sqrt(count)

Which is in line with how benchmark.net computes things.

Copy link
Copy Markdown
Member

@agocke agocke left a comment

Choose a reason for hiding this comment

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

LGMT

mergedRoot, Function(n) IdentifierComparison.Equals(n, name), filter, cancellationToken)
Return ContainsNameHelper(
mergedRoot,
Function(n) IdentifierComparison.Equals(n, name),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Consider passing through name so you don't allocate in these lambdas.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

it's just a single allocation, so it's not too bad :)

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

@agocke are you ok merging in?

@agocke agocke merged commit f04c128 into dotnet:master May 1, 2018
@CyrusNajmabadi CyrusNajmabadi deleted the symbolSearchO1 branch May 1, 2018 23:55
gafter pushed a commit that referenced this pull request May 31, 2018
…names searches. (#26331)

Followup to #26325 and #26330. This PR updates the IDE to forward certain helpers to these more efficient implementations.

This helps things out by more quickly being able to determine if a type even contains a member with name, and thus whether or not it should even be hydrated into a symbol and have its members created. Previous we would have to do a linear scan on all the members in a type to determine this. Now this data is in a set which can be queried much more efficiently.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-Compilers Community The pull request was submitted by a contributor who is not a Microsoft employee.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Symbol API exposes data that can be mutated by the caller

4 participants