SmolStr has an Arc internally for large strings. This allows
cheap copies of large strings, but we lose that ability
when we convert the SmolStr to a &str and then reconstruct a
SmolStr from that slice.
I was hoping for some larger gains here, considering the impact
of this code change, but it only removes ~50k allocations,
while the impact on the runtime is not noticeable at all.
Still, I believe this is the right thing to do.
Before:
```
allocations: 2338981
Time (mean ± σ): 988.3 ms ± 17.9 ms [User: 690.2 ms, System: 206.4 ms]
Range (min … max): 956.4 ms … 1016.3 ms 10 runs
```
After:
```
allocations: 2287723
Time (mean ± σ): 989.8 ms ± 23.2 ms [User: 699.2 ms, System: 197.6 ms]
Range (min … max): 945.3 ms … 1021.4 ms 10 runs
```
This is rarely used, but using Rc here like elsewhere allows us to
elide a few unneccessary memory allocations when copying such types.
The speed impact is not measurable though. With heaptrack I see that
we get rid of the last ~7600 allocations in my benchmark when cloning
Type.
This makes copying such types much cheaper and will allow us to
intern common struct types in the future too. This further
drops the sample cost for langtype.rs from ~6.6% down to 4.0%.
We are now also able to share/intern common struct types.
Before:
```
Time (mean ± σ): 1.073 s ± 0.021 s [User: 0.759 s, System: 0.215 s]
Range (min … max): 1.034 s … 1.105 s 10 runs
allocations: 3074261
```
After:
```
Time (mean ± σ): 1.034 s ± 0.026 s [User: 0.733 s, System: 0.201 s]
Range (min … max): 1.000 s … 1.078 s 10 runs
allocations: 2917476
```
This removes a lot of allocations and speeds up the compiler step
a bit. Sadly, this patch is very invasive as it touches a lot of
files. That said, each individual hunk is pretty trivial.
For a non-trivial real-world example, the impact is significant,
we get rid of ~29% of all allocations and improve the runtime by
about 4.8% (measured until the viewer loop would start).
Before:
```
Benchmark 1: ./target/release/slint-viewer ../slint-perf/app.slint
Time (mean ± σ): 664.2 ms ± 6.7 ms [User: 589.2 ms, System: 74.0 ms]
Range (min … max): 659.0 ms … 682.4 ms 10 runs
allocations: 4886888
temporary allocations: 857508
```
After:
```
Benchmark 1: ./target/release/slint-viewer ../slint-perf/app.slint
Time (mean ± σ): 639.5 ms ± 17.8 ms [User: 556.9 ms, System: 76.2 ms]
Range (min … max): 621.4 ms … 666.5 ms 10 runs
allocations: 3544318
temporary allocations: 495685
```
In rust, use f32 instead of f64 for arithmetic comparison.
In the interpreter, use approx_eq
The test is failling in nightly because of precision change in `log`.
By using f32, it actually should work
Also Revert "Disable builds with nightly Rust temporarily"
This reverts commit 4afc3a2e84.
Fixes#5722
Use this snapshot to keep a unoptimized typeloader around, so that the preview
does not need to do another parsing run.
Move the document cache in the preview over to use the snapshot.
This change exposes functionality of already existing internal API
that all renderers use to obtain pixels for upload to the screen - so
it's rather well tested.
This also exposes the `SharedImageBuffer` API, an enum that represents
different SharedPixelBuffer encodings.
Updated the version from 1.1 to 1.2
Renamed the header to "Slint Royalty-free Desktop, Mobile, and Web Applications License"
Added definition of "Mobile Application" and grant of right
Moved "Limitations" to 3rd section and "License Conditions - Attributions" to 2nd section
Added flexibility to choose between showing "MadeWithSlint" as a dialog/splash screen or on a public webpage
Moved the para on copyright notices to section under "Limitations"
Refactor the code in the compiler a bit to allow using the
`TypeLoader` for the root document itself and use that in the
interpreter.
You need to run passes *before* the `TypeLoader` takes ownership
of the Document, so the `load_file` in `TypeLoader` needed a bit of
changing.
We need to decorate an Element so we can interact with it. I want
to decorate only *one* instance of a repeated element to avoid
cluttering up the screen. So pick one good candidate for decoration:
Ideally the one the user clicked on, got for the first one
otherwise.
Store this information so we can get it back after re-rendering,
and so that we can actually mark newly added elements for selection
after they get rendered.
They are not commonly used so no need to use semi-public api for that
and it's really easy to similate with ust two clicks anyway
The previous test function were added before there was public way to
send events
The preview can not leave it up to the interpreter to handle element selection
and highlighting. So add new functions to the interpreter (behind the
"highlight" feature-gate) to query positions of elements.
This exposes some of the code that is used by the existing highlighting code
and extends it where needed.
Two use-cases need to be covered:
1. Query the positions of a component (given by source file path and offset).
This is then used to highlight all occurences of a component as the
cursor position in a source file changes.
2. Query the position of an element (given as `ElementRc`).
This is used when selecting elements in the UI. We need to work at
the element level for this, not at the component level.
Also make the `highlight` module public but feature-gated, so that we
can put helper-types there.
A None value means the file on disk is the golden version.
We have an editor, the LSP and the preview that all need to at least
notice when they have newer data then their peers. So IMHO it makes
sense to have an optional document version around.
The language server protocol makes use of a version number already. This
patch moves that code into the compiler so that it is stored with the
actual data getting versioned.
... and use it to hide internal functionality so users will notice that
they depend on fucntionality we do not provide any guarantees for.
Make the lsp and viewer request the internal feature when building the
interpreter.