Skip to content

Reduce number of font file handles opened #5295

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

Merged
merged 3 commits into from
Oct 29, 2015

Conversation

mdboom
Copy link
Member

@mdboom mdboom commented Oct 21, 2015

Reduce number of font files opened

This should hopefully address the long-reported "Too many open files"
error message (Fix #3315).

To reproduce: On a Mac or Windows box with starvation for file
handles (Linux has a much higher file handle limit by default), build
the docs, then immediately build again. This will trigger the caching
bug.

The font cache in the mathtext renderer was broken. It was caching a
font file once for every combination of font properties, including
things like size. Therefore, in a complex math expression containing
many different sizes of the same font, the font file was opened once for
each of those sizes.

Font files are opened and kept open (rather than opened, read,
and closed) so that FreeType only needs to load the actual glyphs that
are used, rather than the entire font. In an era of cheap memory and
fast disk, it probably doesn't matter for our current fonts, but once
#5214 is merged, we will have larger font files with many more glyphs

and this loading time will matter more.

The solution here is to do all font file loading in one place and to use
lru_cache (available since Python 3.2) to do the caching, and to use
only the file name and hinting parameters as a cache key. For earlier
versions of Python, the functools32 backport package is required. (Or
we can discuss whether we want to vendor it).

Milestoning as 2.0, since it should be tied to #5214.

@mdboom mdboom added this to the next major release (2.0) milestone Oct 21, 2015
@mdboom
Copy link
Member Author

mdboom commented Oct 22, 2015

Test failure is due to functools32 not working with Python 2.6. Since this is slated for matplotlib 2.0, which is currently planned to drop support for Python 2.6, I don't think it matters.

@jkseppan
Copy link
Member

👍

I think this needs an entry in api_changes.rst

@mdboom
Copy link
Member Author

mdboom commented Oct 26, 2015

What's the API change? Everything is backward compatible here -- I've just replaced a bunch of independent caches with a central one (that also works correctly).

@jkseppan
Copy link
Member

I mean that backends should now use get_font instead of FT2Font directly.

@mdboom
Copy link
Member Author

mdboom commented Oct 26, 2015

That's not strictly true, though. That's only if they want to have the font file cached in memory for later use. There are places still in the matplotlib code base that instantiate an FT2Font directly (such as the font lookup cache creation).

I guess what's at issue is that I see api_changes as being about backward-incompatible changes in API, not for new APIs...

@mdboom
Copy link
Member Author

mdboom commented Oct 27, 2015

Status update: This is ready to go once we turn off Python 2.6 (#5215)

@mdboom mdboom force-pushed the too-many-open-files branch from 4952394 to e05d646 Compare October 27, 2015 19:15
This should hopefully address the long-reported "Too many open files"
error message (Fix matplotlib#3315).

To reproduce: On a Mac or Windows box with starvation for file
handles (Linux has a much higher file handle limit by default), build
the docs, then immediately build again.  This will trigger the caching
bug.

The font cache in the mathtext renderer was broken.  It was caching a
font file once for every *combination* of font properties, including
things like size.  Therefore, in a complex math expression containing
many different sizes of the same font, the font file was opened once for
each of those sizes.

Font files are opened and kept open (rather than opened, read,
and closed) so that FreeType only needs to load the actual glyphs that
are used, rather than the entire font.  In an era of cheap memory and
fast disk, it probably doesn't matter for our current fonts, but once
 matplotlib#5214 is merged, we will have larger font files with many more glyphs
and this loading time will matter more.

The solution here is to do all font file loading in one place and to use
`lru_cache` (available since Python 3.2) to do the caching, and to use
only the file name and hinting parameters as a cache key.  For earlier
versions of Python, the functools32 backport package is required.  (Or
we can discuss whether we want to vendor it).
@mdboom mdboom force-pushed the too-many-open-files branch from e05d646 to 5e93dfc Compare October 28, 2015 15:33
tacaswell added a commit that referenced this pull request Oct 29, 2015
MNT: Reduce number of font file handles opened
@tacaswell tacaswell merged commit a33bf58 into matplotlib:master Oct 29, 2015
@mdboom
Copy link
Member Author

mdboom commented Oct 30, 2015

Backported to v2.0.x as cdea77c

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

"Too many open files" in test runs on Python 3.3
3 participants