1+ using System . Collections . Concurrent ;
2+ using System . Globalization ;
3+ using System . Net ;
4+ using System . Reflection ;
5+ using BenchmarkDotNet . Attributes ;
6+
7+ namespace ManagedCode . Communication . Benchmark ;
8+
9+ [ MemoryDiagnoser ]
10+ [ SimpleJob ( warmupCount : 3 , iterationCount : 10 ) ]
11+ public class ResultCreationBenchmark
12+ {
13+ private static readonly Exception TestException = new InvalidOperationException ( "Benchmark test" ) ;
14+ private static readonly Type ResultIntType = typeof ( Result < int > ) ;
15+ private static readonly ConcurrentDictionary < Type , MethodInfo > MethodCache = new ( ) ;
16+ private readonly Exception _exception = TestException ;
17+ private readonly object [ ] _exceptionArray = new object [ 1 ] ;
18+
19+ private MethodInfo _cachedMethod = null ! ;
20+
21+ [ GlobalSetup ]
22+ public void Setup ( )
23+ {
24+ _cachedMethod = ResultIntType . GetMethod ( nameof ( Result . Fail ) , [ typeof ( Exception ) , typeof ( HttpStatusCode ) ] ) ! ;
25+ MethodCache [ ResultIntType ] = _cachedMethod ;
26+ _exceptionArray [ 0 ] = TestException ;
27+ }
28+
29+ [ Benchmark ( Baseline = true ) ]
30+ public Result < int > DirectCall ( )
31+ {
32+ return Result < int > . Fail ( TestException ) ;
33+ }
34+
35+ [ Benchmark ]
36+ public object Reflection_FindMethodEveryTime ( )
37+ {
38+ var method = ResultIntType . GetMethod ( nameof ( Result . Fail ) , [ typeof ( Exception ) , typeof ( HttpStatusCode ) ] ) ;
39+ return method ! . Invoke ( null , [ TestException , HttpStatusCode . InternalServerError ] ) ! ;
40+ }
41+
42+ [ Benchmark ]
43+ public object Reflection_CachedMethod ( )
44+ {
45+ return _cachedMethod . Invoke ( null , [ TestException , HttpStatusCode . InternalServerError ] ) ! ;
46+ }
47+
48+ [ Benchmark ]
49+ public object Reflection_CachedMethod_ReuseArray ( )
50+ {
51+ // Can't reuse array because we need 2 parameters
52+ return _cachedMethod . Invoke ( null , [ TestException , HttpStatusCode . InternalServerError ] ) ! ;
53+ }
54+
55+ [ Benchmark ]
56+ public object Reflection_ConcurrentDictionary ( )
57+ {
58+ var method = MethodCache . GetOrAdd ( ResultIntType , type => type . GetMethod ( nameof ( Result . Fail ) , [ typeof ( Exception ) , typeof ( HttpStatusCode ) ] ) ! ) ;
59+ return method . Invoke ( null , [ TestException , HttpStatusCode . InternalServerError ] ) ! ;
60+ }
61+
62+ [ Benchmark ]
63+ public object Activator_TryCreateInstance ( )
64+ {
65+ var result = Activator . CreateInstance ( ResultIntType ) ;
66+ return result ! ;
67+ }
68+
69+ [ Benchmark ]
70+ public object Activator_WithPropertySet ( )
71+ {
72+ var resultType = Activator . CreateInstance ( ResultIntType , BindingFlags . NonPublic | BindingFlags . Instance , null , [ TestException ] ,
73+ CultureInfo . CurrentCulture ) ;
74+
75+ return resultType ! ;
76+ }
77+ }
0 commit comments