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
+30-27Lines changed: 30 additions & 27 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -74,15 +74,17 @@ When I did the benchmarks for setting a value using reflection, I saw using an i
74
74
75
75
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
76
77
+
## Version 2: (Update on 16th March 2025)
78
+
Uses `ReadOnlySpan<char>` but same like V3.
77
79
78
-
## Version 2: (Update on 16th March 2025)
80
+
## Version 3: (Update on 22th March 2025)
79
81
80
82
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.
81
83
82
84
I renamed the interface like
83
85
84
86
```csharp
85
-
publicinterfaceINoReflection
87
+
publicinterfaceIObject
86
88
{
87
89
boolSetValue(stringpropertyName, objectvalue);
88
90
objectGetValue(stringpropertyName);
@@ -93,7 +95,7 @@ I renamed the interface like
93
95
Nothing changed in my interface. But the implementation changed a bit.
94
96
95
97
```csharp
96
-
[TypedAccessorAttribute]
98
+
[DynamicIObject]
97
99
publicpartialclassFoo
98
100
{
99
101
publicintInteger { get; set; } =int.MaxValue;
@@ -102,7 +104,7 @@ public partial class Foo
102
104
}
103
105
```
104
106
105
-
Notice the `TypedAccessorAttribute` on top of class. And yes this time I used Incremental Source Generators as they are stable.
107
+
Notice the `DynamicIObject` on top of class. And yes this time I used Incremental Source Generators as they are stable.
106
108
107
109
And my implementation is like
108
110
@@ -111,48 +113,49 @@ And my implementation is like
As I said, I took ChatGPT help, I am not 100% sure how `MethodImpl` helps. But this code brought down time taken to set a property from V1 to a min of 40% and max of 55%.
141
+
As I said, I took ChatGPT help, I am not 100% sure how `MethodImpl` helps.
142
+
143
+
### Here are the benchmarks
144
144
145
-
### Here are the V2 Benchmarks:
145
+
1. Reflection_Without_Cache
146
+
2. Reflection_With_Cache
147
+
3. V1 - use `nameof(Integer)` inside switch
148
+
4. V2 - use `case 8 when span.SequenceEqual("DateTime")` inside switch
149
+
5. V3 - use ` case 4 when string.CompareOrdinal(propertyName, "Guid") == 0` inside switch
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.
0 commit comments