Skip to content

Performance improvements suggestion #32

@indreka

Description

@indreka

Loading in bigger ttf files is noticeably slow. After using xdebug profiler it was evident that most common function being called is BinaryStream->readUInt16()

When viewing the places that call it, there seem to be many loops which just call the function multiple times in a row.
The function itself uses unpack, which allocates new array for each invocation and only the single value in it is used.

Proposal is to add a few helper functions to BinaryReader like

public function readUInt16Many($count) {
$str = $this->read(2 * $count);
return array_values(unpack("n_", $str));
}
public function readInt16Many($count) {
$str = $this->read(2 * $count);
$vals_uint16 = unpack("n_", $str);
$vals = array();
foreach ($vals_uint16 as $v)
$vals[] = $v >= 0x8000 ? $v - 0x10000 : $v;
return $vals;
}

array_values is needed because when using * for unpack, the array indexes start from 1, instead of 0.

Then the helpers could be used for example in cmap, hmtx, kern, post parsers:
$endCode = $font->readUInt16Many($segCount);
$idRangeOffset = $font->readUInt16Many($segCount);

In addition there is a generic r function in BinaryStream that accepts array with type + count, that one should also be optimized to call readUInt16Many.
Plus, the ->r(array()) cases could be even more optimized, since many of the calling places know to ask for uint16 array, so calling ->readUInt16Many($count); should also give a little boost, because it doesn't have to pass through the long switch list anymore.

When testing FreeSerif font with original code, the readUInt16() is called 76580 times, consuming 33% of the total font load time. After optimizations, the UInt16Many was called 10 times consuming 0.64% of time and readUInt16 11025 times consuming 13.21% of total time.
Also ->r() calls were reduced from ~2800 to ~500.

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