Skip to content

Developer guide: show what the protocol generators actually emit - #5811

Merged
shai-almog merged 9 commits into
masterfrom
dg-appendix-goals
Sep 14, 2026
Merged

Developer guide: show what the protocol generators actually emit#5811
shai-almog merged 9 commits into
masterfrom
dg-appendix-goals

Conversation

@shai-almog

Copy link
Copy Markdown
Collaborator

The three generate-* appendices each stop at a colon where a listing should be — six of them:

  • "The @GraphQLClient interface looks like:"
  • "Call sites use the static factory:" (×3)
  • "A subscription returns a GraphQLSubscription handle whose cancel() ends the stream:"
  • "The @GrpcClient interface looks like:"

The listings are generated, not written

Rather than hand-write something that looks like generator output, this runs the generators. GenerateGraphQLMojo.Generator, GenerateGrpcMojo.Generator and GenerateOpenApiMojo.Generator were driven against the exact schema / proto / spec the chapters describe — the same fixtures their own unit tests use — and the output committed under docs/demos/common/src/main/java/com/example/{starwars,hello,petstore}, with only // tag:: markers added.

So the book shows the generators answer, and a change in emission shape lands here as a diff instead of quietly making the chapter wrong.

It caught one

The openapi chapter says models are emitted as @Mapped record (Java 17+) or class (Java 8). The Pet.java it pointed at was a PropertyBusinessObject with Property<Long, Pet> fields — nothing the generator has ever written. The real one is:

@Mapped
public record Pet(@JsonProperty("id") Long id, @JsonProperty("name") String name) {}

PetApi.java was closer but still not the emitted form. Both are now the generators output.

The call sites are hand-written

A generator does not emit those. Each carries the one thing its response type gets wrong by default, in a comment beside the branch:

  • gRPC-Web reports failure under HTTP 200, so getResponseCode() (the gRPC status) is what to read.
  • A GraphQL response can carry data and errors at once, so isOk() is about the errors array, not about whether getData() is null.

Gates

  • check-missing-code-blocks ratchet 34 → 28
  • validate-guide-snippets.py — 1113 include-backed blocks, up from 1107
  • every com/example/** source compiles under JDK 17 against codenameone-core
  • structure (122 documents), xrefs (1691 anchors), links, unused images, alt text — clean
  • asciidoctor --failure-level WARN and asciidoctor-pdf — clean
  • Vale 0 alerts across the three chapters; LanguageTool status: ok, total: 0 on each
  • capitalization, control characters, copyright headers — clean; all sources pure ASCII

One thing for a separate change

The GraphQL generator emits import com.codename1.annotations.JsonProperty; into every response record that never uses it. Harmless, and visible in the committed output — but fixing it is a plugin change, not a docs one.

The three generate-* appendices each stop at a colon where a listing
should be: "The @GraphQLClient interface looks like:", "Call sites use
the static factory:", "A subscription returns a GraphQLSubscription
handle whose cancel() ends the stream:". Six of them.

Rather than hand-writing something that looks like generated code, this
runs the generators. GenerateGraphQLMojo.Generator, GenerateGrpcMojo.
Generator and GenerateOpenApiMojo.Generator were driven against the exact
schema, proto and spec the chapters describe -- the same fixtures their
unit tests use -- and the output committed under docs/demos/common, with
only tag markers added. So the listings are the generators' answer, not a
plausible reconstruction of it, and a change in emission shape shows up
here as a diff.

That also settles a claim that was wrong: the openapi chapter says models
are emitted as "@mapped record (Java 17+) or class (Java 8)", and the
Pet.java it pointed at was a PropertyBusinessObject. The real one is a
record. PetApi.java was close but not what the generator writes either.
Both are now the generator's output.

The call sites are hand-written, because a generator does not emit those.
Each carries the one thing its response type gets wrong by default: gRPC-
Web reports failure under HTTP 200 so the status is the thing to read,
and a GraphQL response can carry data and errors at once so isOk() is
about the errors array rather than about getData().

Ratchet drops from 34 to 28.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 13, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-13T17:57:20.620593Z 14bf421 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 187fb6018d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/demos/common/src/main/java/com/example/starwars/StarWarsCallSite.java Outdated
Comment thread docs/demos/common/src/main/java/com/example/starwars/StarWarsCallSite.java Outdated
shai-almog and others added 2 commits September 13, 2026 20:08
…pty answer

Three of the four listings dereferenced whatever came back.

GraphQL is the sharp one, twice. isOk() reports that the errors array came
back empty, which is not the same as the query having found anything: the
schema declares hero as Character, not Character!, so a clean response can
carry a null selection. And on a subscription, onError is the end of the
stream -- a per-field failure arrives at onNext instead, as a next payload
whose errors array is non-empty and whose data may be partial or absent,
which is what GraphQLSubscription.Handler#onNext documents.

REST and gRPC get the smaller version of the same: a 2xx with an empty or
unmappable body, and an OK status with no message frame, both leave the
response data null.

Each guard carries the reason, since the trap is in the response type's
contract rather than in this code.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
check-copyright-headers covers every added source, and the generators do
not emit one. The header goes above the "Generated by" line, alongside the
tag markers, as the only edits made to the generators' output.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5652e0674e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/demos/common/src/main/java/com/example/starwars/StarWarsCallSite.java Outdated
A GraphQL call that never reached the server comes back from
GraphQL.postResponse as new GraphQLResponse(0, null, emptyList(),
message) -- httpCode 0, no errors, no data -- and decodeJson does the
same for an empty or unparseable body. isOk() only asks whether the
errors array is empty, so it answers true for every one of those, and
the listing reported "No hero for that episode" for an auth failure, a
500 and a dropped connection alike.

The query call site now checks the HTTP code first and only then
classifies the payload. The reason is beside the check, since it is the
response type's contract that makes it necessary.

The subscription call site needs no equivalent: deliverNext builds its
response with code 200 and a message only from the errors array, and
every transport failure goes to onError instead, so hasErrors() is the
right discriminator there.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dc1bace9ff

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/demos/common/src/main/java/com/example/petstore/PetApiCallSite.java Outdated
RestClientAnnotationProcessor's generated impl calls back with null when
the request never completed, and on a 4xx or 5xx its error handler
forwards the raw Response<String> cast to Response<Pet>. So the one
parameter arrives as null, as an error body typed as a Pet, or as a Pet,
and the listing read getResponseData() first.

The error-status case is the nasty one and it is worth the reader knowing
about: reading that payload as a Pet is a cast that does not throw on
ParparVM, so on a device it hands String bytes to Pet's field reads
rather than raising ClassCastException.

Guarded in the order the response has to be classified, with the reason
beside it.

gRPC and GraphQL need no equivalent: GrpcWeb always answers with a
GrpcResponse carrying STATUS_TRANSPORT_FAILURE, and GraphQL.postResponse
always answers with a GraphQLResponse. Neither ever passes null, and
neither reuses another payload's type.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 89b0c5a458

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/demos/common/src/main/java/com/example/petstore/PetApi.java Outdated
@github-actions

Copy link
Copy Markdown
Contributor

Cloudflare Preview

@github-actions

github-actions Bot commented Sep 13, 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)

Generating from the Swagger Petstore, the spec this appendix names, produces
a Pet.java that does not compile:

  cannot find symbol
    symbol:   class Tag
    location: package com.example.petstore.model

Tag and Category declare the same two properties, unifyShapes collapses
identical shapes to one record, and Tag is the one that goes. But property
types are resolved in pass 2, before unification has run, so Pet.tags kept
the name of the class that was about to be dropped and nothing ever emits
it. Operations are immune because they are built after unifyShapes -- the
comment there even says so -- which is why no test caught it.

unifyShapes now records what it renamed and re-points the property types
afterwards, matching on a token boundary so model.Tag inside
model.TagSummary is left alone. A regression test drives the two-identical-
schemas case and asserts both halves: Tag.java is not emitted, and Pet
names Category.

That is also what this change documents. The appendix's file tree listed
Tag.java among the emitted models and the listings beside it came from a
two-field test fixture, so the chapter described neither what the goal
emits nor what it emitted here. Both listings are now the goal's output for
the cut-down Petstore spec committed alongside, the file tree is what that
run actually wrote, and the missing Tag.java is explained rather than
quietly absent.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a7f2f6c8fb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/demos/common/src/main/java/com/example/starwars/StarWarsCallSite.java Outdated
Comment thread docs/developer-guide/appendix_goal_generate_openapi.adoc Outdated
decodeJson keeps the HTTP code when the body is empty or unparseable and
returns no errors and no data, so the HTTP-range check added last round
still let that land on "No hero for that episode". getResponseErrorMessage()
is the one accessor that is null only on a clean success -- it carries the
first GraphQL error, the transport failure, or the parse failure -- so that
is what the guard reads now, with the range check kept for an error status
whose body happened to decode.

And the openapi appendix claimed the committed files come back byte for
byte from a rerun, which they do not: they carry a license header and the
tag:: markers the guide includes them by, and emitApi/emitModel write
neither. Said plainly instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 13, 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)
    • build-hint-catalog: 0 findings (no issues)
    • build-hint-tools: 0 findings (no issues)
    • codenameone-maven-plugin: 0 findings (no issues)
    • core-unittests: 0 findings (no issues)
    • ios: 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.

…w checks

check-copyright-headers accepts the short Oracle-era header only on files a
change does not touch. Adding the regression test made this one modified, so
it needs the complete Codename One header.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4082fadd47

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

All three appendices document both emission modes, and all three call sites
were written against the record output: constructors with arguments, reads
through accessors. On a Java 8 target the generator writes classes with a
public no-arg constructor and public fields, so none of those lines compile.

Each call site now carries a note saying which shape it shows and what
changes on the other, which is smaller than duplicating three listings and
keeps the compiled examples matching what the docs module actually builds.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@shai-almog

shai-almog commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 151 screenshots: 151 matched.

Native Android coverage

  • 📊 Line coverage: 9.24% (9184/99417 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 8.99% (47193/524920), branch 3.55% (1767/49739), complexity 3.52% (1868/53026), method 5.43% (1514/27888), class 10.89% (407/3736)
    • 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)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1187 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)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.Frame – 0.00% (0/570 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 9.24% (9184/99417 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 8.99% (47193/524920), branch 3.55% (1767/49739), complexity 3.52% (1868/53026), method 5.43% (1514/27888), class 10.89% (407/3736)
    • 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)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1187 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)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.Frame – 0.00% (0/570 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend scalar fallback (no native SIMD)
SIMD int-add (64K x300) java 194ms / native 140ms = 1.3x speedup
SIMD float-mul (64K x300) java 133ms / native 153ms = 0.8x 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 66.000 ms
Base64 CN1 decode 79.000 ms
Base64 native encode 503.000 ms
Base64 encode ratio (CN1/native) 0.131x (86.9% faster)
Base64 native decode 387.000 ms
Base64 decode ratio (CN1/native) 0.204x (79.6% faster)
Image encode benchmark status skipped (SIMD unsupported)

@shai-almog

shai-almog commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

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

@shai-almog

shai-almog commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

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

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 54ms / native 3ms = 18.0x speedup
SIMD float-mul (64K x300) java 61ms / native 3ms = 20.3x 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 170.000 ms
Base64 CN1 decode 97.000 ms
Image encode benchmark iterations 100
Image createMask (SIMD off) 6.000 ms
Image createMask (SIMD on) 2.000 ms
Image createMask ratio (SIMD on/off) 0.333x (66.7% faster)
Image applyMask (SIMD off) 93.000 ms
Image applyMask (SIMD on) 27.000 ms
Image applyMask ratio (SIMD on/off) 0.290x (71.0% faster)
Image modifyAlpha (SIMD off) 34.000 ms
Image modifyAlpha (SIMD on) 24.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.706x (29.4% faster)
Image modifyAlpha removeColor (SIMD off) 29.000 ms
Image modifyAlpha removeColor (SIMD on) 22.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.759x (24.1% faster)

@shai-almog

shai-almog commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

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

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 82ms / native 3ms = 27.3x speedup
SIMD float-mul (64K x300) java 71ms / native 3ms = 23.6x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 257.000 ms
Base64 CN1 decode 155.000 ms
Base64 native encode 1038.000 ms
Base64 encode ratio (CN1/native) 0.248x (75.2% faster)
Base64 native decode 379.000 ms
Base64 decode ratio (CN1/native) 0.409x (59.1% faster)
Base64 SIMD encode 76.000 ms
Base64 encode ratio (SIMD/CN1) 0.296x (70.4% faster)
Base64 SIMD decode 65.000 ms
Base64 decode ratio (SIMD/CN1) 0.419x (58.1% faster)
Base64 encode ratio (SIMD/native) 0.073x (92.7% faster)
Base64 decode ratio (SIMD/native) 0.172x (82.8% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 11.000 ms
Image createMask (SIMD on) 3.000 ms
Image createMask ratio (SIMD on/off) 0.273x (72.7% faster)
Image applyMask (SIMD off) 52.000 ms
Image applyMask (SIMD on) 36.000 ms
Image applyMask ratio (SIMD on/off) 0.692x (30.8% faster)
Image modifyAlpha (SIMD off) 53.000 ms
Image modifyAlpha (SIMD on) 35.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.660x (34.0% faster)
Image modifyAlpha removeColor (SIMD off) 43.000 ms
Image modifyAlpha removeColor (SIMD on) 42.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.977x (2.3% faster)

@shai-almog

shai-almog commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

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

@shai-almog

shai-almog commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 144 screenshots: 144 matched.
✅ Native Apple TV (tvOS, Metal) screenshot tests passed.

@shai-almog

shai-almog commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 149 screenshots: 149 matched.
✅ Native iOS Metal screenshot tests passed.

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 65000 ms
Simulator Boot (Run) 0 ms
App Install 12000 ms
App Launch 2000 ms
Test Execution 367000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 55ms / native 3ms = 18.3x speedup
SIMD float-mul (64K x300) java 55ms / native 3ms = 18.3x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 201.000 ms
Base64 CN1 decode 101.000 ms
Base64 native encode 476.000 ms
Base64 encode ratio (CN1/native) 0.422x (57.8% faster)
Base64 native decode 533.000 ms
Base64 decode ratio (CN1/native) 0.189x (81.1% faster)
Base64 SIMD encode 51.000 ms
Base64 encode ratio (SIMD/CN1) 0.254x (74.6% faster)
Base64 SIMD decode 75.000 ms
Base64 decode ratio (SIMD/CN1) 0.743x (25.7% faster)
Base64 encode ratio (SIMD/native) 0.107x (89.3% faster)
Base64 decode ratio (SIMD/native) 0.141x (85.9% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 7.000 ms
Image createMask (SIMD on) 3.000 ms
Image createMask ratio (SIMD on/off) 0.429x (57.1% faster)
Image applyMask (SIMD off) 38.000 ms
Image applyMask (SIMD on) 113.000 ms
Image applyMask ratio (SIMD on/off) 2.974x (197.4% slower)
Image modifyAlpha (SIMD off) 78.000 ms
Image modifyAlpha (SIMD on) 129.000 ms
Image modifyAlpha ratio (SIMD on/off) 1.654x (65.4% slower)
Image modifyAlpha removeColor (SIMD off) 111.000 ms
Image modifyAlpha removeColor (SIMD on) 93.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.838x (16.2% faster)

@shai-almog

shai-almog commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 143 screenshots: 143 matched.
✅ Native iOS screenshot tests passed.

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 68000 ms
Simulator Boot (Run) 1000 ms
App Install 17000 ms
App Launch 33000 ms
Test Execution 493000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 62ms / native 3ms = 20.6x speedup
SIMD float-mul (64K x300) java 141ms / native 30ms = 4.7x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 177.000 ms
Base64 CN1 decode 118.000 ms
Base64 native encode 839.000 ms
Base64 encode ratio (CN1/native) 0.211x (78.9% faster)
Base64 native decode 318.000 ms
Base64 decode ratio (CN1/native) 0.371x (62.9% faster)
Base64 SIMD encode 71.000 ms
Base64 encode ratio (SIMD/CN1) 0.401x (59.9% faster)
Base64 SIMD decode 55.000 ms
Base64 decode ratio (SIMD/CN1) 0.466x (53.4% faster)
Base64 encode ratio (SIMD/native) 0.085x (91.5% faster)
Base64 decode ratio (SIMD/native) 0.173x (82.7% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 11.000 ms
Image createMask (SIMD on) 3.000 ms
Image createMask ratio (SIMD on/off) 0.273x (72.7% faster)
Image applyMask (SIMD off) 76.000 ms
Image applyMask (SIMD on) 54.000 ms
Image applyMask ratio (SIMD on/off) 0.711x (28.9% faster)
Image modifyAlpha (SIMD off) 74.000 ms
Image modifyAlpha (SIMD on) 46.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.622x (37.8% faster)
Image modifyAlpha removeColor (SIMD off) 71.000 ms
Image modifyAlpha removeColor (SIMD on) 56.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.789x (21.1% faster)

@shai-almog
shai-almog merged commit f4a6933 into master Sep 14, 2026
43 checks passed
@shai-almog
shai-almog deleted the dg-appendix-goals branch September 14, 2026 01:42
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.

1 participant