Skip to content

Commit 0199641

Browse files
committed
Updates
1 parent 09d659c commit 0199641

File tree

5 files changed

+67
-80
lines changed

5 files changed

+67
-80
lines changed

Gemfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
source 'https://rubygems.org'
22

3-
gem "jekyll", "~> 4.3.3" # installed by `gem jekyll`
3+
gem "jekyll", "~> 4.4.1" # installed by `gem jekyll`
44
# gem "webrick" # required when using Ruby >= 3 and Jekyll <= 4.2.2
55

6-
gem "just-the-docs", "0.10.0" # pinned to the current release
6+
gem "just-the-docs", "0.10.1" # pinned to the current release
77
# gem "just-the-docs" # always download the latest release
88

99
gem "jekyll-last-modified-at", "~> 1.3"

Gemfile.lock

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,62 @@
11
GEM
22
remote: https://rubygems.org/
33
specs:
4-
addressable (2.8.6)
5-
public_suffix (>= 2.0.2, < 6.0)
4+
addressable (2.8.7)
5+
public_suffix (>= 2.0.2, < 7.0)
6+
base64 (0.2.0)
7+
bigdecimal (3.1.9)
68
colorator (1.1.0)
7-
concurrent-ruby (1.2.3)
9+
concurrent-ruby (1.3.5)
10+
csv (3.3.3)
811
em-websocket (0.5.3)
912
eventmachine (>= 0.12.9)
1013
http_parser.rb (~> 0)
1114
eventmachine (1.2.7)
12-
ffi (1.16.3)
13-
ffi (1.16.3-x64-mingw-ucrt)
15+
ffi (1.17.1-x64-mingw-ucrt)
1416
forwardable-extended (2.6.0)
15-
google-protobuf (4.26.1-x64-mingw-ucrt)
16-
rake (>= 13)
17-
google-protobuf (4.26.1-x86_64-linux)
17+
google-protobuf (4.30.1-x64-mingw-ucrt)
18+
bigdecimal
1819
rake (>= 13)
1920
http_parser.rb (0.8.0)
20-
i18n (1.14.4)
21+
i18n (1.14.7)
2122
concurrent-ruby (~> 1.0)
22-
jekyll (4.3.3)
23+
jekyll (4.4.1)
2324
addressable (~> 2.4)
25+
base64 (~> 0.2)
2426
colorator (~> 1.0)
27+
csv (~> 3.0)
2528
em-websocket (~> 0.5)
2629
i18n (~> 1.0)
2730
jekyll-sass-converter (>= 2.0, < 4.0)
2831
jekyll-watch (~> 2.0)
32+
json (~> 2.6)
2933
kramdown (~> 2.3, >= 2.3.1)
3034
kramdown-parser-gfm (~> 1.0)
3135
liquid (~> 4.0)
32-
mercenary (>= 0.3.6, < 0.5)
36+
mercenary (~> 0.3, >= 0.3.6)
3337
pathutil (~> 0.9)
3438
rouge (>= 3.0, < 5.0)
3539
safe_yaml (~> 1.0)
3640
terminal-table (>= 1.8, < 4.0)
3741
webrick (~> 1.7)
3842
jekyll-include-cache (0.2.1)
3943
jekyll (>= 3.7, < 5.0)
40-
jekyll-last-modified-at (1.3.0)
44+
jekyll-last-modified-at (1.3.2)
4145
jekyll (>= 3.7, < 5.0)
42-
posix-spawn (~> 0.3.9)
43-
jekyll-sass-converter (3.0.0)
44-
sass-embedded (~> 1.54)
46+
jekyll-sass-converter (3.1.0)
47+
sass-embedded (~> 1.75)
4548
jekyll-seo-tag (2.8.0)
4649
jekyll (>= 3.8, < 5.0)
4750
jekyll-watch (2.2.1)
4851
listen (~> 3.0)
49-
just-the-docs (0.10.0)
52+
json (2.10.2)
53+
just-the-docs (0.10.1)
5054
jekyll (>= 3.8.5)
5155
jekyll-include-cache
5256
jekyll-seo-tag (>= 2.0)
5357
rake (>= 12.3.1)
54-
kramdown (2.4.0)
55-
rexml
58+
kramdown (2.5.1)
59+
rexml (>= 3.3.9)
5660
kramdown-parser-gfm (1.1.0)
5761
kramdown (~> 2.0)
5862
liquid (4.0.4)
@@ -62,32 +66,28 @@ GEM
6266
mercenary (0.4.0)
6367
pathutil (0.16.2)
6468
forwardable-extended (~> 2.6)
65-
posix-spawn (0.3.15)
66-
public_suffix (5.0.5)
69+
public_suffix (6.0.1)
6770
rake (13.2.1)
6871
rb-fsevent (0.11.2)
69-
rb-inotify (0.10.1)
72+
rb-inotify (0.11.1)
7073
ffi (~> 1.0)
71-
rexml (3.2.6)
72-
rouge (4.2.1)
74+
rexml (3.4.1)
75+
rouge (4.5.1)
7376
safe_yaml (1.0.5)
74-
sass-embedded (1.75.0-x64-mingw-ucrt)
75-
google-protobuf (>= 3.25, < 5.0)
76-
sass-embedded (1.75.0-x86_64-linux-gnu)
77-
google-protobuf (>= 3.25, < 5.0)
77+
sass-embedded (1.86.0-x64-mingw-ucrt)
78+
google-protobuf (~> 4.30)
7879
terminal-table (3.0.2)
7980
unicode-display_width (>= 1.1.1, < 3)
80-
unicode-display_width (2.5.0)
81-
webrick (1.8.1)
81+
unicode-display_width (2.6.0)
82+
webrick (1.9.1)
8283

8384
PLATFORMS
8485
x64-mingw-ucrt
85-
x86_64-linux
8686

8787
DEPENDENCIES
88-
jekyll (~> 4.3.3)
88+
jekyll (~> 4.4.1)
8989
jekyll-last-modified-at (~> 1.3)
90-
just-the-docs (= 0.10.0)
90+
just-the-docs (= 0.10.1)
9191

9292
BUNDLED WITH
93-
2.5.6
93+
2.6.6

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,7 @@ Notes(For all)
1515
Use github actions for deploying the site.
1616

1717
Notes(For my self)
18-
`git push -u --force origin main`
18+
`git push -u --force origin main`
19+
20+
21+
--Update the gems and lock file - `bundle update --bundler`

docs/Posts/c# cost of reflection.md

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,6 @@ public class FooV1 : IObject
6767

6868
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%.
6969

70-
### Here are the V1 Benchmarks:
71-
{% include_relative reflection-benchmarks-v1-net8.md %}
72-
[V1 Source Code](https://github.com/sj-net/DotNet.Benchmarks/tree/main/Dotnet.Benchmarks)
73-
74-
7570
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.
7671

7772
## Version 2: (Update on  16th March 2025)
@@ -81,31 +76,17 @@ Uses `ReadOnlySpan<char>` but same like V3.
8176

8277
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.
8378

84-
I renamed the interface like
85-
86-
```csharp
87-
public interface IObject
88-
{
89-
bool SetValue(string propertyName, object value);
90-
object GetValue(string propertyName);
91-
T GetValue<T>(string propertyName); // I skipped the implementation of this in this post. Please find that in source code.
92-
}
93-
```
94-
9579
Nothing changed in my interface. But the implementation changed a bit.
9680

9781
```csharp
98-
[DynamicIObject]
99-
public partial class Foo
82+
public class Foo : IObject
10083
{
10184
public int Integer { get; set; } = int.MaxValue;
10285
public string String { get; set; } = "some random string";
10386

10487
}
10588
```
10689

107-
Notice the `DynamicIObject` on top of class. And yes this time I used Incremental Source Generators as they are stable.
108-
10990
And my implementation is like
11091

11192
```csharp
@@ -140,7 +121,9 @@ public object GetValue(string propertyName)
140121

141122
As I said, I took ChatGPT help, I am not 100% sure how `MethodImpl` helps.
142123

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)))
144127

145128
1. Reflection_Without_Cache
146129
2. Reflection_With_Cache
@@ -153,11 +136,12 @@ For some scenarios, V1 and V2 are better than V3. But ultimately V1, V2, V3 are
153136

154137
.NET 8 only.
155138
{% include_relative reflection-benchmarks-v1-v2-v3-net8.md %}
156-
[Source Code](https://github.com/DotNetExtended/Default/tree/main/src/DotNetExtended.NoReflection)
157-
[Benchmarks Source Code](https://github.com/DotNetExtended/Default/tree/main/src/DotNetExtended.NoReflection.Tests)
158-
[Source Generator](https://github.com/DotNetExtended/Default/tree/main/src/DotNetExtended.NoReflection.SourceGenerators)
139+
- [Source Code](https://github.com/DotNetExtended/Default/tree/main/src/DotNetExtended.NoReflection)
140+
- [Benchmarks Source Code](https://github.com/DotNetExtended/Default/tree/main/src/DotNetExtended.NoReflection.Tests)
141+
- [Source Generator](https://github.com/DotNetExtended/Default/tree/main/src/DotNetExtended.NoReflection.SourceGenerators)
159142

160143

161144
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.
162145

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.

docs/dotnet/source_generator.md

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,27 @@ grand_parent: My Docs
66
published: true
77
---
88

9-
### Source Generators in .Net Standard 2.0
9+
## Source Generators in .Net Standard 2.0
1010

11-
#### How to write one ?
11+
### How to write one ?
1212

13-
1. Create a blank solution
14-
2. Create a class libary in .Net Standard 2.0. Ex: `PrivateFieldGenerator.csproj`
15-
3. Update the `csproj` file with below things.
16-
4.
17-
```xml
13+
- Create a blank solution
14+
- Create a class libary in .Net Standard 2.0. Ex: `PrivateFieldGenerator.csproj`
15+
- Update the `csproj` file with below things.
16+
17+
```xml
1818
<LangVersion>latest</LangVersion>
1919
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
2020
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
2121
<IsRoslynComponent>true</IsRoslynComponent>
2222
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
2323
```
2424

25-
5. Install `Microsoft.CodeAnalysis.CSharp` & `Microsoft.CodeAnalysis.Analyzers`
26-
6. Add a class file and name is `PrivateFieldIncrementalGenerator`. We will be using the `IIncrementalGenerator`
27-
7. Decorate the class with the `[GeneratorAttribute]`
28-
8. Implement the class like below
29-
9.
25+
- Install `Microsoft.CodeAnalysis.CSharp` & `Microsoft.CodeAnalysis.Analyzers`
26+
- Add a class file and name is `PrivateFieldIncrementalGenerator`. We will be using the `IIncrementalGenerator`
27+
- Decorate the class with the `[GeneratorAttribute]`
28+
- Implement the class like below
29+
3030
```c#
3131
public class PrivateFieldGenerator : IIncrementalGenerator
3232
{
@@ -145,9 +145,9 @@ public class PrivateFieldGenerator : IIncrementalGenerator
145145
}
146146
}
147147
```
148-
9. Done you are ready with your generator.
148+
- Done you are ready with your generator.
149149

150-
#### How to use this generator in your real project.
150+
### How to use this generator in your real project.
151151

152152
1. In this case, I am taking a class library to create a nuget but you can shoose a API or MVC or a WPF project too.
153153
2. What ever project you choose add below line to that `csproj` where you want this generator to work.
@@ -159,18 +159,18 @@ public class PrivateFieldGenerator : IIncrementalGenerator
159159
```
160160

161161

162-
#### How to Debug ?
162+
### How to Debug ?
163163

164164
I learnt from [here](https://github.com/JoanComasFdz/dotnet-how-to-debug-source-generator-vs2022)
165165

166166
1. Go to your source generator project and create a Properties Folder and then `launchSettings.json` with the below contents.
167167
```json
168168
{
169169
"profiles": {
170-
"Name of your generator": {
171-
"commandName": "DebugRoslynComponent",
172-
"targetProject": "path to .csproj file"
173-
}
170+
"Name of your generator": {
171+
"commandName": "DebugRoslynComponent",
172+
"targetProject": "path to .csproj file"
173+
}
174174
}
175175
}
176176
```

0 commit comments

Comments
 (0)