Anki-android: Changing Japanese font slows down ankidroid considerably

Created on 22 May 2018  ·  27Comments  ·  Source: ankidroid/Anki-Android

Changed to a different font using the "add font to media folder and use @font family to the template" method. Loading every card and it's answer takes around half a second. Attempted it with two different fonts, and only the default font makes ankidroid run normally.
Tested fonts were Hanamin and Ryumin

Reproduction Steps
  1. Download font
  2. Add it to Anki media collection on the desktop
  3. Set it up as a template for all cards in a single deck
Expected Result

The font changed on every card.

Actual Result

The font changed, but now ankidroid takes around half a second to load every card while going through reps.

Accepted Bug upstream-issue

Most helpful comment

For anyone having fun and following along at home, there appears to be renewed interest in the issue, but migrated to a different chromium bug id https://bugs.chromium.org/p/chromium/issues/detail?id=945117

All 27 comments

Hi there - I can maybe analyze the performance on this, though I suspect it is in the rendering, which is done by a system component and not something we control.

Can you upload a collection with the font installed and cards that use it so I can reproduce this more easily?

Also, you did not indicate what version of Android or AnkiDroid you are using, that information along with your WebView implementation version is necessary to pin this down

Thanks!

Sure thing. I'm using ankidroid 2.8.3 and Android 6.0.1. The WebView implementation version is 66.0.3359.158. Thanks!
Anki collection.zip

Using custom Chinese font and this issue persists in latest alpha of 2.9 on Android 7.0.12.

Card also flashes whenever this happen. CSS styling also doesn't load properly due to this.

I can confirm this is the issue with the latest WebView. It works perfectly fine with WebView 55 (I've used 'Uninstall updates' to downgrade to the stock version for my device) but not with the latest WebView 67 (I've also tried 68.0.3440.40 beta with the same result).

I've created an issue on Chromium Issue Tracker: https://bugs.chromium.org/p/chromium/issues/detail?id=866244

I don't think that chromium issue is going to receive any attention unless you provide the full html and font file for a card that is slow to load. If you compile ankidroid from source there's a flag you can enable somewhere which enables saving the rendered html of each card to a file inside the ankidroid folder

Hi all--Android WebView engineer here! Yes, if you can attach an HTML file to the chromium issue, that will greatly help debugging. Or even better, a minimal repro app (compiled APK + zipped source code) would be super helpful.

Hi @nfischer with the collection above and recent alpha builds (forwards- and backwards-compatible with 2.8, no worries for your database) I've enabled chromium webview debugging and also output the HTML of the card on the device with every card. So the workbench is laid out if you have the time to look at this.

https://github.com/ankidroid/Anki-Android/pull/4979

https://github.com/ankidroid/Anki-Android/wiki/Development-Guide#html-javascript-inspection

Hi @mikehardy. Thanks for following up. I left a comment on the crbug.

OK I read it I'll try to get one of those html files wrapped up with a repro bow if I can reproduce in the app

@TorridCheese @Xyde or @alex7kom - It sounds like at least one of you is using the latest alpha. I don't know if any of you have ever built from source or run a debug build but in the newest alphas, if you do so the HTML drops right on the device filesystem in /sdcard/AnkiDroid so we can pinpoint this.

Are any of you still experiencing this and able to build the current alpha code so you have this HTML debug feature?

Having someone else handle the build / generate-html / submit to chromium tracker / handle feedback loop would be a big help to me. I can assert that the Alpha at this point is backwards compatible and has no known crash bugs so I'm not asking you to put your collection or study time at risk ;-). Please let me know, thanks.

I've obtained html of the same card with default system font, and the slow version with Noto-CJK.
card.zip

That is fantastic! Thank you - @nfischer - see above, we seem to have HTML?

Okay - word from the chromium bugtracker is that they have looked at the cards in isolation and they can't reproduce it. I just loaded the collection attached to this bug into the API29 / Android 9 Pie emulator, and I see it. Somewhere between the HTML in isolation and the HTML in the webview, there is an answer. As @nfischer mentioned it is probably in our callbacks - we have a couple javascript files that fire and an interaction between the app and the webview on each card load, it must be one of those. (edit: I think it was that the font wasn't provided with the reproduction - with the font I see it easily in chrome)

I reproduced this in stock html on desktop chrome and attached the same to the chromium bug. We'll see...

It looks like they have reproduced this, thanks everyone for the help - https://bugs.chromium.org/p/chromium/issues/detail?id=866244#c13

I'm going to close this because there is nothing we can do, and even when fixed there will be no action to take that I'm aware of. But I have starred the bug upstream and I recommend anyone interested in the resolution to do the same

if it is even possible, can “installing fonts” (like you'd do on a desktop os) help?

otherwise, seeing that rendering the answer takes time as well as the question, it seems to me that the app is changing the whole document each time. is that the case? if it is, wouldn't things be considerably faster if only the relevant parts would be changing, through javascript or otherwise?

The card with the answer is technically a whole different page so the result is indeed being re-rendered. I've tried various fonts and the bigger the local font file the longer it takes (Noto-CJK is in particular huge) so it seems that the web backend has to reload the same font file every time which I think is a design flaw, but Chromium guys see no problem with it.

I don't see a way to install a custom font into a system on my devices, so the solution I've come to is to use a smaller font like Sawarabi Mincho, the lag is still there on slower devices but at least it is bearable.

Has anyone here tried the font-display: block CSS attribute? It was mentioned on the chromium tracker as being a possibility to optimize things slightly

It might also be interesting to see if someone can get any performance out of the official Google Fonts API: https://developers.google.com/fonts/docs/getting_started

I have been using the Noto (non-combined) Japanese font for years on various devices and never had a problem. Here is an apkg with a few cards from my Japanese deck using this font. Most likely you will not notice any significant delay after the first card when using my deck.

https://github.com/ankidroid/Anki-Android/issues/5213#issuecomment-466602921

The card with the answer is technically a whole different page so the result is indeed being re-rendered.

css is often shared between cards of the same (and sometimes different) type, so you probably can get away with doing something along body.innerHTML = 'new contents' or even answer.innerHTML = 'answer' since the flip side often starts with {{FrontSide}} anyway. probably the widget has means of altering particular elements through the framework (java) as well. shouldn't this be much faster? changing the <style> contents should be possible, too

given how anki itself is doing this fade thing in the new version, i take it they are doing similar things—perhaps for the same reasons?

@oakkitten - In theory, since AnkiDroid will only ever display one card at a time, we could maintain a single WebView for the lifetime of the application (currently it is maintained only for the "started" states of the Activities that use AbstractFlashcardViewer if I recall correctly). Further, we could maintain an HTML document "shell" inside that webview and programmatically inject whatever we wanted in order to alter contents in response to showing new questions or answers. Possibly even looking at the different "slots" that we allow (front, style, back, again if I recall correctly) and only injecting a new version if it differs from the old one. In that way we would certainly be asking Chrome to do the least amount of work.

But.

This would be a non-trivial change, it may not even work (it's a performance change so there would need to be very very easily reproducible tests that showed before and after timings), and in the end Chrome could change again in the future to make something in that strategy slow.

Before anything, It's important to isolate exactly what things are slow. For instance, it seems clear from Tim's comment that some fonts are indeed slow (we know that) but also that at least one Japanese font (Noto non-combined) is sufficiently fast. Only once we understand exactly what's slow and why can we even make a reasonable decision.

Note that AnkiDroid has some abilities that would help a curious person do exactly that - https://github.com/ankidroid/Anki-Android/wiki/Development-Guide#html-javascript-inspection

For anyone having fun and following along at home, there appears to be renewed interest in the issue, but migrated to a different chromium bug id https://bugs.chromium.org/p/chromium/issues/detail?id=945117

Not sure if anyone has tried this, but apparently the fallback logic in chromium for ideographic languages has a tough time. You might try setting lang="ja" in the html element of the note (is that possible? may not be - you might have to hack card.html in our source code to test it...). Or lang="zh" as the case may be (for your card)

https://bugs.chromium.org/p/chromium/issues/detail?id=945117#c33

They did split the issue again. This one discusses cache and font sizes:
https://bugs.chromium.org/p/chromium/issues/detail?id=893318#c4

I can confirm that the font re-renders, front and back, after updating my OS to Pie. It only needed to do it on the first card before. The larger the font, the longer the delay. With a rooted phone, I installed older versions of WebView, but it seems they are not compatible with Pie, as any app that uses Webview crashed.

Here's a workaround for rendering Noto Sans JP quickly: Test-GoogleAPI.apkg.zip
(remove ".zip" from the filename to import)

It imports the font from Google API, which serves WOFF2 format with small file size, so rendering is very fast. (You have to be online to load for the first time, then the font will display even when offline. I assume this is because it gets cached in Webview).

Was this page helpful?
0 / 5 - 0 ratings