[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-2d-dev
Subject:    [OpenJDK 2D-Dev] RFR: 8209113 : Use WeakReference for lastFontStrike for created Fonts
From:       Phil Race <philip.race () oracle ! com>
Date:       2019-11-27 21:42:42
Message-ID: 0e95939f-fd80-a790-d0bc-f047c2d5588d () oracle ! com
[Download RAW message or body]

Bug : https://bugs.openjdk.java.net/browse/JDK-8209113 
<https://bugs.openjdk.java.net/browse/JDK-8209113>

Webrev: http://cr.openjdk.java.net/~prr/8209113/


This fix is intended to update the ergonomics of font glyph caching which
uses off-java heap native memory and so is not considered by garbage 
collection.
The update has become needed as the GCs have changed to favour performance
over reclaimation of resources as heaps have grown very large and client
(and server) applications are being run with VMs with server focused 
ergonomics

Also note that this is actually more of a server problem than a client one,
since a UI client usually uses a small number of fonts.
Servers are often processing thousands of documents that contain custom
fonts - typically all different - and reclaiming these more promptly 
will free
up the native memory used by the font rasterizer data structures, and the
temporary font files they use as well as the memory used to cache glyph 
images.

Each font instance has its own cache of strikes which in turn reference 
the native
images, so there is no global management.
This fix does not go so far as to look for a way to limit the amount of 
memory used
by each font which would require some major surgery to the current GC 
managed
approach.
So the changes here are to allow more prompt clearing of references and
recollection of the native memory by each font.

The important change is in Font2D where there is a SoftReference to the 
last used strike.
https://bugs.openjdk.java.net/browse/JDK-8209113 observes that the 
reluctance of
the VM to clear this SoftReference causes delays in freeing all of the 
resources.
Now the code is updated to conditionally use a WeakReference.
Using a WeakReference is controlled from the code in SunFontManager based
on whether this is a temporary "created" font and how many temp fonts are
being created. So this should not affect system fonts at all, and should 
also not
affect an app using a small number of custom fonts while helping the 
server case a lot.

The other change is that FontStrikeDisposer no longer holds a reference 
to the Font2D.
It needed it solely to call back to remove its strike from the Map of 
Strikes once
it was collected. Now it holds a reference directly to the Map and its 
dispose
method does the removal without needing to ask the Font2D.
This does not make a lot of difference, but every bit helps.

Instrumented testing shows that together, for at least some workloads, these
changes help smooth out native memory usage by making collection of 
temporary
fonts more prompt. There are doubtless pathological cases that are still 
a problem
and if you want to hold concurrent references in your application to 
100,000 java.awt.Font
instances, all of which are being used, then you need to size your 
server to cope ...

But this will be helpful in the typical ephemeral font case.

Random ideas that could go further but are out of scope of this fix are
1) An explicit dispose() method on a Font.
     Problems here include the semantics of this for System fonts, 
backwards compatibility
and ensuring no one is still using it. Even if the implementation is 
limited to clearing
just the native memory usage these can still be issues and if you remove 
the backing
file then you can never re-create it.
2) Some automatic internal per-font limitation on the amount of storage 
a Font uses.
   Here there would also need to be some way to ensure code was locked 
out from using
   it whilst this was happening. It may be more doable but it would 
mainly help the cases
  where applications used the same font extensively. Not the case where 
thousands of
  fonts are used minimally.
3) Looking to see if two fonts are actually identical. If a temp font is 
created from
   a byte stream and the byte stream is identical to some other temp 
font then really
   these are the same. If you have thousands of such shareable fonts 
this would be a big
  win. But we'd need to have a way to locate all such temp fonts (that 
did not itself
prevent their prompt collection) and quickly compare them - probably a 
hash calculated
when they were created - and then do a full comparison when the hashes 
match.
But if shareable fonts are rare, it won't help at all. However it might 
be worth exploring
some day.

-phil.



[Attachment #3 (text/html)]

<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <font size="+1"><tt><br>
      </tt><tt><a
          href="https://bugs.openjdk.java.net/browse/JDK-8209113"
          target="_blank">Bug :
          https://bugs.openjdk.java.net/browse/JDK-8209113</a></tt></font><br>
    <br>
    Webrev: <a class="moz-txt-link-freetext" \
href="http://cr.openjdk.java.net/~prr/8209113/">http://cr.openjdk.java.net/~prr/8209113/</a><br>
  <br>
    <br>
    This fix is intended to update the ergonomics of font glyph caching
    which<br>
    uses off-java heap native memory and so is not considered by garbage
    collection.<br>
    The update has become needed as the GCs have changed to favour
    performance<br>
    over reclaimation of resources as heaps have grown very large and
    client<br>
    (and server) applications are being run with VMs with server focused
    ergonomics<br>
    <br>
    Also note that this is actually more of a server problem than a
    client one,<br>
    since a UI client usually uses a small number of fonts.<br>
    Servers are often processing thousands of documents that contain
    custom<br>
    fonts - typically all different - and reclaiming these more promptly
    will free<br>
    up the native memory used by the font rasterizer data structures,
    and the<br>
    temporary font files they use as well as the memory used to cache
    glyph images.<br>
    <br>
    Each font instance has its own cache of strikes which in turn
    reference the native<br>
    images, so there is no global management.<br>
    This fix does not go so far as to look for a way to limit the amount
    of memory used<br>
    by each font which would require some major surgery to the current
    GC managed<br>
    approach.<br>
    So the changes here are to allow more prompt clearing of references
    and<br>
    recollection of the native memory by each font.<br>
    <br>
    The important change is in Font2D where there is a SoftReference to
    the last used strike.<br>
    <a class="moz-txt-link-freetext" \
href="https://bugs.openjdk.java.net/browse/JDK-8209113">https://bugs.openjdk.java.net/browse/JDK-8209113</a> \
observes that the  reluctance of<br>
    the VM to clear this SoftReference causes delays in freeing all of
    the resources.<br>
    Now the code is updated to conditionally use a WeakReference.<br>
    Using a WeakReference is controlled from the code in SunFontManager
    based<br>
    on whether this is a temporary "created" font and how many temp
    fonts are<br>
    being created. So this should not affect system fonts at all, and
    should also not<br>
    affect an app using a small number of custom fonts while helping the
    server case a lot.<br>
    <br>
    The other change is that FontStrikeDisposer no longer holds a
    reference to the Font2D.<br>
    It needed it solely to call back to remove its strike from the Map
    of Strikes once<br>
    it was collected. Now it holds a reference directly to the Map and
    its dispose<br>
    method does the removal without needing to ask the Font2D.<br>
    This does not make a lot of difference, but every bit helps.<br>
    <br>
    Instrumented testing shows that together, for at least some
    workloads, these<br>
    changes help smooth out native memory usage by making collection of
    temporary<br>
    fonts more prompt. There are doubtless pathological cases that are
    still a problem<br>
    and if you want to hold concurrent references in your application to
    100,000 java.awt.Font<br>
    instances, all of which are being used, then you need to size your
    server to cope ...<br>
    <br>
    But this will be helpful in the typical ephemeral font case.<br>
    <br>
    Random ideas that could go further but are out of scope of this fix
    are<br>
    1) An explicit dispose() method on a Font.<br>
        Problems here include the semantics of this for System fonts,
    backwards compatibility<br>
    and ensuring no one is still using it. Even if the implementation is
    limited to clearing<br>
    just the native memory usage these can still be issues and if you
    remove the backing<br>
    file then you can never re-create it.<br>
    2) Some automatic internal per-font limitation on the amount of
    storage a Font uses.<br>
      Here there would also need to be some way to ensure code was
    locked out from using<br>
      it whilst this was happening. It may be more doable but it would
    mainly help the cases<br>
     where applications used the same font extensively. Not the case
    where thousands of<br>
     fonts are used minimally.<br>
    3) Looking to see if two fonts are actually identical. If a temp
    font is created from<br>
      a byte stream and the byte stream is identical to some other temp
    font then really<br>
      these are the same. If you have thousands of such shareable fonts
    this would be a big<br>
     win. But we'd need to have a way to locate all such temp fonts
    (that did not itself<br>
    prevent their prompt collection) and quickly compare them - probably
    a hash calculated<br>
    when they were created - and then do a full comparison when the
    hashes match.<br>
    But if shareable fonts are rare, it won't help at all. However it
    might be worth exploring<br>
    some day.<br>
    <br>
    -phil.<br>
    <br>
    <br>
  </body>
</html>



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic