{"id":26202264,"url":"https://github.com/astef/benchmark-dotnet-boxing","last_synced_at":"2026-05-15T21:33:09.743Z","repository":{"id":143541351,"uuid":"291869102","full_name":"astef/benchmark-dotnet-boxing","owner":"astef","description":"Benchmark of the real overhead (including GC) of the value types boxing compared to direct serialization into the byte array.","archived":false,"fork":false,"pushed_at":"2020-09-01T17:48:21.000Z","size":14,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-01T09:52:48.460Z","etag":null,"topics":["benchmark","benchmarkdotnet","boxing","csharp","dotnet-core","garbage-collection","optimization","serialization"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/astef.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-09-01T01:54:58.000Z","updated_at":"2020-09-01T17:48:24.000Z","dependencies_parsed_at":null,"dependency_job_id":"22a606aa-7a1d-426d-8061-2228f9b3d328","html_url":"https://github.com/astef/benchmark-dotnet-boxing","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/astef/benchmark-dotnet-boxing","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/astef%2Fbenchmark-dotnet-boxing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/astef%2Fbenchmark-dotnet-boxing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/astef%2Fbenchmark-dotnet-boxing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/astef%2Fbenchmark-dotnet-boxing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/astef","download_url":"https://codeload.github.com/astef/benchmark-dotnet-boxing/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/astef%2Fbenchmark-dotnet-boxing/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268166270,"owners_count":24206428,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-01T02:00:08.611Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["benchmark","benchmarkdotnet","boxing","csharp","dotnet-core","garbage-collection","optimization","serialization"],"created_at":"2025-03-12T03:34:02.270Z","updated_at":"2026-05-15T21:33:04.723Z","avatar_url":"https://github.com/astef.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# benchmark-dotnet-boxing\nBenchmark of the real overhead (including GC) of the value types boxing compared to direct serialization into the byte array.\n\nAfter the performance-critical synchronous procedure, there's basically two non-blocking ways of sharing the result of processing with other threads:\n - populate some kind of generic buffer, e.g. `object[]`\n   - easy to implement (every value is an `object` already)\n   - extra boxing cost in the main procedure for every value in the message\n   - extra collection cost in the application for every value in the message\n - populate value-typed buffer, e.g. `byte[]`\n   - need to implement serialization for every possible type (can be tricky for custom reference types)\n   - extra serialization cost in the main procedure for every value in the message\n   - no boxing, no collection cost\n  \n  The goal is to find out the optimum conditions for selecting one of the above strategies.\n\n## Results\n``` ini\n\nBenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.1016 (1909/November2018Update/19H2)\nIntel Core i7-7820HQ CPU 2.90GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores\n.NET Core SDK=3.1.301\n  [Host]     : .NET Core 3.1.5 (CoreCLR 4.700.20.26901, CoreFX 4.700.20.27001), X64 RyuJIT\n  Job-IKJAKY : .NET Core 3.1.5 (CoreCLR 4.700.20.26901, CoreFX 4.700.20.27001), X64 RyuJIT\n\nIterationCount=5  WarmupCount=1  \n\n```\n|         Method | IterCount | MessageNum |         Mean |        Error |      StdDev |         Gen 0 |         Gen 1 |         Gen 2 |    Allocated |\n|--------------- |---------- |----------- |-------------:|-------------:|------------:|--------------:|--------------:|--------------:|-------------:|\n| **RunWithObjects** |     **16000** |       **5000** |   **9,718.0 ms** |     **93.25 ms** |    **24.22 ms** |  **1186000.0000** |   **593000.0000** |   **593000.0000** |   **7324.59 MB** |\n|   RunWithBytes |     16000 |       5000 |   4,421.4 ms |     46.79 ms |     7.24 ms |   593000.0000 |   593000.0000 |   593000.0000 |   1831.42 MB |\n| **RunWithObjects** |     **16000** |      **10000** |  **19,459.8 ms** |    **218.79 ms** |    **56.82 ms** |  **2286000.0000** |  **1143000.0000** |  **1143000.0000** |   **14648.8 MB** |\n|   RunWithBytes |     16000 |      10000 |   8,881.2 ms |    294.69 ms |    76.53 ms |  1143000.0000 |  1143000.0000 |  1143000.0000 |   3662.48 MB |\n| **RunWithObjects** |     **16000** |      **20000** |  **39,103.3 ms** |    **673.01 ms** |   **174.78 ms** |  **4572000.0000** |  **2286000.0000** |  **2286000.0000** |  **29297.24 MB** |\n|   RunWithBytes |     16000 |      20000 |  17,892.4 ms |    471.22 ms |    72.92 ms |  2286000.0000 |  2286000.0000 |  2286000.0000 |   7324.59 MB |\n| **RunWithObjects** |     **16000** |      **40000** |  **93,927.5 ms** |  **1,691.43 ms** |   **439.26 ms** |  **9777000.0000** |  **6221000.0000** |  **3556000.0000** |  **58594.93 MB** |\n|   RunWithBytes |     16000 |      40000 |  35,392.0 ms |    457.73 ms |    70.83 ms |  4000000.0000 |  4000000.0000 |  4000000.0000 |   14648.8 MB |\n| **RunWithObjects** |     **16000** |      **80000** | **215,643.5 ms** |  **1,526.78 ms** |   **396.50 ms** | **18644000.0000** | **11494000.0000** |  **7019000.0000** | **117188.79 MB** |\n|   RunWithBytes |     16000 |      80000 |  71,040.3 ms |    631.03 ms |   163.88 ms |  8000000.0000 |  8000000.0000 |  8000000.0000 |  29297.24 MB |\n| **RunWithObjects** |     **16000** |     **160000** | **447,694.4 ms** |  **2,373.70 ms** |   **616.44 ms** | **38338000.0000** | **24914000.0000** | **15998000.0000** | **234377.38 MB** |\n|   RunWithBytes |     16000 |     160000 | 140,678.0 ms |  1,639.81 ms |   253.76 ms | 16000000.0000 | 16000000.0000 | 16000000.0000 |  58594.12 MB |\n\n\n## Conclusions\nFor the provided message structure and size (three `long` fields), direct serialization is at least two times faster than the cost of boxing.\n\nThe bigger the number of messages, the bigger the difference factor (non-linear dependency): x2.2 for 5k, and x3.2 for 160k.\n\nAllocated memory difference is proportional to the number of messages.\n\nDifferent number of iterations, didn't reveal any effects (was excluded from results for brevity).\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fastef%2Fbenchmark-dotnet-boxing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fastef%2Fbenchmark-dotnet-boxing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fastef%2Fbenchmark-dotnet-boxing/lists"}