Skip to content

Embedded Linux port, hardware API and a garbage-free backend fast path - #6112

Merged
shai-almog merged 24 commits into
masterfrom
embedded-linux-port
Oct 27, 2026
Merged

shai-almog merged 24 commits into
masterfrom
embedded-linux-port

Conversation

@shai-almog

Copy link
Copy Markdown
Collaborator

Summary

  • Embedded Linux port (CN1_LINUX_EMBEDDED): DRM/KMS, fbdev or memory display, evdev input, a software rasterizer and FreeType text, with no GTK. scripts/embedded translates and builds for arm64, arm, amd64 and riscv64, and has Raspberry Pi OS, Yocto and Buildroot recipes.
  • Hardware API (com.codename1.hardware): GPIO, I2C, SPI, serial, PWM, CAN, watchdog and backlight. One C implementation (cn1_hardware_impl.h) serves the Linux port and the backend, and the JavaSE simulator has virtual devices.
  • Board profiles and cn1:deploy-device for Maven and Gradle: copies the binary over SSH and installs a systemd service.
  • Backend: a JSON request allocates nothing beyond the handler's result. The Host header is reused per connection, and each generated route encodes through one static Json.Encoder. This applies to every backend application with no flags.
  • Developer guide: an Embedded Linux chapter, plus benchmark tables and charts against Slint, Qt, JavaFX, Chromium, Rust, Go, Node.js, Python and Spring Boot.

CI

  • embedded-linux.yml (arm64 runner):
    • Checks the generated stubs.
    • Builds the demo the way the README tells a user to, runs it on the memory display, and fails on a missing, wrong-sized or blank frame or on slipped fps, first-frame or memory.
  • backend-performance.yml (arm64 runner):
    • Counts what a request allocates, exactly (census build, two runs subtracted).
    • Runs the headless comparison against Rust and Go on the same cores.
    • gate.py judges speed relative to Rust from the same job, and memory and allocation absolutely.
    • Uploads results and charts, so the guide's numbers can be refreshed from CI.

Hardening from review

  • Deploy: host, user and service names that could be read as options are refused, and -- ends ssh's options. The binary is streamed over ssh into a mktemp -d directory instead of a predictable /tmp path that root then installs from. Environment entries are quoted and escaped for systemd.
  • Hardware: serial opens only /dev/ paths. Names containing NUL are refused. I2C transfers over 65535 bytes are rejected instead of silently truncated.
  • Display: fbdev and DRM buffers smaller than the visible area are refused. A failed DRM buffer setup is unwound. The cursor is clipped on every edge. A glyph bitmap with a negative pitch is drawn blank instead of being read out of bounds.

Test plan

  • DeviceDeployerTest (option-injection cases added), backend SpotBugs/PMD 0, build-engine SpotBugs 0, control-character, author/since and copyright checks
  • Embedded demo built for arm64 and checked with check-demo-run.py (59 fps, first frame 159 ms, 18 MB RSS)
  • Backend gate dry run: on an uncontended round, 354–367k requests/s against Rust's 272–289k, and 1.00 object per request
  • Both new workflows green on the runner

🤖 Generated with Claude Code

The embedded variant of the native Linux port (DRM/KMS, fbdev or memory
display, evdev input, a software rasterizer, no GTK), a core hardware API
(GPIO, I2C, SPI, serial, PWM, CAN, watchdog, backlight) for the Linux port,
the backend and the simulator, board profiles and a deploy-to-device goal
for Maven and Gradle, and Yocto, Buildroot and Raspberry Pi OS recipes.

The backend answers a JSON request without allocating anything beyond the
handler's own result: the Host header is reused per connection and each
generated route encodes through one static Json.Encoder.

CI: embedded-linux.yml builds and runs the demo on an arm64 runner and
checks its frame, speed and memory; backend-performance.yml runs the
headless comparison against Rust and Go, counts per-request allocation
exactly and fails when the developer guide's numbers slip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shai-almog

shai-almog commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 12 screenshots: 12 matched.
✅ JavaSE simulator integration screenshots matched stored baselines.

… guide snippets by include

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shai-almog

shai-almog commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 227 screenshots: 227 matched.
✅ JavaScript-port screenshot tests passed.

@shai-almog

shai-almog commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 191 screenshots: 191 matched.

Native Android coverage

  • 📊 Line coverage: 18.90% (48254/255341 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 17.65% (229221/1299035), branch 12.04% (16821/139675), complexity 9.68% (12914/133466), method 14.57% (9124/62628), class 25.17% (1775/7052)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6367 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.ClassReader – 0.00% (0/1524 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.MethodWriter – 0.00% (0/922 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/736 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • okio.okio.Buffer – 0.00% (0/687 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • com.codename1.androidcompat.rt.com.codename1.androidcompat.rt.TextXmlPullParser – 0.00% (0/623 lines covered)
      • com.codename1.androidcompat.androidx.constraintlayout.core.widgets.com.codename1.androidcompat.androidx.constraintlayout.core.widgets.Flow – 0.00% (0/576 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 18.90% (48254/255341 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 17.65% (229221/1299035), branch 12.04% (16821/139675), complexity 9.68% (12914/133466), method 14.57% (9124/62628), class 25.17% (1775/7052)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6367 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.ClassReader – 0.00% (0/1524 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.MethodWriter – 0.00% (0/922 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/736 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • okio.okio.Buffer – 0.00% (0/687 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • com.codename1.androidcompat.rt.com.codename1.androidcompat.rt.TextXmlPullParser – 0.00% (0/623 lines covered)
      • com.codename1.androidcompat.androidx.constraintlayout.core.widgets.com.codename1.androidcompat.androidx.constraintlayout.core.widgets.Flow – 0.00% (0/576 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend scalar fallback (no native SIMD)
SIMD int-add (64K x300) java 427ms / native 168ms = 2.5x speedup
SIMD float-mul (64K x300) java 107ms / native 70ms = 1.5x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 93.000 ms
Base64 CN1 decode 84.000 ms
Base64 native encode 442.000 ms
Base64 encode ratio (CN1/native) 0.210x (79.0% faster)
Base64 native decode 275.000 ms
Base64 decode ratio (CN1/native) 0.305x (69.5% faster)
Image encode benchmark status skipped (SIMD unsupported)

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

✅ Continuous Quality Report

Test & Coverage

Static Analysis

  • SpotBugs [Report archive]
    • ✅ ByteCodeTranslator: 0 findings (no issues)
    • ✅ android: 0 findings (no issues)
    • ✅ android-compat: 0 findings (no issues)
    • ✅ android-res-compiler: 0 findings (no issues)
    • ✅ backend: 0 findings (no issues)
    • ✅ backend-test: 0 findings (no issues)
    • ✅ build-engine: 0 findings (no issues)
    • ✅ build-hint-catalog: 0 findings (no issues)
    • ✅ build-hint-tools: 0 findings (no issues)
    • ✅ codenameone-gradle-plugin: 0 findings (no issues)
    • ✅ codenameone-maven-plugin: 0 findings (no issues)
    • ✅ core-unittests: 0 findings (no issues)
    • ✅ desktop-compat-runtime: 0 findings (no issues)
    • ✅ fxml-compiler: 0 findings (no issues)
    • ✅ ios: 0 findings (no issues)
    • ✅ javac: 0 findings (no issues)
    • ✅ javafx-compat: 0 findings (no issues)
    • ✅ project-model: 0 findings (no issues)
    • ✅ swing-compat: 0 findings (no issues)
  • ✅ PMD: 0 findings (no issues) [Report archive]
  • ✅ Checkstyle: 0 findings (no issues) [Report archive]

Generated automatically by the PR CI workflow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Flutter vs Codename One

Same application, built both ways: Flutter's AOT compile of the gallery, and the identical Dart source transpiled to Java on Codename One. Lower is better for every metric, so a ratio above 1.00x means Codename One is ahead by that factor.

android

9 interleaved rounds; host load 0.45, 1.54, 1.28

Metric Codename One Flutter Ratio Winner
Installed size 78.2 MB 95.8 MB 1.22x Codename One
Executable code 4.7 MB 20.6 MB 4.41x Codename One
Download size (zipped) 78.2 MB 95.8 MB 1.22x Codename One
Cold start to first frame on screen 378 ms 1597 ms 3.67x Codename One
Memory at rest 45.2 MB 86.7 MB 1.92x Codename One

Start-up and memory at rest are judged round by round: the ratio is the median of the per-round ratios, each from two launches made back to back, and the times and sizes shown are each side's median, so the ratio need not equal their quotient. Codename One was ahead in 9 of 9 rounds on cold start to first frame on screen; 9 of 9 rounds on memory at rest.

Compute -- the VM workloads (vm/benchmarks), run inside each app; time is the best of the app's own repetitions, higher ratio means Codename One is faster.

Workload Codename One Flutter Ratio
intArithmetic 78 ms 164 ms 2.10x
longArithmetic 55 ms 52 ms 0.94x
mathTranscendental 216 ms 285 ms 1.32x
arraySequential 27 ms 31 ms 1.15x
arrayRandom 200 ms 239 ms 1.20x
objectAllocation 60 ms 33 ms 0.55x
valueEscape 6 ms 6 ms 1.00x
hashMapChurn 119 ms 243 ms 2.04x
stringBuilding 76 ms 98 ms 1.29x
recursion 66 ms 236 ms 3.58x
quicksortBench 131 ms 133 ms 1.01x
Geometric mean 1.31x

Gate: within tolerance against scripts/flutter-bench/baseline.

Android sizes are for the arm64-v8a slice a phone is delivered, on both sides; Flutter's release apk carries three ABIs and would otherwise count its engine about three times.
Android start-up and memory come from an x86_64 emulator with a software GPU. They compare the two runtimes on one machine; they are not phone timings, and a renderer that leans on the GPU is penalised more there.
This platform's adapter has not been exercised end to end before; treat the first published run as the thing under review.

javascript

9 interleaved rounds; host load 2.03, 1.29, 0.57

Metric Codename One Flutter Ratio Winner
Installed size 104.0 MB 122.5 MB 1.18x Codename One
Executable code 12.9 MB 25.2 MB 1.95x Codename One
Download size (zipped) 76.3 MB 84.1 MB 1.10x Codename One
Cold start to first frame on screen -- -- -- not measured
Memory at rest -- -- -- not measured

Compute -- the VM workloads (vm/benchmarks), run inside each app; time is the best of the app's own repetitions, higher ratio means Codename One is faster.

Workload Codename One Flutter Ratio
intArithmetic 644 ms wrong result Flutter: wrong result
longArithmetic 4959 ms did not run Flutter: did not run
mathTranscendental 574 ms did not run Flutter: did not run
arraySequential 228 ms 82 ms 0.36x
arrayRandom 998 ms wrong result Flutter: wrong result
objectAllocation 38 ms 27 ms 0.71x
valueEscape 154 ms 7 ms 0.04x
hashMapChurn 1138 ms 248 ms 0.22x
stringBuilding 525 ms 108 ms 0.21x
recursion 507 ms 490 ms 0.97x
quicksortBench 415 ms wrong result Flutter: wrong result
Geometric mean 0.28x

Gate: within tolerance against scripts/flutter-bench/baseline; BEHIND FLUTTER on Compute (geomean of the VM workloads) (reported, not gated: a loss to Flutter on the web is currently accepted).

the JavaScript adapter needs a Chrome DevTools driver; sizes are reported and timings are not
This platform's adapter has not been exercised end to end before; treat the first published run as the thing under review.

linux

9 interleaved rounds; host load 0.2, 3.13, 2.67

Metric Codename One Flutter Ratio Winner
Installed size 111.7 MB 143.8 MB 1.29x Codename One
Executable code 14.2 MB 16.1 MB 1.13x Codename One
Download size (zipped) 80.9 MB 92.9 MB 1.15x Codename One
Cold start to first frame on screen 154 ms 219 ms 1.48x Codename One
Memory at rest 84.7 MB 225.4 MB 2.67x Codename One

Start-up and memory at rest are judged round by round: the ratio is the median of the per-round ratios, each from two launches made back to back, and the times and sizes shown are each side's median, so the ratio need not equal their quotient. Codename One was ahead in 9 of 9 rounds on cold start to first frame on screen; 9 of 9 rounds on memory at rest.

Compute -- the VM workloads (vm/benchmarks), run inside each app; time is the best of the app's own repetitions, higher ratio means Codename One is faster.

Workload Codename One Flutter Ratio
intArithmetic 74 ms 183 ms 2.47x
longArithmetic 56 ms 55 ms 0.98x
mathTranscendental 253 ms 276 ms 1.09x
arraySequential 15 ms 35 ms 2.33x
arrayRandom 355 ms 283 ms 0.80x
objectAllocation 26 ms 38 ms 1.46x
valueEscape 5 ms 7 ms 1.40x
hashMapChurn 48 ms 325 ms 6.77x
stringBuilding 32 ms 112 ms 3.50x
recursion 87 ms 257 ms 2.95x
quicksortBench 138 ms 149 ms 1.08x
Geometric mean 1.83x

Gate: within tolerance against scripts/flutter-bench/baseline.

This platform's adapter has not been exercised end to end before; treat the first published run as the thing under review.

windows

9 interleaved rounds

Metric Codename One Flutter Ratio Winner
Installed size 107.8 MB 121.1 MB 1.12x Codename One
Executable code 11.4 MB 14.1 MB 1.24x Codename One
Download size (zipped) 77.9 MB 86.4 MB 1.11x Codename One
Cold start to first frame on screen 173 ms 276 ms 1.59x Codename One
Memory at rest 57.9 MB 92.5 MB 1.59x Codename One

Start-up and memory at rest are judged round by round: the ratio is the median of the per-round ratios, each from two launches made back to back, and the times and sizes shown are each side's median, so the ratio need not equal their quotient. Codename One was ahead in 9 of 9 rounds on cold start to first frame on screen; 9 of 9 rounds on memory at rest.

Compute -- the VM workloads (vm/benchmarks), run inside each app; time is the best of the app's own repetitions, higher ratio means Codename One is faster.

Workload Codename One Flutter Ratio
intArithmetic 82 ms 183 ms 2.23x
longArithmetic 63 ms 58 ms 0.92x
mathTranscendental 198 ms 268 ms 1.35x
arraySequential 14 ms 36 ms 2.57x
arrayRandom 265 ms 316 ms 1.19x
objectAllocation 25 ms 41 ms 1.64x
valueEscape 1 ms 7 ms 7.00x
hashMapChurn 49 ms 358 ms 7.31x
stringBuilding 35 ms 131 ms 3.74x
recursion 197 ms 266 ms 1.35x
quicksortBench 139 ms 149 ms 1.07x
Geometric mean 2.12x

Gate: within tolerance against scripts/flutter-bench/baseline. Smaller than its baseline, which does not fail the gate: Executable code -10.62%; Download size (zipped) -0.76% -- rebaseline to tighten. To accept the move, download this platform's baseline-<platform>.json artifact and run python3 scripts/flutter-bench/flutter_baseline.py calibrate --pr 6112 --reason "<why these moved>" baseline-windows.json, then commit the overlay it writes.

This platform's adapter has not been exercised end to end before; treat the first published run as the thing under review.

Codename One wins 18 of 18 measured metrics across 4 platform(s).

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Developer Guide build artifacts are available for download from this workflow run:

Developer Guide quality checks:

  • AsciiDoc linter: No issues found (report)
  • Vale: No alerts found (report)
  • Paragraph capitalization: No paragraph capitalization issues (report)
  • LanguageTool: No grammar matches (report)
  • Image references: No unused images detected (report)

@github-actions

Copy link
Copy Markdown
Contributor

Cloudflare Preview

@shai-almog

shai-almog commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 206 screenshots: 206 matched.
Native Windows port, REAL shipping pipeline: the hellocodenameone screenshot suite rendered by a binary CROSS-COMPILED on Linux (clang-cl + xwin, WebView2 linked) and RUN on a Windows x64 runner. Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 56ms / native 5ms = 11.2x speedup
SIMD float-mul (64K x300) java 57ms / native 5ms = 11.4x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 72.000 ms
Base64 CN1 decode 90.000 ms
Base64 SIMD encode 113.000 ms
Base64 encode ratio (SIMD/CN1) 1.569x (56.9% slower)
Base64 SIMD decode 106.000 ms
Base64 decode ratio (SIMD/CN1) 1.178x (17.8% slower)
Image encode benchmark iterations 100
Image createMask (SIMD off) 9.000 ms
Image createMask (SIMD on) 3.000 ms
Image createMask ratio (SIMD on/off) 0.333x (66.7% faster)
Image applyMask (SIMD off) 24.000 ms
Image applyMask (SIMD on) 28.000 ms
Image applyMask ratio (SIMD on/off) 1.167x (16.7% slower)
Image modifyAlpha (SIMD off) 31.000 ms
Image modifyAlpha (SIMD on) 22.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.710x (29.0% faster)
Image modifyAlpha removeColor (SIMD off) 28.000 ms
Image modifyAlpha removeColor (SIMD on) 17.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.607x (39.3% faster)

@shai-almog

shai-almog commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 206 screenshots: 206 matched.
Native Windows port (x64 / Intel-AMD): full hellocodenameone screenshot suite rendered offscreen with Direct2D/DirectWrite, plus the real benchmarks (base64 native/CN1/SIMD, image createMask/applyMask/modifyAlpha/PNG/JPEG, SSE2 SIMD kernels). Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 63ms / native 4ms = 15.7x speedup
SIMD float-mul (64K x300) java 56ms / native 4ms = 14.0x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 74.000 ms
Base64 CN1 decode 90.000 ms
Base64 SIMD encode 109.000 ms
Base64 encode ratio (SIMD/CN1) 1.473x (47.3% slower)
Base64 SIMD decode 112.000 ms
Base64 decode ratio (SIMD/CN1) 1.244x (24.4% slower)
Image encode benchmark iterations 100
Image createMask (SIMD off) 10.000 ms
Image createMask (SIMD on) 2.000 ms
Image createMask ratio (SIMD on/off) 0.200x (80.0% faster)
Image applyMask (SIMD off) 26.000 ms
Image applyMask (SIMD on) 51.000 ms
Image applyMask ratio (SIMD on/off) 1.962x (96.2% slower)
Image modifyAlpha (SIMD off) 61.000 ms
Image modifyAlpha (SIMD on) 29.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.475x (52.5% faster)
Image modifyAlpha removeColor (SIMD off) 53.000 ms
Image modifyAlpha removeColor (SIMD on) 25.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.472x (52.8% faster)

ParparVM vs HotSpot (JDK 25): Windows x64

Runner CPU: AMD64 Family 25 Model 1 Stepping 1, AuthenticAMD (baseline windows-x64@amd64-family-25-model-1-authenticamd)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in vm/selfhost/perf-baseline/ is a regression and fails; one that far below is an improvement, reported but not failed (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (WinHelloMain) 4 1.39x (base 1.22x, +13.8%) 0.57x (base 0.94x, -39.3%) ok
translator (self) 4 0.76x (base 0.83x, -8.2%) 0.54x (base 0.54x, +0.5%) ok
intArithmetic 4 1.10x (base 1.10x, +0.0%) 0.06x (base 0.06x, +2.8%) ok
longArithmetic 4 1.14x (base 1.08x, +5.1%) 0.06x (base 0.05x, +3.5%) ok
mathTranscendental 4 0.79x (base 0.79x, -0.2%) 0.06x (base 0.06x, +3.0%) ok
arraySequential 4 1.40x (base 1.36x, +2.8%) 0.39x (base 0.39x, +0.1%) ok
arrayRandom 4 1.02x (base 1.06x, -3.6%) 0.23x (base 0.23x, +0.5%) ok
objectAllocation 4 1.46x (base 1.56x, -6.3%) 0.31x (base 0.39x, -18.6%) ok
valueEscape 4 0.10x (base 0.10x, +0.4%) 0.05x (base 0.04x, +5.1%) ok
hashMapChurn 4 1.86x (base 1.80x, +3.6%) 0.09x (base 0.09x, +0.2%) ok
stringBuilding 4 1.34x (base 1.22x, +10.6%) 0.32x (base 0.32x, -0.2%) ok
recursion 4 1.41x (base 1.49x, -5.9%) 0.06x (base 0.06x, +1.7%) ok
quicksort 4 1.11x (base 1.13x, -2.0%) 0.12x (base 0.12x, +0.8%) ok

Result: no regression

@shai-almog

shai-almog commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 206 screenshots: 206 matched.
Native Windows port (arm64 / Apple Silicon - Arm): full hellocodenameone screenshot suite rendered offscreen with Direct2D/DirectWrite, plus the real benchmarks (base64 native/CN1/SIMD, image createMask/applyMask/modifyAlpha/PNG/JPEG, NEON SIMD kernels). Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 49ms / native 3ms = 16.3x speedup
SIMD float-mul (64K x300) java 49ms / native 2ms = 24.5x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 60.000 ms
Base64 CN1 decode 73.000 ms
Base64 SIMD encode 77.000 ms
Base64 encode ratio (SIMD/CN1) 1.283x (28.3% slower)
Base64 SIMD decode 73.000 ms
Base64 decode ratio (SIMD/CN1) 1.000x (0.0% slower)
Image encode benchmark iterations 100
Image createMask (SIMD off) 6.000 ms
Image createMask (SIMD on) 1.000 ms
Image createMask ratio (SIMD on/off) 0.167x (83.3% faster)
Image applyMask (SIMD off) 21.000 ms
Image applyMask (SIMD on) 28.000 ms
Image applyMask ratio (SIMD on/off) 1.333x (33.3% slower)
Image modifyAlpha (SIMD off) 26.000 ms
Image modifyAlpha (SIMD on) 27.000 ms
Image modifyAlpha ratio (SIMD on/off) 1.038x (3.8% slower)
Image modifyAlpha removeColor (SIMD off) 26.000 ms
Image modifyAlpha removeColor (SIMD on) 20.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.769x (23.1% faster)

ParparVM vs HotSpot (JDK 25): Windows arm64

Runner CPU: ARMv8 (64-bit) Family 8 Model D49 Revision 0, MICROSOFT CORPORATION (baseline windows-arm64@armv8-64-bit-family-8-model-d49-microsoft-corporation)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in vm/selfhost/perf-baseline/ is a regression and fails; one that far below is an improvement, reported but not failed (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (WinHelloMain) 4 1.00x (base 1.11x, -9.2%) 0.60x (base 0.75x, -20.5%) ok
translator (self) 4 0.88x (base 0.84x, +5.2%) 0.49x (base 0.51x, -3.9%) ok
intArithmetic 4 1.04x (base 1.04x, -0.0%) 0.06x (base 0.06x, +3.0%) ok
longArithmetic 4 0.79x (base 0.80x, -0.0%) 0.06x (base 0.06x, +3.4%) ok
mathTranscendental 4 0.72x (base 0.72x, +0.0%) 0.07x (base 0.06x, +1.6%) ok
arraySequential 4 0.38x (base 0.46x, -17.0%) 0.39x (base 0.39x, +0.0%) ok
arrayRandom 4 0.94x (base 0.94x, +0.1%) 0.23x (base 0.23x, +0.2%) ok
objectAllocation 4 1.84x (base 1.82x, +0.9%) 0.40x (base 0.43x, -6.8%) ok
valueEscape 4 0.76x (base 0.76x, +0.0%) 0.05x (base 0.05x, +3.4%) ok
hashMapChurn 4 0.99x (base 0.98x, +0.9%) 0.11x (base 0.12x, -7.5%) ok
stringBuilding 4 1.61x (base 1.43x, +12.6%) 0.27x (base 0.27x, -0.4%) ok
recursion 4 1.55x (base 1.46x, +5.9%) 0.07x (base 0.07x, +1.2%) ok
quicksort 4 1.00x (base 1.00x, +0.3%) 0.12x (base 0.12x, +0.6%) ok

Result: no regression

shai-almog and others added 3 commits October 26, 2026 12:09
- Optional GLES2 compositor for the embedded port (CN1_EMBEDDED_GPU, the
  linux.embedded.renderer hint, board defaults), with the software raster as
  fallback and a CI check that both draw the same pixels. The software raster
  now applies a SOURCE/CLEAR operation alpha as coverage, as Cairo does.
- Multicast DNS in Java (com.codename1.impl.MdnsEngine, shared with the
  backend) over a libc UDP socket (cn1_mdns_impl.h): Bonjour on the Linux
  ports with no Avahi, and com.codename1.backend.Discovery on the backend.
  Interoperates with Apple's mDNSResponder (dns-sd browses and resolves it).
- com.codename1.qrcode: QR generation (all versions and levels), shared with
  the backend for SVG; QrCodeImage on the client.
- Catch LinkageError in LinuxImplementation: the device class library has no
  UnsatisfiedLinkError, which broke every translated Linux build.
- Print the allocation census before the exit walks, so a server's racing
  exit no longer loses it (backend-performance gate).
- Developer guide prose fixes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… docs gates

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shai-almog

shai-almog commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 206 screenshots: 206 matched.
Native Linux port (arm64), GTK3/Cairo/Pango, ParparVM bytecode-to-C (no JVM): the hellocodenameone screenshot suite rendered by a native ELF built + run on the GitHub arm64 runner. Baseline: scripts/linux/screenshots-arm.

ParparVM vs HotSpot (JDK 25): Linux arm64

Runner CPU: Neoverse-N2 (baseline linux-arm64@neoverse-n2)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in vm/selfhost/perf-baseline/ is a regression and fails; one that far below is an improvement, reported but not failed (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (LinuxHelloMain) 4 0.92x (base 1.02x, -9.8%) 0.65x (base 0.93x, -30.5%) ok
translator (self) 4 0.74x (base 0.70x, +6.0%) 0.42x (base 0.43x, -3.0%) ok
intArithmetic 4 1.04x (base 1.04x, -0.0%) 0.04x (base 0.03x, +7.1%) ok
longArithmetic 4 0.79x (base 0.79x, -0.0%) 0.03x (base 0.03x, +5.0%) ok
mathTranscendental 4 1.10x (base 1.10x, -0.0%) 0.04x (base 0.03x, +9.3%) ok
arraySequential 4 0.36x (base 0.36x, -1.1%) 0.37x (base 0.37x, +0.2%) ok
arrayRandom 4 0.94x (base 0.94x, +0.4%) 0.20x (base 0.20x, +0.7%) ok
objectAllocation 4 1.98x (base 1.77x, +11.8%) 0.37x (base 0.37x, -0.5%) ok
valueEscape 4 0.51x (base 0.51x, -0.1%) 0.03x (base 0.03x, +4.9%) ok
hashMapChurn 4 0.85x (base 0.84x, +0.8%) 0.11x (base 0.12x, -5.0%) ok
stringBuilding 4 1.49x (base 1.57x, -5.1%) 0.26x (base 0.26x, -0.2%) ok
recursion 4 1.41x (base 1.43x, -1.4%) 0.04x (base 0.04x, +3.0%) ok
quicksort 4 1.02x (base 0.99x, +2.4%) 0.09x (base 0.09x, +1.1%) ok

Result: no regression

shai-almog and others added 2 commits October 26, 2026 15:42
…(CI shows THP is madvise, 0 kB huge)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…links

An idle server mapped libcurl and the distribution's TLS stack behind it
(GnuTLS, p11-kit, Kerberos, GMP, Nettle: ~5.5MB of 13.3MB PSS) without
ever calling out. Static links keep -lcurl.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

✅ ByteCodeTranslator Quality Report

Test & Coverage

  • ✅ Tests: 882 total, 0 failed, 55 skipped

Benchmark Results

  • Execution Time: 6772 ms

  • Hotspots (Top 20 sampled methods):

    • 9.16% com.codename1.tools.translator.IteratorEscape.ctorOnlyStoresParamsIntoThis (95 samples)
    • 8.39% java.util.ArrayList.indexOf (87 samples)
    • 6.17% java.lang.System.identityHashCode (64 samples)
    • 5.50% com.codename1.tools.translator.BytecodeMethod.equals (57 samples)
    • 4.24% java.lang.Object.hashCode (44 samples)
    • 2.80% com.codename1.tools.translator.IteratorEscape.walk (29 samples)
    • 2.80% com.codename1.tools.translator.IteratorEscape.mangle (29 samples)
    • 2.70% java.lang.StringBuilder.append (28 samples)
    • 1.83% java.util.HashMap.hash (19 samples)
    • 1.83% java.util.AbstractCollection.containsAll (19 samples)
    • 1.64% com.codename1.tools.translator.JavascriptReachability.enqueueResolved (17 samples)
    • 1.64% java.lang.String.equals (17 samples)
    • 1.54% java.io.FileOutputStream.writeBytes (16 samples)
    • 1.45% com.codename1.tools.translator.classfile.analysis.SourceInterpreter.merge (15 samples)
    • 1.45% com.codename1.tools.translator.Parser.cullMethods (15 samples)
    • 1.45% com.codename1.tools.translator.BytecodeMethod.updateInlinableFieldDependencies (15 samples)
    • 1.35% com.codename1.tools.translator.NativeSymbolIndex.<init> (14 samples)
    • 1.25% com.codename1.tools.translator.ByteCodeClass.hasDeclaredMethod (13 samples)
    • 1.06% com.codename1.tools.translator.DeadFieldElimination.run (11 samples)
    • 0.96% java.io.FileOutputStream.open0 (10 samples)
  • ⚠️ Coverage report not generated.

Static Analysis

  • ✅ SpotBugs: no findings (report was not generated by the build).
  • ⚠️ PMD report not generated.
  • ⚠️ Checkstyle report not generated.

Generated automatically by the PR CI workflow.

@shai-almog

shai-almog commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 192 screenshots: 192 matched.
✅ Native Mac screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 471 seconds

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 59ms / native 3ms = 19.6x speedup
SIMD float-mul (64K x300) java 60ms / native 3ms = 20.0x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 48.000 ms
Base64 CN1 decode 55.000 ms
Image encode benchmark iterations 100
Image createMask (SIMD off) 7.000 ms
Image createMask (SIMD on) 2.000 ms
Image createMask ratio (SIMD on/off) 0.286x (71.4% faster)
Image applyMask (SIMD off) 56.000 ms
Image applyMask (SIMD on) 40.000 ms
Image applyMask ratio (SIMD on/off) 0.714x (28.6% faster)
Image modifyAlpha (SIMD off) 35.000 ms
Image modifyAlpha (SIMD on) 38.000 ms
Image modifyAlpha ratio (SIMD on/off) 1.086x (8.6% slower)
Image modifyAlpha removeColor (SIMD off) 32.000 ms
Image modifyAlpha removeColor (SIMD on) 27.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.844x (15.6% faster)

ParparVM vs HotSpot (JDK 25): macOS arm64

Runner CPU: Apple M1 (Virtual) (baseline macos-arm64)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in vm/selfhost/perf-baseline/ is a regression and fails; one that far below is an improvement, reported but not failed (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (HelloCodenameOne) 3 0.85x (base 0.96x, -10.8%) 0.92x (base 0.93x, -0.7%) ok
translator (self) 3 0.66x (base 0.62x, +5.7%) 0.53x (base 0.78x, -32.0%) ok
intArithmetic 3 1.06x (base 1.03x, +2.2%) 0.12x (base 0.12x, +1.6%) ok
longArithmetic 3 1.03x (base 1.03x, +0.0%) 0.11x (base 0.07x, +62.0%) ok
mathTranscendental 3 1.01x (base 1.01x, -0.0%) 0.12x (base 0.12x, +1.8%) ok
arraySequential 3 0.45x (base 0.42x, +7.2%) 0.53x (base 0.53x, +0.3%) ok
arrayRandom 3 0.98x (base 0.99x, -1.2%) 0.32x (base 0.32x, +0.1%) ok
objectAllocation 3 0.99x (base 1.11x, -10.2%) 0.48x (base 0.72x, -33.3%) ok
valueEscape 3 0.50x (base 0.51x, -0.5%) 0.09x (base 0.09x, +0.8%) ok
hashMapChurn 3 1.08x (base 1.18x, -8.2%) 0.07x (base 0.07x, +4.2%) ok
stringBuilding 3 0.91x (base 0.84x, +7.8%) 0.39x (base 0.46x, -15.9%) ok
recursion 3 1.21x (base 1.24x, -2.0%) 0.12x (base 0.12x, +1.5%) ok
quicksort 3 1.01x (base 1.01x, -0.6%) 0.11x (base 0.11x, +0.3%) ok

Result: no regression

shai-almog and others added 7 commits October 26, 2026 20:00
Outbox (com.codename1.io.outbox, shared with the backend) keeps outgoing
messages in the session's database, in the caller's transaction, and sends
them in order with backoff, at least once, keyed for deduplication.
CertificateRequest encodes and signs PKCS#10 requests on either side.
ConnectionRequest.setClientCertificate presents a client certificate on
JavaSE, Android and Linux (libcurl blobs); the Linux port also honours
setInsecure, which it ignored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
deploy-device writes CN1_PROFILE=device into the unit unless the environment
names a profile (cn1.device.profile overrides, empty disables), so one backend
module carries device and cloud roles selected with @Profile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…apes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s missing

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	docs/developer-guide/languagetool-accept.txt
Comment thread Ports/Android/src/com/codename1/impl/android/TrustModifier.java Fixed
Comment thread Ports/JavaSE/src/com/codename1/impl/javase/TrustModifier.java Fixed
…headers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shai-almog and others added 5 commits October 27, 2026 01:07
…d with the lazy load

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nable

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…equest fails; bench gates warm start

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shai-almog

shai-almog commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 206 screenshots: 206 matched.
Native Linux port (x64), GTK3/Cairo/Pango, ParparVM bytecode-to-C (no JVM): the hellocodenameone screenshot suite rendered by a native ELF built + run on the GitHub x64 runner. Baseline: scripts/linux/screenshots.

ParparVM vs HotSpot (JDK 25): Linux x64

Runner CPU: AMD EPYC 7763 64-Core Processor (baseline linux-x64@amd-epyc-7763-64-core-processor)

2 improvements past the baseline (not a failure; rebaseline to lock them in):

  • translator (self) on all 4 CPUs: time 0.50x against a 0.64x baseline (-22.1%, tolerance 20%)
  • objectAllocation on all 4 CPUs: RAM 0.23x against a 0.35x baseline (-34.1%, tolerance 30%)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in vm/selfhost/perf-baseline/ is a regression and fails; one that far below is an improvement, reported but not failed (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (LinuxHelloMain) 4 0.83x (base 0.85x, -1.9%) 0.69x (base 0.83x, -17.2%) ok
translator (self) 4 0.50x (base 0.64x, -22.1%) 0.49x (base 0.52x, -5.9%) improved: rebaseline to lock in (time -22.1%)
intArithmetic 4 1.10x (base 1.12x, -1.2%) 0.06x (base 0.06x, +1.3%) ok
longArithmetic 4 1.14x (base 1.08x, +5.1%) 0.06x (base 0.05x, +5.1%) ok
mathTranscendental 4 1.08x (base 1.08x, -0.1%) 0.06x (base 0.07x, -21.7%) ok
arraySequential 4 2.46x (base 2.00x, +22.9%) 0.36x (base 0.36x, -0.2%) ok
arrayRandom 4 1.09x (base 0.91x, +19.7%) 0.21x (base 0.21x, -0.1%) ok
objectAllocation 4 1.73x (base 1.65x, +4.9%) 0.23x (base 0.35x, -34.1%) improved: rebaseline to lock in (RAM -34.1%)
valueEscape 4 0.10x (base 0.10x, -0.3%) 0.04x (base 0.04x, +1.7%) ok
hashMapChurn 4 1.51x (base 1.48x, +1.8%) 0.10x (base 0.09x, +1.3%) ok
stringBuilding 4 1.44x (base 1.39x, +3.9%) 0.26x (base 0.31x, -16.9%) ok
recursion 4 1.39x (base 1.25x, +10.4%) 0.08x (base 0.08x, +1.5%) ok
quicksort 4 1.09x (base 1.07x, +1.6%) 0.13x (base 0.11x, +16.5%) ok

A change that moves performance ON PURPOSE records the new baseline in vm/selfhost/perf-baseline/pr/6112.json, with the reason, from this job's perf-results.json. The rebaseline is then part of this pull request's diff:

python3 vm/selfhost/calibrate-perf-baseline.py --pr 6112 --reason "<why these benchmarks moved>" perf-results.json

Result: no regression (improved past the baseline: consider rebaselining)

@shai-almog

shai-almog commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 249 screenshots: 249 matched.
✅ Native Apple Watch (watchOS, Core Graphics) screenshot tests passed.

shai-almog and others added 3 commits October 27, 2026 10:36
@shai-almog
shai-almog merged commit b0f4618 into master Oct 27, 2026
117 of 139 checks passed
@shai-almog
shai-almog deleted the embedded-linux-port branch October 27, 2026 17:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants