Skip to content

Commit

Permalink
perf: reduce glyph memory consumption by 57%
Browse files Browse the repository at this point in the history
I learned about optimal memory layouts recently [1] and remembered
that glyphs waste a lot of space, especially the flags. This new
struct was a pain to get working: I tried DataView first, but it
performed worse in node. I didn't want the class to take up a lot
of memory, so I finally landed on TypedArray with bit shifting and
maksing.

Performance is pretty much the same as before, although sadly perf-1
runs a tiny bit slower. The memory savings are good, though, and
readability is significantly better. I may explore AST transforms
to inline the function calls later. perf-2 is a little bit faster,
which is probably due to better CPU cacheability.

[1] https://www.youtube.com/watch?v=rX0ItVEVjHc
  • Loading branch information
chearon committed Dec 15, 2024
1 parent 1ee56f8 commit cd9da9b
Show file tree
Hide file tree
Showing 10 changed files with 303 additions and 226 deletions.
Binary file modified dist/dropflow.wasm
Binary file not shown.
27 changes: 14 additions & 13 deletions src/dropflow.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@
HB_BEGIN_DECLS

typedef struct hbjs_glyph {
uint32_t id;
uint32_t cl;
int32_t ax;
int32_t ay;
int32_t dx;
int32_t dy;
int32_t fl;
uint16_t id;
int16_t ad;
int16_t dx;
int16_t dy;
} hbjs_glyph;

/* imports */
Expand Down Expand Up @@ -100,13 +98,16 @@ hbjs_extract_glyphs(hb_buffer_t* buf) {
hbjs_glyph* ret = (hbjs_glyph*) malloc(sizeof(hbjs_glyph) * len);

for (unsigned int i = 0; i < len; i++) {
ret[i].id = infos[i].codepoint;
ret[i].cl = infos[i].cluster;
ret[i].ax = positions[i].x_advance;
ret[i].ay = positions[i].y_advance;
ret[i].dx = positions[i].x_offset;
ret[i].dy = positions[i].y_offset;
ret[i].fl = hb_glyph_info_get_glyph_flags(infos + i);
hb_glyph_flags_t flags = hb_glyph_info_get_glyph_flags(infos + i);
ret[i].cl = infos[i].cluster << 2;
ret[i].id = static_cast<int16_t>(infos[i].codepoint);
// TODO: vertical text
ret[i].ad = static_cast<int16_t>(positions[i].x_advance);

if (flags & HB_GLYPH_FLAG_UNSAFE_TO_BREAK) ret[i].cl |= 0x1;
if (flags & HB_GLYPH_FLAG_UNSAFE_TO_CONCAT) ret[i].cl |= 0x2;
ret[i].dx = static_cast<int16_t>(positions[i].x_offset);
ret[i].dy = static_cast<int16_t>(positions[i].y_offset);
}

return ret;
Expand Down
Loading

0 comments on commit cd9da9b

Please sign in to comment.