1- using BenchmarkDotNet . Running ;
1+ using System . Diagnostics ;
2+ using System . Reflection ;
3+ using BenchmarkDotNet . Running ;
24using BenchmarkDotNet . Toolchains . InProcess . NoEmit ;
5+ using Autofac . Core ;
36
47namespace Autofac . BenchmarkProfiling ;
58
@@ -10,6 +13,11 @@ class Program
1013{
1114 static void Main ( string [ ] args )
1215 {
16+ if ( ! string . IsNullOrEmpty ( Environment . GetEnvironmentVariable ( "AUTOFAC_SCOPE_DIAGNOSTICS" ) ) )
17+ {
18+ AppContext . SetSwitch ( "Autofac.ScopeIsolatedDiagnostics" , true ) ;
19+ }
20+
1321 // Pick a benchmark.
1422 var availableBenchmarks = Benchmarks . BenchmarkSet . All ;
1523
@@ -98,6 +106,20 @@ void workloadAction(int repeat)
98106 // Warmup.
99107 workloadAction ( 100 ) ;
100108
109+ if ( int . TryParse ( Environment . GetEnvironmentVariable ( "AUTOFAC_MEASURE_ITERATIONS" ) , out var measurementIterations ) &&
110+ measurementIterations > 0 )
111+ {
112+ var sw = Stopwatch . StartNew ( ) ;
113+ workloadAction ( measurementIterations ) ;
114+ sw . Stop ( ) ;
115+ var perIteration = sw . Elapsed . TotalMilliseconds / measurementIterations ;
116+ Console . WriteLine (
117+ "[Profiling] Duration: {0} iterations took {1:F2} ms (avg {2:F4} ms)" ,
118+ measurementIterations ,
119+ sw . Elapsed . TotalMilliseconds ,
120+ perIteration ) ;
121+ }
122+
101123 // Now start a new thread.
102124 var runThread = new Thread ( new ThreadStart ( ( ) =>
103125 {
@@ -112,6 +134,8 @@ void workloadAction(int repeat)
112134 runThread . Join ( ) ;
113135
114136 cleanupAction . InvokeSingle ( ) ;
137+
138+ LogScopeDiagnosticsIfEnabled ( ) ;
115139 }
116140
117141 private static void PrintBenchmarks ( Type [ ] availableBenchmarks )
@@ -137,4 +161,36 @@ private static void PrintCases(BenchmarkRunInfo benchRunInfo)
137161 }
138162 }
139163 }
164+
165+ private static void LogScopeDiagnosticsIfEnabled ( )
166+ {
167+ if ( ! AppContext . TryGetSwitch ( "Autofac.ScopeIsolatedDiagnostics" , out var enabled ) || ! enabled )
168+ {
169+ return ;
170+ }
171+
172+ var diagnosticsType = typeof ( IComponentRegistry ) . Assembly . GetType ( "Autofac.Core.Registration.ScopeIsolatedServiceDiagnostics" ) ;
173+ var snapshotProperty = diagnosticsType ? . GetProperty (
174+ "Snapshot" ,
175+ BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . Static ) ;
176+
177+ if ( snapshotProperty ? . GetValue ( null ) is object snapshot )
178+ {
179+ var cacheHits = ( long ) ( snapshot . GetType ( ) . GetProperty ( "CacheHits" ) ? . GetValue ( snapshot ) ?? 0L ) ;
180+ var cacheMisses = ( long ) ( snapshot . GetType ( ) . GetProperty ( "CacheMisses" ) ? . GetValue ( snapshot ) ?? 0L ) ;
181+ var cacheAdds = ( long ) ( snapshot . GetType ( ) . GetProperty ( "CacheAdds" ) ? . GetValue ( snapshot ) ?? 0L ) ;
182+ var cacheRemovals = ( long ) ( snapshot . GetType ( ) . GetProperty ( "CacheRemovals" ) ? . GetValue ( snapshot ) ?? 0L ) ;
183+ var cachedInitializations = ( long ) ( snapshot . GetType ( ) . GetProperty ( "CachedInitializations" ) ? . GetValue ( snapshot ) ?? 0L ) ;
184+ var discardedInfos = ( long ) ( snapshot . GetType ( ) . GetProperty ( "ServiceInfoDiscarded" ) ? . GetValue ( snapshot ) ?? 0L ) ;
185+
186+ Console . WriteLine (
187+ "[Profiling] Scope cache stats -> Hits={0}, Misses={1}, Adds={2}, Removes={3}, CachedInit={4}, Discarded={5}" ,
188+ cacheHits ,
189+ cacheMisses ,
190+ cacheAdds ,
191+ cacheRemovals ,
192+ cachedInitializations ,
193+ discardedInfos ) ;
194+ }
195+ }
140196}
0 commit comments