Open dhowe opened 5 years ago
After a bit of profiling it seems that, as expected, most of the rendering time is spent on canvas drawing/path primitives. Unexpectedly, however, _handleAlignment appears to be more costly than getPath
Some quick experiments with alignment and path caching (basically memoizing these two functions) raises the framerate of my test case (modified from the above test so that characters are reused across frames) by about 30%. Non-scientific numbers on time-spent below (from these estimates, it may not be worth the complexity/memory hit)...
current code: _renderPath: 50.4%, _getPath: 26.5%
memoizing alignments: _renderPath: 42.7%, _getPath: 15.2%
memoizing paths & alignments: _renderPath: 37.0%, _getPath: 8.9%
another option might be to draw text paths to an offscreen buffer, which can apparently speed things up significantly (perhaps an order of magnitude), but has all the usual problems of offscreen buffers
while it won't help in all cases, for this particular example, the following additional check knocks ~25% off the running time:
to:
if (typeof textWidth === 'undefined' &&
renderer._textAlign !== constants.LEFT) {
textWidth = this._textWidth(line, fontSize);
}
when the _textWidth
call is unavoidable, i think it's a lost opportunity that the getPath
call doesn't return the accumulated advanceWidth
somehow. this could be used instead of having to re-calculate exactly the same value in order to do the right/center justification.
@dhowe is this the same issue as https://github.com/processing/p5.js/issues/950? can we close one of them?
Hey folks, running into serious fps issues rendering ttf font, 40+ FPS using default p5js font:
And only 6 FPS with VCR_OSD_MONO_1.001.ttf:
Also, I don't know how to begin searching for less fonts with less complex "font-paths" in case I need to live with this.
I would imagine finding fonts with less complex font paths will be difficult as most of them will be relatively complex. The suggestions of drawing to an offscreen buffer (ie. p5.Graphics) may work depending on your use case, if you are drawing a lot of the same text it should help, if you are modifying the text often unpredictably then it will likely have the same issue.
One way to possibly get performance of custom fonts closer to built in fonts would be to load them via CSS and access them via font name. I think @munusshih looked into this but can't at this moment remember what the conclusion was.
It has been noted that there is a significant performance hit when using a custom font (.otf or .ttf) vs the default or other browser-fonts (see this post for one example). I've looked at the p5.js text rendering code and I don't think (others are welcome to chime in) there is much that can be done in terms of optimization here, as it largely delegates to opentype.js for the computation (and creation) of paths and then simply renders them with primitive canvas ops. There may well be optimizations that can be done within opentype, but this is a bigger undertaking.
Alternatively we may see some performance gains via the caching of paths returned from opentype, but this would likely not help (or not help much) with the sketch linked above as the characters change each frame. However, this sketch is probably not a very typical use case for p5, as most text will remain in place for multiple frames, thus recomputing the path data (and re-creating Path objects) is not optimal. The tradeoff would likely be a memory hit, but tests would be needed to see how significant this would be. I'm happy to look into this (though probably not right away) if people think it is worthwhile. Mostly I wanted to log this as a known issue.