zplCore.comzplCore.com

Plattformen & Cloud

Läuft überall, wo Ihr Backend läuft

Ein .NET-10-SDK ohne Druckertreiber, das Sie mit dotnet publish wie jede andere Abhängigkeit ausliefern: unter Windows, Linux und macOS, im IIS, in Docker-Containern und im Kubernetes-Cluster, on-premises oder in der Cloud wie Azure und AWS.

  • Windows
  • Linux
  • macOS
  • Docker
  • Kubernetes
  • Raspberry Pi
  • Synology NAS
  • IIS
  • Azure
  • AWS
GeprüftWindowsLinuxmacOS

Windows · Linux · macOS

Eine .NET-10-Assembly auf Basis von SkiaSharp und HarfBuzz. Die automatisierten Tests laufen auf Windows 11, macOS und Linux grün. Kein Druckertreiber und kein GUI nötig.

Cloud & EdgeDockerKubernetesLinuxRaspberry Pi

Container, NAS & Pi

Getestet in den .NET-Images für Debian, Ubuntu Chiseled und Azure Linux 3.0 (Distroless & NativeAOT). Selbst ein vorhandenes NAS wie eine Synology DS923+ (Container Manager) oder ein Raspberry Pi wird damit ohne Zusatzpakete zum lokalen Labelprint-Server.

Beispiel

Minimal-API-Beispiel

ASP.NET-Core-Beispiel mit Streaming-Endpunkten, einer begrenzten Queue (Channel + BackgroundService) und parallelen Workern.

Docker & Kubernetes: Dockerfile und Helm-Chart im Lieferumfang

  • Alle Tests laufen grün in den offiziellen .NET-10-Container-Images für Debian, Ubuntu 24.04 Chiseled und Azure Linux 3.0.
  • Dockerfile.server im Lieferumfang: Distroless-Image, läuft ohne Root-Rechte, mit /health-Endpunkt (oder als NativeAOT auf runtime-deps:10.0-noble-chiseled-extra ab ~79 MB).
  • Helm-Chart für Kubernetes im Lieferumfang. Das Image bauen Sie selbst, es liegt in keiner öffentlichen Registry.
  • Keine zusätzlichen Systempakete nötig, die nativen Bibliotheken bringt das NuGet-Paket mit.
  • Macht aus einem vorhandenen NAS (z. B. Synology DS923+ über den Container Manager, ~90 MiB RAM, 295 PNG-Labels/s mit NativeAOT) oder einem Raspberry Pi sofort einen lokalen Labelprint-Server im Lager.
  • Asynchrones ASP.NET-Core-Minimal-API-Beispiel mit Job-Queue (199.000 Labels/s ZPL-Erzeugung auf einem Mac).
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish samples/WebApiDemo -c Release -o /app

FROM mcr.microsoft.com/dotnet/aspnet:10.0-azurelinux3.0-distroless
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet","WebApiDemo.dll"]

Performance

Schnell genug für den Versandschluss um 18 Uhr

Alle Zahlen sind gemessen, nicht geschätzt: Release-Build, .NET 10, Apple M3 Max (10 Performance- + 4 Effizienzkerne). Die Benchmarks liegen im Repository bei.

Echtes Versandetikett: über 200.000 Etiketten pro Sekunde

Gemessen am 21.10.2026 mit samples/ShippingBench: Apple M3 Max (10 Performance- + 4 Effizienzkerne, 14 insgesamt), macOS 26.6, .NET 10, Release-Build, Workstation-GC. Ende zu Ende von den Datensätzen bis zur ZPL-Datei auf der Platte, Median aus 5 Läufen nach einem Aufwärmlauf. Alle Datenquellen schreiben eine byte-identische Datei mit 131 MB (per SHA-256 geprüft), unter JIT und NativeAOT gleichermaßen.

200.000+Versandetiketten/sDictionary- oder JSON-Datensätze → ZPL-Datei, JIT und NativeAOT
< 0,5 s100.000 VersandetikettenDictionary 0,40 s, JSON 0,46 s (Median)
1.000+PNG-Vorschauen/salle 14 Kerne, 203 dpi (1.224 JIT / 1.182 NativeAOT)
100.000+Etiketten/s aus C#-ObjektenPOCO-Bindung, JIT (124.995/s)
Das Benchmark-Etikett: Versandetikett 100 × 150 mm mit Absender, EXPRESS-Servicefeld, Empfänger, Routing-Code, Gewicht, Packstücken, Versanddatum, QR-Code, Code-128-Sendungsnummer und GS1-128-SSCC
Das Testetikett mit 203 dpi, einer der 100.000 Datensätze. Klick für 300 dpi.

Das Etikett

Ein Versandetikett 100 × 150 mm (4 × 6 Zoll) mit 33 Elementen: Absenderblock, invertiertes Servicefeld, Empfänger (Name, Straße, Ort, Land per Ausdruck), Routing-Code, Gewicht (0.0 kg), Packstücke, Versanddatum (Format(ToDate([ShipDate]), "dd.MM.yyyy")), QR-Code (Tracking-URL als Ausdruck), Code 128 (Sendungsnummer), GS1-128-SSCC (18 Stellen mit Prüfziffer), Seitenzähler, Rahmen und Linien. Der Druckauftrag ergänzt ein Start-Label (Tour, Depot, Gesamtgewicht und Packstücke, erste/letzte SSCC) und ein End-Label (Anzahl, erster/letzter Schlüssel).

Die Datensätze variieren wie echte Daten: Namen mit Umlauten und Doppelnamen, Firmenzusätze unterschiedlicher Länge, Türnummern, 9 Orte in AT/DE/CH/IT, 6 Services, 2,5–29 kg, 1–7 Packstücke, gültige SSCCs.

Methode

  • Datensätze → ZPL → Datei auf der Platte (StreamWriter, 64-KB-Puffer), wie bei einem Druckserver oder Batch-Job.
  • Byte-identische Ausgabe über alle Datenquellen, vor der Messung per SHA-256 geprüft; sonst bricht der Lauf ab.
  • Gleiche Daten, gleiche Reihenfolge, gleiche Maschine; ein Aufwärmlauf, dann der Median aus 5 Läufen.

Downloads

  • Etikett: PDF (Vektor, 1 Seite, 116 KB) · ZPL (203 dpi, 1,3 KB)
  • Druckauftrag (Start-Label + 3 Sendungen + End-Label): PDF (5 Seiten, 615 KB) · ZPL (300 dpi, 6,3 KB)
  • Bild: PNG 203 dpi · PNG 300 dpi

100.000 Versandetiketten + Start- und End-Label in eine ZPL-Datei. JIT- und NativeAOT-Build desselben Codes, Median aus 5 Läufen.

DatenquelleJIT Etiketten/sNativeAOT Etiketten/s100.000 Etiketten dauern
IReadOnlyDictionary<string, object?>-Datensätze249.286238.5900,40–0,42 s
JSON-Datensätze (JsonElement)216.171213.6370,46–0,47 s
POCO mit Map() je Feld128.16591.7840,78–1,09 s
POCO, For<T>() (Reflection)124.99583.9940,80–1,19 s
Gespeichertes Format (^DF/^XF), POCO109.53172.1130,91–1,39 s

Für Massendaten Dictionaries oder JSON übergeben: Sie bleiben unter JIT und NativeAOT über 200.000 Etiketten/s (langsamster Einzellauf 208.068/s). C#-Objekte (POCO) erreichen unter JIT rund 125.000/s, unter NativeAOT rund 84.000/s.

Selbst nachmessen

Der Benchmark liegt im Repository bei. sample schreibt das Etikett als PNG, PDF und ZPL; das Docker-Image entsteht aus build/Dockerfile.shippingbench. Die Werte hängen von Ihrer Hardware ab; sie sind Messungen, keine Garantie.

# JIT
dotnet run -c Release --project samples/ShippingBench
# NativeAOT (derselbe Code)
dotnet publish samples/ShippingBench -c Release -r osx-arm64 -p:PublishAot=true -o out
# Docker (NativeAOT) + 5 Millionen JSON-Lines-Datensätze
docker build -f build/Dockerfile.shippingbench -t zplcore-shippingbench .
docker run --rm -v zplcore-bench:/data zplcore-shippingbench 1000 10 1 5000000
# Etikett als PNG/PDF/ZPL
dotnet run -c Release --project samples/ShippingBench -- sample out/sample

Weitere Messungen: kleines Label mit 7 Elementen

Die folgenden Zahlen stammen aus samples/PerfTest, samples/RenderBench und samples/WebApiDemo, überwiegend mit einem kleinen Label 100 × 60 mm (PerfTest: 7 Elemente, also Text, Ausdruck, Zahlenformat, Code 128, Zähler), nicht mit dem Versandetikett oben. Derselbe Apple M3 Max.

199.000Labels/s ZPLgespeichertes Format, 100.000 Labels in einem Job (LiteDB → Datei: 0,50 s)
5.022PNG-Renderings/s10 Threads, Rendern + PNG, 9,2× gegenüber 1 Thread
24,8 s100.000 PNG-Vorschauenparallel auf 14 Kernen, 4.033 Labels/s (sequenziell 3,4 min)
1 Mio.Labels ohne LeckSpeicher bleibt flach, GC-Heap 2–3 MB

Ein Druckauftrag: Start-Label + 100.000 Sendungs-Labels + End-Label, Schnitt nur nach dem letzten Label. 14 Kerne, samples/PerfTest.

SzenarioZeitLabels/sGrößeSpeicher (Heap)
Objekte → ZPL, gespeichertes Format (^DF/^XF)0,73 s136.00014,7 MB24 MB
Objekte → ZPL, volles Format je Label0,39 s256.00029,1 MB24 MB
EF Core / SQLite AsAsyncEnumerable() → Datei0,57 s176.00014,7 MB29 MB
LiteDB-Query → Datei0,50 s202.00014,7 MB64 MB
PNG-Vorschau sequenziell (799 × 480 px, Graustufen)3,4 min49018,2 MB / 2.00084 MB
PNG-Vorschau parallel (14 Kerne)24,8 s4.03317,1 MB / 2.000106 MB

Die ZPL-Erzeugung ist praktisch kostenlos und streamt mit konstantem Speicher. Das gespeicherte Format halbiert die Datenmenge zum Drucker (14,7 statt 29,1 MB).

Methodik & Edge/NAS-Container

Release-Build, .NET 10, Apple M3 Max (10 Performance- + 4 Effizienzkerne). Zusätzlich als NativeAOT-Container (runtime-deps:10.0-noble-chiseled-extra, ~79 MB) auf einem Synology DS923+ NAS (AMD Ryzen R1600, 2 Kerne / 4 Threads) gemessen: 237.428 Labels/s Parsen, 1.233 Labels/s Bitmap-Rendern und 295 PNG-Labels/s (> 17.500 PNGs/min). Alle Messungen lassen sich mit einem Befehl wiederholen.

# 100.000-Label-Druckauftrag
dotnet run -c Release --project samples/PerfTest -- 100000
# Thread-Skalierung (label|text|barcode|box|empty)
dotnet run -c Release --project samples/RenderBench -- 150 scale