pop-os / cosmic-text

Pure Rust multi-line text handling
https://pop-os.github.io/cosmic-text/cosmic_text/
Apache License 2.0
1.51k stars 88 forks source link

Buffer::set_text seems very slow? #245

Open ChangeCaps opened 2 months ago

ChangeCaps commented 2 months ago

On both my laptop and my desktop, calling Buffer::set_text takes anywhere from 100µs to 1.3ms, averaging around 600µs for a string of around 20-22 characters using Shaping::Advanced. Using Shaping::Basic takes around 450µs. This to me seems very slow, calling Buffer::set_text a couple of times per frame takes up a serious part of the frame budget.

OS: nixos/arch Rustc: 1.77.2 Cosmic-text: 0.11.2 Font: Roboto Regular

Edit:

This only seems to be a problem with the mono space version of the font.

ChangeCaps commented 2 months ago
use std::time::Instant;

use cosmic_text::{
    Attrs, Buffer, CacheKeyFlags, Family, FontSystem, Metrics, Shaping, Stretch, Style, Weight,
};

fn set_text(font_system: &mut FontSystem, buffer: &mut Buffer, family: Family, i: u64) {
    buffer.set_text(
        font_system,
        &format!("rgb(69  , 103  , {i})"),
        Attrs {
            color_opt: None,
            family,
            stretch: Stretch::Normal,
            style: Style::Normal,
            weight: Weight::NORMAL,
            metadata: 0,
            cache_key_flags: CacheKeyFlags::empty(),
        },
        Shaping::Advanced,
    );
}

fn main() {
    let mut font_system = FontSystem::new();

    let mut buffer = Buffer::new(&mut font_system, Metrics::new(12.0, 16.0));

    buffer.set_size(&mut font_system, 100.0, 100.0);

    let serif_start = Instant::now();

    for i in 0..1000 {
        set_text(&mut font_system, &mut buffer, Family::Serif, i);
    }

    let serif_duration = serif_start.elapsed() / 1000;
    println!("Time: {:?}", serif_duration);

    let monospace_start = Instant::now();

    for i in 0..1000 {
        set_text(&mut font_system, &mut buffer, Family::Monospace, i);
    }

    let monospace_duration = monospace_start.elapsed() / 1000;
    println!("Time: {:?}", monospace_duration);

    println!(
        "Monospace was {} times slower than Serif",
        monospace_duration.as_secs_f64() / serif_duration.as_secs_f64()
    );
}

This crude examples gives the result that Monospace is around 28 times slower than Serif on my machine.