You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/Posts/c# cost of reflection.md
+9-25Lines changed: 9 additions & 25 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -67,11 +67,6 @@ public class FooV1 : IObject
67
67
68
68
When I did the benchmarks for setting a value using reflection, I saw using an interface brought down the time taken to set a property to a min of 70% and max of 91%.
As this worked out very well, and I had too many model's so I built our own source generator using a console app as I was using .NET6 where the source generators are still experimental. And this whole implementation brought down our app launch time from 60+ seconds to less than 20 seconds. Btw, the properties inside the Model used to change very rarely. So when they did, we used to run the generator again and copy the files. And we ensure these generated files should never be changed manually and named them something like Foo.g.cs which helps me review the PR's easily from the team. And ofcourse, I wrote an API to return the properties and their metadata in the way that I need so that my generator can generate the classes for me.
76
71
77
72
## Version 2: (Update on 16th March 2025)
@@ -81,31 +76,17 @@ Uses `ReadOnlySpan<char>` but same like V3.
81
76
82
77
I read in multiple blogs that .NET invested a lot in performance improvement using ReadOnlySpan over the years. I was wondering if we can still make this better. So I tried again with ChatGPT help. Now compared to V1, V2 had at least 40% improvement over V1.
83
78
84
-
I renamed the interface like
85
-
86
-
```csharp
87
-
publicinterfaceIObject
88
-
{
89
-
boolSetValue(stringpropertyName, objectvalue);
90
-
objectGetValue(stringpropertyName);
91
-
TGetValue<T>(stringpropertyName); // I skipped the implementation of this in this post. Please find that in source code.
92
-
}
93
-
```
94
-
95
79
Nothing changed in my interface. But the implementation changed a bit.
96
80
97
81
```csharp
98
-
[DynamicIObject]
99
-
publicpartialclassFoo
82
+
publicclassFoo : IObject
100
83
{
101
84
publicintInteger { get; set; } =int.MaxValue;
102
85
publicstringString { get; set; } ="some random string";
103
86
104
87
}
105
88
```
106
89
107
-
Notice the `DynamicIObject` on top of class. And yes this time I used Incremental Source Generators as they are stable.
108
-
109
90
And my implementation is like
110
91
111
92
```csharp
@@ -140,7 +121,9 @@ public object GetValue(string propertyName)
140
121
141
122
As I said, I took ChatGPT help, I am not 100% sure how `MethodImpl` helps.
142
123
143
-
### Here are the benchmarks
124
+
Major benefits I saw are switch case speed was improved by 20% at least when I was checking the lenhth of the property name first.
125
+
126
+
### Here are the benchmarks ([Source Models]([here](https://github.com/DotNetExtended/Default/blob/main/src/DotNetExtended.NoReflection.Tests/ReflectionBenchmarkModels.cs)))
144
127
145
128
1. Reflection_Without_Cache
146
129
2. Reflection_With_Cache
@@ -153,11 +136,12 @@ For some scenarios, V1 and V2 are better than V3. But ultimately V1, V2, V3 are
This is one of my best performance improvements I have ever done. This might not be significant in many places but for situations like mine, this saves a lot of time during run time.
162
145
163
-
All different variations used for benchmarks are [here](https://github.com/DotNetExtended/Default/blob/main/src/DotNetExtended.NoReflection.Tests/ReflectionBenchmarkModels.cs)
146
+
147
+
Note: I tried to use this logic in `System.Text.Json` but couldn't beat it though it was using reflection. It was highly optimized and I gave up.
0 commit comments