Starlings.Runtime.Onnx 0.3.0

dotnet add package Starlings.Runtime.Onnx --version 0.3.0
                    
NuGet\Install-Package Starlings.Runtime.Onnx -Version 0.3.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Starlings.Runtime.Onnx" Version="0.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Starlings.Runtime.Onnx" Version="0.3.0" />
                    
Directory.Packages.props
<PackageReference Include="Starlings.Runtime.Onnx" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Starlings.Runtime.Onnx --version 0.3.0
                    
#r "nuget: Starlings.Runtime.Onnx, 0.3.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Starlings.Runtime.Onnx@0.3.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Starlings.Runtime.Onnx&version=0.3.0
                    
Install as a Cake Addin
#tool nuget:?package=Starlings.Runtime.Onnx&version=0.3.0
                    
Install as a Cake Tool

Starlings.Runtime.Onnx

ONNX Runtime session ownership for Starlings models: provider selection with no silent fallback (CPU, or CUDA with TF32 always off), native/managed version check, diagnostics (versions, providers, options, model SHA-256, graph signature), cancellation (at node boundaries on CPU, after the current run on CUDA) and reference-counted disposal. The API may still change.

Maturity

Maturity is per profile, generated from the registry manifests by model-pipeline catalog (do not edit this table by hand). Gates, evidence and capabilities per profile: the model catalog.

Profile Maturity Platforms
embeddinggemma-2/image-fp32-cpu stable linux-x64 cpu: supported; windows-x64 cpu: untested
embeddinggemma-2/image-fp32-cuda stable linux-x64 cuda: supported; windows-x64 cuda: untested
embeddinggemma-2/onnx-fp32-cpu stable linux-x64 cpu: supported; windows-x64 cpu: experimental
embeddinggemma-2/onnx-fp32-cuda stable linux-x64 cuda: supported; windows-x64 cuda: untested
embeddinggemma-2/video-fp32-cpu stable linux-x64 cpu: supported; windows-x64 cpu: untested
embeddinggemma-2/video-fp32-cuda stable linux-x64 cuda: supported; windows-x64 cuda: untested
gliner2-base-v1/onnx-fp32-cpu stable linux-x64 cpu: supported; linux-x64 cuda: supported; windows-x64 cpu: experimental
gliner2-base-v1/onnx-fp32-cuda stable linux-x64 cuda: supported; windows-x64 cuda: untested
kev-0.8b/onnx-fp32-cpu experimental linux-x64 cpu: experimental; linux-x64 cuda: experimental; windows-x64 cpu: untested
kev-0.8b/onnx-fp32-cuda experimental linux-x64 cuda: experimental; windows-x64 cuda: untested
kev-4b/onnx-fp32-cpu experimental linux-x64 cpu: experimental; linux-x64 cuda: experimental; windows-x64 cpu: untested
kev-4b/onnx-fp32-cuda experimental linux-x64 cuda: experimental; windows-x64 cuda: untested
multilingual-e5-small/onnx-fp32-cpu stable linux-x64 cpu: supported; windows-x64 cpu: experimental
multilingual-e5-small/onnx-fp32-cuda stable linux-x64 cuda: supported; windows-x64 cuda: untested

API

using Microsoft.ML.OnnxRuntime;
using Starlings.Runtime.Onnx;

using var session = OnnxModelSession.Create("model.onnx", new OnnxSessionOptions
{
    Provider = OnnxExecutionProvider.Cpu,          // or Cuda; no fallback either way
    ExpectedModelSha256 = "<lowercase hex sha256>", // optional; mismatch throws OnnxModelIntegrityException
});
Console.WriteLine(session.Diagnostics.OrtVersion);
using var outputs = session.Run(inputNames, inputValues, outputNames, cancellationToken);
  • OnnxModelSession.Create(modelPath | byte[] model, options) loads once; Run is safe to call concurrently. One Run overload returns outputs the caller owns and disposes (before the session); the other writes into caller-allocated OrtValues. Input values stay caller-owned. Inputs, Outputs, Diagnostics, Placement and IsDisposed describe the session. Dispose is idempotent; runs already executing complete first.
  • OnnxSessionOptions (immutable record): Provider (default Cpu), CudaDeviceId (default 0), IntraOpNumThreads and InterOpNumThreads (null: defaults, below), ExpectedModelSha256, ComputeModelSha256 (default true), CapturePlacement (default false; when true, profiles the first run and publishes Placement, an OnnxPlacementReport of nodes per provider), and the memory settings under "Memory on Linux".
  • OnnxSessionDiagnostics: native and managed versions, available and session providers, provider options, thread counts, memory settings, graph optimization level, model source, size, SHA-256, metadata, and input and output signatures (OnnxTensorInfo).
  • OnnxRuntimeInfo: NativeVersion, ManagedVersion, AvailableProviders, CpuProviderName, CudaProviderName.
  • Exceptions: OnnxRuntimeUnavailableException (native library missing or of another version), OnnxProviderUnavailableException (the requested provider cannot be used; never followed by a fallback), OnnxModelIntegrityException (SHA-256 mismatch). A cancelled run throws OperationCanceledException; the session stays usable.

Native runtime

The package references only Microsoft.ML.OnnxRuntime.Managed (exactly 1.30.0). The application references exactly one native package of the same version:

Deployment Package
CPU Microsoft.ML.OnnxRuntime 1.30.0
CUDA, Linux x64 Microsoft.ML.OnnxRuntime.Gpu.Linux 1.30.0 (needs the CUDA 13 runtime, cuBLAS and cuDNN 9 on the loader path; not shipped)

Both ship libonnxruntime under the same file name. Without a native package, or with a different version, session creation fails with OnnxRuntimeUnavailableException naming the package to add.

Threads in containers

When IntraOpNumThreads is not set and a CPU quota or affinity mask limits the process (Environment.ProcessorCount below the host's online CPUs on Linux), the session uses Environment.ProcessorCount intra-op threads. ONNX Runtime's own default ignores a container's CPU quota and starts one thread per physical core of the host (147 threads, each with its own glibc malloc arena, for one CUDA e5 session in a 31-CPU container on a 256-CPU host). On an unconstrained host the ONNX Runtime default is kept. OnnxSessionDiagnostics.IntraOpNumThreads reports the count used. Evidence: CUDA soak growth.

Most applications use this package through a model package such as Starlings.Models.E5. Documentation: ai-dotnet/README.md.

Micro-batching (experimental)

Starlings.Runtime.Onnx.Batching.MicroBatcher<TItem, TResult> coalesces items queued by concurrent callers into batches for one batch function: at most MicroBatchingOptions.MaxRows items and MaxTokens padded token cells (rows x longest row, from a per-item token count), dispatched when full or when the oldest item has waited MaxWait; an optional group key keeps items that must not share a batch apart. One dispatcher thread runs one batch at a time with a token the batcher owns: a caller's cancellation removes its queued item, or cancels only its own task once dispatched (the batch token is cancelled only when every caller of the batch has cancelled). At most QueueCapacity items wait; further callers wait for a slot (backpressure). An exception from the batch function faults every caller of that batch, so callers validate items before queueing them. Disposal faults queued items with ObjectDisposedException, lets a running batch finish and waits for the dispatcher. The e5 and EmbeddingGemma 2 embedding generators and the GLiNER2 extractor expose it as an opt-in MicroBatching option.

Memory on Linux

When a session's native memory is released (after Dispose and the last in-flight run), the package calls glibc's malloc_trim(0) on Linux. glibc otherwise keeps the freed memory of the session (graph, initializers, ONNX Runtime's CPU arena, run buffers) resident in its heaps, so a process that loads and unloads models keeps up to about a model's worth of freed memory per malloc arena. On the hosted qualification runner the resident memory after unloading fell from about 1,480 to 400 to 500 MiB for EmbeddingGemma 2 text and from about 1,110 to 260 MiB for GLiNER2 without MALLOC_MMAP_THRESHOLD_ (evidence).

  • malloc_trim only returns memory that is already free. It changes no allocator setting (unlike mallopt or the MALLOC_* environment variables) and touches no live allocation. It runs once per released session, not on the request path; it costs a few milliseconds per release, and the next load faults the returned pages in again. The opt-in trims after load and after each run (below) call the same function.

  • It is a no-op on Windows and macOS, and on Linux without glibc (musl: the first release finds no libc.so.6 and turns it off; OnnxSessionDiagnostics.TrimNativeHeapOnRelease can report true for sessions created before that).

  • Opt out per session with OnnxSessionOptions.TrimNativeHeapOnRelease = false, or for the whole process (also for sessions a model package creates) with the AppContext switch Starlings.Runtime.Onnx.DisableNativeHeapTrim, for example in the application's project file:

    <ItemGroup>
      <RuntimeHostConfigurationOption Include="Starlings.Runtime.Onnx.DisableNativeHeapTrim" Value="true" />
    </ItemGroup>
    
  • CPU memory arena: OnnxSessionOptions.CpuMemoryArena turns ONNX Runtime's CPU arena (enable_cpu_mem_arena) on or off; null, the default, keeps ONNX Runtime's default (on) for sessions created directly and lets a model package choose for the sessions it creates (EmbeddingGemma 2 turns it off on CPU). With the arena, ONNX Runtime keeps the CPU buffers of every run in regions it does not return while the session lives; their resident size can climb toward the region size over many runs, and regions of up to 32 MiB freed at release stay resident in glibc's per-thread heaps, which malloc_trim cannot return. Outputs are the same either way. OnnxSessionDiagnostics.CpuMemoryArena reports the effective setting. Evidence: EmbeddingGemma 2 hosted soak.

  • Dedicated run threads: with OnnxSessionOptions.DedicatedRunThreads = true, runs execute on a small process-wide set of long-lived threads owned by this package, and the caller blocks until its run completes. A thread is started only when every existing one is busy, up to Environment.ProcessorCount; further concurrent runs wait for a free one. null, the default, runs on the calling thread for sessions created directly and lets a model package choose (EmbeddingGemma 2 and e5 use them on CPU). Why: without ONNX Runtime's CPU arena, a run allocates and frees its buffers with malloc on the thread that calls it, and glibc serves each thread from its own malloc arena. The free memory at the top of a non-main arena stays resident: malloc_trim does not return it, and free returns it only above the dynamic trim threshold (up to 64 MiB). When runs come from a rotating set of thread-pool threads, more and more arenas each keep 20 to 60 MiB, and resident memory steps up over an hour. On the dedicated threads the same few arenas serve every run, so that memory is reused. Results are the same either way. Cancellation works the same (the token sets ONNX Runtime's terminate flag); a run started from a dedicated thread executes inline. OnnxSessionDiagnostics.DedicatedRunThreads reports the setting. Evidence: EmbeddingGemma 2 soak reliability.

  • Trims after load and after each run: OnnxSessionOptions.TrimNativeHeapAfterLoad calls malloc_trim(0) once when the session has been created, and OnnxSessionOptions.TrimNativeHeapAfterRun calls it on the thread that ran, after each run. null, the default, means off for sessions created directly and lets a model package choose (the EmbeddingGemma 2 image and video path turns both on for its CPU sessions). Why: creating a large session allocates and frees copies of the graph and its initializers, and glibc keeps that memory resident while the session lives (about 400 MiB for the EmbeddingGemma 2 vision and multimodal sessions, varying from load to load). A run without ONNX Runtime's arena leaves its freed buffers as free chunks in the running thread's heap (60 to 190 MiB per thread for EmbeddingGemma 2 images, rising in steps). The trim returns both; it cannot return the top chunk of a non-main heap. The run trim is part of the run (milliseconds) and the next run faults the pages in again, so it suits runs that take seconds, not short ones. The AppContext switch above turns both off. OnnxSessionDiagnostics.TrimNativeHeapAfterLoad and TrimNativeHeapAfterRun report them. Evidence: EmbeddingGemma 2 image loaded soak.

  • Transparent huge pages: with /sys/kernel/mm/transparent_hugepage/enabled set to always, the kernel's khugepaged collapses partly used 2 MiB ranges of the heaps into huge pages and fills in their absent pages, so resident memory can rise over time with no allocation behind it. A library cannot change that policy for its host; madvise (the Ubuntu default) or never avoids it.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on Starlings.Runtime.Onnx:

Package Downloads
Starlings.Models.EmbeddingGemma2

google/embeddinggemma-2 (revision 914f7f89) text and image embeddings on ONNX Runtime, from text through the owned tokenizer (Starlings.Tokenizers, profile gemma-bpe-embeddinggemma2: no Microsoft.ML.Tokenizers, no native tokenizer) or from token ids: right-padded batching, mean pooling over every token including the prompt, L2 normalization, Matryoshka sizes 768/512/256/128, explicit named prompts (never added silently), inputs above 8,192 tokens rejected. Images: image-only and interleaved text-and-image embeddings from already-decoded RGB (no native dependency; the upstream processor restated bit for bit, including PyTorch's uint8 antialiased bicubic resize), default budget 280 soft tokens, vision graph plus multimodal text graph; text-only input keeps the released text graph. Videos: video-only and interleaved text/image/video embeddings from decoded RGB frames at the checkpoint settings (1 fps, at most 32 frames, 140 soft tokens per frame, no timestamps; upstream sampling restated exactly; frames without timing rejected unless opted in), same graphs; decoding is the optional FFmpeg adapter. Audio is not supported. Ships the asset locks (Starling's ONNX graphs and the pinned tokenizer.json), not the weights; acquire them explicitly. Profiles embeddinggemma-2/onnx-fp32-cpu, onnx-fp32-cuda, image-fp32-cpu, image-fp32-cuda, video-fp32-cpu and video-fp32-cuda (Linux x64). Apache-2.0 weights; deployments must adhere to the Gemma Prohibited Use Policy. The application adds the ONNX Runtime native package. Maturity is per model profile (Stable, Preview or Experimental): see the README, generated from the model registry.

Starlings.Models.E5

intfloat/multilingual-e5-small (revision 614241f6) sentence embeddings on ONNX Runtime, from text through the owned tokenizer (Starlings.Tokenizers: no Microsoft.ML.Tokenizers, no native tokenizer) or from token ids: right padding, mean pooling, L2 normalization. Ships the model's asset lock, not the weights; acquire them explicitly. Profiles multilingual-e5-small/onnx-fp32-cpu and onnx-fp32-cuda. The application adds the ONNX Runtime native package. Maturity is per model profile (Stable, Preview or Experimental): see the README, generated from the model registry.

Starlings.Models.Gliner2

fastino/gliner2-base-v1 (revision f9634218, GLiNER2 2.0.0) English entity extraction with labels and a threshold on ONNX Runtime: GLiNER2's Python text semantics (normalization, word splitter, lower-casing) and schema prefix through the owned tokenizer (Starlings.Tokenizers: no Microsoft.ML.Tokenizers, no native tokenizer), one ONNX graph, GLiNER2's span decoding, offsets into the original text. Ships the asset lock, not the weights; acquire them explicitly. Profiles gliner2-base-v1/onnx-fp32-cpu and onnx-fp32-cuda. The application adds the ONNX Runtime native package. Maturity is per model profile (Stable, Preview or Experimental): see the README, generated from the model registry.

Starlings.Models.Kev

Kev decision models (jaredpalmer/kev-0.8b and jaredpalmer/kev-4b, Kev 1.0) on ONNX Runtime: one state and typed questions (noul, choice, score) in, a calibrated probability per option out, in one prefill pass without generating text. Kev's request rendering and delimiter escaping in C#, token ids from the owned tokenizer (Starlings.Tokenizers profile qwen2-bpe-kev: no Microsoft.ML.Tokenizers), the Qwen3.5 backbone as an fp32 ONNX graph (the LoRA merged; ONNX Runtime GenAI builder without the LM head), the state run once and every question as its own row on the cached state, and Kev's pointer head. Ships the asset locks, not the weights. Profiles kev-0.8b/onnx-fp32-cpu and kev-4b/onnx-fp32-cpu, and onnx-fp32-cuda on the same bundles (TF32 off). The application adds the ONNX Runtime native package. Maturity is per model profile (Stable, Preview or Experimental): see the README, generated from the model registry.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.3.0 152 10/19/2026
0.2.0 226 10/17/2026
0.1.0-preview.6 127 10/14/2026