Re: [GCJ] Performance of GUI applications on embedded systems
You're right. However I'm experiencing slowness when testing some other GUI sample application (e.g. the test case attached at the end). In this particular test case, the application takes a lot of time to startup (compared to the same device, running WinCE and CrEme JVM) and during start up the CPU usage is always at 100%. After startup, I'v also noticed that highlighting and/or clicking a certain number of times on buttons cause the application to hang and after that the CPU usage is always 100%. I've identified some serious GTK locking problems with this version of gcj. I'm investigating. Found a very silly (:-) merge error in CairoGraphics2D.c. This fixes it. I don't think there should be any differences between the GTK peers in Classpath and gcj, should there? Or indeed, and differences between the CNI code in Classpath and gcj. Andrew. Index: gnu_java_awt_peer_gtk_CairoGraphics2D.c === --- gnu_java_awt_peer_gtk_CairoGraphics2D.c (revision 141575) +++ gnu_java_awt_peer_gtk_CairoGraphics2D.c (working copy) @@ -351,7 +351,6 @@ for (i = 0; i n; i++) { PangoFcFont *font = JLONG_TO_PTR(PangoFcFont, fonts[i]); - gdk_threads_leave (); /* Draw as many glyphs as possible with the current font */ int length = 0; Hi Andrew, I can see that with your patch the application now doesn't hang anymore when highlighting and/or clicking on buttons. GUI performance of applications on my embbeded system seems also to be quite better now. I wonder if there's still some place for UI performance improvement. Thank you, Francesco
Re: [GCJ] Performance of GUI applications on embedded systems
ffileppo wrote: I can see that with your patch the application now doesn't hang anymore when highlighting and/or clicking on buttons. GUI performance of applications on my embbeded system seems also to be quite better now. Good. I wonder if there's still some place for UI performance improvement. I'm sure there is! Patches welcome. Andrew.
Re: [GCJ] Performance of GUI applications on embedded systems
Hi Andrew, On Sun, 2008-11-09 at 00:24 +, Andrew John Hughes wrote: So is the bug GCJ only? I got the impression we were also seeing this on Classpath. I cannot replicate it with jamvm/classpath, so I assume it is gcj only. The erroneous gdk_threads_leave () line is also not in the classpath CVS sources. Cheers, Mark
Re: [GCJ] Performance of GUI applications on embedded systems
Andrew John Hughes wrote: 2008/11/8 Andrew Haley [EMAIL PROTECTED]: Andrew Haley wrote: Index: gnu_java_awt_peer_gtk_CairoGraphics2D.c === --- gnu_java_awt_peer_gtk_CairoGraphics2D.c (revision 141575) +++ gnu_java_awt_peer_gtk_CairoGraphics2D.c (working copy) @@ -351,7 +351,6 @@ for (i = 0; i n; i++) { PangoFcFont *font = JLONG_TO_PTR(PangoFcFont, fonts[i]); - gdk_threads_leave (); /* Draw as many glyphs as possible with the current font */ int length = 0; Incidentally, this bug was introduced on 2007-06-04, so this patch needs applying to a bunch of systems and gcc branches. It affects Fedora systems and (presumably) recent Debians. So is the bug GCJ only? I got the impression we were also seeing this on Classpath. This one is gcj only, for sure. This patch removes the difference between gcj and Classpath. Andrew.
Re: [GCJ] Performance of GUI applications on embedded systems
Andrew Haley wrote: ffileppo wrote: Here's one improvement. If you can get rid of the places in the GTK peers where class and method lookups are performed at runtime you'll probably have a fix. This shouldn't be a massive amount of work, just rather boring. In gcj, * Compiled java code is quite fast. * Class lookup by name is slow. * Calling JNI code from compiled java code is quite fast. * Calling compiled java code from JNI code is slow. * Exceptions are slow. I'm testing your patch on my embedded system and now I can see that GUI performance are very much better (particularly during application startup). Thank you so much! However running my test case (please see my first post) I see that CPU usage is always at 100% (after the application is running), so the responsiveness is still not very good. What do you expect? You're setting up a Timer with a delay of 0 milliseconds between events, and it's running continuously. Andrew. You're right. However I'm experiencing slowness when testing some other GUI sample application (e.g. the test case attached at the end). In this particular test case, the application takes a lot of time to startup (compared to the same device, running WinCE and CrEme JVM) and during start up the CPU usage is always at 100%. After startup, I'v also noticed that highlighting and/or clicking a certain number of times on buttons cause the application to hang and after that the CPU usage is always 100%. I've identified some serious GTK locking problems with this version of gcj. I'm investigating. Found a very silly (:-) merge error in CairoGraphics2D.c. This fixes it. I don't think there should be any differences between the GTK peers in Classpath and gcj, should there? Or indeed, and differences between the CNI code in Classpath and gcj. Andrew. Index: gnu_java_awt_peer_gtk_CairoGraphics2D.c === --- gnu_java_awt_peer_gtk_CairoGraphics2D.c (revision 141575) +++ gnu_java_awt_peer_gtk_CairoGraphics2D.c (working copy) @@ -351,7 +351,6 @@ for (i = 0; i n; i++) { PangoFcFont *font = JLONG_TO_PTR(PangoFcFont, fonts[i]); - gdk_threads_leave (); /* Draw as many glyphs as possible with the current font */ int length = 0;
Re: [GCJ] Performance of GUI applications on embedded systems
Andrew Haley wrote: Index: gnu_java_awt_peer_gtk_CairoGraphics2D.c === --- gnu_java_awt_peer_gtk_CairoGraphics2D.c (revision 141575) +++ gnu_java_awt_peer_gtk_CairoGraphics2D.c (working copy) @@ -351,7 +351,6 @@ for (i = 0; i n; i++) { PangoFcFont *font = JLONG_TO_PTR(PangoFcFont, fonts[i]); - gdk_threads_leave (); /* Draw as many glyphs as possible with the current font */ int length = 0; Incidentally, this bug was introduced on 2007-06-04, so this patch needs applying to a bunch of systems and gcc branches. It affects Fedora systems and (presumably) recent Debians. Andrew.
Re: [GCJ] Performance of GUI applications on embedded systems
2008/11/8 Andrew Haley [EMAIL PROTECTED]: Andrew Haley wrote: Index: gnu_java_awt_peer_gtk_CairoGraphics2D.c === --- gnu_java_awt_peer_gtk_CairoGraphics2D.c (revision 141575) +++ gnu_java_awt_peer_gtk_CairoGraphics2D.c (working copy) @@ -351,7 +351,6 @@ for (i = 0; i n; i++) { PangoFcFont *font = JLONG_TO_PTR(PangoFcFont, fonts[i]); - gdk_threads_leave (); /* Draw as many glyphs as possible with the current font */ int length = 0; Incidentally, this bug was introduced on 2007-06-04, so this patch needs applying to a bunch of systems and gcc branches. It affects Fedora systems and (presumably) recent Debians. Andrew. So is the bug GCJ only? I got the impression we were also seeing this on Classpath. -- Andrew :-) Support Free Java! Contribute to GNU Classpath and the OpenJDK http://www.gnu.org/software/classpath http://openjdk.java.net PGP Key: 94EFD9D8 (http://subkeys.pgp.net) Fingerprint: F8EF F1EA 401E 2E60 15FA 7927 142C 2591 94EF D9D8
Re: [GCJ] Performance of GUI applications on embedded systems
Here's one improvement. If you can get rid of the places in the GTK peers where class and method lookups are performed at runtime you'll probably have a fix. This shouldn't be a massive amount of work, just rather boring. In gcj, * Compiled java code is quite fast. * Class lookup by name is slow. * Calling JNI code from compiled java code is quite fast. * Calling compiled java code from JNI code is slow. * Exceptions are slow. I'm testing your patch on my embedded system and now I can see that GUI performance are very much better (particularly during application startup). Thank you so much! However running my test case (please see my first post) I see that CPU usage is always at 100% (after the application is running), so the responsiveness is still not very good. What do you expect? You're setting up a Timer with a delay of 0 milliseconds between events, and it's running continuously. Andrew. You're right. However I'm experiencing slowness when testing some other GUI sample application (e.g. the test case attached at the end). In this particular test case, the application takes a lot of time to startup (compared to the same device, running WinCE and CrEme JVM) and during start up the CPU usage is always at 100%. After startup, I'v also noticed that highlighting and/or clicking a certain number of times on buttons cause the application to hang and after that the CPU usage is always 100%. I'm still trying to get oprofile working on my target device to see what's going wrong. Thank you, Francesco Test case: import javax.swing.JComponent; import javax.swing.JFrame; import java.awt.BorderLayout; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JTabbedPane; public class GUITest { public static void main(String[] args) { JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JComponent newContentPane = new TestUI(); frame.setTitle(TestUI); newContentPane.setOpaque(true); frame.setContentPane(newContentPane); frame.setBounds(10, 10, 500, 400); frame.setVisible(true); } static class TestUI extends JPanel { long startTime; JPanel createPanel(int start) { JPanel p = new JPanel(); p.setLayout(null); for (int i=0; i100; i++) { JButton ltit = new JButton(Variable +(i+start)+: ); long val = System.currentTimeMillis() - startTime; JButton lval = new JButton(+val); ltit.setBounds(5, 10+20*i, 150, 15); lval.setBounds(200, 10+20*i, 150, 15); p.add(ltit); p.add(lval); } return p; } TestUI() { super(new BorderLayout()); startTime = System.currentTimeMillis(); JTabbedPane p = new JTabbedPane(); for (int i=0; i10; i++) { JPanel page1 = createPanel(i*100+1); p.add(P+i, page1); } add(p, BorderLayout.CENTER); } } }
Re: [GCJ] Performance of GUI applications on embedded systems
ffileppo wrote: However I'm experiencing slowness when testing some other GUI sample application (e.g. the test case attached at the end). In this particular test case, the application takes a lot of time to startup (compared to the same device, running WinCE and CrEme JVM) and during start up the CPU usage is always at 100%. After startup, I'v also noticed that highlighting and/or clicking a certain number of times on buttons cause the application to hang and after that the CPU usage is always 100%. I'm still trying to get oprofile working on my target device to see what's going wrong. Well, it doesn't have to run on the target device. It was easy for me to duplicate your previous problem on my desktop machine with gcj and oprofile. There's nothing to stop you doing the same. Andrew. Test case: import javax.swing.JComponent; import javax.swing.JFrame; import java.awt.BorderLayout; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JTabbedPane; public class GUITest { public static void main(String[] args) { JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JComponent newContentPane = new TestUI(); frame.setTitle(TestUI); newContentPane.setOpaque(true); frame.setContentPane(newContentPane); frame.setBounds(10, 10, 500, 400); frame.setVisible(true); } static class TestUI extends JPanel { long startTime; JPanel createPanel(int start) { JPanel p = new JPanel(); p.setLayout(null); for (int i=0; i100; i++) { JButton ltit = new JButton(Variable +(i+start)+: ); long val = System.currentTimeMillis() - startTime; JButton lval = new JButton(+val); ltit.setBounds(5, 10+20*i, 150, 15); lval.setBounds(200, 10+20*i, 150, 15); p.add(ltit); p.add(lval); } return p; } TestUI() { super(new BorderLayout()); startTime = System.currentTimeMillis(); JTabbedPane p = new JTabbedPane(); for (int i=0; i10; i++) { JPanel page1 = createPanel(i*100+1); p.add(P+i, page1); } add(p, BorderLayout.CENTER); } } }
Re: [GCJ] Performance of GUI applications on embedded systems
ffileppo wrote: Here's one improvement. If you can get rid of the places in the GTK peers where class and method lookups are performed at runtime you'll probably have a fix. This shouldn't be a massive amount of work, just rather boring. In gcj, * Compiled java code is quite fast. * Class lookup by name is slow. * Calling JNI code from compiled java code is quite fast. * Calling compiled java code from JNI code is slow. * Exceptions are slow. I'm testing your patch on my embedded system and now I can see that GUI performance are very much better (particularly during application startup). Thank you so much! However running my test case (please see my first post) I see that CPU usage is always at 100% (after the application is running), so the responsiveness is still not very good. What do you expect? You're setting up a Timer with a delay of 0 milliseconds between events, and it's running continuously. Andrew. You're right. However I'm experiencing slowness when testing some other GUI sample application (e.g. the test case attached at the end). In this particular test case, the application takes a lot of time to startup (compared to the same device, running WinCE and CrEme JVM) and during start up the CPU usage is always at 100%. After startup, I'v also noticed that highlighting and/or clicking a certain number of times on buttons cause the application to hang and after that the CPU usage is always 100%. I've identified some serious GTK locking problems with this version of gcj. I'm investigating. Andrew.
Re: [GCJ] Performance of GUI applications on embedded systems
Here's one improvement. If you can get rid of the places in the GTK peers where class and method lookups are performed at runtime you'll probably have a fix. This shouldn't be a massive amount of work, just rather boring. In gcj, * Compiled java code is quite fast. * Class lookup by name is slow. * Calling JNI code from compiled java code is quite fast. * Calling compiled java code from JNI code is slow. * Exceptions are slow. Andrew. Hi Andrew, I'm testing your patch on my embedded system and now I can see that GUI performance are very much better (particularly during application startup). Thank you so much! However running my test case (please see my first post) I see that CPU usage is always at 100% (after the application is running), so the responsiveness is still not very good. Do you think that there is still some places for improvement? I'll try to use oprofile on my embedded system to see what's going wrong Best Regards, Francesco
Re: [GCJ] Performance of GUI applications on embedded systems
ffileppo wrote: Here's one improvement. If you can get rid of the places in the GTK peers where class and method lookups are performed at runtime you'll probably have a fix. This shouldn't be a massive amount of work, just rather boring. In gcj, * Compiled java code is quite fast. * Class lookup by name is slow. * Calling JNI code from compiled java code is quite fast. * Calling compiled java code from JNI code is slow. * Exceptions are slow. I'm testing your patch on my embedded system and now I can see that GUI performance are very much better (particularly during application startup). Thank you so much! However running my test case (please see my first post) I see that CPU usage is always at 100% (after the application is running), so the responsiveness is still not very good. What do you expect? You're setting up a Timer with a delay of 0 milliseconds between events, and it's running continuously. Andrew.
Re: [GCJ] Performance of GUI applications on embedded systems
On Thu, 2008-11-06 at 16:40 +, Andrew Haley wrote: What do you expect? You're setting up a Timer with a delay of 0 milliseconds between events, and it's running continuously. That may be because of this (taken from GNU Classpath's vm/reference/java/lang/VMThread.java): // Note: JDK treats a zero length sleep is like Thread.yield(), // without checking the interrupted status of the thread. // It's unclear if this is a bug in the implementation or the spec. // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213203 GCJ does this: if (millis == 0 nanos == 0) ++nanos; and sleeps. Maybe... - Christian
Re: [GCJ] Performance of GUI applications on embedded systems
Here's one improvement. If you can get rid of the places in the GTK peers where class and method lookups are performed at runtime you'll probably have a fix. This shouldn't be a massive amount of work, just rather boring. In gcj, * Compiled java code is quite fast. * Class lookup by name is slow. * Calling JNI code from compiled java code is quite fast. * Calling compiled java code from JNI code is slow. * Exceptions are slow. Andrew. Hi Andrew, I tried your improvement but now I'm getting Segmentation Fault whenever I execute any GUI application. (Non-gui code is working fine) Do you have any idea to investigate this problem? Thank you, Francesco
Re: [GCJ] Performance of GUI applications on embedded systems
ffileppo wrote: Here's one improvement. If you can get rid of the places in the GTK peers where class and method lookups are performed at runtime you'll probably have a fix. This shouldn't be a massive amount of work, just rather boring. In gcj, * Compiled java code is quite fast. * Class lookup by name is slow. * Calling JNI code from compiled java code is quite fast. * Calling compiled java code from JNI code is slow. * Exceptions are slow. I tried your improvement but now I'm getting Segmentation Fault whenever I execute any GUI application. (Non-gui code is working fine) Do you have any idea to investigate this problem? It didn't do that to me. Where does the segfault occur? Do you still get the segfault after backing out the patch? Andrew.
Re: [GCJ] Performance of GUI applications on embedded systems
Mark Wielaard wrote: On Wed, 2008-11-05 at 09:24 +0100, ffileppo wrote: I tried your improvement but now I'm getting Segmentation Fault whenever I execute any GUI application. (Non-gui code is working fine) Do you have any idea to investigate this problem? Run it under GDB and post a backtrace please. For what it's worth, I very much suspect that this will be a build problem. ffileppo, we also need to know what configure options you used. Andrew.
Re: [GCJ] Performance of GUI applications on embedded systems
ffileppo wrote: Mark Wielaard wrote: On Wed, 2008-11-05 at 09:24 +0100, ffileppo wrote: I tried your improvement but now I'm getting Segmentation Fault whenever I execute any GUI application. (Non-gui code is working fine) Do you have any idea to investigate this problem? Run it under GDB and post a backtrace please. For what it's worth, I very much suspect that this will be a build problem. ffileppo, we also need to know what configure options you used. Andrew. Hi, I tried rebuilding gcj (with Andrew's improvement) on a clean system but I'm still getting Segmentation Fault when I run GUI applications on my embedded system. Here is configure : Configured with: ../configure --prefix=/root/WiTP/inst-gcc --with-sysroot=/root/WiTP/f8/rootfs-f8 --disable-libssp --disable-libgomp --disable-libmudflap --enable-libgcj --disable-bootstrap --disable-multilib --disable-sjlj-exceptions --target=arm-linux-gnueabi --enable-languages=c,c++,java --with-build-time-tools=/root/WiTP/binutils-inst/arm-linux-gnueabi/bin --with-ld=/root/WiTP/binutils-inst/arm-linux-gnueabi/bin/ld --with-nm=/root/WiTP/binutils-inst/arm-linux-gnueabi/bin/nm --with-strip=/root/WiTP/binutils-inst/arm-linux-gnueabi/bin/strip --with-as=/root/WiTP/binutils-inst/arm-linux-gnueabi/bin/as --with-float=soft --enable-java-awt=gtk --x-libraries=/root/WiTP/arm-rpm/usr/lib Unless you --enable-java-maintainer-mode the Java file won't be recompiled. Andrew.
Re: [GCJ] Performance of GUI applications on embedded systems
Andrew Haley wrote: Unless you --enable-java-maintainer-mode the Java file won't be recompiled. This change is now in gcj trunk. Andrew.
Re: [GCJ] Performance of GUI applications on embedded systems
Mark Wielaard wrote: On Wed, 2008-11-05 at 09:24 +0100, ffileppo wrote: I tried your improvement but now I'm getting Segmentation Fault whenever I execute any GUI application. (Non-gui code is working fine) Do you have any idea to investigate this problem? Run it under GDB and post a backtrace please. For what it's worth, I very much suspect that this will be a build problem. ffileppo, we also need to know what configure options you used. Andrew. Hi, I tried rebuilding gcj (with Andrew's improvement) on a clean system but I'm still getting Segmentation Fault when I run GUI applications on my embedded system. Here is configure : Configured with: ../configure --prefix=/root/WiTP/inst-gcc --with-sysroot=/root/WiTP/f8/rootfs-f8 --disable-libssp --disable-libgomp --disable-libmudflap --enable-libgcj --disable-bootstrap --disable-multilib --disable-sjlj-exceptions --target=arm-linux-gnueabi --enable-languages=c,c++,java --with-build-time-tools=/root/WiTP/binutils-inst/arm-linux-gnueabi/bin --with-ld=/root/WiTP/binutils-inst/arm-linux-gnueabi/bin/ld --with-nm=/root/WiTP/binutils-inst/arm-linux-gnueabi/bin/nm --with-strip=/root/WiTP/binutils-inst/arm-linux-gnueabi/bin/strip --with-as=/root/WiTP/binutils-inst/arm-linux-gnueabi/bin/as --with-float=soft --enable-java-awt=gtk --x-libraries=/root/WiTP/arm-rpm/usr/lib And here is GDB backtrace #0 0x40b92d14 in java::lang::Object::getClass () from /lib/libgcj.so.10 #1 0x40b116f0 in javax::swing::JComponent::isPaintRoot () from /lib/libgcj.so.10 #2 0x42f9b114 in Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getKerning (env=0x24320, obj=value optimized out, rightGlyph=40, leftGlyph=79, fnt=value optimized out, p=0x0) at ../../../../../../../libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c:204 #3 0x41381c30 in gnu::java::awt::peer::gtk::FreetypeGlyphVector::getKerning () from /lib/libgcj.so.10 #4 0x41383f4c in gnu::java::awt::peer::gtk::FreetypeGlyphVector::performDefaultLayout () from /lib/libgcj.so.10 #5 0x4137022c in gnu::java::awt::peer::gtk::FreetypeGlyphVector::FreetypeGlyphVector () from /lib/libgcj.so.10 #6 0x41368ac4 in gnu::java::awt::peer::gtk::GdkFontPeer::layoutGlyphVector () from /lib/libgcj.so.10 #7 0x40e977c0 in java::awt::Font::layoutGlyphVector () from /lib/libgcj.so.10 #8 0x40ef0d10 in java::awt::font::TextLayout::TextLayout () from /lib/libgcj.so.10 #9 0x41358b24 in gnu::java::awt::peer::gtk::GdkFontPeer$GdkFontMetrics::stringWidth () from /lib/libgcj.so.10 #10 0x41150c38 in javax::swing::JComponent::isPaintRoot () from /lib/libgcj.so.10 #11 0x41151704 in javax::swing::SwingUtilities::layoutCompoundLabel () from /lib/libgcj.so.10 #12 0x411c7ec0 in javax::swing::plaf::basic::BasicLabelUI::layoutCL () from /lib/libgcj.so.10 #13 0x411d2500 in javax::swing::plaf::basic::BasicLabelUI::getPreferredSize () from /lib/libgcj.so.10 #14 0x4111f6f0 in javax::swing::JComponent::getPreferredSize () from /lib/libgcj.so.10 #15 0x411bbfdc in javax::swing::plaf::basic::BasicListUI::updateLayoutState () from /lib/libgcj.so.10 #16 0x411944ec in javax::swing::plaf::basic::BasicListUI::maybeUpdateLayoutState () from /lib/libgcj.so.10 #17 0x4119c52c in javax::swing::plaf::basic::BasicListUI::installUI () from /lib/libgcj.so.10 #18 0x4111e778 in javax::swing::JComponent::setUI () from /lib/libgcj.so.10 #19 0x4111e8c0 in javax::swing::JList::setUI () from /lib/libgcj.so.10 #20 0x41143d48 in javax::swing::JList::updateUI () from /lib/libgcj.so.10 #21 0x4116f1bc in javax::swing::JList::init () from /lib/libgcj.so.10 #22 0x4116f230 in javax::swing::JList::JList () from /lib/libgcj.so.10 #23 0x00012d88 in MainPanel::MainPanel () #24 0x00012f80 in MainPanel::main () #25 0x40b7be60 in gnu::java::lang::MainThread::call_main () from /lib/libgcj.so.10 #26 0x40bfe85c in gnu::java::lang::MainThread::run () from /lib/libgcj.so.10 #27 0x40b99648 in _Jv_ThreadRun () from /lib/libgcj.so.10 #28 0x40b0d588 in _Jv_RunMain () from /lib/libgcj.so.10 #29 0x40b0d720 in _Jv_RunMain () from /lib/libgcj.so.10 #30 0x40b0d75c in JvRunMain () from /lib/libgcj.so.10 #31 0x424b5db8 in __libc_start_main () from /lib/libc.so.6 #32 0x0001255c in _start () I'll try to revert Andrew's patch to be sure that's the cause of segmentation fault. Thank you, Francesco
Re: [GCJ] Performance of GUI applications on embedded systems
Hi, The problem is that the program is spending almost all of the time generating stack traces, millions and millions of them. And one reason for that is pointless class lookups in the GTK peer code. Look at this: Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getKerning (JNIEnv *env, jobject obj __attribute__((unused)), jint rightGlyph, jint leftGlyph, jlong fnt) { ... cls = (*env)-FindClass (env, java/awt/geom/Point2D$Double); method = (*env)-GetMethodID (env, cls, init, (DD)V); return (*env)-NewObjectA(env, cls, method, values); } Now, this method only returns a pair of points, and it would have been trivial to pass a 2-element array into it, fill, with x and y, and return the same array. But no, we do a class lookup on java/awt/geom/Point2D$Double and call its constructor with two double values. Or we could cache the MIDs and FIDs, like is recommended in all good JNI books. /Roman -- Dipl.-Inform. (FH) Roman Kennke, Software Engineer, http://kennke.org aicas Allerton Interworks Computer Automated Systems GmbH Haid-und-Neu-Straße 18 * D-76131 Karlsruhe * Germany http://www.aicas.com * Tel: +49-721-663 968-48 USt-Id: DE216375633, Handelsregister HRB 109481, AG Karlsruhe Geschäftsführer: Dr. James J. Hunt
Re: [GCJ] Performance of GUI applications on embedded systems
ffileppo wrote: oprofile is your friend. If you can get oprofile working on your target system, please use it and find out if it does what you need. I did it. The answer is appended. The problem is that the program is spending almost all of the time generating stack traces, millions and millions of them. Hi Andrew, thanks a lot for your help. Do you have any ideas to fix this problem? Here's one improvement. If you can get rid of the places in the GTK peers where class and method lookups are performed at runtime you'll probably have a fix. This shouldn't be a massive amount of work, just rather boring. In gcj, * Compiled java code is quite fast. * Class lookup by name is slow. * Calling JNI code from compiled java code is quite fast. * Calling compiled java code from JNI code is slow. * Exceptions are slow. Andrew. Index: classpath/include/gnu_java_awt_peer_gtk_FreetypeGlyphVector.h === --- classpath/include/gnu_java_awt_peer_gtk_FreetypeGlyphVector.h (revision 141430) +++ classpath/include/gnu_java_awt_peer_gtk_FreetypeGlyphVector.h (working copy) @@ -13,7 +13,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_dispose (JNIEnv *env, jobject, jlongArray); JNIEXPORT jlong JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getNativeFontPointer (JNIEnv *env, jobject, jint); JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphs (JNIEnv *env, jobject, jintArray, jintArray, jlongArray); -JNIEXPORT jobject JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getKerning (JNIEnv *env, jobject, jint, jint, jlong); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getKerning (JNIEnv *env, jobject, jint, jint, jlong, jfloatArray); JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getMetricsNative (JNIEnv *env, jobject, jint, jlong); JNIEXPORT jobject JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphOutlineNative (JNIEnv *env, jobject, jint, jlong); Index: classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c === --- classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c (revision 141430) +++ classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c (working copy) @@ -169,9 +169,10 @@ (*env)-ReleaseLongArrayElements (env, fonts, fontArray, 0); } -JNIEXPORT jobject JNICALL +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getKerning -(JNIEnv *env, jobject obj __attribute__((unused)), jint rightGlyph, jint leftGlyph, jlong fnt) +(JNIEnv *env, jobject obj __attribute__((unused)), jint rightGlyph, jint leftGlyph, + jlong fnt, jfloatArray p) { FT_Face ft_face; FT_Vector kern; @@ -187,12 +188,10 @@ pango_fc_font_unlock_face( font ); - values[0].d = (jdouble)kern.x/64.0; - values[1].d = (jdouble)kern.y/64.0; - - cls = (*env)-FindClass (env, java/awt/geom/Point2D$Double); - method = (*env)-GetMethodID (env, cls, init, (DD)V); - return (*env)-NewObjectA(env, cls, method, values); + jfloat *pelements = (*env)-GetPrimitiveArrayCritical(env, p, NULL); + pelements[0] = (jfloat)kern.x/64.0; + pelements[1] = (jfloat)kern.y/64.0; + (*env)-ReleasePrimitiveArrayCritical (env, p, pelements, 0); } JNIEXPORT jdoubleArray JNICALL Index: classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java === --- classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java(revision 141430) +++ classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java(working copy) @@ -247,7 +247,7 @@ /** * Returns the kerning of a glyph pair */ - private native Point2D getKerning(int leftGlyph, int rightGlyph, long font); + private native void getKerning(int leftGlyph, int rightGlyph, long font, float[] p); private native double[] getMetricsNative(int glyphCode, long font); @@ -301,6 +301,7 @@ GlyphMetrics gm = null; float x = 0; float y = 0; +float[] p = {0.0f, 0.0f}; for(int i = 0; i nGlyphs; i++) { gm = getGlyphMetrics( i ); @@ -314,9 +315,9 @@ // using the same font if (i != nGlyphs-1 fontSet[i] == fontSet[i+1]) { -Point2D p = getKerning(glyphCodes[i], glyphCodes[i + 1], fontSet[i]); -x += p.getX(); -y += p.getY(); +getKerning(glyphCodes[i], glyphCodes[i + 1], fontSet[i], p); +x += p[0]; +y += p[1]; } } glyphPositions[nGlyphs * 2] = x;
Re: [GCJ] Performance of GUI applications on embedded systems
Andrew Haley wrote: ffileppo wrote: I've been investigating about performance of java code compiled with gcj on embedded systems. In particular I'm interested in testing AWT/SWING application using GTK/Xorg as graphical backend (this is the only viable solution since QT peers are not well supported). The embedded device I've been using for testing is a PXA270 processor (armv5te) equipped with 128Mb Ram; running linux kernel 2.6.24 and using libgcj.so.10. GTK peers are running on Xorg, using matchbox as window manager. The crosscompiler on my host is gcc 4.4. During my tests I've noticed that java code using AWT/SWING (for example the test case attached at the end) with GTK peer cause a very high load on the cpu. Furthermore the applications take a lot of time to load and also the UI responsiveness is very slow. Using top I can see that CPU is always at 100% during start up (it takes about 2 minutes to get the application starting, Ram usage is ok). I've also noticed that using optimizations (-O2, -O3...) does not help with graphical performance. [On the same device, running WinCE and a commerical JVM (CrEme), applications have extremely better graphical performance] From my experience with this particual embedded system I can say that gcj has very high performance when dealing with non-gui tasks (e.g. array sorting) compared with most of JVMs but gui performance are very poor. I would like to ask your opinion about the slowness of gui applications in my setup, and also about viable solutions to improve this issue. What do you think is the bottleneck? -- libgcj itself? -- GTK library / GTK peer implementation in classpath? -- something dealing with Xorg? We can only speculate. oprofile is your friend. If you can get oprofile working on your target system, please use it and find out if it does what you need. I did it. The answer is appended. The problem is that the program is spending almost all of the time generating stack traces, millions and millions of them. Andrew. 259512 13.5589 libgcc_s.so.1libgcc_s.so.1 execute_cfa_program 1887029.8592 libgcc_s.so.1libgcc_s.so.1 _Unwind_IteratePhdrCallback 1691398.8371 libgcc_s.so.1libgcc_s.so.1 uw_update_context_1 1554088.1197 libgcj.so.10.0.0 libgcj.so.10.0.0 GC_mark_from 1130825.9083 libgcc_s.so.1libgcc_s.so.1 uw_frame_state_for 77219 4.0345 libgcj.so.10.0.0 libgcj.so.10.0.0 _Jv_platform_gettimeofday() 65323 3.4130 libc-2.8.so libc-2.8.so dl_iterate_phdr 61075 3.1910 no-vmlinux no-vmlinux (no symbols) 55123 2.8800 libgcc_s.so.1libgcc_s.so.1 read_encoded_value_with_base 52303 2.7327 libpthread-2.8.solibpthread-2.8.so pthread_mutex_lock 42087 2.1989 libgcj.so.10.0.0 libgcj.so.10.0.0 GC_add_to_black_list_normal 38694 2.0217 libpthread-2.8.solibpthread-2.8.so __pthread_mutex_unlock_usercnt 32618 1.7042 libc-2.8.so libc-2.8.so strlen 27568 1.4404 libgcc_s.so.1libgcc_s.so.1 _Unwind_Backtrace 27246 1.4235 libgcj.so.10.0.0 libgcj.so.10.0.0 GC_find_start 26285 1.3733 libgcj.so.10.0.0 libgcj.so.10.0.0 _Jv_FindCore(_Jv_core_chain*, java::lang::String*) 24849 1.2983 libgcc_s.so.1libgcc_s.so.1 _Unwind_Find_FDE 21328 1.1143 libc-2.8.so libc-2.8.so memset 18771 0.9807 libz.so.1.2.3libz.so.1.2.3deflate_slow 18318 0.9571 libgcc_s.so.1libgcc_s.so.1 get_cie_encoding 16052 0.8387 libgcj.so.10.0.0 libgcj.so.10.0.0 __gcj_personality_v0 14649 0.7654 libgcj.so.10.0.0 libgcj.so.10.0.0 _Jv_StackTrace::UnwindTraceFn(_Unwind_Context*, void*) 12847 0.6712 libgcj.so.10.0.0 libgcj.so.10.0.0 GC_find_header 11533 0.6026 libgcc_s.so.1libgcc_s.so.1 base_from_cb_data 10373 0.5420 libgcj.so.10.0.0 libgcj.so.10.0.0 GC_local_gcj_malloc 9712 0.5074 libc-2.8.so libc-2.8.so memcpy 9000 0.4702 libgcj.so.10.0.0 libgcj.so.10.0.0 _Jv_IsAssignableFrom(java::lang::Class*, java::lang::Class*) 8478 0.4430 libgcc_s.so.1libgcc_s.so.1 uw_update_context 8216 0.4293 libz.so.1.2.3libz.so.1.2.3fill_window 7534 0.3936 libfreetype.so.6.3.16libfreetype.so.6.3.16(no symbols) 7390 0.3861 libgcj.so.10.0.0 libgcj.so.10.0.0 _Jv_MonitorExit 6617 0.3457 libgcj.so.10.0.0 libgcj.so.10.0.0 _Jv_MonitorEnter 5593 0.2922 libgcj.so.10.0.0
Re: [GCJ] Performance of GUI applications on embedded systems
Andrew Haley wrote: ffileppo wrote: oprofile is your friend. If you can get oprofile working on your target system, please use it and find out if it does what you need. I did it. The answer is appended. The problem is that the program is spending almost all of the time generating stack traces, millions and millions of them. Hi Andrew, thanks a lot for your help. Do you have any ideas to fix this problem? Here's one improvement. If you can get rid of the places in the GTK peers where class and method lookups are performed at runtime you'll probably have a fix. This shouldn't be a massive amount of work, just rather boring. Now, 163269 22.8358 libgcj.so.10.0.0 libgcj.so.10.0.0 _Jv_platform_gettimeofday() calls to _Jv_platform_gettimeofday() are almost a quarter (!) of the total runtime. I think that's your fault. Change your Timer.startTime to something a little less aggressive. :-) Andrew.
Re: [GCJ] Performance of GUI applications on embedded systems
Andrew Haley wrote: Andrew Haley wrote: ffileppo wrote: I've been investigating about performance of java code compiled with gcj on embedded systems. In particular I'm interested in testing AWT/SWING application using GTK/Xorg as graphical backend (this is the only viable solution since QT peers are not well supported). The embedded device I've been using for testing is a PXA270 processor (armv5te) equipped with 128Mb Ram; running linux kernel 2.6.24 and using libgcj.so.10. GTK peers are running on Xorg, using matchbox as window manager. The crosscompiler on my host is gcc 4.4. During my tests I've noticed that java code using AWT/SWING (for example the test case attached at the end) with GTK peer cause a very high load on the cpu. Furthermore the applications take a lot of time to load and also the UI responsiveness is very slow. Using top I can see that CPU is always at 100% during start up (it takes about 2 minutes to get the application starting, Ram usage is ok). I've also noticed that using optimizations (-O2, -O3...) does not help with graphical performance. [On the same device, running WinCE and a commerical JVM (CrEme), applications have extremely better graphical performance] From my experience with this particual embedded system I can say that gcj has very high performance when dealing with non-gui tasks (e.g. array sorting) compared with most of JVMs but gui performance are very poor. I would like to ask your opinion about the slowness of gui applications in my setup, and also about viable solutions to improve this issue. What do you think is the bottleneck? -- libgcj itself? -- GTK library / GTK peer implementation in classpath? -- something dealing with Xorg? We can only speculate. oprofile is your friend. If you can get oprofile working on your target system, please use it and find out if it does what you need. I did it. The answer is appended. The problem is that the program is spending almost all of the time generating stack traces, millions and millions of them. And one reason for that is pointless class lookups in the GTK peer code. Look at this: Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getKerning (JNIEnv *env, jobject obj __attribute__((unused)), jint rightGlyph, jint leftGlyph, jlong fnt) { ... cls = (*env)-FindClass (env, java/awt/geom/Point2D$Double); method = (*env)-GetMethodID (env, cls, init, (DD)V); return (*env)-NewObjectA(env, cls, method, values); } Now, this method only returns a pair of points, and it would have been trivial to pass a 2-element array into it, fill, with x and y, and return the same array. But no, we do a class lookup on java/awt/geom/Point2D$Double and call its constructor with two double values. I don't know if this gross inefficiency in the GTK peer is the whole cause of your pain, but it's a lot of it. Andrew.
Re: [GCJ] Performance of GUI applications on embedded systems
Andrew Haley wrote: Andrew Haley wrote: ffileppo wrote: I've been investigating about performance of java code compiled with gcj on embedded systems. In particular I'm interested in testing AWT/SWING application using GTK/Xorg as graphical backend (this is the only viable solution since QT peers are not well supported). The embedded device I've been using for testing is a PXA270 processor (armv5te) equipped with 128Mb Ram; running linux kernel 2.6.24 and using libgcj.so.10. GTK peers are running on Xorg, using matchbox as window manager. The crosscompiler on my host is gcc 4.4. During my tests I've noticed that java code using AWT/SWING (for example the test case attached at the end) with GTK peer cause a very high load on the cpu. Furthermore the applications take a lot of time to load and also the UI responsiveness is very slow. Using top I can see that CPU is always at 100% during start up (it takes about 2 minutes to get the application starting, Ram usage is ok). I've also noticed that using optimizations (-O2, -O3...) does not help with graphical performance. [On the same device, running WinCE and a commerical JVM (CrEme), applications have extremely better graphical performance] From my experience with this particual embedded system I can say that gcj has very high performance when dealing with non-gui tasks (e.g. array sorting) compared with most of JVMs but gui performance are very poor. I would like to ask your opinion about the slowness of gui applications in my setup, and also about viable solutions to improve this issue. What do you think is the bottleneck? -- libgcj itself? -- GTK library / GTK peer implementation in classpath? -- something dealing with Xorg? We can only speculate. oprofile is your friend. If you can get oprofile working on your target system, please use it and find out if it does what you need. I did it. The answer is appended. The problem is that the program is spending almost all of the time generating stack traces, millions and millions of them. And I've found the reason for that. Every time anyone calls gnu.java.awt.peer.gtk.GdkFontPeer$GdkFontMetrics.stringWidth, a call is made to gnu.java.awt.peer.gtk.FreetypeGlyphVector.getKerning, which does this: cls = (*env)-FindClass (env, java/awt/geom/Point2D$Double); method = (*env)-GetMethodID (env, cls, init, (DD)V); return (*env)-NewObjectA(env, cls, method, values); This call to FindClass does a dynamic lookup of java/awt/geom/Point2D$Double, which requires that the class loaders are invoked in turn. Each one throws a ClassNotFoundException until the class is found. Andrew.
Re: [GCJ] Performance of GUI applications on embedded systems
ffileppo wrote: I've been investigating about performance of java code compiled with gcj on embedded systems. In particular I'm interested in testing AWT/SWING application using GTK/Xorg as graphical backend (this is the only viable solution since QT peers are not well supported). The embedded device I've been using for testing is a PXA270 processor (armv5te) equipped with 128Mb Ram; running linux kernel 2.6.24 and using libgcj.so.10. GTK peers are running on Xorg, using matchbox as window manager. The crosscompiler on my host is gcc 4.4. During my tests I've noticed that java code using AWT/SWING (for example the test case attached at the end) with GTK peer cause a very high load on the cpu. Furthermore the applications take a lot of time to load and also the UI responsiveness is very slow. Using top I can see that CPU is always at 100% during start up (it takes about 2 minutes to get the application starting, Ram usage is ok). I've also noticed that using optimizations (-O2, -O3...) does not help with graphical performance. [On the same device, running WinCE and a commerical JVM (CrEme), applications have extremely better graphical performance] From my experience with this particual embedded system I can say that gcj has very high performance when dealing with non-gui tasks (e.g. array sorting) compared with most of JVMs but gui performance are very poor. I would like to ask your opinion about the slowness of gui applications in my setup, and also about viable solutions to improve this issue. What do you think is the bottleneck? -- libgcj itself? -- GTK library / GTK peer implementation in classpath? -- something dealing with Xorg? We can only speculate. oprofile is your friend. If you can get oprofile working on your target system, please use it and find out if it does what you need. Andrew.
Re: [GCJ] Performance of GUI applications on embedded systems
Roman Kennke wrote: The problem is that the program is spending almost all of the time generating stack traces, millions and millions of them. And one reason for that is pointless class lookups in the GTK peer code. Look at this: Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getKerning (JNIEnv *env, jobject obj __attribute__((unused)), jint rightGlyph, jint leftGlyph, jlong fnt) { ... cls = (*env)-FindClass (env, java/awt/geom/Point2D$Double); method = (*env)-GetMethodID (env, cls, init, (DD)V); return (*env)-NewObjectA(env, cls, method, values); } Now, this method only returns a pair of points, and it would have been trivial to pass a 2-element array into it, fill, with x and y, and return the same array. But no, we do a class lookup on java/awt/geom/Point2D$Double and call its constructor with two double values. Or we could cache the MIDs and FIDs, like is recommended in all good JNI books. Sure, but it would be far slower. Why would you want to call constructors in the middle of a critical loop? Andrew.
Re: [GCJ] Performance of GUI applications on embedded systems
oprofile is your friend. If you can get oprofile working on your target system, please use it and find out if it does what you need. I did it. The answer is appended. The problem is that the program is spending almost all of the time generating stack traces, millions and millions of them. Andrew. Hi Andrew, thanks a lot for your help. Do you have any ideas to fix this problem? Thank you, Francesco
[GCJ] Performance of GUI applications on embedded systems
Hi all, I've been investigating about performance of java code compiled with gcj on embedded systems. In particular I'm interested in testing AWT/SWING application using GTK/Xorg as graphical backend (this is the only viable solution since QT peers are not well supported). The embedded device I've been using for testing is a PXA270 processor (armv5te) equipped with 128Mb Ram; running linux kernel 2.6.24 and using libgcj.so.10. GTK peers are running on Xorg, using matchbox as window manager. The crosscompiler on my host is gcc 4.4. During my tests I've noticed that java code using AWT/SWING (for example the test case attached at the end) with GTK peer cause a very high load on the cpu. Furthermore the applications take a lot of time to load and also the UI responsiveness is very slow. Using top I can see that CPU is always at 100% during start up (it takes about 2 minutes to get the application starting, Ram usage is ok). I've also noticed that using optimizations (-O2, -O3...) does not help with graphical performance. [On the same device, running WinCE and a commerical JVM (CrEme), applications have extremely better graphical performance] From my experience with this particual embedded system I can say that gcj has very high performance when dealing with non-gui tasks (e.g. array sorting) compared with most of JVMs but gui performance are very poor. I would like to ask your opinion about the slowness of gui applications in my setup, and also about viable solutions to improve this issue. What do you think is the bottleneck? -- libgcj itself? -- GTK library / GTK peer implementation in classpath? -- something dealing with Xorg? Your feedback and ideas will be very appreciated. Thank you, Francesco Test case: import java.awt.BorderLayout; import javax.swing.DefaultListModel; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.Timer; import java.awt.event.*; public class MainPanel extends JPanel implements ListSelectionListener { static final int NUM_ROWS = 500; JList list; JLabel lblSelection; DefaultListModel listModel; int startRow = 0; long startTime = 0; javax.swing.Timer t = new javax.swing.Timer(0, new ActionListener() { public void actionPerformed(ActionEvent e) { long deltaTime = System.currentTimeMillis() - startTime; for (int i=startRow; iNUM_ROWS; i++) { listModel.set(i, +deltaTime); } startRow++; startTime = System.currentTimeMillis(); } }); public MainPanel() { super(new BorderLayout()); listModel = new DefaultListModel(); for (int i=0; iNUM_ROWS; i++) { listModel.addElement(Element +i); } list = new JList(listModel); list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); list.setSelectedIndex(0); list.addListSelectionListener(this); list.setVisibleRowCount(5); JScrollPane listScrollPane = new JScrollPane(list); lblSelection = new JLabel( ); add(lblSelection, BorderLayout.SOUTH); add(listScrollPane, BorderLayout.CENTER); t.start(); startTime = System.currentTimeMillis(); } public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting() == false) { if (list.getSelectedIndex() == -1) { lblSelection.setText(); } else { lblSelection.setText(Item selected: +list.getSelectedIndex()); } } } public static void main(String[] args) { JFrame frame = new JFrame(TestUI #1); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JComponent newContentPane = new MainPanel(); newContentPane.setOpaque(true); //content panes must be opaque frame.setContentPane(newContentPane); frame.setBounds(10, 10, 500, 400); frame.setVisible(true); } }