├── .dockerignore ├── .github ├── dependabot.yml └── workflows │ ├── dependabotautomerge.yml │ └── dotnet-ci.yml ├── .gitignore ├── Benchmarks.sln ├── Benchmarks.sln.DotSettings ├── LICENSE ├── README.md ├── assets ├── benchmark.enum │ ├── enum-name.png │ └── enum-value.png ├── benchmarks.collectionsize │ ├── any-10k-elements.png │ ├── any-empty.png │ ├── count-10k-elements.png │ └── count-empty.png ├── benchmarks.groupbyvsdistinct │ ├── group-10.png │ └── group-10k.png ├── benchmarks.serializers.binary │ ├── deserialization-1.png │ ├── deserialization-1k.png │ ├── serialization-1.png │ └── serialization-1k.png ├── benchmarks.serializers.json │ ├── deserialization-byte-1.png │ ├── deserialization-byte-1k.png │ ├── deserialization-string-1.png │ ├── deserialization-string-1k.png │ ├── serialization-byte-1.png │ ├── serialization-byte-1k.png │ ├── serialization-string-1.png │ └── serialization-string-1k.png └── icon.png ├── coverlet.runsettings ├── docfx.json ├── docs ├── getting-started.md ├── introduction.md └── toc.yml ├── global.json ├── index.md ├── src ├── main │ ├── Benchmarks.CollectionSize │ │ ├── Benchmarks.CollectionSize.csproj │ │ ├── Benchmarks │ │ │ └── AnyLengthBenchmarks.cs │ │ ├── Dockerfile │ │ ├── Group.cs │ │ ├── Models │ │ │ └── TestCollections.cs │ │ ├── Program.cs │ │ ├── Readme.md │ │ └── Services │ │ │ ├── AnyLengthService.Any.cs │ │ │ ├── AnyLengthService.Count.cs │ │ │ ├── AnyLengthService.CountPattern.cs │ │ │ └── AnyLengthService.cs │ ├── Benchmarks.Common │ │ ├── Benchmarks.Common.csproj │ │ └── FakerExtensions.cs │ ├── Benchmarks.DynamicPredicateParser │ │ ├── Benchmarks.DynamicPredicateParser.csproj │ │ ├── Dockerfile │ │ ├── ParserBenchmarks.cs │ │ ├── Program.cs │ │ ├── TestModel.cs │ │ └── readme.md │ ├── Benchmarks.Enum │ │ ├── Benchmarks.Enum.csproj │ │ ├── Benchmarks │ │ │ ├── EnumBenchmarksBase.cs │ │ │ ├── EnumNameBenchmarks.cs │ │ │ └── EnumValueBenchmarks.cs │ │ ├── Dockerfile │ │ ├── Extensions │ │ │ └── EnumExtensions.cs │ │ ├── Group.cs │ │ ├── Program.cs │ │ ├── Readme.md │ │ ├── Services │ │ │ ├── EnumNameService.cs │ │ │ └── EnumValueService.cs │ │ └── TestEnum.cs │ ├── Benchmarks.Flattening │ │ ├── Benchmarks.Flattening.csproj │ │ ├── FlatBenchmarks.cs │ │ ├── InternalModel.cs │ │ ├── Program.cs │ │ ├── README.MD │ │ └── UnflatModel.cs │ ├── Benchmarks.GroupByVsDistinct │ │ ├── Benchmarks.GroupByVsDistinct.csproj │ │ ├── DistinctGroupByBenchmarks.cs │ │ ├── Dockerfile │ │ ├── Models │ │ │ ├── InnerModel.cs │ │ │ └── SimpleModel.cs │ │ ├── Program.cs │ │ ├── Readme.md │ │ └── Services │ │ │ └── LinqService.cs │ ├── Benchmarks.Iterators │ │ ├── Benchmarks.Iterators.csproj │ │ ├── Benchmarks │ │ │ ├── BenchmarksBase.cs │ │ │ ├── IteratorBenchmarks.Array.cs │ │ │ ├── IteratorBenchmarks.ICollection.cs │ │ │ ├── IteratorBenchmarks.List.cs │ │ │ ├── IteratorBenchmarks.Serializing.cs │ │ │ └── IteratorBenchmarks.cs │ │ ├── Dockerfile │ │ ├── Group.cs │ │ ├── Models │ │ │ └── SimpleModel.cs │ │ ├── Program.cs │ │ ├── Readme.md │ │ └── Services │ │ │ ├── IterationService.Array.cs │ │ │ ├── IterationService.Collection.cs │ │ │ ├── IterationService.List.cs │ │ │ └── IterationService.cs │ ├── Benchmarks.QueryBuilder │ │ ├── Benchmarks.QueryBuilder.csproj │ │ ├── Benchmarks │ │ │ ├── QueryBuilderBenchmarks.cs │ │ │ └── UriCombineBenchmarks.cs │ │ ├── Dockerfile │ │ ├── Group.cs │ │ ├── Program.cs │ │ ├── Services │ │ │ ├── Query │ │ │ │ ├── QueryClass.cs │ │ │ │ ├── QueryCustomBuilder.cs │ │ │ │ ├── QueryService.cs │ │ │ │ ├── QueryValueStringBuilder.cs │ │ │ │ └── ValueStringBuilder.cs │ │ │ └── Uri │ │ │ │ ├── StringUriCombineService.cs │ │ │ │ └── UriCombineService.cs │ │ └── readme.md │ ├── Benchmarks.Serializers.Binary │ │ ├── Benchmarks.Serializers.Binary.csproj │ │ ├── Benchmarks │ │ │ ├── DeserializationBenchmark.cs │ │ │ └── SerializationBenchmark.cs │ │ ├── Dockerfile │ │ ├── MsgPackLightConverters │ │ │ ├── SimpleModelConverter.cs │ │ │ └── SimpleModelsConverter.cs │ │ ├── Program.cs │ │ ├── Readme.md │ │ ├── SerializationBenchmark.FlatBuffer.cs │ │ ├── SerializationBenchmark.MemoryPack.cs │ │ ├── SerializationBenchmark.MessagePack.cs │ │ ├── SerializationBenchmark.Protobuf.cs │ │ ├── SerializationBenchmark.ZeroFormatter.cs │ │ ├── Serializers.MsgPackLight.cs │ │ └── Serializers.cs │ ├── Benchmarks.Serializers.Json │ │ ├── Benchmarks.Serializers.Json.csproj │ │ ├── Benchmarks │ │ │ ├── Deserialization │ │ │ │ └── Simple │ │ │ │ │ ├── AsyncStreamDeserializationSimpleBenchmarks.cs │ │ │ │ │ ├── ByteDeserializationSimpleBenchmarks.cs │ │ │ │ │ ├── StreamDeserializationSimpleBenchmarks.cs │ │ │ │ │ └── StringDeserializationSimpleBenchmarks.cs │ │ │ ├── DeserializationBenchmark.Jil.cs │ │ │ ├── DeserializationBenchmark.JsonSrcGen.cs │ │ │ ├── DeserializationBenchmark.NetJson.cs │ │ │ ├── DeserializationBenchmark.Newtonsoft.cs │ │ │ ├── DeserializationBenchmark.ServiceStack.cs │ │ │ ├── DeserializationBenchmark.SpanJson.cs │ │ │ ├── DeserializationBenchmark.SystemTextJson.cs │ │ │ ├── DeserializationBenchmark.SystemTextJsonSrcGen.cs │ │ │ ├── DeserializationBenchmark.Utf8Json.cs │ │ │ ├── DeserializationBenchmark.cs │ │ │ ├── JsonComplexBenchmark.cs │ │ │ ├── SerializationBenchmark.Jil.cs │ │ │ ├── SerializationBenchmark.JsonSrcGen.cs │ │ │ ├── SerializationBenchmark.NetJson.cs │ │ │ ├── SerializationBenchmark.Newtonsoft.cs │ │ │ ├── SerializationBenchmark.ServiceStack.cs │ │ │ ├── SerializationBenchmark.SpanJson.cs │ │ │ ├── SerializationBenchmark.SystemTextJson.cs │ │ │ ├── SerializationBenchmark.SystemTextJsonSrcGen.cs │ │ │ ├── SerializationBenchmark.Utf8Json.cs │ │ │ └── SerializationBenchmark.cs │ │ ├── Dockerfile │ │ ├── Extensions │ │ │ └── JsonServiceExtensions.cs │ │ ├── Models │ │ │ ├── ComplexSrcGenModel.cs │ │ │ └── SimpleSrcGenModel.cs │ │ ├── Program.cs │ │ ├── Readme.md │ │ ├── Serializers.Jil.cs │ │ ├── Serializers.JsonSrcGen.cs │ │ ├── Serializers.NetJson.cs │ │ ├── Serializers.Newtonsoft.cs │ │ ├── Serializers.ServiceStack.cs │ │ ├── Serializers.SpanJson.cs │ │ ├── Serializers.SystemTextJson.cs │ │ ├── Serializers.SystemTextJsonSrcGen.cs │ │ ├── Serializers.Utf8Json.cs │ │ └── Serializers.cs │ ├── Benchmarks.Serializers.OutputFormatters │ │ ├── Benchmarks.Serializers.OutputFormatters.csproj │ │ ├── Benchmarks.Serializers.OutputFormatters.http │ │ ├── Controllers │ │ │ └── JsonController.cs │ │ ├── Dockerfile │ │ ├── Extensions │ │ │ └── SimpleModelGenerator.cs │ │ ├── Formatters │ │ │ ├── Jil │ │ │ │ ├── JilInputFormatter.cs │ │ │ │ ├── JilOutputFormatter.cs │ │ │ │ └── MvcOptionsExtensions.cs │ │ │ ├── MemoryPack │ │ │ │ └── MvcOptionsExtensions.cs │ │ │ ├── MessagePack │ │ │ │ └── MvcOptionsExtensions.cs │ │ │ ├── Newtonsoft │ │ │ │ └── MvcOptionsExtensions.cs │ │ │ ├── Protobuf │ │ │ │ └── MvcOptionsExtensions.cs │ │ │ ├── SpanJson │ │ │ │ ├── MvcOptionsExtensions.cs │ │ │ │ ├── SpanJsonFormatter.cs │ │ │ │ ├── SpanJsonInputFormatter.cs │ │ │ │ └── SpanJsonOutputFormatter.cs │ │ │ ├── SystemTextJson │ │ │ │ └── MvcOptionsExtensions.cs │ │ │ └── Utf8Json │ │ │ │ └── MvcOptionsExtensions.cs │ │ ├── Program.cs │ │ ├── appsettings.json │ │ └── locustfile.py │ ├── Benchmarks.Serializers │ │ ├── Benchmark │ │ │ └── Serializers │ │ │ │ └── Models │ │ │ │ ├── SimpleFlatBufferModel.cs │ │ │ │ └── SimpleFlatBufferModels.cs │ │ ├── Benchmarks.Serializers.csproj │ │ ├── Fields.cs │ │ ├── Group.cs │ │ ├── Models │ │ │ ├── ComplexModel.cs │ │ │ └── SimpleModel.cs │ │ ├── ModelsJsonContext.cs │ │ └── SimpleFlatBufferModel.fbs │ ├── Benchmarks.SortArrayByArray │ │ ├── Benchmarks.SortArrayByArray.csproj │ │ ├── Extensions │ │ │ ├── EnumerableExtensions.cs │ │ │ └── SortExtensions.cs │ │ ├── Program.cs │ │ ├── SortBenchmarks.cs │ │ ├── TestModel.cs │ │ └── readme.md │ ├── Benchmarks.Stopwatch │ │ ├── Benchmarks.Stopwatch.csproj │ │ ├── Program.cs │ │ ├── README.MD │ │ └── TimeBenchmarks.cs │ └── Benchmarks.String │ │ ├── Benchmarks.String.csproj │ │ ├── Benchmarks │ │ ├── Abstractions │ │ │ ├── BenchmarkBase.cs │ │ │ └── BenchmarkCollectionBase.cs │ │ ├── ContainsCharBenchmarks.cs │ │ ├── DashStringBenchmarks.cs │ │ ├── GenerationBenchmarks.cs │ │ ├── InterpolationBenchmarks.cs │ │ ├── LinkStringBenchmarks.cs │ │ ├── SingleDashStringBenchmarks.cs │ │ └── SingleLinkStringBenchmarks.cs │ │ ├── Constants.cs │ │ ├── Dockerfile │ │ ├── Group.cs │ │ ├── Models │ │ ├── InterpolationModel.cs │ │ └── StringsTestModel.cs │ │ ├── Program.cs │ │ ├── Readme.md │ │ └── Services │ │ ├── ArrayPoolStringService.cs │ │ ├── GenerationService.cs │ │ ├── InterpolationService.cs │ │ ├── RegexStringService.cs │ │ └── SpanOwnerStringService.cs └── test │ └── Benchmarks.Tests.Unit │ ├── Benchmark.Enum │ ├── EnumNameTests.cs │ └── EnumValueTests.cs │ ├── Benchmark.GroupByVsDistinct │ └── LinqTests.cs │ ├── Benchmark.Iterators │ ├── IteratorTests.cs │ └── TestModel.cs │ ├── Benchmark.QueryBuilder │ ├── QueryTests.cs │ ├── StringUriTests.cs │ └── UriUrlTests.cs │ ├── Benchmark.Serializers │ ├── Json │ │ ├── JilTests.cs │ │ ├── NetJsonTests.cs │ │ ├── NewtonsoftJsonTests.cs │ │ ├── ServiceStackTests.cs │ │ ├── SpanJsonTests.cs │ │ ├── SystemTextJsonTests.cs │ │ ├── TestsBase.cs │ │ └── Utf8JsonTests.cs │ └── Models │ │ └── TestModel.cs │ ├── Benchmark.String │ ├── ArrayPoolStringTests.cs │ ├── GenerationTests.cs │ ├── InterpolationTests.cs │ ├── RegexStringTests.cs │ └── SpanOwnerStringTests.cs │ ├── Benchmarks.Tests.Unit.csproj │ └── GlobalUsings.cs └── toc.yml /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.dockerignore 2 | **/.env 3 | **/.git 4 | **/.gitignore 5 | **/.project 6 | **/.settings 7 | **/.toolstarget 8 | **/.vs 9 | **/.vscode 10 | **/.idea 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | LICENSE 25 | README.md -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Please see the documentation for all configuration options: 2 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 3 | 4 | version: 2 5 | updates: 6 | # NuGet (/*.csproj) 7 | - package-ecosystem: nuget 8 | directory: '/' 9 | schedule: 10 | interval: weekly 11 | time: '08:00' 12 | timezone: Europe/Kyiv 13 | labels: 14 | - 'dependabot:robot:' 15 | commit-message: 16 | prefix: fix 17 | prefix-development: chore 18 | include: scope 19 | 20 | # GitHub Actions (/.github/workflows/*.yml) 21 | - package-ecosystem: github-actions 22 | directory: '/' 23 | schedule: 24 | interval: weekly 25 | time: '08:00' 26 | timezone: Europe/Kyiv 27 | labels: 28 | - 'dependabot:robot:' 29 | commit-message: 30 | prefix: fix 31 | prefix-development: chore 32 | include: scope 33 | -------------------------------------------------------------------------------- /.github/workflows/dependabotautomerge.yml: -------------------------------------------------------------------------------- 1 | name: "Dependabot Automerge - Action" 2 | 3 | on: 4 | pull_request: 5 | 6 | permissions: 7 | contents: write 8 | pull-requests: write 9 | 10 | jobs: 11 | worker: 12 | runs-on: ubuntu-latest 13 | 14 | if: github.actor == 'dependabot[bot]' 15 | steps: 16 | - name: automerge 17 | uses: actions/github-script@0.2.0 18 | with: 19 | script: | 20 | github.pullRequests.createReview({ 21 | owner: context.payload.repository.owner.login, 22 | repo: context.payload.repository.name, 23 | pull_number: context.payload.pull_request.number, 24 | event: 'APPROVE' 25 | }) 26 | github.pullRequests.merge({ 27 | owner: context.payload.repository.owner.login, 28 | repo: context.payload.repository.name, 29 | pull_number: context.payload.pull_request.number 30 | }) 31 | github-token: ${{secrets.GITHUB_TOKEN}} -------------------------------------------------------------------------------- /.github/workflows/dotnet-ci.yml: -------------------------------------------------------------------------------- 1 | name: .NET 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - name: Setup .NET 15 | uses: actions/setup-dotnet@v4 16 | with: 17 | dotnet-version: '9.x.x' 18 | - name: Restore dependencies 19 | run: dotnet restore 20 | - name: Build 21 | run: dotnet build --no-restore 22 | - name: Test 23 | run: dotnet test --no-build --verbosity normal /p:CollectCoverage=true /p:CoverletOutput=TestResults/ /p:CoverletOutputFormat=opencover 24 | - name: Publish coverage report 25 | uses: codecov/codecov-action@v4 26 | with: 27 | token: ${{ secrets.CODECOV_TOKEN }} 28 | -------------------------------------------------------------------------------- /Benchmarks.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2024 Ihor Volokhovych 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /assets/benchmark.enum/enum-name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmark.enum/enum-name.png -------------------------------------------------------------------------------- /assets/benchmark.enum/enum-value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmark.enum/enum-value.png -------------------------------------------------------------------------------- /assets/benchmarks.collectionsize/any-10k-elements.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.collectionsize/any-10k-elements.png -------------------------------------------------------------------------------- /assets/benchmarks.collectionsize/any-empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.collectionsize/any-empty.png -------------------------------------------------------------------------------- /assets/benchmarks.collectionsize/count-10k-elements.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.collectionsize/count-10k-elements.png -------------------------------------------------------------------------------- /assets/benchmarks.collectionsize/count-empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.collectionsize/count-empty.png -------------------------------------------------------------------------------- /assets/benchmarks.groupbyvsdistinct/group-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.groupbyvsdistinct/group-10.png -------------------------------------------------------------------------------- /assets/benchmarks.groupbyvsdistinct/group-10k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.groupbyvsdistinct/group-10k.png -------------------------------------------------------------------------------- /assets/benchmarks.serializers.binary/deserialization-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.serializers.binary/deserialization-1.png -------------------------------------------------------------------------------- /assets/benchmarks.serializers.binary/deserialization-1k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.serializers.binary/deserialization-1k.png -------------------------------------------------------------------------------- /assets/benchmarks.serializers.binary/serialization-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.serializers.binary/serialization-1.png -------------------------------------------------------------------------------- /assets/benchmarks.serializers.binary/serialization-1k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.serializers.binary/serialization-1k.png -------------------------------------------------------------------------------- /assets/benchmarks.serializers.json/deserialization-byte-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.serializers.json/deserialization-byte-1.png -------------------------------------------------------------------------------- /assets/benchmarks.serializers.json/deserialization-byte-1k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.serializers.json/deserialization-byte-1k.png -------------------------------------------------------------------------------- /assets/benchmarks.serializers.json/deserialization-string-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.serializers.json/deserialization-string-1.png -------------------------------------------------------------------------------- /assets/benchmarks.serializers.json/deserialization-string-1k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.serializers.json/deserialization-string-1k.png -------------------------------------------------------------------------------- /assets/benchmarks.serializers.json/serialization-byte-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.serializers.json/serialization-byte-1.png -------------------------------------------------------------------------------- /assets/benchmarks.serializers.json/serialization-byte-1k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.serializers.json/serialization-byte-1k.png -------------------------------------------------------------------------------- /assets/benchmarks.serializers.json/serialization-string-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.serializers.json/serialization-string-1.png -------------------------------------------------------------------------------- /assets/benchmarks.serializers.json/serialization-string-1k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/benchmarks.serializers.json/serialization-string-1k.png -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antomys/CuriousBenchmarks/784b131aee62a3653e58d0679af671b3f9c6ae0c/assets/icon.png -------------------------------------------------------------------------------- /coverlet.runsettings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | opencover 8 | [*.Test]*,[*]*.Program 9 | Obsolete,GeneratedCodeAttribute,CompilerGeneratedAttribute 10 | false 11 | true 12 | true 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /docfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": [ 3 | { 4 | "src": [ 5 | { 6 | "src": "../src/main", 7 | "files": [ 8 | "**/*.csproj" 9 | ] 10 | } 11 | ], 12 | "dest": "api" 13 | } 14 | ], 15 | "build": { 16 | "content": [ 17 | { 18 | "files": [ 19 | "**/*.{md,yml}" 20 | ], 21 | "exclude": [ 22 | "_site/**" 23 | ] 24 | } 25 | ], 26 | "resource": [ 27 | { 28 | "files": [ 29 | "images/**" 30 | ] 31 | } 32 | ], 33 | "output": "_site", 34 | "template": [ 35 | "default", 36 | "modern" 37 | ], 38 | "globalMetadata": { 39 | "_appName": "curious-benchmarks", 40 | "_appTitle": "curious-benchmarks", 41 | "_enableSearch": true, 42 | "pdf": true 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /docs/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting Started -------------------------------------------------------------------------------- /docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction -------------------------------------------------------------------------------- /docs/toc.yml: -------------------------------------------------------------------------------- 1 | - name: Introduction 2 | href: introduction.md 3 | - name: Getting Started 4 | href: getting-started.md -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "8.0", 4 | "rollForward": "latestFeature", 5 | "allowPrerelease": false 6 | } 7 | } -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | --- 2 | _layout: landing 3 | --- 4 | 5 | # This is the **HOMEPAGE**. 6 | 7 | Refer to [Markdown](http://daringfireball.net/projects/markdown/) for how to write markdown files. 8 | 9 | ## Quick Start Notes: 10 | 11 | 1. Add images to the *images* folder if the file is referencing an image. -------------------------------------------------------------------------------- /src/main/Benchmarks.CollectionSize/Benchmarks.CollectionSize.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8 6 | enable 7 | enable 8 | Linux 9 | 10 | 11 | 12 | 13 | .dockerignore 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | AnyLengthService.cs 24 | 25 | 26 | AnyLengthService.cs 27 | 28 | 29 | AnyLengthService.cs 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/Benchmarks.CollectionSize/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base 2 | USER $APP_UID 3 | WORKDIR /app 4 | 5 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build 6 | ARG BUILD_CONFIGURATION=Release 7 | WORKDIR /src 8 | COPY ["src/main/Benchmark.CollectionSize/Benchmark.CollectionSize.csproj", "src/main/Benchmark.CollectionSize/"] 9 | RUN dotnet restore "src/main/Benchmark.CollectionSize/Benchmark.CollectionSize.csproj" 10 | COPY . . 11 | WORKDIR "/src/src/main/Benchmark.CollectionSize" 12 | RUN dotnet build "Benchmark.CollectionSize.csproj" -c $BUILD_CONFIGURATION -o /app/build 13 | 14 | FROM build AS publish 15 | ARG BUILD_CONFIGURATION=Release 16 | RUN dotnet publish "Benchmark.CollectionSize.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false 17 | 18 | FROM base AS final 19 | WORKDIR /app 20 | COPY --from=publish /app/publish . 21 | ENTRYPOINT ["dotnet", "Benchmark.CollectionSize.dll"] 22 | -------------------------------------------------------------------------------- /src/main/Benchmarks.CollectionSize/Group.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.CollectionSize; 2 | 3 | internal static class Group 4 | { 5 | internal const string CountExists = "Count Exists"; 6 | 7 | internal const string CountPatternExists = "Count Pattern Exists"; 8 | 9 | internal const string AnyExists = "Any Exists"; 10 | 11 | internal const string CountEmpty = "Count Empty"; 12 | 13 | internal const string CountPatternEmpty = "Count Pattern Empty"; 14 | 15 | internal const string AnyEmpty = "Any Empty"; 16 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.CollectionSize/Models/TestCollections.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.CollectionSize.Models; 2 | 3 | /// 4 | /// Model for storing different collections for benchmarks. 5 | /// 6 | public sealed class TestCollections 7 | { 8 | /// 9 | /// Collection of type. 10 | /// 11 | public string[] TestArray { get; init; } 12 | 13 | /// 14 | /// Collection of type. 15 | /// 16 | public List TestList { get; init; } 17 | 18 | /// 19 | /// Collection of type. 20 | /// 21 | public ICollection TestICollection { get; init; } 22 | 23 | /// 24 | /// Collection of type. 25 | /// 26 | public IEnumerable TestIEnumerable { get; init; } 27 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.CollectionSize/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | 3 | BenchmarkRunner.Run(typeof(Program).Assembly); -------------------------------------------------------------------------------- /src/main/Benchmarks.CollectionSize/Services/AnyLengthService.Any.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.CollectionSize.Services; 2 | 3 | internal static partial class AnyLengthService 4 | { 5 | public static bool AnyArray(this T[]? tArray) 6 | { 7 | return tArray is not null && tArray.Any(); 8 | } 9 | 10 | public static bool AnyList(this List? tArray) 11 | { 12 | return tArray is not null && tArray.Any(); 13 | } 14 | 15 | public static bool AnyCollection(this ICollection? tArray) 16 | { 17 | return tArray is not null && tArray.Any(); 18 | } 19 | 20 | public static bool AnyEnumerable(this IEnumerable? tArray) 21 | { 22 | return tArray is not null && tArray.Any(); 23 | } 24 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.CollectionSize/Services/AnyLengthService.Count.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.CollectionSize.Services; 2 | 3 | internal static partial class AnyLengthService 4 | { 5 | public static bool CountArray(this T[]? tArray) 6 | { 7 | return tArray is not null && tArray.Length > 0; 8 | } 9 | 10 | public static bool CountList(this List? tArray) 11 | { 12 | return tArray is not null && tArray.Count > 0; 13 | } 14 | 15 | public static bool CountCollection(this ICollection? tArray) 16 | { 17 | return tArray is not null && tArray.Count > 0; 18 | } 19 | 20 | public static bool CountEnumerable(this IEnumerable? tArray) 21 | { 22 | return tArray is not null && tArray.Count() > 0; 23 | } 24 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.CollectionSize/Services/AnyLengthService.CountPattern.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.CollectionSize.Services; 2 | 3 | internal static partial class AnyLengthService 4 | { 5 | public static bool CountArrayPattern(this T[]? tArray) 6 | { 7 | return tArray is {Length: > 0}; 8 | } 9 | 10 | public static bool CountListPattern(this List? tArray) 11 | { 12 | return tArray is {Count: > 0}; 13 | } 14 | 15 | public static bool CountCollectionPattern(this ICollection? tArray) 16 | { 17 | return tArray is {Count: > 0}; 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.CollectionSize/Services/AnyLengthService.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.CollectionSize.Services; 2 | 3 | internal static partial class AnyLengthService; -------------------------------------------------------------------------------- /src/main/Benchmarks.Common/Benchmarks.Common.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8 5 | enable 6 | 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/Benchmarks.DynamicPredicateParser/Benchmarks.DynamicPredicateParser.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8 6 | enable 7 | enable 8 | Linux 9 | 10 | 11 | 12 | 13 | .dockerignore 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/Benchmarks.DynamicPredicateParser/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base 2 | USER $APP_UID 3 | WORKDIR /app 4 | 5 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build 6 | ARG BUILD_CONFIGURATION=Release 7 | WORKDIR /src 8 | COPY ["src/main/Benchmarks.DynamicPredicateParser/Benchmarks.DynamicPredicateParser.csproj", "src/main/Benchmarks.DynamicPredicateParser/"] 9 | RUN dotnet restore "src/main/Benchmarks.DynamicPredicateParser/Benchmarks.DynamicPredicateParser.csproj" 10 | COPY . . 11 | WORKDIR "/src/src/main/Benchmarks.DynamicPredicateParser" 12 | RUN dotnet build "Benchmarks.DynamicPredicateParser.csproj" -c $BUILD_CONFIGURATION -o /app/build 13 | 14 | FROM build AS publish 15 | ARG BUILD_CONFIGURATION=Release 16 | RUN dotnet publish "Benchmarks.DynamicPredicateParser.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false 17 | 18 | FROM base AS final 19 | WORKDIR /app 20 | COPY --from=publish /app/publish . 21 | ENTRYPOINT ["dotnet", "Benchmarks.DynamicPredicateParser.dll"] 22 | -------------------------------------------------------------------------------- /src/main/Benchmarks.DynamicPredicateParser/ParserBenchmarks.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using System.Linq.Dynamic.Core; 3 | using BenchmarkDotNet.Attributes; 4 | using BenchmarkDotNet.Configs; 5 | using BenchmarkDotNet.Engines; 6 | using BenchmarkDotNet.Order; 7 | using Bogus; 8 | using PredicateParser; 9 | 10 | namespace Benchmarks.DynamicPredicateParser; 11 | 12 | /// 13 | /// Distinct/GroupBy benchmarks. 14 | /// 15 | [MemoryDiagnoser, CategoriesColumn, AllStatisticsColumn, Orderer(SummaryOrderPolicy.FastestToSlowest), 16 | GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory), MarkdownExporterAttribute.GitHub, CsvMeasurementsExporter, RPlotExporter, ExcludeFromCodeCoverage] 17 | public class ParserBenchmarks 18 | { 19 | private const string Predicate = "Id==\"id\"&&Number==123"; 20 | 21 | private readonly Consumer _consumer = new(); 22 | private TestModel[] _testModels = []; 23 | 24 | /// 25 | /// Size of generation. 26 | /// **NOTE:** Intentionally left public for BenchmarkDotNet Params. 27 | /// 28 | [Params(100, 1000, 10000)] 29 | public int GenerationSize { get; set; } 30 | 31 | /// 32 | /// Setting private fields. 33 | /// 34 | [GlobalSetup] 35 | public void Setup() 36 | { 37 | var faker = new Faker() 38 | .RuleFor(x => x.Id, faker => faker.Random.String2(10)) 39 | .RuleFor(x => x.Number, faker => faker.Random.Int()) 40 | .Generate(GenerationSize - 1); 41 | 42 | faker.Add(new TestModel 43 | { 44 | Id = "id", 45 | Number = 123 46 | }); 47 | 48 | _testModels = faker.ToArray(); 49 | } 50 | 51 | /// 52 | /// Testing GroupBy and Take. 53 | /// 54 | [Benchmark(Baseline = true)] 55 | public TestModel? DynamicCore() 56 | { 57 | var predicate = DynamicExpressionParser 58 | .ParseLambda( 59 | ParsingConfig.Default, 60 | createParameterCtor: true, 61 | Predicate) 62 | .Compile(); 63 | 64 | return _testModels.FirstOrDefault(predicate); 65 | } 66 | 67 | /// 68 | /// Testing GroupBy and Take. 69 | /// 70 | [Benchmark] 71 | public TestModel? PredicateParser() 72 | { 73 | var predicate = PredicateParser.Parse(Predicate).Compile(); 74 | 75 | return _testModels.FirstOrDefault(predicate); 76 | } 77 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.DynamicPredicateParser/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | 3 | BenchmarkRunner.Run(typeof(Program).Assembly); -------------------------------------------------------------------------------- /src/main/Benchmarks.DynamicPredicateParser/TestModel.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.DynamicPredicateParser; 2 | 3 | public sealed class TestModel 4 | { 5 | public string Id { get; init; } 6 | 7 | public int Number { get; init; } 8 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.DynamicPredicateParser/readme.md: -------------------------------------------------------------------------------- 1 | ``` 2 | 3 | BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3880/23H2/2023Update/SunValley3) 4 | 13th Gen Intel Core i9-13905H, 1 CPU, 20 logical and 14 physical cores 5 | .NET SDK 8.0.100 6 | [Host] : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2 7 | DefaultJob : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2 8 | 9 | 10 | ``` 11 | | Method | GenerationSize | Mean | Error | StdDev | StdErr | Min | Q1 | Median | Q3 | Max | Op/s | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio | 12 | |-----------------|----------------|----------:|---------:|---------:|---------:|----------:|----------:|----------:|----------:|----------:|---------:|------:|--------:|-------:|-------:|----------:|------------:| 13 | | DynamicCore | 100 | 48.40 μs | 0.297 μs | 0.264 μs | 0.070 μs | 47.78 μs | 48.35 μs | 48.46 μs | 48.54 μs | 48.72 μs | 20,660.3 | 1.00 | 0.00 | 0.8545 | 0.7324 | 10.53 KB | 1.00 | 14 | | PredicateParser | 100 | 58.96 μs | 0.476 μs | 0.445 μs | 0.115 μs | 58.18 μs | 58.64 μs | 58.87 μs | 59.29 μs | 59.67 μs | 16,959.4 | 1.22 | 0.01 | 1.3428 | 1.2207 | 16.8 KB | 1.60 | 15 | | | | | | | | | | | | | | | | | | | | 16 | | DynamicCore | 1000 | 52.92 μs | 0.237 μs | 0.198 μs | 0.055 μs | 52.61 μs | 52.77 μs | 52.95 μs | 53.05 μs | 53.28 μs | 18,897.9 | 1.00 | 0.00 | 0.8545 | 0.7324 | 10.53 KB | 1.00 | 17 | | PredicateParser | 1000 | 77.43 μs | 0.672 μs | 0.628 μs | 0.162 μs | 75.91 μs | 77.15 μs | 77.57 μs | 77.83 μs | 78.26 μs | 12,914.8 | 1.47 | 0.01 | 1.2207 | 0.9766 | 16.8 KB | 1.60 | 18 | | | | | | | | | | | | | | | | | | | | 19 | | DynamicCore | 10000 | 84.19 μs | 1.638 μs | 2.012 μs | 0.429 μs | 81.12 μs | 82.54 μs | 84.49 μs | 85.82 μs | 87.00 μs | 11,878.4 | 1.00 | 0.00 | 0.7324 | 0.4883 | 10.52 KB | 1.00 | 20 | | PredicateParser | 10000 | 254.42 μs | 0.679 μs | 0.602 μs | 0.161 μs | 253.23 μs | 254.13 μs | 254.60 μs | 254.85 μs | 255.16 μs | 3,930.6 | 2.98 | 0.04 | 0.9766 | 0.4883 | 16.79 KB | 1.60 | 21 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Enum/Benchmarks.Enum.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8 6 | enable 7 | enable 8 | Linux 9 | 10 | 11 | 12 | 13 | .dockerignore 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Enum/Benchmarks/EnumBenchmarksBase.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using BenchmarkDotNet.Attributes; 3 | using BenchmarkDotNet.Configs; 4 | using BenchmarkDotNet.Order; 5 | 6 | namespace Benchmarks.Enum.Benchmarks; 7 | 8 | /// 9 | /// Enum boxing/unboxing benchmarks base. 10 | /// 11 | [MemoryDiagnoser, MarkdownExporter, CategoriesColumn, AllStatisticsColumn, Orderer(SummaryOrderPolicy.FastestToSlowest), 12 | GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory), ExcludeFromCodeCoverage] 13 | public class EnumBenchmarksBase 14 | { 15 | /// 16 | /// Gets collection of enums. 17 | /// 18 | protected static TestEnum[] TestEnums { get; private set; } = default!; 19 | 20 | /// 21 | /// Global setup of private fields. 22 | /// 23 | [GlobalSetup] 24 | public void Setup() 25 | { 26 | TestEnums = 27 | [ 28 | TestEnum.First, 29 | TestEnum.Second, 30 | TestEnum.Third, 31 | TestEnum.Fourth, 32 | TestEnum.Fifth, 33 | TestEnum.Sixth, 34 | TestEnum.Seventh, 35 | TestEnum.Eighth, 36 | TestEnum.Ninth, 37 | TestEnum.Tenth, 38 | TestEnum.Eleventh, 39 | TestEnum.Twelfth 40 | ]; 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Enum/Benchmarks/EnumNameBenchmarks.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using BenchmarkDotNet.Attributes; 3 | using Benchmarks.Enum.Services; 4 | 5 | namespace Benchmarks.Enum.Benchmarks; 6 | 7 | /// 8 | /// Getting Name of Enum benchmarks. 9 | /// 10 | [ExcludeFromCodeCoverage] 11 | public class EnumNameBenchmarks : EnumBenchmarksBase 12 | { 13 | /// 14 | /// Getting string enum name by .ToString(). (Boxing allocation). 15 | /// 16 | /// value. 17 | [BenchmarkCategory(Group.Name), Benchmark] 18 | public string DefaultToString() 19 | { 20 | return TestEnums[0].DefaultToString(); 21 | } 22 | 23 | /// 24 | /// Getting string enum name by Enum.GetName(). 25 | /// 26 | /// value. 27 | [BenchmarkCategory(Group.Name), Benchmark] 28 | public string? EnumGetName() 29 | { 30 | return TestEnums[0].EnumGetName(); 31 | } 32 | 33 | /// 34 | /// Getting string enum name by written custom method. 35 | /// 36 | /// value. 37 | [BenchmarkCategory(Group.Name), Benchmark] 38 | public string CustomGetName() 39 | { 40 | return TestEnums[0].CustomGetName(); 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Enum/Benchmarks/EnumValueBenchmarks.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using BenchmarkDotNet.Attributes; 3 | using Benchmarks.Enum.Services; 4 | 5 | namespace Benchmarks.Enum.Benchmarks; 6 | 7 | /// 8 | /// Benchmarks of getting int value from enum. 9 | /// 10 | [ExcludeFromCodeCoverage] 11 | public class EnumValueBenchmarks : EnumBenchmarksBase 12 | { 13 | /// 14 | /// Getting int value from enum by .ToString(). 15 | /// 16 | [BenchmarkCategory(Group.Value), Benchmark] 17 | public string ToStringFormatD() 18 | { 19 | return TestEnums[0].ToStringFormatD(); 20 | } 21 | 22 | /// 23 | /// Getting int value from enum by implicit cast of enum 24 | /// 25 | [BenchmarkCategory(Group.Value), Benchmark] 26 | public string IntCastToString() 27 | { 28 | return TestEnums[0].IntCastToString(); 29 | } 30 | 31 | /// 32 | /// Getting int value from enum by custom method 33 | /// 34 | [BenchmarkCategory(Group.Value), Benchmark] 35 | public string ExternalMethodToString() 36 | { 37 | return TestEnums[0].CustomGetValue(); 38 | } 39 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Enum/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base 2 | USER $APP_UID 3 | WORKDIR /app 4 | 5 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build 6 | ARG BUILD_CONFIGURATION=Release 7 | WORKDIR /src 8 | COPY ["Benchmark.Enum/Benchmark.Enum.csproj", "Benchmark.Enum/"] 9 | RUN dotnet restore "Benchmark.Enum/Benchmark.Enum.csproj" 10 | COPY . . 11 | WORKDIR "/src/Benchmark.Enum" 12 | RUN dotnet build "Benchmark.Enum.csproj" -c $BUILD_CONFIGURATION -o /app/build 13 | 14 | FROM build AS publish 15 | ARG BUILD_CONFIGURATION=Release 16 | RUN dotnet publish "Benchmark.Enum.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false 17 | 18 | FROM base AS final 19 | WORKDIR /app 20 | COPY --from=publish /app/publish . 21 | ENTRYPOINT ["dotnet", "Benchmark.Enum.dll"] 22 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Enum/Extensions/EnumExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.Enum.Extensions; 2 | 3 | /// 4 | /// Enum extensions. 5 | /// 6 | internal static class EnumExtensions 7 | { 8 | /// 9 | /// The simplest method to get name of the enum. 10 | /// 11 | /// . 12 | /// input enum name. 13 | /// If out of range of enum. 14 | internal static string GetName(this TestEnum testEnum) 15 | { 16 | return testEnum switch 17 | { 18 | TestEnum.First => nameof(TestEnum.First), 19 | TestEnum.Second => nameof(TestEnum.Second), 20 | TestEnum.Third => nameof(TestEnum.Third), 21 | TestEnum.Fourth => nameof(TestEnum.Fourth), 22 | TestEnum.Fifth => nameof(TestEnum.Fifth), 23 | TestEnum.Sixth => nameof(TestEnum.Sixth), 24 | TestEnum.Seventh => nameof(TestEnum.Seventh), 25 | TestEnum.Eighth => nameof(TestEnum.Eighth), 26 | TestEnum.Ninth => nameof(TestEnum.Ninth), 27 | TestEnum.Tenth => nameof(TestEnum.Tenth), 28 | TestEnum.Eleventh => nameof(TestEnum.Eleventh), 29 | TestEnum.Twelfth => nameof(TestEnum.Twelfth), 30 | TestEnum.Zero => nameof(TestEnum.Zero), 31 | _ => throw new ArgumentOutOfRangeException(nameof(testEnum), testEnum, default) 32 | }; 33 | } 34 | 35 | /// 36 | /// The simplest method to get name of the enum. 37 | /// 38 | /// . 39 | /// input enum name. 40 | /// If out of range of enum. 41 | internal static byte GetValue(this TestEnum testEnum) 42 | { 43 | return testEnum switch 44 | { 45 | TestEnum.First => 1, 46 | TestEnum.Second => 2, 47 | TestEnum.Third => 3, 48 | TestEnum.Fourth => 4, 49 | TestEnum.Fifth => 5, 50 | TestEnum.Sixth => 6, 51 | TestEnum.Seventh => 7, 52 | TestEnum.Eighth => 8, 53 | TestEnum.Ninth => 9, 54 | TestEnum.Tenth => 10, 55 | TestEnum.Eleventh => 11, 56 | TestEnum.Twelfth => 12, 57 | TestEnum.Zero => 0, 58 | _ => throw new ArgumentOutOfRangeException(nameof(testEnum), testEnum, default) 59 | }; 60 | } 61 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Enum/Group.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.Enum; 2 | 3 | /// 4 | /// Special constants class for splitting results into groups. 5 | /// 6 | internal static class Group 7 | { 8 | internal const string Name = "Get Enum Name"; 9 | 10 | internal const string Value = "Get Enum Value"; 11 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Enum/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | 3 | BenchmarkRunner.Run(typeof(Program).Assembly); -------------------------------------------------------------------------------- /src/main/Benchmarks.Enum/Services/EnumNameService.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Enum.Extensions; 2 | 3 | namespace Benchmarks.Enum.Services; 4 | 5 | /// 6 | /// Enum getting name service for benchmarks and unit testing. 7 | /// 8 | public static class EnumNameService 9 | { 10 | /// 11 | /// Gets enum name by using default 'ToString' method. 12 | /// 13 | /// Note: Boxing allocation: inherited 'System.Object' virtual method call on value type instance. 14 | /// 15 | /// 16 | /// . 17 | /// Name of Enum. 18 | public static string DefaultToString(this TestEnum testEnum) 19 | { 20 | return testEnum.ToString(); 21 | } 22 | 23 | /// 24 | /// Gets enum name by using default extensions method of class 25 | /// 26 | /// . 27 | /// Name of Enum. 28 | public static string? EnumGetName(this TestEnum testEnum) 29 | { 30 | return System.Enum.GetName(testEnum); 31 | } 32 | 33 | /// 34 | /// Gets enum name by using custom-made method from . 35 | /// 36 | /// . 37 | /// Name of Enum. 38 | public static string CustomGetName(this TestEnum testEnum) 39 | { 40 | return testEnum.GetName(); 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Enum/Services/EnumValueService.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Enum.Extensions; 2 | 3 | namespace Benchmarks.Enum.Services; 4 | 5 | /// 6 | /// Enum getting value service for benchmarks and unit testing. 7 | /// 8 | public static class EnumValueService 9 | { 10 | /// 11 | /// Getting integer value from enum using default method 'ToString' with format 'D - integer value'. 12 | /// 13 | /// . 14 | /// Value of Enum. 15 | public static string ToStringFormatD(this TestEnum testEnum) 16 | { 17 | return testEnum.ToString("D"); 18 | } 19 | 20 | /// 21 | /// Getting integer value from enum by casting firstly to and then using 22 | /// 'ToString'. 23 | /// 24 | /// . 25 | /// Value of Enum. 26 | public static string IntCastToString(this TestEnum testEnum) 27 | { 28 | return ((int)testEnum).ToString(); 29 | } 30 | 31 | /// 32 | /// Getting integer value from enum using method from to get int value 33 | /// . 34 | /// 35 | /// . 36 | /// Value of Enum. 37 | public static string CustomGetValue(this TestEnum testEnum) 38 | { 39 | return testEnum.GetValue().ToString(); 40 | } 41 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Enum/TestEnum.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.Enum; 2 | 3 | /// 4 | /// Test enum entity. 5 | /// 6 | public enum TestEnum 7 | { 8 | /// 9 | /// Zero. 10 | /// 11 | Zero = 0, 12 | 13 | /// 14 | /// First. 15 | /// 16 | First = 1, 17 | 18 | /// 19 | /// Second. 20 | /// 21 | Second = 2, 22 | 23 | /// 24 | /// Third. 25 | /// 26 | Third = 3, 27 | 28 | /// 29 | /// Fourth. 30 | /// 31 | Fourth = 4, 32 | 33 | /// 34 | /// Fifth. 35 | /// 36 | Fifth = 5, 37 | 38 | /// 39 | /// Sixth. 40 | /// 41 | Sixth = 6, 42 | 43 | /// 44 | /// Seventh. 45 | /// 46 | Seventh = 7, 47 | 48 | /// 49 | /// Eighth. 50 | /// 51 | Eighth = 8, 52 | 53 | /// 54 | /// Ninth. 55 | /// 56 | Ninth = 9, 57 | 58 | /// 59 | /// Tenth. 60 | /// 61 | Tenth = 10, 62 | 63 | /// 64 | /// Eleventh. 65 | /// 66 | Eleventh = 11, 67 | 68 | /// 69 | /// Twelfth. 70 | /// 71 | Twelfth = 12 72 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Flattening/Benchmarks.Flattening.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Flattening/InternalModel.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.Flattening; 2 | 3 | public sealed class InternalModel 4 | { 5 | public string? Address { get; init; } 6 | 7 | public string? City { get; init; } 8 | 9 | public string? Country { get; init; } 10 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Flattening/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | 3 | namespace Benchmarks.Flattening; 4 | 5 | internal static class Program 6 | { 7 | public static void Main(string[] args) 8 | { 9 | BenchmarkRunner.Run(typeof(Program).Assembly); 10 | } 11 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Flattening/README.MD: -------------------------------------------------------------------------------- 1 | ``` 2 | 3 | BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3194) 4 | Unknown processor 5 | .NET SDK 9.0.100 6 | [Host] : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX2 7 | DefaultJob : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX2 8 | 9 | ``` 10 | 11 | | Method | Mean | Error | StdDev | StdErr | Min | Q1 | Median | Q3 | Max | Op/s | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio | 12 | |----------------------------------|---------:|--------:|--------:|--------:|---------:|---------:|---------:|---------:|---------:|------------:|------:|--------:|-------:|----------:|------------:| 13 | | 'ToFlat direct model' | 151.8 ns | 0.81 ns | 0.76 ns | 0.20 ns | 150.5 ns | 151.4 ns | 151.8 ns | 152.2 ns | 153.1 ns | 6,587,404.6 | 1.00 | 0.01 | 0.0408 | 512 B | 1.00 | 14 | | 'ToFlat with reflection' | 326.8 ns | 2.16 ns | 2.02 ns | 0.52 ns | 322.4 ns | 325.5 ns | 327.1 ns | 328.0 ns | 330.5 ns | 3,059,850.7 | 2.15 | 0.02 | 0.0668 | 840 B | 1.64 | 15 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Flattening/UnflatModel.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.Flattening; 2 | 3 | public sealed class UnflatModel 4 | { 5 | public string? Email { get; init; } 6 | 7 | public bool? IsEmailConfirmed { get; init; } 8 | 9 | public bool? IsPhoneConfirmed { get; init; } 10 | 11 | public InternalModel? InternalModel { get; init; } 12 | 13 | public string? Phone { get; init; } 14 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.GroupByVsDistinct/Benchmarks.GroupByVsDistinct.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8 6 | enable 7 | enable 8 | Linux 9 | 10 | 11 | 12 | 13 | .dockerignore 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/main/Benchmarks.GroupByVsDistinct/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base 2 | USER $APP_UID 3 | WORKDIR /app 4 | 5 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build 6 | ARG BUILD_CONFIGURATION=Release 7 | WORKDIR /src 8 | COPY ["src/main/Benchmark.GroupByVsDistinct/Benchmark.GroupByVsDistinct.csproj", "src/main/Benchmark.GroupByVsDistinct/"] 9 | RUN dotnet restore "src/main/Benchmark.GroupByVsDistinct/Benchmark.GroupByVsDistinct.csproj" 10 | COPY . . 11 | WORKDIR "/src/src/main/Benchmark.GroupByVsDistinct" 12 | RUN dotnet build "Benchmark.GroupByVsDistinct.csproj" -c $BUILD_CONFIGURATION -o /app/build 13 | 14 | FROM build AS publish 15 | ARG BUILD_CONFIGURATION=Release 16 | RUN dotnet publish "Benchmark.GroupByVsDistinct.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false 17 | 18 | FROM base AS final 19 | WORKDIR /app 20 | COPY --from=publish /app/publish . 21 | ENTRYPOINT ["dotnet", "Benchmark.GroupByVsDistinct.dll"] 22 | -------------------------------------------------------------------------------- /src/main/Benchmarks.GroupByVsDistinct/Models/InnerModel.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | namespace Benchmarks.GroupByVsDistinct.Models; 4 | 5 | /// 6 | /// Inner test class of test class. 7 | /// 8 | [SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Global")] 9 | public sealed class InnerModel 10 | { 11 | /// 12 | /// Id of inner test model. 13 | /// 14 | public string InnerId { get; init; } = string.Empty; 15 | 16 | /// 17 | /// Date 18 | /// 19 | public DateTime DateOnly { get; init; } = DateTime.Now; 20 | 21 | /// 22 | /// Test int value. 23 | /// 24 | public int Integer { get; init; } 25 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.GroupByVsDistinct/Models/SimpleModel.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | namespace Benchmarks.GroupByVsDistinct.Models; 4 | 5 | /// 6 | /// Test model. 7 | /// 8 | [SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Global")] 9 | public sealed class SimpleModel 10 | { 11 | /// 12 | /// Id of test model. 13 | /// 14 | public string TestModelId { get; set; } = string.Empty; 15 | 16 | /// 17 | /// Id of inner test model. 18 | /// 19 | public string InnerTestModelId { get; set; } = string.Empty; 20 | 21 | /// 22 | /// Test Date. 23 | /// 24 | public DateTime DateOnly { get; set; } = DateTime.Now; 25 | 26 | /// 27 | /// Test int value. 28 | /// 29 | public int Integer { get; set; } 30 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.GroupByVsDistinct/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | 3 | BenchmarkRunner.Run(typeof(Program).Assembly); -------------------------------------------------------------------------------- /src/main/Benchmarks.GroupByVsDistinct/Services/LinqService.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.GroupByVsDistinct.Models; 2 | 3 | namespace Benchmarks.GroupByVsDistinct.Services; 4 | 5 | /// 6 | /// Linq methods testing service. 7 | /// 8 | public static class LinqService 9 | { 10 | /// 11 | /// Gets collection of using GroupBy and Select methods. 12 | /// 13 | /// collection. 14 | /// Dictionary of value with key as string. 15 | /// Specific string id, to be retrieved by. 16 | /// Collection of . 17 | public static IEnumerable GroupByTake( 18 | this IEnumerable testModelsList, Dictionary innerTestModels, string innerTestModelConstId) 19 | { 20 | return testModelsList 21 | .GroupBy(x => x.InnerTestModelId) 22 | .Select(_ => innerTestModels[innerTestModelConstId]); 23 | } 24 | 25 | /// 26 | /// Gets collection of using DistinctBy and Select methods. 27 | /// 28 | /// collection. 29 | /// Dictionary of value with key as string. 30 | /// Specific string id, to be retrieved by. 31 | /// Collection of . 32 | public static IEnumerable DistinctByTake( 33 | this IEnumerable testModelsList, Dictionary innerTestModels, string innerTestModelConstId) 34 | { 35 | return testModelsList 36 | .DistinctBy(x => x.InnerTestModelId) 37 | .Select(_ => innerTestModels[innerTestModelConstId]); 38 | } 39 | 40 | /// 41 | /// Gets collection of using Select, then Distinct and then Select methods. 42 | /// 43 | /// collection. 44 | /// Dictionary of value with key as string. 45 | /// Specific string id, to be retrieved by. 46 | /// Collection of . 47 | public static IEnumerable DistinctTake( 48 | this IEnumerable testModelsList, Dictionary innerTestModels, string innerTestModelConstId) 49 | { 50 | return testModelsList 51 | .Select(x => x.InnerTestModelId) 52 | .Distinct() 53 | .Select(_ => innerTestModels[innerTestModelConstId]); 54 | } 55 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Iterators/Benchmarks.Iterators.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8 6 | enable 7 | enable 8 | Linux 9 | 10 | 11 | 12 | 13 | .dockerignore 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | IterationService.cs 24 | 25 | 26 | IterationService.cs 27 | 28 | 29 | IterationService.cs 30 | 31 | 32 | IteratorBenchmarks.cs 33 | 34 | 35 | IteratorBenchmarks.cs 36 | 37 | 38 | IteratorBenchmarks.cs 39 | 40 | 41 | IteratorBenchmarks.cs 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Iterators/Benchmarks/BenchmarksBase.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using BenchmarkDotNet.Attributes; 3 | using BenchmarkDotNet.Configs; 4 | using BenchmarkDotNet.Engines; 5 | using BenchmarkDotNet.Order; 6 | using Benchmarks.Iterators.Models; 7 | using Bogus; 8 | 9 | namespace Benchmarks.Iterators.Benchmarks; 10 | 11 | /// 12 | /// Base class for iterators benchmarks. 13 | /// 14 | [MemoryDiagnoser, AllStatisticsColumn, CategoriesColumn, MarkdownExporterAttribute.GitHub, Orderer(SummaryOrderPolicy.FastestToSlowest), 15 | GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory), ExcludeFromCodeCoverage] 16 | public class BenchmarksBase 17 | { 18 | /// 19 | /// . 20 | /// 21 | protected readonly Consumer Consumer = new(); 22 | 23 | /// 24 | /// Array of int. 25 | /// 26 | protected int[] TestArray = default!; 27 | 28 | /// 29 | /// Collection of int as array 30 | /// 31 | protected ICollection TestCollectionArray = default!; 32 | 33 | /// 34 | /// Collection of int as list 35 | /// 36 | protected ICollection TestCollectionList = default!; 37 | 38 | /// 39 | /// List of . 40 | /// 41 | protected List TestInputModels = default!; 42 | 43 | /// 44 | /// List of int. 45 | /// 46 | protected List TestList = default!; 47 | 48 | /// 49 | /// Parameter for models count. 50 | /// **NOTE:** Intentionally left public for BenchmarkDotNet Params. 51 | /// 52 | [Params(10, 100000)] 53 | public int Size { get; set; } 54 | 55 | /// 56 | /// Global setup of private and protected parameters. 57 | /// 58 | [GlobalSetup] 59 | public void Setup() 60 | { 61 | var faker = new Faker(); 62 | Randomizer.Seed = new Random(420); 63 | 64 | TestInputModels = faker 65 | .RuleFor(testModel => testModel.TestInd, fakerSetter => fakerSetter.Random.Int(-100000, 100000)) 66 | .RuleFor(testModel => testModel.TestString, fakerSetter => fakerSetter.Random.String2(10)) 67 | .RuleFor(testModel => testModel.TestDateTime, fakerSetter => fakerSetter.Date.Past()) 68 | .Generate(Size)!; 69 | 70 | TestArray = TestInputModels.Select(model => model.TestInd).ToArray(); 71 | TestList = TestInputModels.Select(model => model.TestInd).ToList(); 72 | TestCollectionArray = TestInputModels.Select(model => model.TestInd).ToArray(); 73 | TestCollectionList = TestInputModels.Select(model => model.TestInd).ToList(); 74 | } 75 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Iterators/Benchmarks/IteratorBenchmarks.Array.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Attributes; 2 | using Benchmarks.Iterators.Services; 3 | 4 | namespace Benchmarks.Iterators.Benchmarks; 5 | 6 | public partial class IteratorBenchmarks 7 | { 8 | /// 9 | /// Testing with 'for' method. 10 | /// 11 | [BenchmarkCategory(Group.Array), Benchmark(Description = "For")] 12 | public int ForArray() 13 | { 14 | return TestArray.For(); 15 | } 16 | 17 | /// 18 | /// Testing with 'Foreach' method. 19 | /// 20 | [BenchmarkCategory(Group.Array), Benchmark(Description = "Foreach")] 21 | public int ForeachArray() 22 | { 23 | return TestArray.Foreach(); 24 | } 25 | 26 | /// 27 | /// Testing with 'Linq.Aggregate' methods. 28 | /// 29 | [BenchmarkCategory(Group.Array), Benchmark(Description = "Linq Aggregate")] 30 | public int? LinqArray() 31 | { 32 | return TestArray.LinqAggregate(); 33 | } 34 | 35 | /// 36 | /// Testing with 'Linq.Sum' methods. 37 | /// 38 | [BenchmarkCategory(Group.Array), Benchmark(Description = "Linq Sum")] 39 | public int? SumArray() 40 | { 41 | return TestArray.LinqSum(); 42 | } 43 | 44 | /// 45 | /// Testing with 'foreach(ref)' methods. 46 | /// 47 | [BenchmarkCategory(Group.Array), Benchmark(Description = "Ref Foreach")] 48 | public int RefForeachArray() 49 | { 50 | return TestArray.RefForeach(); 51 | } 52 | 53 | /// 54 | /// Testing with '.AsSpan + for' methods. 55 | /// 56 | [BenchmarkCategory(Group.Array), Benchmark(Description = "AsSpan + For")] 57 | public int SpanForArray() 58 | { 59 | return TestArray.SpanFor(); 60 | } 61 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Iterators/Benchmarks/IteratorBenchmarks.ICollection.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Attributes; 2 | using Benchmarks.Iterators.Services; 3 | 4 | namespace Benchmarks.Iterators.Benchmarks; 5 | 6 | public partial class IteratorBenchmarks 7 | { 8 | /// 9 | /// Testing with 'Foreach' method. 10 | /// 11 | [BenchmarkCategory(Group.Collection), Benchmark(Description = "Foreach. Array as ICollection")] 12 | public int ForeachICollectionArray() 13 | { 14 | return TestCollectionArray.Foreach(); 15 | } 16 | 17 | /// 18 | /// Testing with 'Linq.Aggregate' methods. 19 | /// 20 | [BenchmarkCategory(Group.Collection), Benchmark(Description = "Linq Aggregate. Array as ICollection")] 21 | public int? LinqICollectionArray() 22 | { 23 | return TestCollectionArray.LinqAggregate(); 24 | } 25 | 26 | /// 27 | /// Testing with 'Linq.Sum' methods. 28 | /// 29 | [BenchmarkCategory(Group.Collection), Benchmark(Description = "Linq Sum. Array as ICollection")] 30 | public int? SumICollectionArray() 31 | { 32 | return TestCollectionArray.LinqSum(); 33 | } 34 | 35 | /// 36 | /// Testing with 'Foreach' method. 37 | /// 38 | [BenchmarkCategory(Group.Collection), Benchmark(Description = "Foreach. List as ICollection")] 39 | public int ForeachICollectionList() 40 | { 41 | return TestCollectionList.Foreach(); 42 | } 43 | 44 | /// 45 | /// Testing with 'Linq.Aggregate' methods. 46 | /// 47 | [BenchmarkCategory(Group.Collection), Benchmark(Description = "Linq Aggregate. List as ICollection")] 48 | public int? LinqICollectionList() 49 | { 50 | return TestCollectionList.LinqAggregate(); 51 | } 52 | 53 | /// 54 | /// Testing with 'Linq.Sum' methods. 55 | /// 56 | [BenchmarkCategory(Group.Collection), Benchmark(Description = "Linq Sum. List as ICollection")] 57 | public int? SumICollectionList() 58 | { 59 | return TestCollectionList.LinqSum(); 60 | } 61 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Iterators/Benchmarks/IteratorBenchmarks.List.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Attributes; 2 | using Benchmarks.Iterators.Services; 3 | 4 | namespace Benchmarks.Iterators.Benchmarks; 5 | 6 | public partial class IteratorBenchmarks 7 | { 8 | /// 9 | /// Testing with 'for' method. 10 | /// 11 | [BenchmarkCategory(Group.List), Benchmark(Description = "For", Baseline = true)] 12 | public int ForList() 13 | { 14 | return TestList.For(); 15 | } 16 | 17 | /// 18 | /// Testing with 'Foreach' method. 19 | /// 20 | [BenchmarkCategory(Group.List), Benchmark(Description = "Foreach")] 21 | public int ForeachList() 22 | { 23 | return TestList.Foreach(); 24 | } 25 | 26 | /// 27 | /// Testing with 'Linq.Aggregate' methods. 28 | /// 29 | [BenchmarkCategory(Group.List), Benchmark(Description = "Linq Aggregate")] 30 | public int? LinqList() 31 | { 32 | return TestList.LinqAggregate(); 33 | } 34 | 35 | /// 36 | /// Testing with 'Linq.Sum' methods. 37 | /// 38 | [BenchmarkCategory(Group.List), Benchmark(Description = "Linq Sum")] 39 | public int? SumList() 40 | { 41 | return TestList.LinqSum(); 42 | } 43 | 44 | /// 45 | /// Testing with 'foreach(ref)' methods. 46 | /// 47 | [BenchmarkCategory(Group.List), Benchmark(Description = "Ref Foreach")] 48 | public int RefForeachList() 49 | { 50 | return TestList.RefForeach(); 51 | } 52 | 53 | /// 54 | /// Testing with '.AsSpan + for' methods. 55 | /// 56 | [BenchmarkCategory(Group.List), Benchmark(Description = "AsSpan + For")] 57 | public int SpanForList() 58 | { 59 | return TestList.SpanFor(); 60 | } 61 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Iterators/Benchmarks/IteratorBenchmarks.Serializing.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Attributes; 2 | using BenchmarkDotNet.Engines; 3 | using Benchmarks.Iterators.Models; 4 | using Benchmarks.Iterators.Services; 5 | 6 | namespace Benchmarks.Iterators.Benchmarks; 7 | 8 | /// 9 | public partial class IteratorBenchmarks 10 | { 11 | /// 12 | /// Testing with 'for' method. 13 | /// 14 | [BenchmarkCategory(Group.Serializing), Benchmark(Description = $"For serialization {nameof(SimpleModel)}", Baseline = true)] 15 | public void For() 16 | { 17 | TestInputModels.For().Consume(Consumer); 18 | } 19 | 20 | /// 21 | /// Testing with 'for' method. 22 | /// 23 | [BenchmarkCategory(Group.Serializing), Benchmark(Description = $"ArrayPool + For serialization {nameof(SimpleModel)}")] 24 | public void ForArrayPool() 25 | { 26 | TestInputModels.ForArrayPool().Consume(Consumer); 27 | } 28 | 29 | /// 30 | /// Testing with 'Foreach' method. 31 | /// 32 | [BenchmarkCategory(Group.Serializing), Benchmark(Description = $"Foreach serialization {nameof(SimpleModel)}")] 33 | public void Foreach() 34 | { 35 | TestInputModels.Foreach().Consume(Consumer); 36 | } 37 | 38 | /// 39 | /// Testing with 'Linq' methods. 40 | /// 41 | [BenchmarkCategory(Group.Serializing), Benchmark(Description = $"Linq serialization {nameof(SimpleModel)}")] 42 | public void Linq() 43 | { 44 | TestInputModels.Linq().Consume(Consumer); 45 | } 46 | 47 | /// 48 | /// Testing with 'Yield' methods. 49 | /// 50 | [BenchmarkCategory(Group.Serializing), Benchmark(Description = $"Yield serialization {nameof(SimpleModel)}")] 51 | public void Yield() 52 | { 53 | TestInputModels.Yield().Consume(Consumer); 54 | } 55 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Iterators/Benchmarks/IteratorBenchmarks.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | namespace Benchmarks.Iterators.Benchmarks; 4 | 5 | [ExcludeFromCodeCoverage] 6 | public partial class IteratorBenchmarks : BenchmarksBase; -------------------------------------------------------------------------------- /src/main/Benchmarks.Iterators/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base 2 | USER $APP_UID 3 | WORKDIR /app 4 | 5 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build 6 | ARG BUILD_CONFIGURATION=Release 7 | WORKDIR /src 8 | COPY ["src/main/Benchmark.Iterators/Benchmark.Iterators.csproj", "src/main/Benchmark.Iterators/"] 9 | RUN dotnet restore "src/main/Benchmark.Iterators/Benchmark.Iterators.csproj" 10 | COPY . . 11 | WORKDIR "/src/src/main/Benchmark.Iterators" 12 | RUN dotnet build "Benchmark.Iterators.csproj" -c $BUILD_CONFIGURATION -o /app/build 13 | 14 | FROM build AS publish 15 | ARG BUILD_CONFIGURATION=Release 16 | RUN dotnet publish "Benchmark.Iterators.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false 17 | 18 | FROM base AS final 19 | WORKDIR /app 20 | COPY --from=publish /app/publish . 21 | ENTRYPOINT ["dotnet", "Benchmark.Iterators.dll"] 22 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Iterators/Group.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.Iterators; 2 | 3 | internal static class Group 4 | { 5 | internal const string List = "List"; 6 | 7 | internal const string Array = "Array"; 8 | 9 | internal const string Collection = "ICollection"; 10 | 11 | internal const string Serializing = "Serializing model"; 12 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Iterators/Models/SimpleModel.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.Iterators.Models; 2 | 3 | /// 4 | /// Test model class. 5 | /// 6 | public sealed class SimpleModel 7 | { 8 | /// 9 | /// Test id. 10 | /// 11 | public int TestInd { get; set; } 12 | 13 | /// 14 | /// Test string. 15 | /// 16 | public string? TestString { get; set; } 17 | 18 | /// 19 | /// Test date time. 20 | /// 21 | public DateTime? TestDateTime { get; set; } 22 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Iterators/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | 3 | BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(); -------------------------------------------------------------------------------- /src/main/Benchmarks.Iterators/Services/IterationService.Array.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.Iterators.Services; 2 | 3 | /// . 4 | public static partial class IterationService 5 | { 6 | /// 7 | /// Testing with 'for' method. 8 | /// 9 | public static int For(this int[] inputArray) 10 | { 11 | var sumResult = 0; 12 | 13 | for (var i = 0; i < inputArray.Length; i++) 14 | { 15 | sumResult += inputArray[i]; 16 | } 17 | 18 | return sumResult; 19 | } 20 | 21 | /// 22 | /// Testing with 'Foreach' method. 23 | /// 24 | public static int Foreach(this int[] inputArray) 25 | { 26 | var sumResult = 0; 27 | 28 | foreach (var testModel in inputArray) sumResult += testModel; 29 | 30 | return sumResult; 31 | } 32 | 33 | /// 34 | /// Testing with 'Linq' methods. 35 | /// 36 | public static int? LinqAggregate(this int[] inputArray) 37 | { 38 | return inputArray.Aggregate((a, b) => a + b); 39 | } 40 | 41 | /// 42 | /// Testing with 'Linq' methods. 43 | /// 44 | public static int? LinqSum(this int[] inputArray) 45 | { 46 | return inputArray.Sum(); 47 | } 48 | 49 | /// 50 | /// Testing with 'Ref Foreach' methods. 51 | /// 52 | public static int RefForeach(this int[] inputArray) 53 | { 54 | var sumResult = 0; 55 | 56 | foreach (ref var input in inputArray.AsSpan()) sumResult += input; 57 | 58 | return sumResult; 59 | } 60 | 61 | /// 62 | /// Testing with 'Span For' methods. 63 | /// 64 | public static int SpanFor(this int[] inputArray) 65 | { 66 | var sumResult = 0; 67 | 68 | var array = inputArray.AsSpan(); 69 | 70 | for (var i = 0; i < array.Length; i++) 71 | { 72 | sumResult += inputArray[i]; 73 | } 74 | 75 | return sumResult; 76 | } 77 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Iterators/Services/IterationService.Collection.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.Iterators.Services; 2 | 3 | /// 4 | /// . 5 | public static partial class IterationService 6 | { 7 | /// 8 | /// Testing with 'Foreach' method. 9 | /// 10 | public static int Foreach(this ICollection inputCollection) 11 | { 12 | var sumResult = 0; 13 | 14 | foreach (var testModel in inputCollection) sumResult += testModel; 15 | 16 | return sumResult; 17 | } 18 | 19 | /// 20 | /// Testing with 'Linq' methods. 21 | /// 22 | public static int? LinqAggregate(this ICollection inputCollection) 23 | { 24 | return inputCollection.Aggregate((a, b) => a + b); 25 | } 26 | 27 | /// 28 | /// Testing with 'Linq' methods. 29 | /// 30 | public static int? LinqSum(this ICollection inputCollection) 31 | { 32 | return inputCollection.Sum(); 33 | } 34 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Iterators/Services/IterationService.List.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Benchmarks.Iterators.Services; 4 | 5 | /// 6 | /// . 7 | public static partial class IterationService 8 | { 9 | /// 10 | /// Testing with 'for' method. 11 | /// 12 | public static int For(this List inputList) 13 | { 14 | var sumResult = 0; 15 | 16 | for (var i = 0; i < inputList.Count; i++) 17 | { 18 | sumResult += inputList[i]; 19 | } 20 | 21 | return sumResult; 22 | } 23 | 24 | /// 25 | /// Testing with 'Foreach' method. 26 | /// 27 | public static int Foreach(this List inputList) 28 | { 29 | var sumResult = 0; 30 | 31 | foreach (var testModel in inputList) sumResult += testModel; 32 | 33 | return sumResult; 34 | } 35 | 36 | /// 37 | /// Testing with 'Linq' methods. 38 | /// 39 | public static int? LinqAggregate(this List inputList) 40 | { 41 | return inputList.Aggregate((a, b) => a + b); 42 | } 43 | 44 | /// 45 | /// Testing with 'Linq' methods. 46 | /// 47 | public static int? LinqSum(this List inputList) 48 | { 49 | return inputList.Sum(); 50 | } 51 | 52 | /// 53 | /// Testing with 'Ref Foreach' methods. 54 | /// 55 | public static int RefForeach(this List inputList) 56 | { 57 | var sumResult = 0; 58 | 59 | foreach (ref var input in CollectionsMarshal.AsSpan(inputList)) sumResult += input; 60 | 61 | return sumResult; 62 | } 63 | 64 | /// 65 | /// Testing with 'Span For' methods. 66 | /// 67 | public static int SpanFor(this List inputList) 68 | { 69 | var sumResult = 0; 70 | 71 | var array = CollectionsMarshal.AsSpan(inputList); 72 | 73 | for (var i = 0; i < array.Length; i++) 74 | { 75 | sumResult += inputList[i]; 76 | } 77 | 78 | return sumResult; 79 | } 80 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Iterators/Services/IterationService.cs: -------------------------------------------------------------------------------- 1 | using System.Buffers; 2 | using System.Text.Json; 3 | using Benchmarks.Iterators.Models; 4 | 5 | namespace Benchmarks.Iterators.Services; 6 | 7 | /// 8 | /// Iteration service. Made static for faster development 9 | /// 10 | public static partial class IterationService 11 | { 12 | /// 13 | /// Testing with 'for' method. 14 | /// 15 | /// 16 | public static string[] For(this List testInputModels) 17 | { 18 | var testOutputModels = new string[testInputModels.Count]; 19 | 20 | for (var i = 0; i < testInputModels.Count; i++) 21 | { 22 | if (testInputModels[i] is null) continue; 23 | 24 | testOutputModels[i] = JsonSerializer.Serialize(testInputModels[i]); 25 | } 26 | 27 | return testOutputModels; 28 | } 29 | 30 | /// 31 | /// Testing with 'for' method. 32 | /// 33 | /// 34 | public static string[] ForArrayPool(this List testInputModels) 35 | { 36 | var pooledArray = ArrayPool.Shared.Rent(testInputModels.Count); 37 | 38 | try 39 | { 40 | Span spanArray = pooledArray; 41 | 42 | var index = 0; 43 | 44 | while (index < testInputModels.Count) 45 | { 46 | if (testInputModels[index] is null) 47 | { 48 | index++; 49 | continue; 50 | } 51 | 52 | spanArray[index] = JsonSerializer.Serialize(testInputModels[index]); 53 | index++; 54 | } 55 | 56 | return spanArray[..index].ToArray(); 57 | } 58 | finally 59 | { 60 | ArrayPool.Shared.Return(pooledArray); 61 | } 62 | } 63 | 64 | /// 65 | /// Testing with 'for' method. 66 | /// 67 | /// 68 | public static IEnumerable Yield(this List testInputModels) 69 | { 70 | foreach (var testModel in testInputModels) 71 | { 72 | if (testModel is null) continue; 73 | 74 | yield return JsonSerializer.Serialize(testModel); 75 | } 76 | } 77 | 78 | /// 79 | /// Testing with 'Foreach' method. 80 | /// 81 | public static List Foreach(this List testInputModels) 82 | { 83 | var testOutputModels = new List(testInputModels.Count); 84 | 85 | foreach (var testModel in testInputModels) 86 | { 87 | if (testModel is null) continue; 88 | 89 | testOutputModels.Add(JsonSerializer.Serialize(testModel)); 90 | } 91 | 92 | return testOutputModels; 93 | } 94 | 95 | /// 96 | /// Testing with 'Linq' methods. 97 | /// 98 | public static IEnumerable Linq(this IEnumerable testInputModels) 99 | { 100 | return testInputModels 101 | .Where(testModel => testModel is not null) 102 | .Select(testModel => JsonSerializer.Serialize(testModel)); 103 | } 104 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.QueryBuilder/Benchmarks.QueryBuilder.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8 6 | enable 7 | enable 8 | Linux 9 | true 10 | 11 | 12 | 13 | 14 | .dockerignore 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/Benchmarks.QueryBuilder/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base 2 | USER $APP_UID 3 | WORKDIR /app 4 | 5 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build 6 | ARG BUILD_CONFIGURATION=Release 7 | WORKDIR /src 8 | COPY ["src/main/Benchmark.QueryBuilder/Benchmark.QueryBuilder.csproj", "src/main/Benchmark.QueryBuilder/"] 9 | RUN dotnet restore "src/main/Benchmark.QueryBuilder/Benchmark.QueryBuilder.csproj" 10 | COPY . . 11 | WORKDIR "/src/src/main/Benchmark.QueryBuilder" 12 | RUN dotnet build "Benchmark.QueryBuilder.csproj" -c $BUILD_CONFIGURATION -o /app/build 13 | 14 | FROM build AS publish 15 | ARG BUILD_CONFIGURATION=Release 16 | RUN dotnet publish "Benchmark.QueryBuilder.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false 17 | 18 | FROM base AS final 19 | WORKDIR /app 20 | COPY --from=publish /app/publish . 21 | ENTRYPOINT ["dotnet", "Benchmark.QueryBuilder.dll"] 22 | -------------------------------------------------------------------------------- /src/main/Benchmarks.QueryBuilder/Group.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.QueryBuilder; 2 | 3 | internal static class Group 4 | { 5 | internal const string StringUrl = "String Url"; 6 | 7 | internal const string UriUrl = "Uri Url"; 8 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.QueryBuilder/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | 3 | BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(); -------------------------------------------------------------------------------- /src/main/Benchmarks.QueryBuilder/Services/Query/QueryClass.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.QueryBuilder.Services.Query; 2 | 3 | /// 4 | /// Override of with length. 5 | /// 6 | public sealed class QueryDictionary : Dictionary 7 | { 8 | /// 9 | public QueryDictionary(int size) : base(size) 10 | { 11 | } 12 | 13 | /// 14 | /// Gets overall length of all keys and values by chars. 15 | /// 16 | public int QueryLength { get; private set; } 17 | 18 | /// 19 | /// Override of of dictionary with adding length of key and value. 20 | /// 21 | /// Key. 22 | /// Value. 23 | public new void Add(string key, string value) 24 | { 25 | QueryLength += key.Length + value.Length; 26 | 27 | base.Add(key, value); 28 | } 29 | 30 | /// 31 | /// Override of of dictionary with adding length of key and value. 32 | /// 33 | /// Key. 34 | /// Value. 35 | public new bool TryAdd(string key, string value) 36 | { 37 | QueryLength += key.Length + value.Length; 38 | 39 | return base.TryAdd(key, value); 40 | } 41 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.QueryBuilder/Services/Query/QueryValueStringBuilder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections; 5 | using System.Text.Encodings.Web; 6 | using Microsoft.AspNetCore.Http; 7 | 8 | namespace Benchmarks.QueryBuilder.Services.Query; 9 | 10 | // The IEnumerable interface is required for the collection initialization syntax: new QueryBuilder() { { "key", "value" } }; 11 | public sealed class QueryValueStringBuilder : IEnumerable> 12 | { 13 | private readonly IList> _params; 14 | 15 | public QueryValueStringBuilder() 16 | { 17 | _params = new List>(); 18 | } 19 | 20 | public QueryValueStringBuilder(IEnumerable> parameters) 21 | { 22 | _params = new List>(parameters); 23 | } 24 | 25 | public IEnumerator> GetEnumerator() 26 | { 27 | return _params.GetEnumerator(); 28 | } 29 | 30 | IEnumerator IEnumerable.GetEnumerator() 31 | { 32 | return _params.GetEnumerator(); 33 | } 34 | 35 | public void Add(string key, IEnumerable values) 36 | { 37 | foreach (var value in values) _params.Add(new KeyValuePair(key, value)); 38 | } 39 | 40 | public void Add(string key, string value) 41 | { 42 | _params.Add(new KeyValuePair(key, value)); 43 | } 44 | 45 | public override string ToString() 46 | { 47 | var builder = new ValueStringBuilder(); 48 | var first = true; 49 | 50 | for (var i = 0; i < _params.Count; i++) 51 | { 52 | var pair = _params[i]; 53 | builder.Append(first ? "?" : "&"); 54 | first = false; 55 | builder.Append(UrlEncoder.Default.Encode(pair.Key)); 56 | builder.Append("="); 57 | builder.Append(UrlEncoder.Default.Encode(pair.Value)); 58 | } 59 | 60 | return builder.ToString(); 61 | } 62 | 63 | public QueryString ToQueryString() 64 | { 65 | return new QueryString(ToString()); 66 | } 67 | 68 | public override int GetHashCode() 69 | { 70 | return ToQueryString().GetHashCode(); 71 | } 72 | 73 | public override bool Equals(object obj) 74 | { 75 | return ToQueryString().Equals(obj); 76 | } 77 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Binary/Benchmarks.Serializers.Binary.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8 6 | enable 7 | enable 8 | Linux 9 | true 10 | true 11 | true 12 | 13 | 14 | 15 | 16 | .dockerignore 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Serializers.cs 28 | 29 | 30 | Serializers.cs 31 | 32 | 33 | Serializers.cs 34 | 35 | 36 | Serializers.cs 37 | 38 | 39 | Serializers.cs 40 | 41 | 42 | Serializers.cs 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Binary/Benchmarks/SerializationBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using Benchmarks.Serializers.Models; 3 | using BenchmarkDotNet.Attributes; 4 | using BenchmarkDotNet.Configs; 5 | using BenchmarkDotNet.Order; 6 | using Bogus; 7 | 8 | namespace Benchmarks.Serializers.Binary.Benchmarks; 9 | 10 | [MemoryDiagnoser, CategoriesColumn, AllStatisticsColumn, Orderer(SummaryOrderPolicy.FastestToSlowest), 11 | GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory), ExcludeFromCodeCoverage] 12 | public class SerializationBenchmark 13 | { 14 | /// 15 | /// Collection of testing . 16 | /// 17 | private SimpleModel[] _simpleModels = []; 18 | 19 | /// 20 | /// Size of generation. 21 | /// **NOTE:** Intentionally left public for BenchmarkDotNet Params. 22 | /// 23 | [Params(1, 100, 1000)] 24 | public int CollectionSize { get; set; } 25 | 26 | /// 27 | /// Setting private fields. 28 | /// 29 | [GlobalSetup] 30 | public void Setup() 31 | { 32 | _simpleModels = new Faker() 33 | .RuleFor(model => model.TestBool, faker => faker.Random.Bool()) 34 | .RuleFor(model => model.TestInt, faker => faker.Random.Int()) 35 | .RuleFor(model => model.TestString, faker => faker.Name.FullName()) 36 | .Generate(CollectionSize) 37 | .ToArray(); 38 | } 39 | 40 | [BenchmarkCategory(Group.SerializationByte), Benchmark] 41 | public byte[] MessagePack() 42 | { 43 | return Serializers.MessagePackSerializeBytes(_simpleModels); 44 | } 45 | 46 | [BenchmarkCategory(Group.SerializationByte), Benchmark] 47 | public byte[] MsgPackLight() 48 | { 49 | return Serializers.MsgPackLightSerializeBytes(_simpleModels); 50 | } 51 | 52 | [BenchmarkCategory(Group.SerializationByte), Benchmark] 53 | public byte[] MemoryPack() 54 | { 55 | return Serializers.MemoryPackSerializeBytes(_simpleModels); 56 | } 57 | 58 | [BenchmarkCategory(Group.SerializationByte), Benchmark] 59 | public byte[] ZeroFormatter() 60 | { 61 | return Serializers.ZeroFormatterSerializeBytes(_simpleModels); 62 | } 63 | 64 | [BenchmarkCategory(Group.SerializationByte), Benchmark] 65 | public byte[] Protobuf() 66 | { 67 | return Serializers.ProtobufSerializeBytes(_simpleModels); 68 | } 69 | 70 | [BenchmarkCategory(Group.SerializationByte), Benchmark] 71 | public byte[] FlatBuffers() 72 | { 73 | return Serializers.FlatBufferSerializeBytes(_simpleModels); 74 | } 75 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Binary/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base 2 | USER $APP_UID 3 | WORKDIR /app 4 | 5 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build 6 | ARG BUILD_CONFIGURATION=Release 7 | WORKDIR /src 8 | COPY ["src/main/Benchmark.Serializers.Binary/Benchmark.Serializers.Binary.csproj", "src/main/Benchmark.Serializers.Binary/"] 9 | RUN dotnet restore "src/main/Benchmark.Serializers.Binary/Benchmark.Serializers.Binary.csproj" 10 | COPY . . 11 | WORKDIR "/src/src/main/Benchmark.Serializers.Binary" 12 | RUN dotnet build "Benchmark.Serializers.Binary.csproj" -c $BUILD_CONFIGURATION -o /app/build 13 | 14 | FROM build AS publish 15 | ARG BUILD_CONFIGURATION=Release 16 | RUN dotnet publish "Benchmark.Serializers.Binary.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false 17 | 18 | FROM base AS final 19 | WORKDIR /app 20 | COPY --from=publish /app/publish . 21 | ENTRYPOINT ["dotnet", "Benchmark.Serializers.Binary.dll"] 22 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Binary/MsgPackLightConverters/SimpleModelConverter.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers.Models; 2 | using FastSerialization; 3 | using ProGaudi.MsgPack.Light; 4 | 5 | namespace Benchmarks.Serializers.Binary.MsgPackLightConverters; 6 | 7 | sealed internal class SimpleModelConverter : IMsgPackConverter 8 | { 9 | private IMsgPackConverter _stringConverter; 10 | private IMsgPackConverter _intConverter; 11 | private IMsgPackConverter _boolConverter; 12 | private MsgPackContext _context; 13 | 14 | public void Write(SimpleModel value, IMsgPackWriter writer) 15 | { 16 | if (value == null) 17 | { 18 | _context.NullConverter.Write(null, writer); 19 | return; 20 | } 21 | 22 | writer.WriteMapHeader(3); 23 | 24 | _stringConverter.Write(nameof(value.TestInt), writer); 25 | _intConverter.Write(value.TestInt, writer); 26 | 27 | _stringConverter.Write(nameof(value.TestString), writer); 28 | _stringConverter.Write(value.TestString, writer); 29 | 30 | _stringConverter.Write(nameof(value.TestBool), writer); 31 | _boolConverter.Write(value.TestBool, writer); 32 | } 33 | 34 | public SimpleModel Read(IMsgPackReader reader) 35 | { 36 | var length = reader.ReadMapLength(); 37 | if (length == null) 38 | { 39 | return null!; 40 | } 41 | 42 | if (length != 3) 43 | { 44 | throw new SerializationException("Bad format"); 45 | } 46 | 47 | var result = new SimpleModel(); 48 | for (var i = 0; i < length.Value; i++) 49 | { 50 | var propertyName = _stringConverter.Read(reader); 51 | 52 | switch (propertyName) 53 | { 54 | case nameof(result.TestInt): 55 | result.TestInt = _intConverter.Read(reader); 56 | break; 57 | case nameof(result.TestString): 58 | result.TestString = _stringConverter.Read(reader); 59 | break; 60 | case nameof(result.TestBool): 61 | result.TestBool = _boolConverter.Read(reader); 62 | break; 63 | default: 64 | throw new SerializationException("Bad format"); 65 | } 66 | } 67 | 68 | return result; 69 | } 70 | 71 | public void Initialize(MsgPackContext context) 72 | { 73 | _stringConverter = context.GetConverter(); 74 | _intConverter = context.GetConverter(); 75 | _boolConverter = context.GetConverter(); 76 | _context = context; 77 | } 78 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Binary/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | 3 | BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(); -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Binary/SerializationBenchmark.FlatBuffer.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers.Models; 2 | using Google.FlatBuffers; 3 | 4 | namespace Benchmarks.Serializers.Binary; 5 | 6 | public static partial class Serializers 7 | { 8 | /// 9 | /// Serializes with . 10 | /// 11 | /// 12 | /// 13 | /// 14 | public static SimpleFlatBufferModels FlatBufferDeserializeBytes(byte[] bytes) 15 | { 16 | var buf = new ByteBuffer(bytes); 17 | 18 | return SimpleFlatBufferModels.GetRootAsSimpleFlatBufferModels(buf); 19 | } 20 | 21 | /// 22 | /// Serializes with . 23 | /// 24 | /// 25 | /// 26 | /// 27 | public static byte[] FlatBufferSerializeBytes(Span simpleModels) 28 | { 29 | var builder = new FlatBufferBuilder(1024); 30 | SimpleFlatBufferModels.StartModelsVector(builder, simpleModels.Length); 31 | 32 | for (var i = 0; i < simpleModels.Length; i++) 33 | { 34 | SimpleFlatBufferModel.CreateSimpleFlatBufferModel( 35 | builder, 36 | simpleModels[i].TestInt, 37 | builder.CreateString(simpleModels[i].TestString), 38 | simpleModels[i].TestBool); 39 | } 40 | 41 | var models = builder.EndVector(); 42 | 43 | SimpleFlatBufferModels.StartSimpleFlatBufferModels(builder); 44 | SimpleFlatBufferModels.AddModels(builder, models); 45 | 46 | var simpleFlatBufferModel = SimpleFlatBufferModels.EndSimpleFlatBufferModels(builder); 47 | 48 | builder.Finish(simpleFlatBufferModel.Value); 49 | 50 | return builder.SizedByteArray(); 51 | } 52 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Binary/SerializationBenchmark.MemoryPack.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.Serializers.Binary; 2 | 3 | public static partial class Serializers 4 | { 5 | /// 6 | /// Serializes with . 7 | /// 8 | /// 9 | /// 10 | /// 11 | public static ICollection MemoryPackDeserializeBytes(byte[] bytes) 12 | { 13 | return MemoryPack.MemoryPackSerializer.Deserialize>(bytes)!; 14 | } 15 | /// 16 | /// Serializes with . 17 | /// 18 | /// 19 | /// 20 | /// 21 | public static byte[] MemoryPackSerializeBytes(T[] simpleModels) 22 | { 23 | return MemoryPack.MemoryPackSerializer.Serialize(simpleModels); 24 | } 25 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Binary/SerializationBenchmark.MessagePack.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.Serializers.Binary; 2 | 3 | public static partial class Serializers 4 | { 5 | /// 6 | /// Serializes with . 7 | /// 8 | /// 9 | /// 10 | /// 11 | public static ICollection MessagePackDeserializeBytes(byte[] bytes) 12 | { 13 | return MessagePack.MessagePackSerializer.Deserialize>(bytes); 14 | } 15 | /// 16 | /// Serializes with . 17 | /// 18 | /// 19 | /// 20 | /// 21 | public static byte[] MessagePackSerializeBytes(T[] simpleModels) 22 | { 23 | return MessagePack.MessagePackSerializer.Serialize(simpleModels); 24 | } 25 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Binary/SerializationBenchmark.Protobuf.cs: -------------------------------------------------------------------------------- 1 | using System.Buffers; 2 | 3 | namespace Benchmarks.Serializers.Binary; 4 | 5 | public static partial class Serializers 6 | { 7 | /// 8 | /// Serializes with . 9 | /// 10 | /// 11 | /// 12 | /// 13 | public static ICollection ProtobufDeserializeBytes(ReadOnlySpan bytes) 14 | { 15 | return ProtoBuf.Serializer.Deserialize>(bytes); 16 | } 17 | /// 18 | /// Serializes with . 19 | /// 20 | /// 21 | /// 22 | /// 23 | public static byte[] ProtobufSerializeBytes(T[] simpleModels) 24 | { 25 | var writer = new ArrayBufferWriter(); 26 | 27 | ProtoBuf.Serializer.Serialize(writer, simpleModels); 28 | 29 | return writer.WrittenSpan.ToArray(); 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Binary/SerializationBenchmark.ZeroFormatter.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.Serializers.Binary; 2 | 3 | public static partial class Serializers 4 | { 5 | /// 6 | /// Serializes with . 7 | /// 8 | /// 9 | /// 10 | /// 11 | public static ICollection ZeroFormatterDeserializeBytes(byte[] bytes) 12 | { 13 | return ZeroFormatter.ZeroFormatterSerializer.Deserialize>(bytes); 14 | } 15 | /// 16 | /// Serializes with . 17 | /// 18 | /// 19 | /// 20 | /// 21 | public static byte[] ZeroFormatterSerializeBytes(T[] simpleModels) 22 | { 23 | return ZeroFormatter.ZeroFormatterSerializer.Serialize(simpleModels); 24 | } 25 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Binary/Serializers.MsgPackLight.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers.Models; 2 | using ProGaudi.MsgPack.Light; 3 | 4 | namespace Benchmarks.Serializers.Binary; 5 | 6 | public static partial class Serializers 7 | { 8 | /// 9 | /// Serializes with . 10 | /// 11 | /// 12 | /// 13 | /// 14 | public static ICollection MsgPackLightDeserializeBytes(byte[] bytes) 15 | { 16 | return MsgPackSerializer.Deserialize>(bytes, MsgPackContext); 17 | } 18 | /// 19 | /// Serializes with . 20 | /// 21 | /// 22 | /// 23 | /// 24 | public static byte[] MsgPackLightSerializeBytes(SimpleModel[] simpleModels) 25 | { 26 | return MsgPackSerializer.Serialize(simpleModels, MsgPackContext); 27 | } 28 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Binary/Serializers.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers.Binary.MsgPackLightConverters; 2 | using ProGaudi.MsgPack.Light; 3 | 4 | namespace Benchmarks.Serializers.Binary; 5 | 6 | public static partial class Serializers 7 | { 8 | private readonly static MsgPackContext MsgPackContext = new(); 9 | 10 | static Serializers() 11 | { 12 | MsgPackContext.RegisterConverter(new SimpleModelsConverter()); 13 | MsgPackContext.RegisterConverter(new SimpleModelConverter()); 14 | } 15 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/DeserializationBenchmark.Jil.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using Benchmarks.Serializers.Models; 3 | using BenchmarkDotNet.Attributes; 4 | 5 | namespace Benchmarks.Serializers.Json.Benchmarks; 6 | 7 | public partial class DeserializationBenchmark 8 | { 9 | [BenchmarkCategory(Group.DeserializationString), Benchmark] 10 | public ICollection JilString() 11 | { 12 | return Serializers.JilDeserialize(_testString); 13 | } 14 | 15 | [BenchmarkCategory(Group.DeserializationByte), Benchmark] 16 | public ICollection JilBytes() 17 | { 18 | return Serializers.JilDeserializeBytes(_testBytes); 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/DeserializationBenchmark.JsonSrcGen.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using BenchmarkDotNet.Attributes; 3 | using Benchmarks.Serializers.Json.Models; 4 | 5 | namespace Benchmarks.Serializers.Json.Benchmarks; 6 | 7 | public partial class DeserializationBenchmark 8 | { 9 | [BenchmarkCategory(Group.DeserializationString), Benchmark] 10 | public SimpleSrcGenModel?[]? JsonSrcGenString() 11 | { 12 | return Serializers.JsonSrcGenDeserializeSimpleString(_testString); 13 | } 14 | 15 | [BenchmarkCategory(Group.DeserializationByte), Benchmark] 16 | public SimpleSrcGenModel?[]? JsonSrcGenByte() 17 | { 18 | return Serializers.JsonSrcGenDeserializeSimpleByte(_testBytes); 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/DeserializationBenchmark.NetJson.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using Benchmarks.Serializers.Models; 3 | using BenchmarkDotNet.Attributes; 4 | 5 | namespace Benchmarks.Serializers.Json.Benchmarks; 6 | 7 | public partial class DeserializationBenchmark 8 | { 9 | [BenchmarkCategory(Group.DeserializationString), Benchmark] 10 | public ICollection NetJsonString() 11 | { 12 | return Serializers.NetJsonString(_testString); 13 | } 14 | 15 | [BenchmarkCategory(Group.DeserializationByte), Benchmark] 16 | public ICollection NetJsonByte() 17 | { 18 | return Serializers.NetJsonByte(_testBytes); 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/DeserializationBenchmark.Newtonsoft.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using Benchmarks.Serializers.Models; 3 | using BenchmarkDotNet.Attributes; 4 | 5 | namespace Benchmarks.Serializers.Json.Benchmarks; 6 | 7 | public partial class DeserializationBenchmark 8 | { 9 | [BenchmarkCategory(Group.DeserializationString), Benchmark] 10 | public ICollection? NewtonsoftString() 11 | { 12 | return Serializers.NewtonsoftString(_testString); 13 | } 14 | 15 | [BenchmarkCategory(Group.DeserializationByte), Benchmark] 16 | public ICollection? NewtonsoftBytes() 17 | { 18 | return Serializers.NewtonsoftBytes(_testBytes); 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/DeserializationBenchmark.ServiceStack.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using Benchmarks.Serializers.Models; 3 | using BenchmarkDotNet.Attributes; 4 | 5 | namespace Benchmarks.Serializers.Json.Benchmarks; 6 | 7 | public partial class DeserializationBenchmark 8 | { 9 | [BenchmarkCategory(Group.DeserializationString), Benchmark] 10 | public ICollection ServiceStackString() 11 | { 12 | return Serializers.ServiceStackString(_testString); 13 | } 14 | 15 | [BenchmarkCategory(Group.DeserializationByte), Benchmark] 16 | public ICollection ServiceStackByte() 17 | { 18 | return Serializers.ServiceStackByte(_testBytes); 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/DeserializationBenchmark.SpanJson.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using Benchmarks.Serializers.Models; 3 | using BenchmarkDotNet.Attributes; 4 | 5 | namespace Benchmarks.Serializers.Json.Benchmarks; 6 | 7 | public partial class DeserializationBenchmark 8 | { 9 | [BenchmarkCategory(Group.DeserializationString), Benchmark] 10 | public ICollection SpanJsonString() 11 | { 12 | return Serializers.SpanJsonString(_testString); 13 | } 14 | 15 | [BenchmarkCategory(Group.DeserializationByte), Benchmark] 16 | public ICollection SpanJsonByte() 17 | { 18 | return Serializers.SpanJsonByte(_testBytes); 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/DeserializationBenchmark.SystemTextJson.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using Benchmarks.Serializers.Models; 3 | using BenchmarkDotNet.Attributes; 4 | 5 | namespace Benchmarks.Serializers.Json.Benchmarks; 6 | 7 | public partial class DeserializationBenchmark 8 | { 9 | [BenchmarkCategory(Group.DeserializationString), Benchmark] 10 | public ICollection? SystemTextJsonString() 11 | { 12 | return Serializers.SystemTextJsonString(_testString); 13 | } 14 | 15 | [BenchmarkCategory(Group.DeserializationByte), Benchmark] 16 | public ICollection? SystemTextJsonByte() 17 | { 18 | return Serializers.SystemTextJsonByte(_testBytes); 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/DeserializationBenchmark.SystemTextJsonSrcGen.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using Benchmarks.Serializers.Models; 3 | using BenchmarkDotNet.Attributes; 4 | 5 | namespace Benchmarks.Serializers.Json.Benchmarks; 6 | 7 | public partial class DeserializationBenchmark 8 | { 9 | [BenchmarkCategory(Group.DeserializationString), Benchmark] 10 | public ICollection? SystemTextJsonSourceGenString() 11 | { 12 | return Serializers.SystemTextJsonSourceGenSimpleString(_testString); 13 | } 14 | 15 | [BenchmarkCategory(Group.DeserializationByte), Benchmark] 16 | public ICollection? SystemTextJsonSourceGenByte() 17 | { 18 | return Serializers.SystemTextJsonSourceGenSimpleByte(_testBytes); 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/DeserializationBenchmark.Utf8Json.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using Benchmarks.Serializers.Models; 3 | using BenchmarkDotNet.Attributes; 4 | 5 | namespace Benchmarks.Serializers.Json.Benchmarks; 6 | 7 | public partial class DeserializationBenchmark 8 | { 9 | [BenchmarkCategory(Group.DeserializationString), Benchmark] 10 | public ICollection Utf8JsonString() 11 | { 12 | return Serializers.Utf8JsonString(_testString); 13 | } 14 | 15 | [BenchmarkCategory(Group.DeserializationByte), Benchmark] 16 | public ICollection Utf8JsonByte() 17 | { 18 | return Serializers.Utf8JsonByte(_testBytes); 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/DeserializationBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | using Benchmarks.Serializers.Models; 5 | using BenchmarkDotNet.Attributes; 6 | using BenchmarkDotNet.Configs; 7 | using BenchmarkDotNet.Order; 8 | using Bogus; 9 | 10 | namespace Benchmarks.Serializers.Json.Benchmarks; 11 | 12 | [MemoryDiagnoser, 13 | CategoriesColumn, 14 | AllStatisticsColumn, 15 | Orderer(SummaryOrderPolicy.FastestToSlowest), 16 | GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory), ExcludeFromCodeCoverage] 17 | public partial class DeserializationBenchmark 18 | { 19 | /// 20 | /// Static for . 21 | /// 22 | private readonly static Faker Faker = new(); 23 | 24 | private byte[] _testBytes = []; 25 | 26 | private string _testString = string.Empty; 27 | 28 | /// 29 | /// Size of generation. 30 | /// **NOTE:** Intentionally left public for BenchmarkDotNet Params. 31 | /// 32 | [Params(1, 100, 1000)] 33 | public int CollectionSize { get; set; } 34 | 35 | /// 36 | /// Setting private fields. 37 | /// 38 | [GlobalSetup] 39 | public void Setup() 40 | { 41 | var models = Faker 42 | .RuleFor(model => model.TestBool, faker => faker.Random.Bool()) 43 | .RuleFor(model => model.TestInt, faker => faker.Random.Int()) 44 | .RuleFor(model => model.TestString, faker => faker.Name.FullName()) 45 | .Generate(CollectionSize); 46 | 47 | var sb = new StringBuilder(); 48 | sb.Append('['); 49 | 50 | var span = CollectionsMarshal.AsSpan(models); 51 | 52 | for (var i = 0; i < span.Length - 1; i++) 53 | { 54 | sb.Append(span[i]); 55 | sb.Append(','); 56 | } 57 | 58 | sb.Append(span[^1]); 59 | sb.Append(']'); 60 | 61 | _testString = sb.ToString(); 62 | _testBytes = Encoding.UTF8.GetBytes(_testString); 63 | } 64 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/SerializationBenchmark.Jil.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using BenchmarkDotNet.Attributes; 3 | 4 | namespace Benchmarks.Serializers.Json.Benchmarks; 5 | 6 | public partial class SerializationBenchmark 7 | { 8 | [BenchmarkCategory(Group.SerializationString), Benchmark] 9 | public string JilString() 10 | { 11 | return Serializers.JilSerialize(_simpleModels); 12 | } 13 | 14 | [BenchmarkCategory(Group.SerializationByte), Benchmark] 15 | public byte[] JilBytes() 16 | { 17 | return Serializers.JilSerializeBytes(_simpleModels); 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/SerializationBenchmark.JsonSrcGen.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using BenchmarkDotNet.Attributes; 3 | 4 | namespace Benchmarks.Serializers.Json.Benchmarks; 5 | 6 | public partial class SerializationBenchmark 7 | { 8 | [BenchmarkCategory(Group.SerializationString), Benchmark] 9 | public string JsonSrcGenString() 10 | { 11 | return Serializers.JsonSrcGenSerializeSimpleString(_simpleSrcGenModels); 12 | } 13 | 14 | [BenchmarkCategory(Group.SerializationByte), Benchmark] 15 | public byte[] JsonSrcGenByte() 16 | { 17 | return Serializers.JsonSrcGenSerializeSimpleByte(_simpleSrcGenModels); 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/SerializationBenchmark.NetJson.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using BenchmarkDotNet.Attributes; 3 | 4 | namespace Benchmarks.Serializers.Json.Benchmarks; 5 | 6 | public partial class SerializationBenchmark 7 | { 8 | [BenchmarkCategory(Group.SerializationString), Benchmark] 9 | public string NetJsonString() 10 | { 11 | return Serializers.NetJsonString(_simpleModels); 12 | } 13 | 14 | [BenchmarkCategory(Group.SerializationByte), Benchmark] 15 | public byte[] NetJsonByte() 16 | { 17 | return Serializers.NetJsonByte(_simpleModels); 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/SerializationBenchmark.Newtonsoft.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using BenchmarkDotNet.Attributes; 3 | 4 | namespace Benchmarks.Serializers.Json.Benchmarks; 5 | 6 | public partial class SerializationBenchmark 7 | { 8 | [BenchmarkCategory(Group.SerializationString), Benchmark] 9 | public string NewtonsoftString() 10 | { 11 | return Serializers.NewtonsoftString(_simpleModels); 12 | } 13 | 14 | [BenchmarkCategory(Group.SerializationByte), Benchmark] 15 | public byte[] NewtonsoftBytes() 16 | { 17 | return Serializers.NewtonsoftBytes(_simpleModels); 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/SerializationBenchmark.ServiceStack.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using BenchmarkDotNet.Attributes; 3 | 4 | namespace Benchmarks.Serializers.Json.Benchmarks; 5 | 6 | public partial class SerializationBenchmark 7 | { 8 | [BenchmarkCategory(Group.SerializationString), Benchmark] 9 | public string ServiceStackString() 10 | { 11 | return Serializers.ServiceStackString(_simpleModels); 12 | } 13 | 14 | [BenchmarkCategory(Group.SerializationByte), Benchmark] 15 | public byte[] ServiceStackByte() 16 | { 17 | return Serializers.ServiceStackByte(_simpleModels); 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/SerializationBenchmark.SpanJson.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using BenchmarkDotNet.Attributes; 3 | 4 | namespace Benchmarks.Serializers.Json.Benchmarks; 5 | 6 | public partial class SerializationBenchmark 7 | { 8 | [BenchmarkCategory(Group.SerializationString), Benchmark] 9 | public string SpanJsonString() 10 | { 11 | return Serializers.SpanJsonString(_simpleModels); 12 | } 13 | 14 | [BenchmarkCategory(Group.SerializationByte), Benchmark] 15 | public byte[] SpanJsonByte() 16 | { 17 | return Serializers.SpanJsonByte(_simpleModels); 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/SerializationBenchmark.SystemTextJson.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using BenchmarkDotNet.Attributes; 3 | 4 | namespace Benchmarks.Serializers.Json.Benchmarks; 5 | 6 | public partial class SerializationBenchmark 7 | { 8 | [BenchmarkCategory(Group.SerializationString), Benchmark] 9 | public string SystemTextJsonString() 10 | { 11 | return Serializers.SystemTextJsonString(_simpleModels); 12 | } 13 | 14 | [BenchmarkCategory(Group.SerializationByte), Benchmark] 15 | public byte[] SystemTextJsonByte() 16 | { 17 | return Serializers.SystemTextJsonByte(_simpleModels); 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/SerializationBenchmark.SystemTextJsonSrcGen.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using BenchmarkDotNet.Attributes; 3 | 4 | namespace Benchmarks.Serializers.Json.Benchmarks; 5 | 6 | public partial class SerializationBenchmark 7 | { 8 | [BenchmarkCategory(Group.SerializationString), Benchmark] 9 | public string SystemTextJsonSourceGenString() 10 | { 11 | return Serializers.SystemTextJsonSourceGenString(_simpleModels); 12 | } 13 | 14 | [BenchmarkCategory(Group.SerializationByte), Benchmark] 15 | public byte[] SystemTextJsonSourceGenByte() 16 | { 17 | return Serializers.SystemTextJsonSourceGenByte(_simpleModels); 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/SerializationBenchmark.Utf8Json.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using BenchmarkDotNet.Attributes; 3 | 4 | namespace Benchmarks.Serializers.Json.Benchmarks; 5 | 6 | public partial class SerializationBenchmark 7 | { 8 | [BenchmarkCategory(Group.SerializationString), Benchmark] 9 | public string Utf8JsonString() 10 | { 11 | return Serializers.Utf8JsonString(_simpleModels); 12 | } 13 | 14 | [BenchmarkCategory(Group.SerializationByte), Benchmark] 15 | public byte[] Utf8JsonByte() 16 | { 17 | return Serializers.Utf8JsonByte(_simpleModels); 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Benchmarks/SerializationBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using Benchmarks.Serializers.Models; 3 | using BenchmarkDotNet.Attributes; 4 | using BenchmarkDotNet.Configs; 5 | using BenchmarkDotNet.Order; 6 | using Benchmarks.Serializers.Json.Models; 7 | using Bogus; 8 | 9 | namespace Benchmarks.Serializers.Json.Benchmarks; 10 | 11 | [MemoryDiagnoser, CategoriesColumn, AllStatisticsColumn, Orderer(SummaryOrderPolicy.FastestToSlowest), 12 | GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory), ExcludeFromCodeCoverage] 13 | public partial class SerializationBenchmark 14 | { 15 | /// 16 | /// Static for . 17 | /// 18 | private readonly static Faker Faker = new(); 19 | 20 | /// 21 | /// Static for . 22 | /// 23 | private readonly static Faker FakerSrcGen = new(); 24 | 25 | /// 26 | /// Collection of testing . 27 | /// 28 | private SimpleModel[] _simpleModels = []; 29 | 30 | /// 31 | /// Collection of testing . 32 | /// 33 | private SimpleSrcGenModel[] _simpleSrcGenModels = []; 34 | 35 | /// 36 | /// Size of generation. 37 | /// **NOTE:** Intentionally left public for BenchmarkDotNet Params. 38 | /// 39 | [Params(1, 100, 1000)] 40 | public int CollectionSize { get; set; } 41 | 42 | /// 43 | /// Setting private fields. 44 | /// 45 | [GlobalSetup] 46 | public void Setup() 47 | { 48 | _simpleModels = Faker 49 | .RuleFor(model => model.TestBool, faker => faker.Random.Bool()) 50 | .RuleFor(model => model.TestInt, faker => faker.Random.Int()) 51 | .RuleFor(model => model.TestString, faker => faker.Name.FullName()) 52 | .Generate(CollectionSize) 53 | .ToArray(); 54 | 55 | _simpleSrcGenModels = FakerSrcGen 56 | .RuleFor(model => model.TestBool, faker => faker.Random.Bool()) 57 | .RuleFor(model => model.TestInt, faker => faker.Random.Int()) 58 | .RuleFor(model => model.TestString, faker => faker.Name.FullName()) 59 | .Generate(CollectionSize) 60 | .ToArray(); 61 | } 62 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base 2 | USER $APP_UID 3 | WORKDIR /app 4 | 5 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build 6 | ARG BUILD_CONFIGURATION=Release 7 | WORKDIR /src 8 | COPY ["src/main/Benchmarks.Json/Benchmarks.Json.csproj", "src/main/Benchmarks.Json/"] 9 | RUN dotnet restore "src/main/Benchmarks.Json/Benchmarks.Json.csproj" 10 | COPY . . 11 | WORKDIR "/src/src/main/Benchmarks.Json" 12 | RUN dotnet build "Benchmarks.Json.csproj" -c $BUILD_CONFIGURATION -o /app/build 13 | 14 | FROM build AS publish 15 | ARG BUILD_CONFIGURATION=Release 16 | RUN dotnet publish "Benchmarks.Json.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false 17 | 18 | FROM base AS final 19 | WORKDIR /app 20 | COPY --from=publish /app/publish . 21 | ENTRYPOINT ["dotnet", "Benchmarks.Json.dll"] 22 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Extensions/JsonServiceExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Jil; 3 | using MessagePack; 4 | using NetJSON; 5 | using Newtonsoft.Json; 6 | using Newtonsoft.Json.Serialization; 7 | using ServiceStack.Text; 8 | 9 | namespace Benchmarks.Serializers.Json.Extensions; 10 | 11 | /// 12 | /// Extensions for Json services. 13 | /// 14 | public static class JsonServiceExtensions 15 | { 16 | /// 17 | /// Default Options for System.Text.Json. 18 | /// 19 | public readonly static JsonSerializerOptions Options = new() 20 | { 21 | PropertyNamingPolicy = JsonNamingPolicy.CamelCase 22 | }; 23 | 24 | public readonly static NetJSONSettings NetJsonOptions = new() 25 | { 26 | DateFormat = NetJSONDateFormat.ISO, 27 | TimeZoneFormat = NetJSONTimeZoneFormat.Utc, 28 | UseStringOptimization = true, 29 | CamelCase = true 30 | }; 31 | 32 | public readonly static JsonSerializerSettings NewtonsoftOptions = new() 33 | { 34 | ContractResolver = new CamelCasePropertyNamesContractResolver(), 35 | DateFormatHandling = DateFormatHandling.IsoDateFormat 36 | }; 37 | 38 | public readonly static Config ServiceStackOptions = new() 39 | { 40 | DateHandler = DateHandler.ISO8601, 41 | AlwaysUseUtc = true, 42 | TextCase = TextCase.CamelCase 43 | }; 44 | 45 | public readonly static Options JilOptions = 46 | new(dateFormat: DateTimeFormat.ISO8601, 47 | serializationNameFormat: SerializationNameFormat.CamelCase); 48 | 49 | public readonly static MessagePackSerializerOptions MsgPackOptions 50 | = MessagePackSerializerOptions.Standard.WithCompression(MessagePackCompression.Lz4BlockArray); 51 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Models/SimpleSrcGenModel.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers; 2 | using JsonSrcGen; 3 | 4 | namespace Benchmarks.Serializers.Json.Models; 5 | 6 | /// 7 | /// Simple deserialization model. Used for tests. 8 | /// 9 | [Json] 10 | public class SimpleSrcGenModel 11 | { 12 | /// 13 | /// Gets or sets test string value. 14 | /// 15 | [JsonName(Fields.TestIntField)] 16 | public virtual int TestInt { get; set; } 17 | 18 | /// 19 | /// Gets or sets test string value. 20 | /// 21 | [JsonName(Fields.TestStringField)] 22 | public virtual string TestString { get; set; } = string.Empty; 23 | 24 | /// 25 | /// Gets or sets test string value. 26 | /// 27 | [JsonName(Fields.TestBoolField)] 28 | public virtual bool TestBool { get; set; } 29 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | using Benchmarks.Serializers.Json.Models; 3 | using JsonSrcGen; 4 | 5 | [assembly: JsonArray(typeof(ComplexSrcGenModel))] 6 | [assembly: JsonArray(typeof(SimpleSrcGenModel))] 7 | 8 | BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(); -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Serializers.Jil.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Benchmarks.Serializers.Json.Extensions; 3 | using Jil; 4 | 5 | namespace Benchmarks.Serializers.Json; 6 | 7 | public static partial class Serializers 8 | { 9 | /// 10 | /// Serializes with . 11 | /// 12 | /// 13 | /// 14 | /// 15 | public static ICollection JilDeserialize(string input) 16 | { 17 | return JSON.Deserialize>(input, JsonServiceExtensions.JilOptions); 18 | } 19 | 20 | /// 21 | /// Serializes with . 22 | /// 23 | /// 24 | /// 25 | /// 26 | public static ICollection JilDeserializeBytes(byte[] bytes) 27 | { 28 | return JSON.Deserialize>(Encoding.UTF8.GetString(bytes), JsonServiceExtensions.JilOptions); 29 | } 30 | 31 | /// 32 | /// Serializes with . 33 | /// 34 | /// 35 | /// 36 | /// 37 | /// 38 | public static string JilSerialize(T simpleModels) 39 | { 40 | return JSON.Serialize(simpleModels, JsonServiceExtensions.JilOptions); 41 | } 42 | 43 | /// 44 | /// Serializes with . 45 | /// 46 | /// 47 | /// 48 | /// 49 | public static byte[] JilSerializeBytes(T simpleModels) 50 | { 51 | using var writer = new StringWriter(); 52 | 53 | JSON.Serialize(simpleModels, writer, JsonServiceExtensions.JilOptions); 54 | 55 | return Encoding.UTF8.GetBytes(writer.ToString()); 56 | } 57 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Serializers.JsonSrcGen.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers.Json.Models; 2 | using JsonSrcGen; 3 | 4 | namespace Benchmarks.Serializers.Json; 5 | 6 | public partial class Serializers 7 | { 8 | private readonly static JsonConverter JsonConverter = new(); 9 | 10 | /// 11 | /// Serializes with to string. 12 | /// 13 | /// 14 | /// 15 | /// 16 | public static SimpleSrcGenModel?[]? JsonSrcGenDeserializeSimpleString(string testString) 17 | { 18 | return JsonConverter.FromJson(new List().ToArray(), testString); 19 | } 20 | 21 | /// 22 | /// Serializes with . 23 | /// 24 | /// 25 | /// 26 | /// 27 | public static SimpleSrcGenModel?[]? JsonSrcGenDeserializeSimpleByte(byte[] testBytes) 28 | { 29 | return JsonConverter.FromJson(new List().ToArray(), testBytes); 30 | } 31 | 32 | /// 33 | /// Serializes with to string. 34 | /// 35 | /// 36 | /// 37 | /// 38 | /// 39 | public static string JsonSrcGenSerializeSimpleString(SimpleSrcGenModel[] simpleSrcGenModels) 40 | { 41 | return JsonConverter.ToJson(simpleSrcGenModels).ToString(); 42 | } 43 | 44 | /// 45 | /// Serializes with . 46 | /// 47 | /// 48 | /// 49 | /// 50 | public static byte[] JsonSrcGenSerializeSimpleByte(SimpleSrcGenModel[] simpleSrcGenModels) 51 | { 52 | return JsonConverter.ToJsonUtf8(simpleSrcGenModels).ToArray(); 53 | } 54 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Serializers.NetJson.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Benchmarks.Serializers.Json.Extensions; 3 | 4 | namespace Benchmarks.Serializers.Json; 5 | 6 | public partial class Serializers 7 | { 8 | /// 9 | /// Serializes with to string. 10 | /// 11 | /// 12 | /// 13 | /// 14 | public static ICollection NetJsonString(string testString) 15 | { 16 | return NetJSON.NetJSON.Deserialize>(testString, JsonServiceExtensions.NetJsonOptions); 17 | } 18 | 19 | /// 20 | /// Serializes with to string. 21 | /// 22 | /// 23 | /// 24 | /// 25 | public static ICollection NetJsonByte(byte[] testBytes) 26 | { 27 | return NetJSON.NetJSON.Deserialize>(Encoding.UTF8.GetString(testBytes), JsonServiceExtensions.NetJsonOptions); 28 | } 29 | 30 | /// 31 | /// Serializes with to string. 32 | /// 33 | /// 34 | /// 35 | /// 36 | public static string NetJsonString(T[] array) 37 | { 38 | return NetJSON.NetJSON.Serialize(array, JsonServiceExtensions.NetJsonOptions); 39 | } 40 | 41 | /// 42 | /// Serializes with to string. 43 | /// 44 | /// 45 | /// 46 | /// 47 | public static byte[] NetJsonByte(T[] array) 48 | { 49 | using var writer = new StringWriter(); 50 | 51 | NetJSON.NetJSON.Serialize(array, writer, JsonServiceExtensions.NetJsonOptions); 52 | 53 | return Encoding.UTF8.GetBytes(writer.ToString()); 54 | } 55 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Serializers.Newtonsoft.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Benchmarks.Serializers.Json.Extensions; 3 | using Newtonsoft.Json; 4 | 5 | namespace Benchmarks.Serializers.Json; 6 | 7 | public partial class Serializers 8 | { 9 | /// 10 | /// Serializes with Newtonsoft.Json. 11 | /// 12 | /// 13 | /// 14 | /// 15 | /// 16 | public static ICollection? NewtonsoftString(string testString) 17 | { 18 | return JsonConvert.DeserializeObject>(testString, JsonServiceExtensions.NewtonsoftOptions); 19 | } 20 | 21 | /// 22 | /// Serializes with Newtonsoft.Json. 23 | /// 24 | /// 25 | /// 26 | /// 27 | /// 28 | public static ICollection? NewtonsoftBytes(byte[] testBytes) 29 | { 30 | return JsonConvert.DeserializeObject>(Encoding.UTF8.GetString(testBytes), JsonServiceExtensions.NewtonsoftOptions); 31 | } 32 | 33 | public static string NewtonsoftString(T[] simpleModels) 34 | { 35 | return JsonConvert.SerializeObject(simpleModels, JsonServiceExtensions.NewtonsoftOptions); 36 | } 37 | 38 | public static byte[] NewtonsoftBytes(T[] simpleModels) 39 | { 40 | return Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(simpleModels, JsonServiceExtensions.NewtonsoftOptions)); 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Serializers.ServiceStack.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Benchmarks.Serializers.Json.Extensions; 3 | using ServiceStack.Text; 4 | 5 | namespace Benchmarks.Serializers.Json; 6 | 7 | public partial class Serializers 8 | { 9 | /// 10 | /// Serializes with to string. 11 | /// 12 | /// 13 | /// 14 | /// 15 | /// 16 | public static ICollection ServiceStackString(string testString) 17 | { 18 | using (JsConfig.With(JsonServiceExtensions.ServiceStackOptions)) 19 | { 20 | return JsonSerializer.DeserializeFromString>(testString); 21 | } 22 | } 23 | 24 | /// 25 | /// Serializes with to string. 26 | /// 27 | /// 28 | /// 29 | /// 30 | /// 31 | public static ICollection ServiceStackByte(byte[] testBytes) 32 | { 33 | using (JsConfig.With(JsonServiceExtensions.ServiceStackOptions)) 34 | { 35 | return JsonSerializer.DeserializeFromSpan>(Encoding.UTF8.GetString(testBytes)); 36 | } 37 | } 38 | 39 | public static string ServiceStackString(T[] simpleModels) 40 | { 41 | using (JsConfig.With(JsonServiceExtensions.ServiceStackOptions)) 42 | { 43 | return JsonSerializer.SerializeToString(simpleModels); 44 | } 45 | } 46 | 47 | public static byte[] ServiceStackByte(T[] simpleModels) 48 | { 49 | using var writer = new StringWriter(); 50 | 51 | using (JsConfig.With(JsonServiceExtensions.ServiceStackOptions)) 52 | { 53 | JsonSerializer.SerializeToWriter(simpleModels, writer); 54 | } 55 | 56 | return Encoding.UTF8.GetBytes(writer.ToString()); 57 | } 58 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Serializers.SpanJson.cs: -------------------------------------------------------------------------------- 1 | using SpanJson; 2 | 3 | namespace Benchmarks.Serializers.Json; 4 | 5 | public partial class Serializers 6 | { 7 | /// 8 | /// Serializes with to string. 9 | /// 10 | /// 11 | /// 12 | /// 13 | /// 14 | public static ICollection SpanJsonString(string testString) 15 | { 16 | return JsonSerializer.Generic.Utf16.Deserialize>(testString)!; 17 | } 18 | 19 | /// 20 | /// Serializes with to string. 21 | /// 22 | /// 23 | /// 24 | /// 25 | /// 26 | public static ICollection SpanJsonByte(byte[] testBytes) 27 | { 28 | return JsonSerializer.Generic.Utf8.Deserialize>(testBytes)!; 29 | } 30 | 31 | public static string SpanJsonString(T[] simpleModels) 32 | { 33 | return JsonSerializer.Generic.Utf16.Serialize(simpleModels)!; 34 | } 35 | 36 | public static byte[] SpanJsonByte(T[] simpleModels) 37 | { 38 | return JsonSerializer.Generic.Utf8.Serialize(simpleModels)!; 39 | } 40 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Serializers.SystemTextJson.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Benchmarks.Serializers.Json.Extensions; 3 | 4 | namespace Benchmarks.Serializers.Json; 5 | 6 | public partial class Serializers 7 | { 8 | /// 9 | /// Serializes with . 10 | /// 11 | /// 12 | /// . 13 | public static ICollection? SystemTextJsonString(string testString) 14 | { 15 | return JsonSerializer.Deserialize>(testString, JsonServiceExtensions.Options); 16 | } 17 | 18 | /// 19 | /// Serializes with . 20 | /// 21 | /// 22 | /// . 23 | public static ICollection? SystemTextJsonByte(byte[] testBytes) 24 | { 25 | return JsonSerializer.Deserialize>(testBytes, JsonServiceExtensions.Options); 26 | } 27 | 28 | public static string SystemTextJsonString(T[] simpleModels) 29 | { 30 | return JsonSerializer.Serialize(simpleModels, JsonServiceExtensions.Options); 31 | } 32 | 33 | public static byte[] SystemTextJsonByte(T[] simpleModels) 34 | { 35 | return JsonSerializer.SerializeToUtf8Bytes(simpleModels, JsonServiceExtensions.Options); 36 | } 37 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Serializers.SystemTextJsonSrcGen.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Benchmarks.Serializers.Models; 3 | using ModelsJsonContext = Benchmarks.Serializers.ModelsJsonContext; 4 | 5 | namespace Benchmarks.Serializers.Json; 6 | 7 | public partial class Serializers 8 | { 9 | /// 10 | /// Serializes with source gen. 11 | /// 12 | /// 13 | /// . 14 | public static ICollection? SystemTextJsonSourceGenSimpleString(string testString) 15 | { 16 | return JsonSerializer.Deserialize(testString, ModelsJsonContext.Default.ICollectionSimpleModel); 17 | } 18 | 19 | /// 20 | /// Serializes with source gen. 21 | /// 22 | /// 23 | /// . 24 | public static ICollection? SystemTextJsonSourceGenSimpleByte(byte[] testBytes) 25 | { 26 | return JsonSerializer.Deserialize(testBytes, ModelsJsonContext.Default.ICollectionSimpleModel); 27 | } 28 | 29 | /// 30 | /// Serializes with source gen. 31 | /// 32 | /// 33 | /// . 34 | public static string SystemTextJsonSourceGenString(T[] models) 35 | { 36 | return JsonSerializer.Serialize(models, ModelsJsonContext.Default.ICollectionSimpleModel); 37 | } 38 | 39 | /// 40 | /// Serializes with source gen. 41 | /// 42 | /// 43 | /// . 44 | public static byte[] SystemTextJsonSourceGenByte(T[] models) 45 | { 46 | return JsonSerializer.SerializeToUtf8Bytes(models, ModelsJsonContext.Default.ICollectionSimpleModel); 47 | } 48 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Serializers.Utf8Json.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Utf8Json; 3 | 4 | namespace Benchmarks.Serializers.Json; 5 | 6 | public partial class Serializers 7 | { 8 | /// 9 | /// Serializes with . 10 | /// 11 | /// 12 | /// 13 | /// 14 | /// 15 | public static ICollection Utf8JsonString(string testString) 16 | { 17 | return JsonSerializer.Deserialize>(testString); 18 | } 19 | 20 | /// 21 | /// Serializes with Utf8Json. 22 | /// 23 | /// 24 | /// 25 | /// 26 | public static ICollection Utf8JsonByte(byte[] testBytes) 27 | { 28 | return JsonSerializer.Deserialize>(testBytes); 29 | } 30 | 31 | /// 32 | /// Serializes with . 33 | /// 34 | /// 35 | /// 36 | /// 37 | /// 38 | public static string Utf8JsonString(T[] models) 39 | { 40 | return Encoding.UTF8.GetString(JsonSerializer.Serialize(models)); 41 | } 42 | 43 | /// 44 | /// Serializes with Utf8Json. 45 | /// 46 | /// 47 | /// 48 | /// 49 | public static byte[] Utf8JsonByte(T[] models) 50 | { 51 | return JsonSerializer.Serialize(models)!; 52 | } 53 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.Json/Serializers.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.Serializers.Json; 2 | 3 | public static partial class Serializers; -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Benchmarks.Serializers.OutputFormatters.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8 5 | enable 6 | enable 7 | true 8 | Linux 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | .dockerignore 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Benchmarks.Serializers.OutputFormatters.http: -------------------------------------------------------------------------------- 1 | @Benchmarks.Serializers.OutputFormatters_HostAddress = http://localhost:5022 2 | 3 | GET {{Benchmarks.Serializers.OutputFormatters_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Controllers/JsonController.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers.Models; 2 | using Benchmarks.Serializers.OutputFormatters.Extensions; 3 | using Microsoft.AspNetCore.Mvc; 4 | 5 | namespace Benchmarks.Serializers.OutputFormatters.Controllers; 6 | 7 | [ApiController] 8 | public sealed class JsonController : ControllerBase 9 | { 10 | [HttpGet("serialize/simple/100")] 11 | public ICollection JsonSimple() 12 | { 13 | return SimpleModelGenerator.SimpleModels; 14 | } 15 | 16 | [HttpPost("deserialize/simple/100")] 17 | public ActionResult JsonSimple([FromBody] IEnumerable entry) => Ok(); 18 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base 2 | USER $APP_UID 3 | WORKDIR /app 4 | EXPOSE 8080 5 | EXPOSE 8081 6 | 7 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build 8 | ARG BUILD_CONFIGURATION=Release 9 | WORKDIR /src 10 | COPY ["src/main/Benchmarks.Serializers.OutputFormatters/Benchmarks.Serializers.OutputFormatters.csproj", "src/main/Benchmarks.Serializers.OutputFormatters/"] 11 | RUN dotnet restore "src/main/Benchmarks.Serializers.OutputFormatters/Benchmarks.Serializers.OutputFormatters.csproj" 12 | COPY . . 13 | WORKDIR "/src/src/main/Benchmarks.Serializers.OutputFormatters" 14 | RUN dotnet build "Benchmarks.Serializers.OutputFormatters.csproj" -c $BUILD_CONFIGURATION -o /app/build 15 | 16 | FROM build AS publish 17 | ARG BUILD_CONFIGURATION=Release 18 | RUN dotnet publish "Benchmarks.Serializers.OutputFormatters.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false 19 | 20 | FROM base AS final 21 | WORKDIR /app 22 | COPY --from=publish /app/publish . 23 | ENTRYPOINT ["dotnet", "Benchmarks.Serializers.OutputFormatters.dll"] 24 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Extensions/SimpleModelGenerator.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers.Models; 2 | using Bogus; 3 | 4 | namespace Benchmarks.Serializers.OutputFormatters.Extensions; 5 | 6 | public static class SimpleModelGenerator 7 | { 8 | public readonly static ICollection SimpleModels = new Faker() 9 | .RuleFor(model => model.TestBool, y=> y.Random.Bool()) 10 | .RuleFor(model => model.TestInt, y=> y.Random.Int()) 11 | .RuleFor(model => model.TestString, y=> y.Name.FullName()) 12 | .Generate(100); 13 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Formatters/Jil/JilInputFormatter.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Jil; 3 | using Microsoft.AspNetCore.Mvc.Formatters; 4 | 5 | namespace Benchmarks.Serializers.OutputFormatters.Formatters.Jil; 6 | 7 | public sealed class JilInputFormatter : InputFormatter 8 | { 9 | private readonly Options _jilOptions; 10 | 11 | public JilInputFormatter(Options jilOptions) 12 | { 13 | _jilOptions = jilOptions; 14 | SupportedMediaTypes.Add("application/json"); 15 | SupportedMediaTypes.Add("text/json"); 16 | SupportedMediaTypes.Add("application/*+json"); 17 | } 18 | 19 | public override async Task ReadRequestBodyAsync(InputFormatterContext context) 20 | { 21 | var request = context.HttpContext.Request; 22 | var result = await JSON.DeserializeDynamicAsync(request.BodyReader, Encoding.UTF8, _jilOptions); 23 | 24 | return await InputFormatterResult.SuccessAsync(result); 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Formatters/Jil/JilOutputFormatter.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Jil; 3 | using Microsoft.AspNetCore.Mvc.Formatters; 4 | 5 | namespace Benchmarks.Serializers.OutputFormatters.Formatters.Jil; 6 | 7 | public sealed class JilOutputFormatter : OutputFormatter 8 | { 9 | private readonly Options _jilOptions; 10 | 11 | public JilOutputFormatter(Options jilOptions) 12 | { 13 | _jilOptions = jilOptions; 14 | SupportedMediaTypes.Add("application/json"); 15 | SupportedMediaTypes.Add("text/json"); 16 | SupportedMediaTypes.Add("application/*+json"); 17 | } 18 | 19 | public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context) 20 | { 21 | if (context.Object is null) 22 | { 23 | var writer = context.HttpContext.Response.BodyWriter; 24 | if (writer is null) 25 | { 26 | context.HttpContext.Response.Body.WriteByte((byte)'{'); 27 | context.HttpContext.Response.Body.WriteByte((byte)'}'); 28 | 29 | return Task.CompletedTask; 30 | } 31 | 32 | var span = writer.GetSpan(2); 33 | span[0] = (byte)'{'; 34 | span[1] = (byte)'}'; 35 | 36 | writer.Advance(2); 37 | 38 | return writer.FlushAsync().AsTask(); 39 | } 40 | else 41 | { 42 | var writer = context.HttpContext.Response.BodyWriter; 43 | 44 | return JSON.SerializeAsync(context.Object, writer: writer, Encoding.UTF8, _jilOptions).AsTask(); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Formatters/Jil/MvcOptionsExtensions.cs: -------------------------------------------------------------------------------- 1 | using Jil; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace Benchmarks.Serializers.OutputFormatters.Formatters.Jil; 5 | 6 | public static class MvcOptionsExtension 7 | { 8 | private readonly static Options JilOptions = new(dateFormat: DateTimeFormat.ISO8601, serializationNameFormat: SerializationNameFormat.CamelCase); 9 | 10 | public static IMvcBuilder AddJilFormatter(this IMvcBuilder mvcBuilder) 11 | { 12 | // // Workaround of Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead. 13 | // mvcBuilder.Services.Configure(options => 14 | // { 15 | // options.AllowSynchronousIO = true; 16 | // }); 17 | 18 | Configure(mvcBuilder.Services); 19 | 20 | return mvcBuilder; 21 | } 22 | 23 | private static void Configure(IServiceCollection serviceCollection) => serviceCollection.Configure((Action) (options => 24 | { 25 | options.OutputFormatters.Clear(); 26 | options.InputFormatters.Clear(); 27 | 28 | options.InputFormatters.Add(new JilInputFormatter(JilOptions)); 29 | options.OutputFormatters.Add(new JilOutputFormatter(JilOptions)); 30 | })); 31 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Formatters/MemoryPack/MvcOptionsExtensions.cs: -------------------------------------------------------------------------------- 1 | using MemoryPack.AspNetCoreMvcFormatter; 2 | using MessagePack; 3 | using Microsoft.AspNetCore.Mvc; 4 | 5 | namespace Benchmarks.Serializers.OutputFormatters.Formatters.MemoryPack; 6 | 7 | public static class MvcOptionsExtension 8 | { 9 | private readonly static MessagePackSerializerOptions MsgPackOptions 10 | = MessagePackSerializerOptions.Standard; 11 | 12 | public static IMvcBuilder AddMemoryPackFormatter(this IMvcBuilder mvcBuilder) 13 | { 14 | Configure(mvcBuilder.Services); 15 | 16 | return mvcBuilder; 17 | } 18 | 19 | private static void Configure(IServiceCollection serviceCollection) => serviceCollection.Configure((Action) (config => 20 | { 21 | config.OutputFormatters.Clear(); 22 | config.InputFormatters.Clear(); 23 | config.OutputFormatters.Add(new MemoryPackOutputFormatter()); 24 | config.InputFormatters.Add(new MemoryPackInputFormatter()); 25 | })); 26 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Formatters/MessagePack/MvcOptionsExtensions.cs: -------------------------------------------------------------------------------- 1 | using MessagePack; 2 | using MessagePack.AspNetCoreMvcFormatter; 3 | using Microsoft.AspNetCore.Mvc; 4 | 5 | namespace Benchmarks.Serializers.OutputFormatters.Formatters.MessagePack; 6 | 7 | public static class MvcOptionsExtension 8 | { 9 | private readonly static MessagePackSerializerOptions MsgPackOptions 10 | = MessagePackSerializerOptions.Standard; 11 | 12 | public static IMvcBuilder AddMsgPackFormatter(this IMvcBuilder mvcBuilder) 13 | { 14 | Configure(mvcBuilder.Services); 15 | 16 | return mvcBuilder; 17 | } 18 | 19 | private static void Configure(IServiceCollection serviceCollection) => serviceCollection.Configure((Action) (config => 20 | { 21 | config.OutputFormatters.Clear(); 22 | config.InputFormatters.Clear(); 23 | config.OutputFormatters.Add(new MessagePackOutputFormatter(MsgPackOptions)); 24 | config.InputFormatters.Add(new MessagePackInputFormatter(MsgPackOptions)); 25 | })); 26 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Formatters/Newtonsoft/MvcOptionsExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace Benchmarks.Serializers.OutputFormatters.Formatters.Newtonsoft; 4 | 5 | public static class MvcOptionsExtension 6 | { 7 | public static IMvcBuilder AddNewtonsoftFormatter(this IMvcBuilder builder) 8 | { 9 | builder.Services.Configure((Action) (config => 10 | { 11 | config.OutputFormatters.Clear(); 12 | config.InputFormatters.Clear(); 13 | })); 14 | 15 | return builder.AddNewtonsoftJson(); 16 | } 17 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Formatters/Protobuf/MvcOptionsExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace Benchmarks.Serializers.OutputFormatters.Formatters.Protobuf; 4 | 5 | public static class MvcOptionsExtension 6 | { 7 | public static IMvcBuilder AddProtobufFormatter(this IMvcBuilder builder) 8 | { 9 | builder.Services.Configure((Action) (config => 10 | { 11 | config.OutputFormatters.Clear(); 12 | config.InputFormatters.Clear(); 13 | })); 14 | 15 | return builder.AddProtoBufNet(); 16 | } 17 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Formatters/SpanJson/MvcOptionsExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using SpanJson; 3 | using SpanJson.AspNetCore.Formatter; 4 | 5 | namespace Benchmarks.Serializers.OutputFormatters.Formatters.SpanJson; 6 | 7 | public static class MvcOptionsExtension 8 | { 9 | public static IMvcBuilder AddSpanJsonFormatter(this IMvcBuilder mvcBuilder) 10 | { 11 | return mvcBuilder.AddSpanJsonCustom>(); 12 | } 13 | 14 | public static IMvcBuilder AddSpanJsonFormatterV2(this IMvcBuilder mvcBuilder) 15 | { 16 | Configure>(mvcBuilder.Services); 17 | 18 | return mvcBuilder; 19 | } 20 | 21 | private static void Configure(IServiceCollection serviceCollection) where TResolver : IJsonFormatterResolver, new() 22 | => serviceCollection.Configure((Action) (config => 23 | { 24 | config.OutputFormatters.Clear(); 25 | config.InputFormatters.Clear(); 26 | config.InputFormatters.Add(new SpanJsonInputFormatter()); 27 | config.OutputFormatters.Add(new SpanJsonOutputFormatter()); 28 | })); 29 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Formatters/SpanJson/SpanJsonFormatter.cs: -------------------------------------------------------------------------------- 1 | using SpanJson.Resolvers; 2 | 3 | namespace Benchmarks.Serializers.OutputFormatters.Formatters.SpanJson; 4 | 5 | sealed internal class SpanJsonFormatter() : ResolverBase>(new SpanJsonOptions 6 | { 7 | NamingConvention = NamingConventions.CamelCase, 8 | NullOption = NullOptions.ExcludeNulls, 9 | EnumOption = EnumOptions.String 10 | }) 11 | where TSymbol : struct; -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Formatters/SpanJson/SpanJsonInputFormatter.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Microsoft.AspNetCore.Mvc.Formatters; 3 | using SpanJson; 4 | 5 | namespace Benchmarks.Serializers.OutputFormatters.Formatters.SpanJson; 6 | 7 | public sealed class SpanJsonInputFormatter : TextInputFormatter where TResolver : IJsonFormatterResolver, new() 8 | { 9 | public SpanJsonInputFormatter() 10 | { 11 | SupportedMediaTypes.Add("application/json"); 12 | SupportedMediaTypes.Add("text/json"); 13 | SupportedMediaTypes.Add("application/*+json"); 14 | SupportedEncodings.Add(UTF8EncodingWithoutBOM); 15 | } 16 | 17 | public override async Task ReadRequestBodyAsync( 18 | InputFormatterContext context, 19 | Encoding encoding) 20 | { 21 | try 22 | { 23 | var model = await JsonSerializer.NonGeneric.Utf8.DeserializeAsync(context.HttpContext.Request.Body, context.ModelType); 24 | 25 | return model is not null || context.TreatEmptyInputAsDefaultValue 26 | ? await InputFormatterResult.SuccessAsync(model) 27 | : await InputFormatterResult.NoValueAsync(); 28 | } 29 | catch (Exception ex) 30 | { 31 | context.ModelState.AddModelError("JSON", ex.Message); 32 | 33 | return await InputFormatterResult.FailureAsync(); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Formatters/SpanJson/SpanJsonOutputFormatter.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Microsoft.AspNetCore.Mvc.Formatters; 3 | using SpanJson; 4 | 5 | namespace Benchmarks.Serializers.OutputFormatters.Formatters.SpanJson; 6 | 7 | public sealed class SpanJsonOutputFormatter : TextOutputFormatter where TResolver : IJsonFormatterResolver, new() 8 | { 9 | public SpanJsonOutputFormatter() 10 | { 11 | SupportedMediaTypes.Add("application/json"); 12 | SupportedMediaTypes.Add("text/json"); 13 | SupportedMediaTypes.Add("application/*+json"); 14 | SupportedEncodings.Add(Encoding.UTF8); 15 | } 16 | 17 | public override async Task WriteResponseBodyAsync( 18 | OutputFormatterWriteContext context, 19 | Encoding encoding) 20 | { 21 | if (context.Object is null) 22 | { 23 | return; 24 | } 25 | 26 | var valueTask = JsonSerializer.NonGeneric.Utf8.SerializeAsync(context.Object, context.HttpContext.Response.Body); 27 | 28 | if (valueTask.IsCompletedSuccessfully) 29 | { 30 | return; 31 | } 32 | 33 | await valueTask; 34 | } 35 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Formatters/SystemTextJson/MvcOptionsExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Benchmarks.Serializers; 3 | 4 | namespace Benchmarks.Serializers.OutputFormatters.Formatters.SystemTextJson; 5 | 6 | public static class MvcOptionsExtension 7 | { 8 | private readonly static JsonSerializerOptions Options = new() 9 | { 10 | PropertyNamingPolicy = JsonNamingPolicy.CamelCase 11 | }; 12 | 13 | public static IMvcBuilder AddSystemTextJsonSrcGenFormatter(this IMvcBuilder builder) 14 | { 15 | builder.AddJsonOptions(options => 16 | { 17 | options.JsonSerializerOptions.AddContext(); 18 | }); 19 | 20 | return builder; 21 | } 22 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Formatters/Utf8Json/MvcOptionsExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Utf8Json.AspNetCoreMvcFormatter; 3 | using Utf8Json.Resolvers; 4 | 5 | namespace Benchmarks.Serializers.OutputFormatters.Formatters.Utf8Json; 6 | 7 | public static class MvcOptionsExtension 8 | { 9 | public static IMvcBuilder AddUtf8JsonFormatter(this IMvcBuilder mvcBuilder) 10 | { 11 | Configure(mvcBuilder.Services); 12 | 13 | return mvcBuilder; 14 | } 15 | 16 | private static void Configure(IServiceCollection serviceCollection) => serviceCollection.Configure((Action) (config => 17 | { 18 | config.OutputFormatters.Clear(); 19 | config.InputFormatters.Clear(); 20 | config.OutputFormatters.Add(new JsonOutputFormatter(StandardResolver.CamelCase)); 21 | config.InputFormatters.Add(new JsonInputFormatter()); 22 | })); 23 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/Program.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers.Models; 2 | using Benchmarks.Serializers.OutputFormatters.Extensions; 3 | using Benchmarks.Serializers.OutputFormatters.Formatters.Jil; 4 | using Benchmarks.Serializers.OutputFormatters.Formatters.MemoryPack; 5 | using Benchmarks.Serializers.OutputFormatters.Formatters.MessagePack; 6 | using Benchmarks.Serializers.OutputFormatters.Formatters.Protobuf; 7 | using Benchmarks.Serializers.OutputFormatters.Formatters.SpanJson; 8 | using Benchmarks.Serializers.OutputFormatters.Formatters.SystemTextJson; 9 | using Benchmarks.Serializers.OutputFormatters.Formatters.Utf8Json; 10 | using Microsoft.AspNetCore.Mvc; 11 | 12 | namespace Benchmarks.Serializers.OutputFormatters; 13 | 14 | public static class Program 15 | { 16 | public static void Main(string[] args) 17 | { 18 | var builder = WebApplication.CreateBuilder(args); 19 | 20 | if (builder.Environment.IsProduction()) 21 | { 22 | builder.Logging.ClearProviders(); 23 | } 24 | 25 | builder.Services 26 | .AddControllers() 27 | // .AddJilFormatter(); 28 | // .AddSystemTextJsonSrcGenFormatter(); 29 | // .AddUtf8JsonFormatter(); 30 | // .AddSpanJsonFormatter(); 31 | // .AddSpanJsonFormatterV2(); 32 | // .AddNewtonsoftJson(); 33 | // .AddJilFormatter(); 34 | .AddProtobufFormatter(); 35 | // .AddMemoryPackFormatter(); 36 | // .AddMsgPackFormatter(); 37 | 38 | builder.Services.AddEndpointsApiExplorer(); 39 | builder.Services.AddSwaggerGen(); 40 | 41 | var app = builder.Build(); 42 | 43 | if (app.Environment.IsDevelopment()) 44 | { 45 | app.UseSwagger(); 46 | app.UseSwaggerUI(); 47 | } 48 | 49 | app.MapControllers(); 50 | 51 | app.Run(); 52 | } 53 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers.OutputFormatters/locustfile.py: -------------------------------------------------------------------------------- 1 | from locust import HttpUser, between, task, tag 2 | 3 | class Tests(HttpUser): 4 | wait_time = between(0.5, 2.5) 5 | 6 | def on_start(self): 7 | self.client.verify = False 8 | 9 | @task 10 | def simpleSerialize(self): 11 | self.client.get( 12 | url="/serialize/simple/100", 13 | verify=False, 14 | headers={"accept": "application/protobuf", "Content-Type": "application/protobuf"}) 15 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers/Benchmarks.Serializers.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8 5 | enable 6 | enable 7 | true 8 | true 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers/Fields.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.Serializers; 2 | 3 | public static class Fields 4 | { 5 | public const string TestIntField = "testInt"; 6 | 7 | public const string TestStringField = "testString"; 8 | 9 | public const string TestBoolField = "testBool"; 10 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers/Group.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.Serializers; 2 | 3 | public static class Group 4 | { 5 | public const string SerializationString = "Serialization. String"; 6 | 7 | public const string SerializationByte = "Serialization. Byte Array"; 8 | 9 | public const string DeserializationString = "Deserialization. String"; 10 | 11 | public const string DeserializationByte = "Deserialization. Byte Array"; 12 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers/Models/SimpleModel.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | using System.Text.Json.Serialization; 3 | using MemoryPack; 4 | using MessagePack; 5 | using NetJSON; 6 | using Newtonsoft.Json; 7 | using ProGaudi.MsgPack.Light; 8 | using ProtoBuf; 9 | using ZeroFormatter; 10 | 11 | namespace Benchmarks.Serializers.Models; 12 | 13 | /// 14 | /// Simple deserialization model. Used for tests. 15 | /// 16 | [ProtoContract, ZeroFormattable, MessagePackObject(true), MemoryPackable] 17 | public partial class SimpleModel 18 | { 19 | /// 20 | /// Gets or sets test string value. 21 | /// 22 | [MsgPackMapElement(nameof(TestInt))] 23 | [MsgPackArrayElement(0)] 24 | [Index(1), ProtoMember(1), DataMember(Name = Fields.TestIntField), JsonPropertyName(Fields.TestIntField), JsonProperty(Fields.TestIntField), 25 | NetJSONProperty(Fields.TestIntField)] 26 | public virtual int TestInt { get; set; } 27 | 28 | /// 29 | /// Gets or sets test string value. 30 | /// 31 | [MsgPackMapElement(nameof(TestString))] 32 | [MsgPackArrayElement(1)] 33 | [Index(2), ProtoMember(2), DataMember(Name = Fields.TestStringField), JsonPropertyName(Fields.TestStringField), JsonProperty(Fields.TestStringField), 34 | NetJSONProperty(Fields.TestStringField)] 35 | public virtual string TestString { get; set; } = string.Empty; 36 | 37 | /// 38 | /// Gets or sets test string value. 39 | /// 40 | [MsgPackMapElement(nameof(TestBool))] 41 | [MsgPackArrayElement(2)] 42 | [Index(3), ProtoMember(3), DataMember(Name = Fields.TestBoolField), JsonPropertyName(Fields.TestBoolField), JsonProperty(Fields.TestBoolField), 43 | NetJSONProperty(Fields.TestBoolField)] 44 | public virtual bool TestBool { get; set; } 45 | 46 | public override string ToString() 47 | { 48 | var boolValue = TestBool ? "true" : "false"; 49 | 50 | return "{" + 51 | $"\"{Fields.TestIntField}\":{TestInt}," + 52 | $"\"{Fields.TestStringField}\":\"{TestString}\"," + 53 | $"\"{Fields.TestBoolField}\":{boolValue}" + 54 | "}"; 55 | } 56 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers/ModelsJsonContext.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | using Benchmarks.Serializers.Models; 3 | 4 | namespace Benchmarks.Serializers; 5 | 6 | /// 7 | [JsonSerializable(typeof(ICollection)), JsonSerializable(typeof(ICollection)), JsonSourceGenerationOptions( 8 | GenerationMode = JsonSourceGenerationMode.Default, 9 | PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)] 10 | public sealed partial class ModelsJsonContext : JsonSerializerContext; -------------------------------------------------------------------------------- /src/main/Benchmarks.Serializers/SimpleFlatBufferModel.fbs: -------------------------------------------------------------------------------- 1 | namespace Benchmark.Serializers.Models; 2 | 3 | table SimpleFlatBufferModel { 4 | test_int:int; 5 | test_string:string; 6 | test_bool:bool; 7 | } 8 | 9 | table SimpleFlatBufferModels { 10 | models:[SimpleFlatBufferModel]; 11 | } 12 | 13 | root_type SimpleFlatBufferModels; -------------------------------------------------------------------------------- /src/main/Benchmarks.SortArrayByArray/Benchmarks.SortArrayByArray.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8 6 | enable 7 | enable 8 | Linux 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/Benchmarks.SortArrayByArray/Extensions/EnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.SortArrayByArray.Extensions; 2 | 3 | public static class EnumerableExtensions 4 | { 5 | 6 | public static IList Shuffle(this IEnumerable sequence) 7 | { 8 | return sequence.Shuffle(Random.Shared); 9 | } 10 | 11 | private static IList Shuffle(this IEnumerable sequence, Random randomNumberGenerator) 12 | { 13 | if (sequence == null) 14 | { 15 | throw new ArgumentNullException(nameof(sequence)); 16 | } 17 | 18 | if (randomNumberGenerator == null) 19 | { 20 | throw new ArgumentNullException(nameof(randomNumberGenerator)); 21 | } 22 | 23 | var values = sequence.ToList(); 24 | var currentlySelecting = values.Count; 25 | while (currentlySelecting > 1) 26 | { 27 | var selectedElement = randomNumberGenerator.Next(currentlySelecting); 28 | --currentlySelecting; 29 | if (currentlySelecting != selectedElement) 30 | { 31 | (values[currentlySelecting], values[selectedElement]) = (values[selectedElement], values[currentlySelecting]); 32 | } 33 | } 34 | 35 | return values; 36 | } 37 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.SortArrayByArray/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | using Benchmarks.SortArrayByArray; 3 | 4 | BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(); -------------------------------------------------------------------------------- /src/main/Benchmarks.SortArrayByArray/TestModel.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.SortArrayByArray; 2 | 3 | public sealed class TestModel 4 | { 5 | public required string Id { get; init; } 6 | 7 | public required int TestNumber { get; init; } 8 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.SortArrayByArray/readme.md: -------------------------------------------------------------------------------- 1 | | Method | Size | Mean | Error | StdDev | StdErr | Min | Q1 | Median | Q3 | Max | Op/s | Ratio | Gen0 | Allocated | Alloc Ratio | 2 | |---------------------|--------|---------:|---------:|---------:|---------:|---------:|---------:|---------:|---------:|---------:|-------------:|------:|-------:|----------:|------------:| 3 | | 'V2 order' | 10 | 23.04 ns | 0.049 ns | 0.046 ns | 0.012 ns | 22.93 ns | 23.02 ns | 23.06 ns | 23.08 ns | 23.09 ns | 43,399,713.7 | 0.26 | 0.0229 | 144 B | 0.38 | 4 | | 'V1 order Improved' | 10 | 37.91 ns | 0.107 ns | 0.100 ns | 0.026 ns | 37.72 ns | 37.83 ns | 37.92 ns | 37.99 ns | 38.03 ns | 26,379,502.7 | 0.43 | 0.0357 | 224 B | 0.60 | 5 | | 'V1 order' | 10 | 88.42 ns | 0.167 ns | 0.156 ns | 0.040 ns | 88.10 ns | 88.29 ns | 88.48 ns | 88.51 ns | 88.62 ns | 11,310,145.7 | 1.00 | 0.0598 | 376 B | 1.00 | 6 | | | | | | | | | | | | | | | | | | 7 | | 'V2 order' | 100000 | 22.96 ns | 0.056 ns | 0.053 ns | 0.014 ns | 22.83 ns | 22.93 ns | 22.97 ns | 23.00 ns | 23.01 ns | 43,561,243.0 | 0.26 | 0.0229 | 144 B | 0.38 | 8 | | 'V1 order Improved' | 100000 | 37.91 ns | 0.048 ns | 0.042 ns | 0.011 ns | 37.84 ns | 37.88 ns | 37.89 ns | 37.93 ns | 37.98 ns | 26,380,337.2 | 0.43 | 0.0357 | 224 B | 0.60 | 9 | | 'V1 order' | 100000 | 88.39 ns | 0.115 ns | 0.108 ns | 0.028 ns | 88.11 ns | 88.37 ns | 88.43 ns | 88.46 ns | 88.52 ns | 11,313,218.9 | 1.00 | 0.0598 | 376 B | 1.00 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Stopwatch/Benchmarks.Stopwatch.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Stopwatch/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | 3 | namespace Benchmarks.Stopwatch; 4 | 5 | internal static class Program 6 | { 7 | public static void Main(string[] args) 8 | { 9 | BenchmarkRunner.Run(typeof(Program).Assembly); 10 | } 11 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.Stopwatch/README.MD: -------------------------------------------------------------------------------- 1 | ``` 2 | 3 | BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3194) 4 | Unknown processor 5 | .NET SDK 9.0.100 6 | [Host] : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX2 7 | DefaultJob : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX2 8 | 9 | 10 | ``` 11 | | Method | Mean | Error | StdDev | StdErr | Min | Q1 | Median | Q3 | Max | Op/s | Ratio | Gen0 | Allocated | Alloc Ratio | 12 | |----------------------------------------------------------------------|---------:|---------:|---------:|---------:|---------:|---------:|---------:|---------:|---------:|-------------:|------:|-------:|----------:|------------:| 13 | | Stopwatch.GetElapsedTime(System.Diagnostics.Stopwatch.GetTimestamp() | 23.61 ns | 0.066 ns | 0.058 ns | 0.016 ns | 23.49 ns | 23.57 ns | 23.61 ns | 23.65 ns | 23.71 ns | 42,356,265.5 | 0.88 | - | - | 0.00 | 14 | | Stopwatch.StartNew().Elapsed | 26.78 ns | 0.113 ns | 0.106 ns | 0.027 ns | 26.52 ns | 26.73 ns | 26.75 ns | 26.86 ns | 26.96 ns | 37,343,337.0 | 1.00 | 0.0032 | 40 B | 1.00 | 15 | -------------------------------------------------------------------------------- /src/main/Benchmarks.Stopwatch/TimeBenchmarks.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using BenchmarkDotNet.Attributes; 3 | using BenchmarkDotNet.Configs; 4 | using BenchmarkDotNet.Order; 5 | 6 | namespace Benchmarks.Stopwatch; 7 | 8 | [MemoryDiagnoser] 9 | [CategoriesColumn] 10 | [AllStatisticsColumn] 11 | [Orderer(SummaryOrderPolicy.FastestToSlowest)] 12 | [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByParams)] 13 | [MarkdownExporterAttribute.GitHub] 14 | [CsvMeasurementsExporter] 15 | [ExcludeFromCodeCoverage] 16 | public class TimeBenchmarks 17 | { 18 | [Benchmark(Description = "Stopwatch.StartNew().Elapsed", Baseline = true)] 19 | public TimeSpan Old() 20 | { 21 | return System.Diagnostics.Stopwatch.StartNew().Elapsed; 22 | } 23 | 24 | [Benchmark(Description = "Stopwatch.GetElapsedTime(System.Diagnostics.Stopwatch.GetTimestamp()")] 25 | public TimeSpan New() 26 | { 27 | return System.Diagnostics.Stopwatch.GetElapsedTime(System.Diagnostics.Stopwatch.GetTimestamp()); 28 | } 29 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.String/Benchmarks.String.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8 6 | enable 7 | enable 8 | Linux 9 | 10 | 11 | 12 | 13 | .dockerignore 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/Benchmarks.String/Benchmarks/Abstractions/BenchmarkBase.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using BenchmarkDotNet.Attributes; 3 | using BenchmarkDotNet.Configs; 4 | using BenchmarkDotNet.Engines; 5 | using BenchmarkDotNet.Order; 6 | using Benchmarks.String.Models; 7 | using Bogus; 8 | 9 | namespace Benchmarks.String.Benchmarks.Abstractions; 10 | 11 | /// 12 | /// Base abstraction for benchmarks. 13 | /// 14 | [MemoryDiagnoser, CategoriesColumn, AllStatisticsColumn, Orderer(SummaryOrderPolicy.FastestToSlowest), 15 | GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByParams), MarkdownExporterAttribute.GitHub, CsvMeasurementsExporter, RPlotExporter, ExcludeFromCodeCoverage] 16 | public class BenchmarkBase 17 | { 18 | /// 19 | /// Benchmark Consumer. 20 | /// 21 | protected readonly Consumer Consumer = new(); 22 | 23 | /// 24 | /// Collection of for benchmarks. 25 | /// 26 | protected StringsTestModel TestStringArray = null!; 27 | 28 | /// 29 | /// Gets or sets flag whether stack should be triggered or other collections. 30 | /// 31 | [Params(true, false)] 32 | public bool IsStack { get; set; } 33 | 34 | /// 35 | /// Global setup. 36 | /// 37 | [GlobalSetup] 38 | public void Setup() 39 | { 40 | //stackalloc is used when sum of chars is less than 64. So we do generate random bigger that 64 to eliminate this behaviour. 41 | 42 | var from = IsStack ? 65 : 5; 43 | var to = IsStack ? 100 : 20; 44 | 45 | TestStringArray = new Faker() 46 | .RuleFor(x => x.Values, y => [y.Random.String2(from, to), y.Random.String2(from, to)]) 47 | .Generate(1)[0]; 48 | } 49 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.String/Benchmarks/Abstractions/BenchmarkCollectionBase.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using BenchmarkDotNet.Attributes; 3 | using BenchmarkDotNet.Configs; 4 | using BenchmarkDotNet.Engines; 5 | using BenchmarkDotNet.Order; 6 | using Benchmarks.String.Models; 7 | using Bogus; 8 | 9 | namespace Benchmarks.String.Benchmarks.Abstractions; 10 | 11 | /// 12 | /// Base abstraction for benchmarks. 13 | /// 14 | [MemoryDiagnoser, CategoriesColumn, AllStatisticsColumn, Orderer(SummaryOrderPolicy.FastestToSlowest), 15 | GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByParams), MarkdownExporterAttribute.GitHub, CsvMeasurementsExporter, ExcludeFromCodeCoverage] 16 | public class BenchmarkCollectionBase 17 | { 18 | /// 19 | /// Benchmark . 20 | /// 21 | protected readonly Consumer Consumer = new(); 22 | 23 | /// 24 | /// Collection of for benchmarks. 25 | /// 26 | protected List TestStringArray = null!; 27 | 28 | /// 29 | /// Gets or sets flag whether stack should be triggered or other collections. 30 | /// 31 | [Params(true, false)] 32 | public bool IsStack { get; set; } 33 | 34 | /// 35 | /// Parameter for models count. 36 | /// **NOTE:** Intentionally left public for BenchmarkDotNet Params. 37 | /// 38 | [Params(10, 100, 1000)] 39 | public int Values { get; set; } 40 | 41 | /// 42 | /// Global setup. 43 | /// 44 | [GlobalSetup] 45 | public void Setup() 46 | { 47 | //stackalloc is used when sum of chars is less than 64. So we do generate random bigger that 64 to eliminate this behaviour. 48 | TestStringArray = IsStack 49 | ? new Faker() 50 | .RuleFor(x => x.Values, y => new[] {y.Random.String2(5, 20), y.Random.String2(5, 20)}) 51 | .Generate(Values) 52 | : new Faker() 53 | .RuleFor(x => x.Values, y => new[] {y.Random.String2(65, 100), y.Random.String2(40, 100)}) 54 | .Generate(Values); 55 | } 56 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.String/Benchmarks/DashStringBenchmarks.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using BenchmarkDotNet.Attributes; 3 | using BenchmarkDotNet.Engines; 4 | using Benchmarks.String.Benchmarks.Abstractions; 5 | using Benchmarks.String.Services; 6 | 7 | namespace Benchmarks.String.Benchmarks; 8 | 9 | /// 10 | /// Benchmarking building link. 11 | /// 12 | [ExcludeFromCodeCoverage] 13 | public class DashStringBenchmarks : BenchmarkCollectionBase 14 | { 15 | /// 16 | /// Dash format with SpanOwner. 17 | /// 18 | [BenchmarkCategory(Group.DashView), Benchmark] 19 | public void DashFormatSpanOwner() 20 | { 21 | TestStringArray 22 | .Select(stringsTestModel => SpanOwnerStringService.ToDashFormat(stringsTestModel.Values)) 23 | .Consume(Consumer); 24 | } 25 | 26 | /// 27 | /// Dash format with SpanOwner. 28 | /// 29 | [BenchmarkCategory(Group.DashView), Benchmark] 30 | public void DashFormatRegex() 31 | { 32 | TestStringArray 33 | .Select(stringsTestModel => RegexStringService.ToDashFormat(stringsTestModel.Values)) 34 | .Consume(Consumer); 35 | } 36 | 37 | /// 38 | /// Dash format with ArrayPool. 39 | /// 40 | [BenchmarkCategory(Group.DashView), Benchmark] 41 | public void DashFormatArrayPool() 42 | { 43 | TestStringArray 44 | .Select(stringsTestModel => ArrayPoolStringService.ToDashFormat(stringsTestModel.Values)) 45 | .Consume(Consumer); 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.String/Benchmarks/GenerationBenchmarks.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using BenchmarkDotNet.Attributes; 3 | using BenchmarkDotNet.Configs; 4 | using BenchmarkDotNet.Engines; 5 | using BenchmarkDotNet.Order; 6 | using Benchmarks.String.Services; 7 | using MlkPwgen; 8 | 9 | namespace Benchmarks.String.Benchmarks; 10 | 11 | /// 12 | /// String generation benchmarks. 13 | /// 14 | [MemoryDiagnoser, CategoriesColumn, AllStatisticsColumn, Orderer(SummaryOrderPolicy.FastestToSlowest), 15 | GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory), MarkdownExporterAttribute.GitHub, CsvMeasurementsExporter, ExcludeFromCodeCoverage] 16 | public class GenerationBenchmarks 17 | { 18 | private readonly Consumer _consumer = new(); 19 | 20 | /// 21 | /// Parameter for models count. 22 | /// **NOTE:** Intentionally left public for BenchmarkDotNet Params. 23 | /// 24 | [Params(10, 100, 1000, 10000, 100000)] 25 | public int GenSize { get; set; } 26 | 27 | /// 28 | /// Gets random string using original method + string.Create. 29 | /// 30 | [Benchmark(Baseline = true)] 31 | public void OriginalRandom() 32 | { 33 | GenerationService.GetUniqueOriginal(GenSize).Consume(_consumer); 34 | } 35 | 36 | /// 37 | /// Gets random string using new method. 38 | /// 39 | [Benchmark] 40 | public void HashSetRandom() 41 | { 42 | GenerationService.GetUniqueHashSet(GenSize).Consume(_consumer); 43 | } 44 | 45 | /// 46 | /// Gets random string using new method with SpanOwner. 47 | /// 48 | [Benchmark] 49 | public void SpanOwnerRandom() 50 | { 51 | GenerationService.GetUniqueSpanOwner(GenSize).Consume(_consumer); 52 | } 53 | 54 | /// 55 | /// Gets random string using new method with ArrayPool. 56 | /// 57 | [Benchmark] 58 | public void ArrayPoolRandom() 59 | { 60 | GenerationService.GetUniqueArrayPool(GenSize).Consume(_consumer); 61 | } 62 | 63 | /// 64 | /// Gets random string using external library created by MlkPwger. 65 | /// 66 | [Benchmark] 67 | public void CryptoMlkPwger() 68 | { 69 | PasswordGenerator.Generate(GenSize).Consume(_consumer); 70 | } 71 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.String/Benchmarks/LinkStringBenchmarks.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using BenchmarkDotNet.Attributes; 3 | using BenchmarkDotNet.Engines; 4 | using Benchmarks.String.Benchmarks.Abstractions; 5 | using Benchmarks.String.Services; 6 | 7 | namespace Benchmarks.String.Benchmarks; 8 | 9 | /// 10 | /// Benchmarking building link. 11 | /// 12 | [ExcludeFromCodeCoverage] 13 | public class LinkStringBenchmarks : BenchmarkCollectionBase 14 | { 15 | /// 16 | /// Generates link format with SpanOwner. 17 | /// 18 | [BenchmarkCategory(Group.LinkFormat), Benchmark] 19 | public void LinkFormatSpanOwner() 20 | { 21 | TestStringArray 22 | .Select(stringsTestModel => SpanOwnerStringService.ToLinkFormat(stringsTestModel.Values)) 23 | .Consume(Consumer); 24 | } 25 | 26 | /// 27 | /// Generates link format with regex. 28 | /// 29 | [BenchmarkCategory(Group.LinkFormat), Benchmark] 30 | public void LinkFormatRegex() 31 | { 32 | TestStringArray 33 | .Select(stringsTestModel => RegexStringService.ToLinkFormat(stringsTestModel.Values)) 34 | .Consume(Consumer); 35 | } 36 | 37 | /// 38 | /// Generate with ArrayPool. 39 | /// 40 | [BenchmarkCategory(Group.LinkFormat), Benchmark] 41 | public void LinkFormatArrayPool() 42 | { 43 | TestStringArray 44 | .Select(stringsTestModel => ArrayPoolStringService.ToLinkFormat(stringsTestModel.Values)) 45 | .Consume(Consumer); 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.String/Benchmarks/SingleDashStringBenchmarks.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using BenchmarkDotNet.Attributes; 3 | using BenchmarkDotNet.Configs; 4 | using BenchmarkDotNet.Engines; 5 | using BenchmarkDotNet.Order; 6 | using Benchmarks.String.Benchmarks.Abstractions; 7 | using Benchmarks.String.Services; 8 | 9 | namespace Benchmarks.String.Benchmarks; 10 | 11 | /// 12 | /// Benchmarking building link. 13 | /// 14 | /// 15 | /// Base abstraction for benchmarks. 16 | /// 17 | [MemoryDiagnoser, CategoriesColumn, AllStatisticsColumn, Orderer(SummaryOrderPolicy.FastestToSlowest), 18 | GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByParams), MarkdownExporterAttribute.GitHub, CsvMeasurementsExporter, ExcludeFromCodeCoverage] 19 | public class SingleDashStringBenchmarks : BenchmarkBase 20 | { 21 | /// 22 | /// Dash format with SpanOwner. 23 | /// 24 | [BenchmarkCategory(Group.DashView), Benchmark] 25 | public void DashFormatSpanOwner() 26 | { 27 | SpanOwnerStringService.ToDashFormat(TestStringArray.Values).Consume(Consumer); 28 | } 29 | 30 | /// 31 | /// Dash format with SpanOwner. 32 | /// 33 | [BenchmarkCategory(Group.DashView), Benchmark] 34 | public void DashFormatRegex() 35 | { 36 | RegexStringService.ToDashFormat(TestStringArray.Values).Consume(Consumer); 37 | } 38 | 39 | /// 40 | /// Dash format with ArrayPool. 41 | /// 42 | [BenchmarkCategory(Group.DashView), Benchmark] 43 | public void DashFormatArrayPool() 44 | { 45 | ArrayPoolStringService.ToDashFormat(TestStringArray.Values).Consume(Consumer); 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.String/Benchmarks/SingleLinkStringBenchmarks.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using BenchmarkDotNet.Attributes; 3 | using BenchmarkDotNet.Engines; 4 | using Benchmarks.String.Benchmarks.Abstractions; 5 | using Benchmarks.String.Services; 6 | 7 | namespace Benchmarks.String.Benchmarks; 8 | 9 | /// 10 | /// Benchmarking building link. 11 | /// 12 | [ExcludeFromCodeCoverage] 13 | public class SingleLinkStringBenchmarks : BenchmarkBase 14 | { 15 | /// 16 | /// Generates link format with SpanOwner. 17 | /// 18 | [BenchmarkCategory(Group.LinkFormat), Benchmark] 19 | public void LinkFormatSpanOwner() 20 | { 21 | SpanOwnerStringService.ToLinkFormat(TestStringArray.Values).Consume(Consumer); 22 | } 23 | 24 | /// 25 | /// Generates link format with regex. 26 | /// 27 | [BenchmarkCategory(Group.LinkFormat), Benchmark] 28 | public void LinkFormatRegex() 29 | { 30 | RegexStringService.ToLinkFormat(TestStringArray.Values).Consume(Consumer); 31 | } 32 | 33 | /// 34 | /// Generate with ArrayPool. 35 | /// 36 | [BenchmarkCategory(Group.LinkFormat), Benchmark] 37 | public void LinkFormatArrayPool() 38 | { 39 | ArrayPoolStringService.ToLinkFormat(TestStringArray.Values).Consume(Consumer); 40 | } 41 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.String/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.String; 2 | 3 | internal static class Constants 4 | { 5 | internal const string DashedViewDelimiter = " - "; 6 | 7 | internal const char Space = ' '; 8 | 9 | internal const char LinkDelimiter = '-'; 10 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.String/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base 2 | USER $APP_UID 3 | WORKDIR /app 4 | 5 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build 6 | ARG BUILD_CONFIGURATION=Release 7 | WORKDIR /src 8 | COPY ["src/main/Benchmark.String/Benchmark.String.csproj", "src/main/Benchmark.String/"] 9 | RUN dotnet restore "src/main/Benchmark.String/Benchmark.String.csproj" 10 | COPY . . 11 | WORKDIR "/src/src/main/Benchmark.String" 12 | RUN dotnet build "Benchmark.String.csproj" -c $BUILD_CONFIGURATION -o /app/build 13 | 14 | FROM build AS publish 15 | ARG BUILD_CONFIGURATION=Release 16 | RUN dotnet publish "Benchmark.String.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false 17 | 18 | FROM base AS final 19 | WORKDIR /app 20 | COPY --from=publish /app/publish . 21 | ENTRYPOINT ["dotnet", "Benchmark.String.dll"] 22 | -------------------------------------------------------------------------------- /src/main/Benchmarks.String/Group.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.String; 2 | 3 | internal static class Group 4 | { 5 | internal const string DashView = "Dash View"; 6 | 7 | internal const string LinkFormat = "Link Format"; 8 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.String/Models/InterpolationModel.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.String.Models; 2 | 3 | /// 4 | /// Model with interpolation. 5 | /// 6 | public sealed class InterpolationModel 7 | { 8 | /// 9 | /// First value 10 | /// 11 | public string FirstValue { get; set; } = string.Empty; 12 | 13 | /// 14 | /// Second value. 15 | /// 16 | public string SecondValue { get; set; } = string.Empty; 17 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.String/Models/StringsTestModel.cs: -------------------------------------------------------------------------------- 1 | namespace Benchmarks.String.Models; 2 | 3 | /// 4 | /// Model for generating link and dash format. 5 | /// 6 | public sealed class StringsTestModel 7 | { 8 | /// 9 | /// Gets or sets collection of values. 10 | /// 11 | public string[] Values { get; set; } = null!; 12 | } -------------------------------------------------------------------------------- /src/main/Benchmarks.String/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | 3 | BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(); -------------------------------------------------------------------------------- /src/main/Benchmarks.String/Readme.md: -------------------------------------------------------------------------------- 1 | # Note: this section is going to be refactored -------------------------------------------------------------------------------- /src/test/Benchmarks.Tests.Unit/Benchmark.Iterators/TestModel.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Benchmarks.Iterators.Models; 3 | 4 | namespace Benchmarks.Tests.Unit.Benchmark.Iterators; 5 | 6 | /// 7 | /// Unit test model. 8 | /// 9 | public sealed class TestModel 10 | { 11 | /// 12 | /// Constructor. 13 | /// 14 | /// . 15 | public TestModel(SimpleModel simpleModel) 16 | { 17 | SimpleModel = simpleModel; 18 | JsonModel = JsonSerializer.Serialize(simpleModel); 19 | } 20 | 21 | /// 22 | /// Gets . 23 | /// 24 | public SimpleModel SimpleModel { get; } 25 | 26 | /// 27 | /// Gets Json string out of . 28 | /// 29 | public string JsonModel { get; } 30 | } -------------------------------------------------------------------------------- /src/test/Benchmarks.Tests.Unit/Benchmark.Serializers/Json/JilTests.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Tests.Unit.Benchmark.Serializers.Models; 2 | using FluentAssertions; 3 | 4 | namespace Benchmarks.Tests.Unit.Benchmark.Serializers.Json; 5 | 6 | /// 7 | /// Unit tests of service . 8 | /// 9 | public sealed class JilTests 10 | { 11 | /// 12 | /// Unit testing of method . 13 | /// 14 | [Fact] 15 | public void JilDeserialize_Returns_ValidModels() 16 | { 17 | // Arrange 18 | var actualString = TestsBase.GetTestString(); 19 | var expectedModels = TestsBase.GetTestModels(); 20 | 21 | // Act 22 | var actualModels = Benchmarks.Serializers.Json.Serializers.JilDeserialize(actualString); 23 | 24 | // Assert 25 | actualModels.Should().BeEquivalentTo(expectedModels); 26 | } 27 | 28 | /// 29 | /// Unit testing of method . 30 | /// 31 | [Fact] 32 | public void JilSerialize_Returns_ValidModel() 33 | { 34 | // Arrange 35 | var expectedModels = TestsBase.GetTestModels(); 36 | 37 | // Act 38 | var actualString = Benchmarks.Serializers.Json.Serializers.JilSerialize(expectedModels); 39 | var actualModels = Benchmarks.Serializers.Json.Serializers.JilDeserialize(actualString); 40 | 41 | // Assert 42 | actualModels.Should().BeEquivalentTo(expectedModels); 43 | } 44 | 45 | /// 46 | /// Unit testing of method . 47 | /// 48 | [Fact] 49 | public void JilDeserializeBytes_Returns_ValidModels() 50 | { 51 | // Arrange 52 | var expectedBytes = TestsBase.GetTestBytes(); 53 | var expectedModels = TestsBase.GetTestModels(); 54 | 55 | // Act 56 | var actualModels = Benchmarks.Serializers.Json.Serializers.JilDeserializeBytes(expectedBytes); 57 | 58 | // Assert 59 | actualModels.Should().BeEquivalentTo(expectedModels); 60 | } 61 | 62 | /// 63 | /// Unit testing of method . 64 | /// 65 | [Fact] 66 | public void JilSerializeBytes_Returns_ValidString() 67 | { 68 | // Arrange 69 | var expectedModels = TestsBase.GetTestModels(); 70 | 71 | // Act 72 | var actualBytes = Benchmarks.Serializers.Json.Serializers.JilSerializeBytes(expectedModels); 73 | var actualModels = Benchmarks.Serializers.Json.Serializers.JilDeserializeBytes(actualBytes); 74 | 75 | // Assert 76 | actualModels.Should().BeEquivalentTo(expectedModels); 77 | } 78 | } -------------------------------------------------------------------------------- /src/test/Benchmarks.Tests.Unit/Benchmark.Serializers/Json/NetJsonTests.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers.Json.Extensions; 2 | using Benchmarks.Tests.Unit.Benchmark.Serializers.Models; 3 | using FluentAssertions; 4 | 5 | namespace Benchmarks.Tests.Unit.Benchmark.Serializers.Json; 6 | 7 | /// 8 | /// Unit tests of . 9 | /// 10 | public class NetJsonTests 11 | { 12 | /// 13 | /// Unit testing of method . 14 | /// 15 | [Fact] 16 | public void NetJsonDeserialize_Returns_ValidModels() 17 | { 18 | // Arrange 19 | var expectedString = TestsBase.GetTestString(); 20 | var expectedModels = TestsBase.GetTestModels(); 21 | 22 | // Act 23 | var actualString = NetJSON.NetJSON.Serialize(expectedModels); 24 | var actualModels = NetJSON.NetJSON.Deserialize>(actualString, JsonServiceExtensions.NetJsonOptions); 25 | 26 | // Assert 27 | actualModels.Should().BeEquivalentTo(expectedModels); 28 | actualString.Should().BeEquivalentTo(expectedString); 29 | } 30 | 31 | /// 32 | /// Unit testing of method . 33 | /// 34 | [Fact] 35 | public void NetJsonSerialize_Returns_ValidStringModels() 36 | { 37 | // Arrange 38 | var expectedString = TestsBase.GetTestString(); 39 | var expectedModels = TestsBase.GetTestModels(); 40 | 41 | // Act 42 | var actualString = NetJSON.NetJSON.Serialize(expectedModels, JsonServiceExtensions.NetJsonOptions); 43 | 44 | // // Assert 45 | Assert.Equal(expectedString, actualString); 46 | actualString.Should().BeEquivalentTo(expectedString); 47 | } 48 | } -------------------------------------------------------------------------------- /src/test/Benchmarks.Tests.Unit/Benchmark.Serializers/Json/NewtonsoftJsonTests.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Benchmarks.Serializers.Json.Extensions; 3 | using Benchmarks.Tests.Unit.Benchmark.Serializers.Models; 4 | using FluentAssertions; 5 | using Newtonsoft.Json; 6 | 7 | namespace Benchmarks.Tests.Unit.Benchmark.Serializers.Json; 8 | 9 | /// 10 | /// Unit tests of service . 11 | /// 12 | public sealed class NewtonsoftJsonTests 13 | { 14 | /// 15 | /// Unit testing of method . 16 | /// 17 | [Fact] 18 | public void NewtonsoftDeserialize_Returns_ValidModels() 19 | { 20 | // Arrange 21 | var actualString = TestsBase.GetTestString(); 22 | var expectedModels = TestsBase.GetTestModels(); 23 | 24 | // Act 25 | var actualModels = JsonConvert.DeserializeObject(actualString, JsonServiceExtensions.NewtonsoftOptions); 26 | 27 | // Assert 28 | actualModels.Should().BeEquivalentTo(expectedModels); 29 | } 30 | 31 | /// 32 | /// Unit testing of method . 33 | /// 34 | [Fact] 35 | public void NewtonsoftSerialize_Returns_ValidString() 36 | { 37 | // Arrange 38 | var expectedString = TestsBase.GetTestString(); 39 | var expectedModels = TestsBase.GetTestModels(); 40 | 41 | // Act 42 | var actualString = JsonConvert.SerializeObject(expectedModels, Formatting.None, JsonServiceExtensions.NewtonsoftOptions); 43 | 44 | // Assert 45 | actualString.Should().BeEquivalentTo(expectedString); 46 | } 47 | 48 | /// 49 | /// Unit testing of method . 50 | /// 51 | [Fact] 52 | public void NewtonsoftDeserializeBytes_Returns_ValidModels() 53 | { 54 | // Arrange 55 | var actualBytes = TestsBase.GetTestBytes(); 56 | var expectedModels = TestsBase.GetTestModels(); 57 | 58 | // Act 59 | var actualModels = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(actualBytes), JsonServiceExtensions.NewtonsoftOptions); 60 | 61 | // Assert 62 | actualModels.Should().BeEquivalentTo(expectedModels); 63 | } 64 | } -------------------------------------------------------------------------------- /src/test/Benchmarks.Tests.Unit/Benchmark.Serializers/Json/ServiceStackTests.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Serializers.Json.Extensions; 2 | using Benchmarks.Tests.Unit.Benchmark.Serializers.Models; 3 | using FluentAssertions; 4 | using ServiceStack.Text; 5 | 6 | namespace Benchmarks.Tests.Unit.Benchmark.Serializers.Json; 7 | 8 | /// 9 | /// Unit tests of service 10 | /// 11 | public sealed class ServiceStackTests 12 | { 13 | /// 14 | /// Unit testing of method . 15 | /// 16 | [Fact] 17 | public void ServiceStackDeserialize_Returns_ValidModels() 18 | { 19 | // Arrange 20 | var actualString = TestsBase.GetTestString(); 21 | var expectedModels = TestsBase.GetTestModels(); 22 | 23 | // Act 24 | TestModel[] actualModels; 25 | 26 | using (JsConfig.With(JsonServiceExtensions.ServiceStackOptions)) 27 | { 28 | actualModels = JsonSerializer.DeserializeFromSpan(actualString); 29 | } 30 | 31 | // Assert 32 | actualModels.Should().BeEquivalentTo(expectedModels); 33 | } 34 | 35 | /// 36 | /// Unit testing of method . 37 | /// 38 | [Fact] 39 | public void ServiceStackDeserialize_Returns_ValidStringModels() 40 | { 41 | // Arrange 42 | var expectedModels = TestsBase.GetTestModels(); 43 | 44 | // Act 45 | TestModel[] actualModels; 46 | 47 | using (JsConfig.With(JsonServiceExtensions.ServiceStackOptions)) 48 | { 49 | var actualString = JsonSerializer.SerializeToString(expectedModels); 50 | actualModels = JsonSerializer.DeserializeFromSpan(actualString); 51 | } 52 | 53 | // Assert 54 | actualModels.Should().BeEquivalentTo(expectedModels); 55 | } 56 | } -------------------------------------------------------------------------------- /src/test/Benchmarks.Tests.Unit/Benchmark.Serializers/Json/SpanJsonTests.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.Tests.Unit.Benchmark.Serializers.Models; 2 | using FluentAssertions; 3 | using SpanJson; 4 | 5 | namespace Benchmarks.Tests.Unit.Benchmark.Serializers.Json; 6 | 7 | /// 8 | /// Unit tests of service . 9 | /// 10 | public sealed class SpanJsonTests 11 | { 12 | /// 13 | /// Unit testing of method . 14 | /// 15 | [Fact] 16 | public void SpanJsonDeserialize_Returns_ValidModels() 17 | { 18 | // Arrange 19 | var actualString = TestsBase.GetTestString(); 20 | var expectedModels = TestsBase.GetTestModels(); 21 | 22 | // Act 23 | var actualModels = JsonSerializer.Generic.Utf16.Deserialize(actualString); 24 | 25 | // Assert 26 | actualModels.Should().BeEquivalentTo(expectedModels); 27 | } 28 | 29 | /// 30 | /// Unit testing of method . 31 | /// 32 | [Fact] 33 | public void SpanJsonSerialize_Returns_ValidString() 34 | { 35 | // Arrange 36 | var expectedString = TestsBase.GetTestString(); 37 | var expectedModels = TestsBase.GetTestModels(); 38 | 39 | // Act 40 | var actualString = JsonSerializer.Generic.Utf16.Serialize(expectedModels); 41 | 42 | // Assert 43 | Assert.Equal(expectedString, actualString); 44 | actualString.Should().BeEquivalentTo(expectedString); 45 | } 46 | 47 | /// 48 | /// Unit testing of method . 49 | /// 50 | [Fact] 51 | public void SpanJsonDeserializeBytes_Returns_ValidModels() 52 | { 53 | // Arrange 54 | var expectedBytes = TestsBase.GetTestBytes(); 55 | var expectedModels = TestsBase.GetTestModels(); 56 | 57 | // Act 58 | var actualModels = JsonSerializer.Generic.Utf8.Deserialize(expectedBytes); 59 | 60 | // Assert 61 | actualModels.Should().BeEquivalentTo(expectedModels); 62 | } 63 | 64 | /// 65 | /// Unit testing of method . 66 | /// 67 | [Fact] 68 | public void SpanJsonSerializeBytes_Returns_ValidString() 69 | { 70 | // Arrange 71 | var expectedModels = TestsBase.GetTestModels(); 72 | 73 | // Act 74 | var actualBytes = JsonSerializer.Generic.Utf8.Serialize(expectedModels); 75 | var actualModels = JsonSerializer.Generic.Utf8.Deserialize(actualBytes); 76 | 77 | // Assert 78 | actualModels.Should().BeEquivalentTo(expectedModels); 79 | } 80 | } -------------------------------------------------------------------------------- /src/test/Benchmarks.Tests.Unit/Benchmark.Serializers/Json/SystemTextJsonTests.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Benchmarks.Tests.Unit.Benchmark.Serializers.Models; 3 | using FluentAssertions; 4 | 5 | namespace Benchmarks.Tests.Unit.Benchmark.Serializers.Json; 6 | 7 | /// 8 | /// Unit tests of 9 | /// 10 | public sealed class SystemTextJsonTests 11 | { 12 | /// 13 | /// Unit testing of method . 14 | /// 15 | [Fact] 16 | public void SystemTextJsonDeserialize_Returns_ValidModels() 17 | { 18 | // Arrange 19 | var actualString = TestsBase.GetTestString(); 20 | var expectedModels = TestsBase.GetTestModels(); 21 | 22 | // Act 23 | var actualModels = JsonSerializer.Deserialize(actualString); 24 | 25 | // Assert 26 | actualModels.Should().BeEquivalentTo(expectedModels); 27 | } 28 | 29 | /// 30 | /// Unit testing of method . 31 | /// 32 | [Fact] 33 | public void SystemTextJsonSerialize_Returns_ValidString() 34 | { 35 | // Arrange 36 | var expectedString = TestsBase.GetTestString(); 37 | var expectedModels = TestsBase.GetTestModels(); 38 | 39 | // Act 40 | var actualString = JsonSerializer.Serialize(expectedModels); 41 | 42 | // Assert 43 | actualString.Should().BeEquivalentTo(expectedString); 44 | } 45 | 46 | /// 47 | /// Unit testing of method . 48 | /// 49 | [Fact] 50 | public void SystemTextJsonDeserializeBytes_Returns_ValidModels() 51 | { 52 | // Arrange 53 | var expectedBytes = TestsBase.GetTestBytes(); 54 | var expectedModels = TestsBase.GetTestModels(); 55 | 56 | // Act 57 | var actualModels = JsonSerializer.Deserialize(expectedBytes); 58 | 59 | // Assert 60 | actualModels.Should().BeEquivalentTo(expectedModels); 61 | } 62 | 63 | /// 64 | /// Unit testing of method . 65 | /// 66 | [Fact] 67 | public void SystemTextJsonSerializeBytes_Returns_ValidString() 68 | { 69 | // Arrange 70 | var expectedBytes = TestsBase.GetTestBytes(); 71 | var expectedModels = TestsBase.GetTestModels(); 72 | 73 | // Act 74 | var actualBytes = JsonSerializer.SerializeToUtf8Bytes(expectedModels); 75 | 76 | // Assert 77 | actualBytes.Should().BeEquivalentTo(expectedBytes); 78 | } 79 | } -------------------------------------------------------------------------------- /src/test/Benchmarks.Tests.Unit/Benchmark.Serializers/Json/TestsBase.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Benchmarks.Tests.Unit.Benchmark.Serializers.Models; 3 | using Bogus; 4 | 5 | namespace Benchmarks.Tests.Unit.Benchmark.Serializers.Json; 6 | 7 | /// 8 | /// Base class with arranged values. 9 | /// 10 | public static class TestsBase 11 | { 12 | private const int InternalCount = 10; 13 | 14 | private readonly static Faker TestModelFaker = new(); 15 | 16 | private readonly static TestModel[] TestModels = TestModelFaker 17 | .RuleFor(testModel => testModel.TestByte, fakerSetter => fakerSetter.Random.Byte()) 18 | .RuleFor(testModel => testModel.TestChar, fakerSetter => fakerSetter.Random.Char('a', 'z')) 19 | .RuleFor(testModel => testModel.TestDouble, fakerSetter => double.Parse(fakerSetter.Random.Double().ToString("N4"))) 20 | .RuleFor(testModel => testModel.TestFloat, fakerSetter => fakerSetter.Random.Float()) 21 | .RuleFor(testModel => testModel.TestInt, fakerSetter => fakerSetter.Random.Int()) 22 | .RuleFor(testModel => testModel.TestLong, fakerSetter => fakerSetter.Random.Long()) 23 | .RuleFor(testModel => testModel.TestShort, fakerSetter => fakerSetter.Random.Short()) 24 | .RuleFor(testModel => testModel.TestString, fakerSetter => fakerSetter.Random.String2(5, 10)) 25 | .RuleFor(testModel => testModel.TestUInt, fakerSetter => fakerSetter.Random.UInt()) 26 | .RuleFor(testModel => testModel.TestUShort, fakerSetter => fakerSetter.Random.UShort()) 27 | .RuleFor(testModel => testModel.TestULong, fakerSetter => fakerSetter.Random.ULong()) 28 | .Generate(InternalCount) 29 | .ToArray(); 30 | 31 | private readonly static string TestString = BuildString(TestModels); 32 | 33 | /// 34 | /// Gets built constructed string. 35 | /// 36 | /// built constructed string. 37 | public static string GetTestString() 38 | { 39 | return TestString; 40 | } 41 | 42 | /// 43 | /// Gets array of bytes from string value. 44 | /// 45 | /// Array of bytes from string value. 46 | public static byte[] GetTestBytes() 47 | { 48 | return Encoding.UTF8.GetBytes(TestString); 49 | } 50 | 51 | /// 52 | /// Gets List of . 53 | /// 54 | /// List of . 55 | public static TestModel[] GetTestModels() 56 | { 57 | return TestModels; 58 | } 59 | 60 | private static string BuildString(Span testModels) 61 | { 62 | var sb = new StringBuilder(); 63 | sb.Append('['); 64 | 65 | for (var i = 0; i < testModels.Length - 1; i++) 66 | { 67 | sb.Append(testModels[i]); 68 | sb.Append(','); 69 | } 70 | 71 | sb.Append(testModels[^1]); 72 | sb.Append(']'); 73 | 74 | return sb.ToString(); 75 | } 76 | } -------------------------------------------------------------------------------- /src/test/Benchmarks.Tests.Unit/Benchmark.Serializers/Json/Utf8JsonTests.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Benchmarks.Tests.Unit.Benchmark.Serializers.Models; 3 | using FluentAssertions; 4 | using Utf8Json; 5 | 6 | namespace Benchmarks.Tests.Unit.Benchmark.Serializers.Json; 7 | 8 | /// 9 | /// Unit tests for service . 10 | /// 11 | public sealed class Utf8JsonTests 12 | { 13 | /// 14 | /// Unit testing of method . 15 | /// 16 | [Fact] 17 | public void Utf8JsonDeserialize_Returns_ValidModels() 18 | { 19 | // Arrange 20 | var actualString = TestsBase.GetTestString(); 21 | var expectedModels = TestsBase.GetTestModels(); 22 | 23 | // Act 24 | var actualModels = JsonSerializer.Deserialize(actualString)!; 25 | 26 | // Assert 27 | actualModels.Should().BeEquivalentTo(expectedModels); 28 | } 29 | 30 | /// 31 | /// Unit testing of method . 32 | /// 33 | [Fact] 34 | public void Utf8JsonSerialize_Returns_ValidString() 35 | { 36 | // Arrange 37 | var expectedString = TestsBase.GetTestString(); 38 | var expectedModels = TestsBase.GetTestModels(); 39 | 40 | // Act 41 | var actualString = Encoding.UTF8.GetString(JsonSerializer.Serialize(expectedModels)); 42 | 43 | // Assert 44 | Assert.Equal(expectedString, actualString); 45 | actualString.Should().BeEquivalentTo(expectedString); 46 | } 47 | 48 | /// 49 | /// Unit testing of method . 50 | /// 51 | [Fact] 52 | public void Utf8JsonDeserializeBytes_Returns_ValidModels() 53 | { 54 | // Arrange 55 | var expectedBytes = TestsBase.GetTestString(); 56 | var expectedModels = TestsBase.GetTestModels(); 57 | 58 | // Act 59 | var actualModels = JsonSerializer.Deserialize(expectedBytes); 60 | 61 | // Assert 62 | actualModels.Should().BeEquivalentTo(expectedModels); 63 | } 64 | 65 | /// 66 | /// Unit testing of method . 67 | /// 68 | [Fact] 69 | public void Utf8JsonBytesSerializeBytes_Returns_ValidString() 70 | { 71 | // Arrange 72 | var expectedBytes = TestsBase.GetTestBytes(); 73 | var expectedModels = TestsBase.GetTestModels(); 74 | 75 | // Act 76 | var actualBytes = JsonSerializer.Serialize(expectedModels); 77 | 78 | // Assert 79 | actualBytes.Should().BeEquivalentTo(expectedBytes); 80 | } 81 | } -------------------------------------------------------------------------------- /src/test/Benchmarks.Tests.Unit/Benchmark.String/GenerationTests.cs: -------------------------------------------------------------------------------- 1 | using Benchmarks.String.Services; 2 | using MlkPwgen; 3 | 4 | namespace Benchmarks.Tests.Unit.Benchmark.String; 5 | 6 | /// 7 | /// Test of . 8 | /// 9 | public sealed class GenerationTests 10 | { 11 | private const char EofChar = '\0'; 12 | 13 | /// 14 | /// Test of 'GenerationService.GetUniqueOriginal' method. 15 | /// 16 | /// Generation length. 17 | [Theory, InlineData(5), InlineData(10), InlineData(100)] 18 | public void GetUniqueOriginal_Returns_RightString(int length) 19 | { 20 | // Act 21 | var generatedString = GenerationService.GetUniqueOriginal(length); 22 | 23 | // Assert 24 | Assert.True(generatedString.Length == length); 25 | Assert.True(generatedString.IndexOf(EofChar) is -1); 26 | } 27 | 28 | /// 29 | /// Test of 'GenerationService.GetUniqueHashSet' method. 30 | /// 31 | /// Generation length. 32 | [Theory, InlineData(5), InlineData(10), InlineData(100)] 33 | public void GetUniqueHashSet_Returns_RightString(int length) 34 | { 35 | // Act 36 | var generatedString = GenerationService.GetUniqueHashSet(length); 37 | 38 | // Assert 39 | Assert.True(generatedString.Length == length); 40 | Assert.True(generatedString.IndexOf(EofChar) is -1); 41 | } 42 | 43 | /// 44 | /// Test of 'GenerationService.GetUniqueSpanOwner' method. 45 | /// 46 | /// Generation length. 47 | [Theory, InlineData(5), InlineData(10), InlineData(100)] 48 | public void GetUniqueSpanOwner_Returns_RightString(int length) 49 | { 50 | // Act 51 | var generatedString = GenerationService.GetUniqueSpanOwner(length); 52 | 53 | // Assert 54 | Assert.True(generatedString.Length == length); 55 | Assert.True(generatedString.IndexOf(EofChar) is -1); 56 | } 57 | 58 | /// 59 | /// Test of 'GenerationService.GetUniqueArrayPool' method. 60 | /// 61 | /// Generation length. 62 | [Theory, InlineData(5), InlineData(10), InlineData(100)] 63 | public void GetUniqueKeyNewArrayPool_Returns_RightString(int length) 64 | { 65 | // Act 66 | var generatedString = GenerationService.GetUniqueArrayPool(length); 67 | // Assert 68 | Assert.True(generatedString.Length == length); 69 | Assert.True(generatedString.IndexOf(EofChar) is -1); 70 | } 71 | 72 | /// 73 | /// Test of 'PasswordGenerator.Generate' method. 74 | /// 75 | /// Generation length. 76 | [Theory, InlineData(5), InlineData(10), InlineData(100)] 77 | public void CryptoMlkPwger_Returns_RightString(int length) 78 | { 79 | // Act 80 | var generatedString = PasswordGenerator.Generate(length); 81 | // Assert 82 | Assert.True(generatedString.Length == length); 83 | Assert.True(generatedString.IndexOf(EofChar) is -1); 84 | } 85 | } -------------------------------------------------------------------------------- /src/test/Benchmarks.Tests.Unit/Benchmarks.Tests.Unit.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8 5 | enable 6 | enable 7 | false 8 | true 9 | 10 | 11 | 12 | 13 | all 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | 16 | 17 | 18 | 19 | 20 | runtime; build; native; contentfiles; analyzers; buildtransitive 21 | all 22 | 23 | 24 | runtime; build; native; contentfiles; analyzers; buildtransitive 25 | all 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/test/Benchmarks.Tests.Unit/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using Xunit; -------------------------------------------------------------------------------- /toc.yml: -------------------------------------------------------------------------------- 1 | - name: Docs 2 | href: docs/ 3 | - name: API 4 | href: api/ --------------------------------------------------------------------------------