slint/internal/compiler/passes/collect_custom_fonts.rs
Milian Wolff 0f6c3a4fd7 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
```
2024-10-17 18:04:58 +02:00

68 lines
2.4 KiB
Rust

// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
//! Passes that fills the root component used_global
use crate::{
expression_tree::{BuiltinFunction, Expression, Unit},
object_tree::*,
};
use smol_str::SmolStr;
use std::collections::BTreeSet;
/// Fill the root_component's used_globals
pub fn collect_custom_fonts<'a>(
doc: &Document,
all_docs: impl Iterator<Item = &'a Document> + 'a,
embed_fonts: bool,
) {
let mut all_fonts = BTreeSet::new();
for doc in all_docs {
all_fonts.extend(doc.custom_fonts.iter().map(|(path, _)| path))
}
let registration_function = if embed_fonts {
Expression::BuiltinFunctionReference(BuiltinFunction::RegisterCustomFontByMemory, None)
} else {
Expression::BuiltinFunctionReference(BuiltinFunction::RegisterCustomFontByPath, None)
};
let prepare_font_registration_argument: Box<dyn Fn(&SmolStr) -> Expression> = if embed_fonts {
Box::new(|font_path| {
Expression::NumberLiteral(
{
let mut resources = doc.embedded_file_resources.borrow_mut();
let resource_id = match resources.get(font_path) {
Some(r) => r.id,
None => {
let id = resources.len();
resources.insert(
font_path.clone(),
crate::embedded_resources::EmbeddedResources {
id,
kind: crate::embedded_resources::EmbeddedResourcesKind::RawData,
},
);
id
}
};
resource_id as _
},
Unit::None,
)
})
} else {
Box::new(|font_path| Expression::StringLiteral(font_path.clone()))
};
for c in doc.exported_roots() {
c.init_code.borrow_mut().font_registration_code.extend(all_fonts.iter().map(|font_path| {
Expression::FunctionCall {
function: Box::new(registration_function.clone()),
arguments: vec![prepare_font_registration_argument(font_path)],
source_location: None,
}
}));
}
}