New issue
Advanced search Search tips

Issue 616414 link

Starred by 1 user

Issue metadata

Status: Duplicate
Merged: issue 621878
Owner:
Closed: Jun 2016
Cc:
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 2
Type: Bug

Blocking:
issue 561099



Sign in to add a comment

Likely leakage of hb_blob_t in HarfBuzzFace

Project Member Reported by drott@chromium.org, Jun 1 2016

Issue description

What steps will reproduce the problem?
(1) Apply https://codereview.chromium.org/2026683003, a CL that adds a quick and dirty checks for whether hb_blob_create and free calls are balanced, and tracks the leaked amount of data.
(2) Visit http://roettsch.es/pagecycle.html with a Chromium build on Linux which prints debug output, a debug build should do. Run in --single-process mode.
(3) Click on "start cycling pages"

What is the expected output?
On Linux, letting 3 iterations of the page cycling happen for a set of popular pages results in ~2.3MB of leaked table data. Running the same on Android Chromium release, results in about 880kb of leaked data.

Testing this in Android webview was unsuccesful due to crashes.

What do you see instead?
Blob creation and freeing should be balance.


 

Comment 1 by drott@chromium.org, Jun 1 2016

Correction for the reproduction: activate complex text on Android in Font.cpp.

Comment 2 by drott@chromium.org, Jun 1 2016

behdad@, what's the expected lifecycle of the retrieved table hb_blob_t's. Should the last instances of them go away only when the hb_face_t is destroyed? Or is the lifecycle shorter and they should only last for the duration of "callback-to-retrieve-table", "use", "destroy right away"?

If the first is the case, we really need to think about the lifecycle of our FontPlatformData objects. When shaping needs a HarfBuzzFace object, we get the SkTypeface uniqueID() from the typeface() of FontPlatformData, and create a hb_face_t object for those, then add it to the HarfBuzzFontCache.

In most of the situations, i.e. if nothing changes in the system's font configuration during the lifetime of the single process browser, we never delete previously create FontPlatformData objects, and thus never call destructors of HarfBuzzFace, and never remove the hb_face_t objects from the cache.

Comment 3 by drott@chromium.org, Jun 1 2016

I've updated the CL to track by table tag, for the above page cycler test, single process, Chromium debug on Linux.

Tag: head leftover kb 0
Tag: hhea leftover kb 0
Tag: GPOS leftover kb 145.408
Tag: vhea leftover kb 0
Tag: OS/2 leftover kb 0
Tag: GSUB leftover kb 28.5391
Tag: vmtx leftover kb 990.488
Tag: hmtx leftover kb 1055.77
Tag: GDEF leftover kb 3.16406
Tag: cmap leftover kb 103.367
---------------------
Total: kb 2326.74

Comment 4 by drott@chromium.org, Jun 2 2016

Okay, it looks like when the hb_font_t cached in HbFontCacheEntry is going away, all the blobs are cleaned up. Experimentally I removed the m_harfBuzzFace member from FontPlatformData and created the HarfBuzzFace objects only temporarily. This removes the hb_blob_t leakage but also makes things a lot slower since it disables that caching.

What this boils down to: Our caches for FontPlatformData objects and SimpleFontData do not have any eviction strategy, except: "process killed" - so in a single process environment like the Android web view, they just keep growing and all FontPlatformData objects are kept alive, and in turn they keep the HarfBuzzFace objects and hb_font_t's around - and that's where we create hb_blob_t's that are kept in memory. For page cycler tests in single proecss, this means that they reach a maximum after the first cycle. But then keep getting reused at least.

Other findings: The purge method of the FontDataCache is broken, because the refcounting of the objects returned from the cache is not kept track of correctly.
Correct.  I still think mmap()ing, and some sane eviction policy, is the right way to do.

Comment 6 by drott@chromium.org, Jun 29 2016

Mergedinto: 621878
Status: Duplicate (was: Started)

Sign in to add a comment