-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Performance optimization of text-width computation #1379
Comments
Hey there, I could look into this, unless you would be interested in submitting a pull request? 😉 |
@PyvesB please do, I'm new to the project, and very limited in time. |
Thanks for the suggestion! Personal testing makes me feel like pdfkit's overhead (ie, its word caching mechanism) over fontkit is mostly positive; calling fontkit directly changes the time spent in node server 1111 >log &
sleep 2
for ((i=0;i<10000;i++)); do
curl -s http://localhost:1111/badge/coverage-"$i"%-green.svg >/dev/null
done
kill $(jobs -p)
<log grep 'makeBadge total' | \
grep -Eo '[0-9\.]+' | \
awk '{s+=$1;n++} END {print s/n}' If we tweak the benchmark to call /badge/coverage"$i"-"$i"%-green.svg to break the pdfkit cache, I get 0.360752ms, against 0.315269ms for fontkit. |
Wow, I totally didn't expect that. |
Continuation of #1377 (comment): Something else we could think about here is multiprocess parallelism: basically doing the badge-width computation in one or more separate processes that don't block. That won't help with a sequential-test metric, but might help if we simulate a production-like load. Also, and more simply, perhaps a bigger cache, or even a static cache, which contains precomputed widths for lots of common values, like in the example badge values, version numbers, and static badges we know we see a lot. This might be a naive question: does kerning prevent us from computing the width character by character? Would it be possible to extract kerning rules from the font, so we could reimplement the computation in an even faster way? |
With fontkit, and Also, what's wrong with just caching every value you ever come across? It's only text and a measurement, so it doesn't take up any space, even with potentially tens of thousands of entries. |
@espadrine It looks like I need to add some logging code for the snippet in #1379 (comment) to work. What would I need to change? I made a naive implementation and it seems to be working… |
@paulmelnikow Here's a diff: diff --git a/server.js b/server.js
index 990c111..949322d 100644
--- a/server.js
+++ b/server.js
@@ -7468,7 +7468,9 @@ function(data, match, end, ask) {
if (isValidStyle(data.style)) {
badgeData.template = data.style;
}
+ console.time('makeBadge total');
const svg = makeBadge(badgeData);
+ console.timeEnd('makeBadge total');
makeSend(format, ask.res, end)(svg);
} catch(e) {
log.error(e.stack); You can add other |
Quick note: the OVH offer we are on, VPS SSD 1, has a single vcore. |
Ah, gotcha… thanks. |
I opened #1390 with the approach I took. |
Ref: #1379 This takes a naive approach to font-width computation, the most compute-intensive part of rendering badges. 1. Add the widths of the individual characters. - These widths are measured on startup using PDFKit. 2. For each character pair, add a kerning adjustment - The difference between the width of each character pair, and the sum of the characters' separate widths. - These are computed for each character pair on startup using PDFKit. 3. For a string with characters outside the printable ASCII character set, fall back to PDFKit. This branch averaged 0.041 ms in `makeBadge`, compared to 0.144 ms on master, a speedup of 73%. That was on a test of 10,000 consecutive requests (using the `benchmark-performance.sh` script, now checked in). The speedup applies to badges containing exclusively printable ASCII characters. It wouldn't be as dramatic on non-ASCII text. Though, we could add some frequently used non-ASCII characters to the cached set.
Do you think this could be closed now that we have #1390 merged? |
Currently,
pdfkit
is used for text width measurements. I would advise to usefontkit
instead (it's also used internally bypdfkit
), to cut down on the overhead and increase performance. See: https://github.com/devongovett/fontkit, method:font.layout()
.The text was updated successfully, but these errors were encountered: