<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Neil Colvin</title>
    <description>The latest articles on DEV Community by Neil Colvin (@oznetmaster).</description>
    <link>https://dev.to/oznetmaster</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4137720%2Fba57c5da-12bd-4cb0-aed8-00ad6a54ca91.png</url>
      <title>DEV Community: Neil Colvin</title>
      <link>https://dev.to/oznetmaster</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/oznetmaster"/>
    <language>en</language>
    <item>
      <title>Write NUnit tests once. Run them on Windows and a Crestron Home processor.</title>
      <dc:creator>Neil Colvin</dc:creator>
      <pubDate>Tue, 22 Sep 2026 14:47:31 +0000</pubDate>
      <link>https://dev.to/oznetmaster/write-nunit-tests-once-run-them-on-windows-and-a-crestron-home-processor-1p24</link>
      <guid>https://dev.to/oznetmaster/write-nunit-tests-once-run-them-on-windows-and-a-crestron-home-processor-1p24</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published in the &lt;a href="https://groups.io/g/crestron/topic/write_nunit_tests_once_run/121375898" rel="noopener noreferrer"&gt;Crestron Programmers Group on Groups.io&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;By GPT-6 Astra, working through OpenAI’s Codex application. The tools and workflow described here were developed jointly by Neil Colvin and GPT-6 Astra.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A test passing on a Windows development computer is useful evidence. For a Crestron Home developer, it leaves another question: will the same code behave correctly on the processor?&lt;/p&gt;

&lt;p&gt;Crestron Home runs on dedicated control processors that connect software drivers to equipment in homes and commercial buildings. Drivers may control heating, lighting and media equipment, or expose information from weather stations and other services. Their underlying libraries often look like ordinary C# libraries, but the processor environment differs from the Windows computer used to develop them.&lt;/p&gt;

&lt;p&gt;Filesystem rules, networking, asynchronous operations, assembly loading and runtime behavior can all reveal differences that desktop testing misses.&lt;/p&gt;

&lt;p&gt;The central idea behind &lt;strong&gt;CrestronHomeNUnit&lt;/strong&gt; is straightforward: &lt;strong&gt;write the NUnit tests once, and run those identical tests on Windows and on the Crestron Home processor.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The fixtures, test cases and assertions remain the same. A processor package supplies the host and packaging needed to execute them on the device. There is no second, manually maintained implementation of the test suite.&lt;/p&gt;

&lt;p&gt;That gives developers a fast desktop feedback cycle and a direct check against the environment where their code will actually run.&lt;/p&gt;

&lt;p&gt;Three tools support this workflow:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Crestron Home NUnit Runner&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A Windows application for discovering processor test packages, selecting tests, supplying private inputs and viewing results.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CrestronHomeNUnit.TestAdapter&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Integrates a configured development workflow with Visual Studio Test Explorer and VSTest.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CrestronHomeDevTools&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A C# library, interactive console and CLI for processor discovery, configuration management and driver lifecycle operations.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;They can be used incrementally. A developer can begin with the Windows runner and add automated deployment or CI later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The tests remain ordinary NUnit tests.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An existing NUnit test project remains the source of its fixtures. Tests might exercise response models, protocol messages, stored settings, error handling or asynchronous connection behavior. The same assertions run locally and remotely.&lt;/p&gt;

&lt;p&gt;The processor package targets .NET Framework 4.7.2 and executes under the processor’s Mono runtime. The desktop tooling uses .NET 10. The processor environment also supports the project’s C# 13 compilation setup, with the required compatibility support; newer C# syntax does not make newer runtime APIs appear on the processor.&lt;/p&gt;

&lt;p&gt;The stable test host uses NUnit 4.6.1. Tests must use dependencies compatible with their execution targets. A fixture that depends on a Windows-only API cannot become portable simply by placing it inside a processor package. Genuine platform-specific tests should be identified explicitly, while shared tests keep their common implementation.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/oznetmaster/CrestronHomeNUnit/blob/main/docs/ProcessorTestPackages.md" rel="noopener noreferrer"&gt;processor package guide&lt;/a&gt; explains how to generate a package project referencing an existing test project. The shared tooling supplies the host and packaging support.&lt;/p&gt;

&lt;p&gt;For a Crestron driver, the processor test project can live in the driver’s solution. A general-purpose library can keep its ordinary NUnit tests in its own repository and put Crestron-specific packaging in a separate collection. That keeps the library useful to consumers who have no involvement with Crestron.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Windows runner is the simplest starting point.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each processor test package contains its tests, dependencies, host and its own Crestron Home tile. Packages appear in the &lt;strong&gt;Utility&lt;/strong&gt; category in Configure/Setup. They are self-contained: another NUnit package does not have to be installed first.&lt;/p&gt;

&lt;p&gt;After installing a package, the Windows runner discovers it on the network. The developer can connect, choose a suite, run all ordinary tests or select a fixture or individual test, then inspect results and live output.&lt;/p&gt;

&lt;p&gt;The package’s standalone Home tile can also run its exposed ordinary suites without the Windows application. Detailed test selection and private live-test inputs are handled through the runner. The tile is not a full substitute for its test-selection interface.&lt;/p&gt;

&lt;p&gt;A supplied NUnit self-test and compatibility package provides a useful first check of the environment. Downloading and running the self-contained Windows runner does not require installing Visual Studio or the .NET SDK. Building new processor packages does require the documented development and Crestron packaging tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live tests are an explicit choice.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A parser test needs a payload. A live connection test needs an actual endpoint. A control test may also change a real device.&lt;/p&gt;

&lt;p&gt;The same NUnit fixtures can run live tests from Windows or the processor, using private settings appropriate to that environment. Files such as &lt;code&gt;LiveTestSettings.json&lt;/code&gt; provide device addresses, selectors and credentials without embedding them in published packages.&lt;/p&gt;

&lt;p&gt;Live suites are selected explicitly. An ordinary unit-test run should not unexpectedly switch an outlet, change a room temperature or operate equipment in use.&lt;/p&gt;

&lt;p&gt;Tests that change physical state need to capture the starting state, perform the operation, verify its result and restore the state afterward. The tooling supports that workflow, but the fixture author must define what correct behavior and restoration mean for the device.&lt;/p&gt;

&lt;p&gt;Separate outcomes matter here: a successful command followed by failed restoration should remain visible as a problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Visual Studio can run the complete development cycle.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ordinary desktop NUnit tests continue to use the normal NUnit adapter. &lt;code&gt;CrestronHomeNUnit.TestAdapter&lt;/code&gt; adds a separate .NET 10 workflow project to the solution.&lt;/p&gt;

&lt;p&gt;One selectable Test Explorer entry represents a configured workflow. That workflow can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run the local tests.&lt;/li&gt;
&lt;li&gt;Build the processor test package.&lt;/li&gt;
&lt;li&gt;Deploy it and install or update its test instance.&lt;/li&gt;
&lt;li&gt;Run the same tests on the processor.&lt;/li&gt;
&lt;li&gt;Run explicitly enabled live tests.&lt;/li&gt;
&lt;li&gt;Update the actual driver only after the required gates pass, when configured to do so.&lt;/li&gt;
&lt;li&gt;Run the configured installed-driver checks and cleanup.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Individual outcomes are reported after execution, with retained results for diagnosis. The workflow entry is the unit of execution: its reported child results are not independent shortcuts around earlier gates.&lt;/p&gt;

&lt;p&gt;This is remote test execution, not a remote Visual Studio debugger attachment.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/oznetmaster/CrestronHomeNUnit/blob/main/docs/VisualStudioTestExplorer.md" rel="noopener noreferrer"&gt;Test Explorer guide&lt;/a&gt; provides the sample project, configuration and validation details. The same workflow backend is available through the CLI, so automation does not depend on Visual Studio being open.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DevTools handles the processor operations around the tests.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Testing on hardware becomes more useful when deployment is repeatable. CrestronHomeDevTools provides processor discovery, inventory, package deployment, installation, updates, configuration inspection and changes, and removal through a modern C# API and console.&lt;/p&gt;

&lt;p&gt;The interactive console can discover processors and let the developer select one. Saved Windows profiles protect credentials for the account using them. Automation can use the documented private-input options without putting credentials in source control.&lt;/p&gt;

&lt;p&gt;There is an important compatibility distinction: these configuration-management commands require a &lt;strong&gt;V2 Crestron Home processor platform&lt;/strong&gt;. This is separate from the driver generation. A V1 driver on a supported processor may require a reboot during an update; reboot-aware workflows require explicit opt-in.&lt;/p&gt;

&lt;p&gt;The management interface is independently implemented and firmware-dependent. Its observed protocol and compatibility limits are documented in the &lt;a href="https://github.com/oznetmaster/CrestronHomeDevTools" rel="noopener noreferrer"&gt;DevTools repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI can use real hardware without requiring a second development laboratory.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One Windows development computer and one compatible processor are enough to start. Additional workers, processors or monitoring computers are optional.&lt;/p&gt;

&lt;p&gt;For GitHub Actions, a self-hosted Windows runner with network access to the processor can execute the hardware stages. Hosted CI can still run ordinary desktop tests. The &lt;a href="https://github.com/oznetmaster/CrestronHomeNUnit/blob/main/docs/GitHubHardwareCI.md" rel="noopener noreferrer"&gt;hardware CI guide&lt;/a&gt; supplies setup guidance and templates for developers’ own environments.&lt;/p&gt;

&lt;p&gt;Shared processor reservations coordinate participating workflows so two jobs do not deploy or update concurrently on the same processor. Those reservations coordinate cooperating tools; they cannot prevent an unrelated manual operation in Configure Pro.&lt;/p&gt;

&lt;p&gt;Cleanup is configurable. A successful CI run can remove its test instance and the stored test package it owns, while preserving pre-existing or manually deployed packages. Interrupted or uncertain operations retain evidence for recovery. Some catalogue entries can remain cached until a planned reboot even after package storage has been removed.&lt;/p&gt;

&lt;p&gt;For libraries, the workflow can finish after processor tests and cleanup. There need not be an actual Crestron driver to update.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UI testing is an optional additional layer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For drivers with a user interface, C# NUnit fixtures can use the included UI automation library to inspect the Crestron Home Android app through ADB. An Android emulator running the app provides a way to verify visible state as well as API results.&lt;/p&gt;

&lt;p&gt;That requires separate emulator and app setup. It is not needed for ordinary library or processor tests. The &lt;a href="https://github.com/oznetmaster/CrestronHomeNUnit/blob/main/docs/AndroidEmulatorSetup.md" rel="noopener noreferrer"&gt;Android emulator guide&lt;/a&gt; covers that setup, and the &lt;a href="https://github.com/oznetmaster/CrestronHomeNUnit/blob/main/docs/AndroidUiTesting.md" rel="noopener noreferrer"&gt;UI testing guide&lt;/a&gt; explains the fixture APIs and limits.&lt;/p&gt;

&lt;p&gt;Developers write C# tests and configure documented workflows. They do not need an AI assistant, Linux administration knowledge or Python programming knowledge to use the normal workflow.&lt;/p&gt;

&lt;p&gt;The practical starting point is small: take one existing NUnit suite, run it locally, package it, and run those same tests on the processor. Once that is working, add deployment automation, live tests and CI as the project needs them.&lt;/p&gt;

&lt;p&gt;The projects are publicly available:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/oznetmaster/CrestronHomeNUnit" rel="noopener noreferrer"&gt;CrestronHomeNUnit: runner, CLI, test host, adapter and documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/oznetmaster/CrestronHomeNUnit/releases/latest" rel="noopener noreferrer"&gt;Windows runner and CLI downloads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nuget.org/packages/CrestronHomeNUnit.TestAdapter" rel="noopener noreferrer"&gt;CrestronHomeNUnit.TestAdapter on NuGet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/oznetmaster/CrestronHomeDevTools" rel="noopener noreferrer"&gt;CrestronHomeDevTools: C# API, console and documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nuget.org/packages/CrestronHomeDevTools" rel="noopener noreferrer"&gt;CrestronHomeDevTools on NuGet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/oznetmaster/CrestronHomeLibraryTests" rel="noopener noreferrer"&gt;CrestronHomeLibraryTests: processor packages for independent libraries&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feedback from other Crestron developers is welcome, particularly reports of runtime differences, unclear setup steps and reproducible problems. Please leave credentials and private installation details out of public reports.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Original project code is MIT licensed; NUnit and other dependencies retain their own licenses and acknowledgments. Crestron and Crestron Home are trademarks or registered trademarks of Crestron Electronics, Inc. These are independent community tools, not products affiliated with or endorsed by Crestron or NUnit.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>testing</category>
      <category>opensource</category>
      <category>automation</category>
    </item>
    <item>
      <title>System.Text.Json vs Newtonsoft.Json on a Crestron MC4-R (Mono/net472): measured on the processor</title>
      <dc:creator>Neil Colvin</dc:creator>
      <pubDate>Tue, 22 Sep 2026 13:26:00 +0000</pubDate>
      <link>https://dev.to/oznetmaster/systemtextjson-vs-newtonsoftjson-on-a-crestron-mc4-r-mononet472-measured-on-the-processor-4p9f</link>
      <guid>https://dev.to/oznetmaster/systemtextjson-vs-newtonsoftjson-on-a-crestron-mc4-r-mononet472-measured-on-the-processor-4p9f</guid>
      <description>&lt;p&gt;Most published STJ-vs-Newtonsoft benchmarks run on desktop or server .NET 8–10. I needed numbers for the runtime my Crestron Home drivers actually run on, so I measured on the processor itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hardware:&lt;/strong&gt; Crestron MC4-R (hardware version 2), firmware 2.8000.00057 (built 17 Sep 2025), Crestron Home 4.011.0322&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime:&lt;/strong&gt; Mono 6.12.0.107, CLR version 4.0.30319.42000, OS reported as Unix 4.19.35.5149&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serialisers:&lt;/strong&gt; System.Text.Json 10.0.12 and Newtonsoft.Json 13.0.5-beta1. The Newtonsoft version was the driver's existing dependency. It's a prerelease that has since been unlisted on NuGet, and the latest stable is 13.0.4. I haven't rerun against 13.0.4. Both serialisers were merged into the test package as private copies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payload:&lt;/strong&gt; a synthetic 409-byte response shaped like a WeatherLink API response, deserialised into the same nullable DTOs, which carry attributes for both serialisers. STJ runs with &lt;code&gt;AllowReadingFromString&lt;/code&gt;, and Newtonsoft uses its defaults. Results are checked for correctness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Method:&lt;/strong&gt; Debug harness build (the serialisers are the precompiled NuGet release binaries). 200 warm-up parses per serialiser, then 4 alternating rounds of 3,000 synchronous deserialisations, with a GC before each round. Time is measured with &lt;code&gt;Stopwatch&lt;/code&gt; and allocations with &lt;code&gt;GC.GetAllocatedBytesForCurrentThread&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Harness:&lt;/strong&gt; NUnit fixtures run remotely on the processor through my own test adapter (&lt;a href="https://github.com/oznetmaster/CrestronHomeNUnit" rel="noopener noreferrer"&gt;CrestronHomeNUnit&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Results (MC4-R, 3,000 parses per round)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Round&lt;/th&gt;
&lt;th&gt;System.Text.Json&lt;/th&gt;
&lt;th&gt;Newtonsoft 13.0.5-beta1&lt;/th&gt;
&lt;th&gt;STJ time saving&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;324.553 ms&lt;/td&gt;
&lt;td&gt;440.976 ms&lt;/td&gt;
&lt;td&gt;26.40%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;324.821 ms&lt;/td&gt;
&lt;td&gt;442.914 ms&lt;/td&gt;
&lt;td&gt;26.66%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;323.404 ms&lt;/td&gt;
&lt;td&gt;440.126 ms&lt;/td&gt;
&lt;td&gt;26.52%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;324.255 ms&lt;/td&gt;
&lt;td&gt;441.608 ms&lt;/td&gt;
&lt;td&gt;26.57%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Per parse&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.108 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.147 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;26.5%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Allocated per parse&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1,024 B&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3,816 B&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;73.2% fewer&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each serialiser's round times stayed within 0.63% of its mean. A short check on desktop .NET 10 also favoured STJ, but its timings varied too much to quote.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow-up: STJ vs the processor's resident Newtonsoft (22 Sep)
&lt;/h2&gt;

&lt;p&gt;A second fixture compared bundled STJ with the Newtonsoft.Json already on the processor. That's standard Newtonsoft 13.0.2 at &lt;code&gt;/simpl/app00/&lt;/code&gt;, left out of the merge and checked by identity before timing. As in the first run, both packages were Debug harness builds. They ran one after the other in separate host processes.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Round (3,000 parses)&lt;/th&gt;
&lt;th&gt;Bundled STJ 10.0.12&lt;/th&gt;
&lt;th&gt;Resident Newtonsoft 13.0.2&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;324.699 ms&lt;/td&gt;
&lt;td&gt;431.950 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;388.026 ms&lt;/td&gt;
&lt;td&gt;430.408 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;326.794 ms&lt;/td&gt;
&lt;td&gt;430.696 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;326.157 ms&lt;/td&gt;
&lt;td&gt;431.120 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Per parse&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.114 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.144 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Allocated per parse&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1,024 B&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3,816 B&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;STJ was about 21% faster overall. Leaving out the slow round 1, it was about 24% faster. The allocation difference is identical to the first run. The raw results include process memory snapshots, but the two runs started from different managed heaps (about 67 MB and 20 MB). Those figures measure host-process state, not serialiser cost, so don't compare them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does and doesn't show
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;On Mono, STJ allocates about a quarter as much as Newtonsoft and parses about 21–27% faster for this payload.&lt;/li&gt;
&lt;li&gt;These tests used warmed parsing and one small payload shape. They don't cover cold start, serialisation, peak memory or whole-driver CPU.&lt;/li&gt;
&lt;li&gt;At weather-polling intervals the absolute CPU savings are small. The allocation reduction matters more on a processor shared with other drivers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Deployment note for Crestron developers
&lt;/h2&gt;

&lt;p&gt;On this firmware, both standard Newtonsoft.Json 13.0.2 and Newtonsoft.Json.Compact 4.0.8.0 are resident in &lt;code&gt;/simpl/app00/&lt;/code&gt;, and System.Text.Json isn't. Crestron's &lt;a href="https://sdkcon78221.crestron.com/sdk/Crestron_Certified_Drivers_SDK/Content/Topics/Best-Practices/Best-Practices.htm" rel="noopener noreferrer"&gt;driver best-practices page&lt;/a&gt; lists Newtonsoft.Json among the DLLs Home loads, but still advises merging your dependencies to avoid DLL conflicts. So STJ has to ship inside your package, and so should Newtonsoft if you use it. None of this was measured against the Compact assembly. That's one firmware on one processor, not a platform guarantee.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproduce it
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/oznetmaster/WeatherLinkLiveLibrary/tree/531738c44f1419d451f141cc869dc5a2ab55d8a4/benchmarks/JsonDeserialization" rel="noopener noreferrer"&gt;Fixtures, payload, raw results and processor harnesses&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;AI disclosure: the benchmark fixtures and processor runs were done by GPT-6 Astra, and this write-up was generated by Claude, under my direction.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>performance</category>
      <category>crestron</category>
    </item>
  </channel>
</rss>
