Use SmolStr in more places of the compiler infrastructure

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
```
This commit is contained in:
Milian Wolff 2024-10-03 18:06:59 +02:00 committed by Olivier Goffart
parent 08a3a6cc4a
commit 0f6c3a4fd7
75 changed files with 679 additions and 555 deletions

View file

@ -25,6 +25,7 @@ use itertools::Either;
use lyon_path::geom::euclid::approxeq::ApproxEq;
use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote};
use smol_str::SmolStr;
use std::collections::{BTreeMap, BTreeSet};
use std::num::NonZeroUsize;
use std::str::FromStr;
@ -382,8 +383,8 @@ fn generate_shared_globals(
fn generate_struct(
name: &str,
fields: &BTreeMap<String, Type>,
rust_attributes: &Option<Vec<String>>,
fields: &BTreeMap<SmolStr, Type>,
rust_attributes: &Option<Vec<SmolStr>>,
) -> TokenStream {
let component_id = struct_name_to_tokens(name);
let (declared_property_vars, declared_property_types): (Vec<_>, Vec<_>) =
@ -2080,6 +2081,7 @@ fn access_item_rc(pr: &llr::PropertyReference, ctx: &EvaluationContext) -> Token
fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream {
match expr {
Expression::StringLiteral(s) => {
let s = s.as_str();
quote!(sp::SharedString::from(#s))
}
Expression::NumberLiteral(n) if n.is_finite() => quote!(#n),
@ -2339,6 +2341,7 @@ fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream
quote!(sp::Image::default())
}
crate::expression_tree::ImageReference::AbsolutePath(path) => {
let path = path.as_str();
quote!(sp::Image::load_from_path(::std::path::Path::new(#path)).unwrap_or_default())
}
crate::expression_tree::ImageReference::EmbeddedData { resource_id, extension } => {
@ -2500,7 +2503,7 @@ fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream
sub_expression,
} => box_layout_function(
cells_variable,
repeater_indices.as_ref().map(String::as_str),
repeater_indices.as_ref().map(SmolStr::as_str),
elements,
*orientation,
sub_expression,
@ -2680,6 +2683,7 @@ fn compile_builtin_function_call(
BuiltinFunction::RegisterCustomFontByPath => {
if let [Expression::StringLiteral(path)] = arguments {
let window_adapter_tokens = access_window_adapter_field(ctx);
let path = path.as_str();
quote!(#window_adapter_tokens.renderer().register_font_from_path(&std::path::PathBuf::from(#path)).unwrap())
} else {
panic!("internal error: invalid args to RegisterCustomFontByPath {:?}", arguments)