-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improving Qute Escaper to be as branch-free as possible #45546
base: main
Are you sure you want to change the base?
Conversation
Using the benchmark at mkouba/qute-benchmarks#1 shows these differences in perf - now:
vs before
which is a good improvement - which tends to pay-off more as the number of chars increases Fyi @mkouba the relevant ones are using 10000 samples since with just 100 the data are very predictable for my CPU model and you cannot really see the benefits of reducing the number of branches |
This comment has been minimized.
This comment has been minimized.
@galderz on mkouba/qute-benchmarks#1 this implementation should really shine with native image, since it doesn't use |
This comment has been minimized.
This comment has been minimized.
independent-projects/qute/core/src/main/java/io/quarkus/qute/JsonEscaper.java
Outdated
Show resolved
Hide resolved
independent-projects/qute/core/src/main/java/io/quarkus/qute/JsonEscaper.java
Show resolved
Hide resolved
I had to rewrite the
Aren't those numbers swapped given the fact that
Ok 👍 |
independent-projects/qute/core/src/main/java/io/quarkus/qute/JsonEscaper.java
Show resolved
Hide resolved
Numbers still look the same? Did you checked 🙏?
Ops 🤣 I copied in the wrong order , let me fix it |
The HTML one can still made faster, working on it |
dd0393c
to
d4d3d81
Compare
d4d3d81
to
a085c01
Compare
Status for workflow
|
🎊 PR Preview 04deb60 has been successfully built and deployed to https://quarkus-pr-main-45546-preview.surge.sh/version/main/guides/
|
// NOTE: this holding 8 values to allow the JIT to remove the bound checks since | ||
// the replacement id is always in range [0, 7] due to the REPLACEMENT_ID_MASK value | ||
private static final String[] REPLACEMENTS = { null, """, "'", "&", "<", ">", null, null }; | ||
// We use 4 bits to pack the replacement id for each Latin character in the [0, 255] range. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The doc here is not up to date with the latest changes..I ended up accepting having a slightly bigger footprint, but better latency
This comment has been minimized.
This comment has been minimized.
a085c01
to
1939891
Compare
Status for workflow
|
Status | Name | Step | Failures | Logs | Raw logs | Build scan |
---|---|---|---|---|---|---|
✖ | Native Tests - Misc4 | Build |
Failures | Logs | Raw logs | 🔍 |
Full information is available in the Build summary check run.
You can consult the Develocity build scans.
Failures
⚙️ Native Tests - Misc4 #
- Failing: integration-tests/observability-lgtm
📦 integration-tests/observability-lgtm
✖ io.quarkus.observability.test.LgtmResourcesIT.testTracing
- History - More details - Source on GitHub
java.lang.RuntimeException:
java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[error]: Build step io.quarkus.observability.deployment.ObservabilityDevServiceProcessor#startContainers threw an exception: java.lang.RuntimeException: org.testcontainers.containers.ContainerLaunchException: Container startup failed for image docker.io/grafana/otel-lgtm:0.8.2
at io.quarkus.observability.deployment.ObservabilityDevServiceProcessor.lambda$startContainers$3(ObservabilityDevServiceProcessor.java:170)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
at io.quarkus.observability.deployment.ObservabilityDevServiceProcessor.startContainers(ObservabilityDevServiceProcessor.java:113)
at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:732)
Flaky tests - Develocity
⚙️ JVM Tests - JDK 17
📦 integration-tests/observability-lgtm
✖ io.quarkus.observability.test.LgtmServicesTest.testTracing
- History
java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors [error]: Build step io.quarkus.observability.deployment.ObservabilityDevServiceProcessor\#startContainers threw an exception: java.lang.RuntimeException: org.testcontainers.containers.ContainerLaunchException: Container startup failed for image docker.io/grafana/otel-lgtm:0.8.2 at io.quarkus.observability.deployment.ObservabilityDevServiceProcessor.lambda$startContainers$3(ObservabilityDevServiceProcessor.java:170) at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625) at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
-java.lang.RuntimeException
java.lang.RuntimeException:
java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[error]: Build step io.quarkus.observability.deployment.ObservabilityDevServiceProcessor#startContainers threw an exception: java.lang.RuntimeException: org.testcontainers.containers.ContainerLaunchException: Container startup failed for image docker.io/grafana/otel-lgtm:0.8.2
at io.quarkus.observability.deployment.ObservabilityDevServiceProcessor.lambda$startContainers$3(ObservabilityDevServiceProcessor.java:170)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
at io.quarkus.observability.deployment.ObservabilityDevServiceProcessor.startContainers(ObservabilityDevServiceProcessor.java:113)
at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:732)
⚙️ JVM Tests - JDK 21
📦 integration-tests/observability-lgtm
✖ io.quarkus.observability.test.LgtmReloadTest.testReload
- History
io.quarkus.builder.BuildException: Build failure: Build failed due to errors [error]: Build step io.quarkus.observability.deployment.ObservabilityDevServiceProcessor\#startContainers threw an exception: java.lang.RuntimeException: org.testcontainers.containers.ContainerLaunchException: Container startup failed for image docker.io/grafana/otel-lgtm:0.8.2 at io.quarkus.observability.deployment.ObservabilityDevServiceProcessor.lambda$startContainers$3(ObservabilityDevServiceProcessor.java:170) at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708) at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
-java.lang.RuntimeException
java.lang.RuntimeException:
io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[error]: Build step io.quarkus.observability.deployment.ObservabilityDevServiceProcessor#startContainers threw an exception: java.lang.RuntimeException: org.testcontainers.containers.ContainerLaunchException: Container startup failed for image docker.io/grafana/otel-lgtm:0.8.2
at io.quarkus.observability.deployment.ObservabilityDevServiceProcessor.lambda$startContainers$3(ObservabilityDevServiceProcessor.java:170)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
at io.quarkus.observability.deployment.ObservabilityDevServiceProcessor.startContainers(ObservabilityDevServiceProcessor.java:113)
at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:733)
This is a show case of the approach at lemire/Code-used-on-Daniel-Lemire-s-blog#116 but biased for the one and two replacement latin chars case.
It could be expanded to cover for non-latin and the 6 bytes replacement too, with more painfull and complex (in term of logic) changes - but it looks already complex as it is IMO.
Feedbacks are wellcome as questions.
I didn't yet benchmarked it (is sadly low in my prio list - so IDK when I'll have time to contribute a proper bench which stress the branch-predictor in qute-benchmark) - and there's a good chance my "bet" to use
StringBuilder
to simplify it, making use of the horriblesetLength
in the hot path, won't pay off.In such unfortunate case, I will move to using char[] despite it requires latinness checks due to compact string, on String construction :"(