Skip to content

Performance problems with hb_ft_* functions #559

@tiffany352

Description

@tiffany352

I'm currently implementing HarfBuzz-based shaping and I'm very close to finishing a shippable version, but there's a few performance issues I'd like to address before doing so. I have HarfBuzz built with only the OpenType shaper, and only the UCDN Unicode functions. It is used alongside Freetype. As such, I am using the Freetype face/font functions.

Originally, I was using hb_ft_font_create, but I found that this was very expensive because of it creating and then destroying an hb_face_t every time it's called. It doesn't appear to cache it at all. This was a big problem because it also meant that shape plans would not be cached, they would be discarded with the hb_font_t reference.

Now, I am using the following code:

FT_Face face;
hb_face_t* hbFace = hb_ft_face_create(face, NULL);
...
hb_font_t* hb_font = hb_font_create(hbFace);
// this line is lifted directly from the HarfBuzz source for hb_ft_font_create
hb_font_set_scale(hb_font,
    (int)(((uint64_t)face->size->metrics.x_scale * (uint64_t)face->units_per_EM + (1u << 15)) >> 16),
    (int)(((uint64_t)face->size->metrics.y_scale * (uint64_t)face->units_per_EM + (1u << 15)) >> 16));
hb_ft_font_set_funcs(hb_font);

Which is about 10 times faster (because I store the hbFace, resulting in shape plans being cached), and I haven't noticed any incorrect behavior. (I could be doing it wrong, though.) However, hb_ft_font_set_funcs still calls FT_New_Memory_Face seemingly unnecessarily, which is now 12% of the CPU usage of the entire application (actually calling hb_shape is only 6%).

I believe I could make this faster still by doing the same thing that hb_ft_font_set_funcs does, but without creating a new FT_Face (using my existing handle). However, this function relies on static functions in HarfBuzz like _hb_ft_font_set_funcs. I'm wondering whether I should add a new function that does the same thing as hb_ft_font_set_funcs but takes an FT_Face reference instead of creating a new one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions