Skip to content
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

Extend smol_str usage #6463

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

Extend smol_str usage #6463

wants to merge 3 commits into from

Conversation

milianw
Copy link

@milianw milianw commented Oct 7, 2024

Use SmolStr in more places to reduce the number of string allocations. This slightly improves runtime performance too.

Originally, on my laptop, I measured:

    Benchmark 1: ./target/release/slint-viewer ../slint-perf/app.slint
      Time (mean ± σ):     676.6 ms ±  15.6 ms    [User: 594.6 ms, System: 77.4 ms]
      Range (min … max):   662.9 ms … 703.4 ms    10 runs
    
            allocations:            5202354
            temporary allocations:  857511

After the second patch this goes down to:

Benchmark 1: ./target/release/slint-viewer ../slint-perf/app.slint
  Time (mean ± σ):     623.7 ms ±   8.4 ms    [User: 549.2 ms, System: 68.4 ms]
  Range (min … max):   609.3 ms … 631.5 ms    10 runs

        allocations:            3393115
        temporary allocations:  466610

Heaptrack showed a lot of memory allocations when the strings
in the NamedReference got copied around. Instead, we now use
SmolStr to benefit from SSO. This already removes ~320000
allocations for the benchmark app I am using here. Runtime
also improves by ca 1.8%.

Before:
```
Benchmark 1: ./target/release/slint-viewer ../slint-perf/app.slint
  Time (mean ± σ):     676.6 ms ±  15.6 ms    [User: 594.6 ms, System: 77.4 ms]
  Range (min … max):   662.9 ms … 703.4 ms    10 runs

        allocations:            5202354
        temporary allocations:  857511
```

After:
```
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
```
@CLAassistant
Copy link

CLAassistant commented Oct 7, 2024

CLA assistant check
All committers have signed the CLA.

@milianw
Copy link
Author

milianw commented Oct 7, 2024

rebase fail, need to reapply some hunks, give me a moment please

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 ± σ):     632.4 ms ±  21.5 ms    [User: 555.1 ms, System: 76.2 ms]
  Range (min … max):   609.9 ms … 658.9 ms    10 runs

        allocations:            3455770
        temporary allocations:  495587
```
@milianw
Copy link
Author

milianw commented Oct 7, 2024

alright, ready for review now

Copy link
Member

@ogoffart ogoffart left a comment

Choose a reason for hiding this comment

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

i haven't looked at everything in details, but it seems sensible. Thanks!

api/rs/build/Cargo.toml Show resolved Hide resolved
impl Struct {
/// Get the value for a given struct field
pub fn get_field(&self, name: &str) -> Option<&Value> {
self.0.get(&*normalize_identifier(name))
}
/// Set the value of a given struct field
pub fn set_field(&mut self, name: String, value: Value) {
pub fn set_field(&mut self, name: SmolStr, value: Value) {
Copy link
Member

Choose a reason for hiding this comment

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

the interpreter API is public API and can unfortunately not be changed. So it must continue using String in its public interface. (in retrospect, this should have been a &str perhaps.)

This is valid for other changes in this file.

We can make an issue to change that with Slint 2.0

internal/core/string.rs Show resolved Hide resolved
Before:
```
Benchmark 1: ./target/release/slint-viewer ../slint-perf/app.slint
  Time (mean ± σ):     632.4 ms ±  21.5 ms    [User: 555.1 ms, System: 76.2 ms]
  Range (min … max):   609.9 ms … 658.9 ms    10 runs

        allocations:            3455770
        temporary allocations:  495587
```

After:
```
Benchmark 1: ./target/release/slint-viewer ../slint-perf/app.slint
  Time (mean ± σ):     623.7 ms ±   8.4 ms    [User: 549.2 ms, System: 68.4 ms]
  Range (min … max):   609.3 ms … 631.5 ms    10 runs

        allocations:            3393115
        temporary allocations:  466610
```
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.

3 participants