Question/discussion about JDK-8129582

Philip Race philip.race at oracle.com
Sun Mar 18 18:28:54 UTC 2018


It seems we should look at this. I apparently never saw or read (acc. to 
my mailer) previous
email where you identified a problem with PangoGlyphLayout else we'd 
likely have looked
at it when you sent it, as I agree this sounds like a major performance 
issue.

-phil.

On 3/18/18, 4:19 AM, Itai wrote:
> Hello,
>
> In hopes of getting this bug fixed, I have made changes to 
> `PangoGlyphLayout` so that is only allocates the FT2 FontMap once, and 
> uses a `PlatformImpl.FinishListener` to unref it when the JavaFX 
> platform exits. Attached is the modified version of the file.
> In my personal tests, depending on hardware used, there is a speedup 
> of between x2 and x10 in layout times, and scrolling large 
> Lists/Tables feels as snappy with CTL languages as with any other 
> language.
> For anyone wanting to test it, remember this bug only affects Linux, 
> and only CTL languages (such as Arabic, Farsi, Hebrew and Hindi).
>
> Regards,
> Itai.
>
> On Sun, Jan 8, 2017 at 11:39 PM, Itai <itaisha at gmail.com 
> <mailto:itaisha at gmail.com>> wrote:
>
>     I think I have found two problems. The first, and probably most
>     critical one, is that a new PangoFontMap is created for every call
>     of PangoGlyphLayout#layout. It is not entirely clear from the
>     Pango documentation what the lifetime or intended usage of a
>     PangoFontMap is, but I have found this comment in [1]:
>
>     "But note that a PangoFontMap is a big expensive object. So, you
>     *really* want to be using only one for your entire program.
>     Frequently calling pango_ft2_font_map_new() is going kill
>     the performance of your application."
>
>     This seems to imply PangoFontMap is intended as a global (per
>     display?) font cache. Indeed, creating only one PangoFontMap seems
>     to improve performance drastically, although I'm not sure what is
>     the best way to handle this object (i.e. when and how it should be
>     re-used and freed), as it should probably (?) be held for the
>     entire lifetime of the JavaFX application.
>
>     The second problem is probably less significant, but could still
>     theoretically hurt performance - it has to do with the usage of
>     g_list_nth_data, which as per [2] has O(N) complexity, and is
>     called once per item in the list, which yields O(N^2) complexity.
>     Replacing it with linked-list traversal with g_list_next should
>     reduce this back to O(N).
>
>     I hope this information is clear enough. As I said I lack the
>     overall understanding of the JavaFX platform to know where and how
>     to manage a global object, such as PangoFontMap should apparently
>     be, so I refrain from posting any patch that I know would be wrong.
>
>     Regards,
>     Itai.
>
>     [1]:
>     https://mail.gnome.org/archives/gtk-list/2005-April/msg00105.html
>     <https://mail.gnome.org/archives/gtk-list/2005-April/msg00105.html>
>     [2]:
>     https://developer.gnome.org/programming-guidelines/stable/glist.html.en
>     <https://developer.gnome.org/programming-guidelines/stable/glist.html.en>
>
>     On Sun, Jan 8, 2017 at 8:08 PM, Itai <itaisha at gmail.com
>     <mailto:itaisha at gmail.com>> wrote:
>
>         Thank you for the link, it's an interesting read indeed!
>
>         I wasn't really skipping layout, just using the much simpler
>         layout used by Latin scripts, but you are correct that this
>         will break for anything more complex - this has nothing to do
>         with BiDi though, more to do with complex layout elements
>         (like diacritic or cantillation marks for Hebrew, or general
>         Arabic/Farsi text).
>         Indeed, this can't be a general solution, but I guess I was
>         driven by frustration.
>
>         I have tried some more configurations though, and found that
>         on Windows the loss of performance is much less noticeable,
>         which seems to mean that the problem is either:
>         1. Pango is inherently slow / inherently slow when laying out
>         BiDi text.
>         2. JavaFX uses Pango in a sub-optimal / redundant way.
>         3. The JNI / native calls to Pango are done in a sub-optimal way.
>
>         Option 1 can be easily debunked, as general Gnome/GTK
>         applications run as smoothly with BiDi text as with Latin /
>         LTR text.
>         For options 2 and 3 I guess some more digging into the code
>         must be done. My understanding is that JNI calls are not
>         likely to incur performance loss to such a degree, unless very
>         large amounts of memory are copied back and forth between Java
>         and native code, so I'll start by reading into the Pango
>         documentation and understanding the logic of PangoGlyphLayout.
>
>         If you have any input on this or believe my assumptions or
>         conclusions are wrong I'd be glad to hear. I realize you are
>         all busy with the upcoming 9 release, so I'll try to get as
>         detailed a result as I can.
>
>         Regards,
>         Itai.
>
>         On Wed, Jan 4, 2017 at 8:44 PM, Phil Race
>         <philip.race at oracle.com <mailto:philip.race at oracle.com>> wrote:
>
>             You can't skip layout just because it is bidi ..
>             where here you are apparently implicitly meaning Hebrew.
>             This might be apparently working but may not always work even
>             for Hebrew and will be a disaster for Arabic.
>
>             Here is a web page which talks about OTL (OpenType Layout)
>             for Hebrew :
>             https://www.microsoft.com/typography/OpenTypeDev/hebrew/intro.htm
>             <https://www.microsoft.com/typography/OpenTypeDev/hebrew/intro.htm>
>             I can't say offhand why this might be exclusive to FX.
>             That test case would be handy.
>             So this needs more analysis even if you found a way to
>             limit this to
>             specifically Latin+Hebrew.
>
>             -phil.
>
>
>             On 01/04/2017 10:32 AM, Itai wrote:
>>             Some quick-and-dirty thing I hacked now and seems to
>>             improve the performance drastically is something like:
>>
>>             if (complex but not bidi) {
>>                use GlyphLayout.
>>             } else if (bidi) {
>>                use java.text.Bidi.reorderVisually to get visual glyph
>>             order, then use same implementation as non-bidi
>>             non-complex layout
>>             } else {
>>                ...
>>             }
>>
>>             Very minimal tests show it working correctly, and
>>             performance is 8-10 times faster (on par with non-bidi
>>             text).
>>             Do you think this solution makes sense? Can you see any
>>             obvious pitfalls?
>>             If it seems OK I'll try some more tests and then work it
>>             into something clean enough to submit as a patch suggestion.
>>
>>
>>             On Wed, Jan 4, 2017 at 7:48 PM, Itai <itaisha at gmail.com
>>             <mailto:itaisha at gmail.com>> wrote:
>>
>>                 Thanks for replying.
>>                 I think I understand what you're saying about the
>>                 cache. As for complexity - I'm mostly working with
>>                 text which is only in Hebrew, which isn't complex as
>>                 far as I understand the definition (no glyph "fusing"
>>                 as in Arabic or Farsi). I can work with minor
>>                 performance drops, but when the same window takes
>>                 more than 10 times to show if it has Hebrew labels is
>>                 a lot more than minor - and this is exclusive to
>>                 JavaFX, so it's not like this problem is unsolvable.
>>
>>                 Perhaps the caching is indeed not the correct
>>                 solution, but maybe there can be a way to simplify
>>                 the layout in non-complex BiDi cases? Or optimize
>>                 PangoGlyphLayout.layout?
>>
>>                 Thank you again for replying, I really hope this
>>                 issue can see some improvement.
>>
>>                 On Wed, Jan 4, 2017 at 7:26 PM, Philip Race
>>                 <philip.race at oracle.com
>>                 <mailto:philip.race at oracle.com>> wrote:
>>
>>                     The cache is a heuristic optimisation and whether
>>                     it helps depends on how well that cache is used.
>>                     It is a time-space trade-off and I'd expect it to
>>                     show up as helping more in micro-benchmarks or
>>                     text-intensive benchmarks which use the same text
>>                     broken in the same way.
>>                     Complex text layout is inherently slower and if
>>                     you are doing a lot of it .. it will be slow .. and
>>                     unless it is repeated a cache won't help.
>>                     During start-up I'd *expect* that there isn't a
>>                     lot of re-use going on.
>>
>>                     You would need to profile how often  the same
>>                     text (and attributes) are passed through this code.
>>                     If you could provide us a test case we could
>>                     examine it too.
>>
>>                     If it were a real use case, then we'd move on to
>>                     examine the feasibility of caching ...
>>
>>                     -phil.
>>
>>
>>
>>                     On 1/4/17, 9:19 AM, Itai wrote:
>>
>>                         Recently JDK-8129582 [1] started really
>>                         affecting me, with startup speed
>>                         and overall responsiveness becoming really bad.
>>
>>                         Digging into it, I have found most time is
>>                         wasted in
>>                         com.sun.javafx.text.GlyphLayout.layout (as
>>                         represented by PangoGlyphLayout
>>                         on my Linux machine), which in turn is called
>>                         by com.sun.javafx.text.PrismTextLayout.shape,
>>                         which has:
>>
>>                              if (run.isComplex()) {
>>                                      /* Use GlyphLayout to shape
>>                         complex text */
>>                                      layout.layout(run, font, strike,
>>                         chars);
>>                              } else {
>>                                      ...
>>                                      if (layoutCache == null) {
>>                                       ...
>>                                       } else {
>>                                        ...
>>                                       }
>>                              }
>>
>>                         which to my very naive reading seems as if
>>                         while non-complex (with all BiDi
>>                         text considered complex) glyph runs are
>>                         cached, complex runs are never
>>                         cached, which forces re-calculation every time.
>>
>>                         I'm trying to read and understand this part
>>                         better, but could it be
>>                         possible that this is the issue? How feasible
>>                         would it be to have a layout
>>                         cache for complex runs, or at least
>>                         non-complex BiDi runs?
>>
>>                         Thanks,
>>                         Itai.
>>
>>                         [1]:
>>                         https://bugs.openjdk.java.net/browse/JDK-8129582
>>                         <https://bugs.openjdk.java.net/browse/JDK-8129582>
>>
>>
>>
>
>
>
>


More information about the openjfx-dev mailing list