Can you get any more performance out of this?

Discussion in 'Java' started by VisionSet, Feb 20, 2006.

  1. VisionSet

    VisionSet Guest

    This demo app loads a bunch of URLs into JEditorPanes in a JTabbedPane.
    I don't think HTML engine in the JRE is much cop, so this is probably a
    non-starter.
    But I'd at least expect my interface to remain responsive. Is my code broken
    or Suns?
    I'm guessing the renderer is just consuming tOo much resources.

    TIA
    Mike W

    compilable example:

    import java.net.URL;
    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.text.*;
    import javax.swing.event.*;
    import java.beans.*;

    public class GuiFrame extends JFrame {

    private JTabbedPane tabbedPane;
    private int idx;

    public GuiFrame() {

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    tabbedPane = new JTabbedPane();
    tabbedPane.setPreferredSize(new Dimension(600,500));
    add(tabbedPane, BorderLayout.CENTER);

    JPanel northPanel = new JPanel(
    new FlowLayout(FlowLayout.CENTER));

    JButton searchButton = new JButton("Load some pages");
    searchButton.addActionListener(searchAction);
    northPanel.add(searchButton);
    add(northPanel, BorderLayout.NORTH);


    pack();
    setVisible(true);
    }

    private ActionListener searchAction = new ActionListener() {
    public void actionPerformed(ActionEvent evt) {

    SwingUtilities.invokeLater(
    new Runnable() {
    public void run() {
    search();
    }
    });
    }
    };

    private URL[] someUrls() {

    try {
    return new URL[] {

    new URL("http://openp2p.com"),
    new URL("http://www.p2pnet.net"),
    new URL("http://en.wikipedia.org/wiki/Peer-to-peer"),
    new URL("http://www.limewire.com/english/content/home.shtml"),
    new URL("http://morpheus.com"),
    new URL("http://p2p.wrox.com"),
    new URL("http://www.slyck.com"),
    new URL("http://p2p.weblogsinc.com"),
    new URL("http://p2p-politics.org")
    };
    }
    catch(MalformedURLException ex) {
    ex.printStackTrace();
    return new URL[0];
    }
    }

    private void search() {

    URL[] urls = someUrls();

    tabbedPane.removeAll();

    idx = 0;

    for (final URL url : urls) {

    System.out.println("adding: " + url);

    Thread pageLoader = new Thread(new Runnable() {
    public void run() {

    PageView view = null;

    try {
    view = new PageView(url);
    }
    catch(IOException ex) {
    return;
    }
    tabbedPane.addTab(
    Integer.toString(++idx), view);
    tabbedPane.revalidate();
    }
    });
    pageLoader.setPriority(Thread.MIN_PRIORITY);
    pageLoader.start();
    }
    }

    public static void main(String[] args) {

    new GuiFrame();
    }
    }

    class PageView extends JPanel {

    private final JScrollPane scrollPane = new JScrollPane();
    private final JEditorPane textComp = new JEditorPane();

    public PageView(URL url) throws IOException {

    setLayout(new BorderLayout());

    textComp.setContentType("text/html");
    textComp.setPage(url);
    textComp.setEditable(false);
    add(scrollPane);

    Document doc = textComp.getDocument();

    if (doc instanceof AbstractDocument) {
    ((AbstractDocument)doc).setAsynchronousLoadPriority(+1);
    }

    textComp.addPropertyChangeListener(
    new PropertyChangeListener() {

    public void propertyChange(PropertyChangeEvent evt) {

    if (evt.getPropertyName().equals("page")) {

    if(scrollPane.getViewport().getView() != null) return;
    scrollPane.setViewportView(textComp);
    revalidate();
    }
    }
    });

    textComp.addHyperlinkListener(new HyperlinkListener() {

    public void hyperlinkUpdate(HyperlinkEvent evt) {

    try{
    if(HyperlinkEvent.EventType.ACTIVATED
    == evt.getEventType()) textComp.setPage(evt.getURL());
    }
    catch(IOException ex) {
    ex.printStackTrace();
    }
    }
    });
    }
    }
    VisionSet, Feb 20, 2006
    #1
    1. Advertising

  2. VisionSet

    Chris Uppal Guest

    VisionSet wrote:

    > This demo app loads a bunch of URLs into JEditorPanes in a JTabbedPane.
    > I don't think HTML engine in the JRE is much cop, so this is probably a
    > non-starter.
    > But I'd at least expect my interface to remain responsive. Is my code
    > broken or Suns?


    I played with this code for a bit. There seem to be some problems with the way
    you use threads and arrange for stuff to happen on the AWT thread, but with
    those fixed to the best of my knowlege (I'm do very little with Swing so "best"
    is none too good) the basic problem remains. It seems that the renderer just
    spends too much time blocking the input handler.

    -- chris
    Chris Uppal, Feb 21, 2006
    #2
    1. Advertising

  3. VisionSet

    VisionSet Guest

    "Chris Uppal" <-THIS.org> wrote in message
    news:43fb2337$0$1172$...

    >
    > I played with this code for a bit. There seem to be some problems with

    the way
    > you use threads and arrange for stuff to happen on the AWT thread...


    Would you be good enough to enlighten me?

    Thanks
    Mike W
    VisionSet, Feb 21, 2006
    #3
  4. VisionSet

    Chris Uppal Guest

    VisionSet wrote:

    [me:]
    > > I played with this code for a bit. There seem to be some problems with
    > > the way you use threads and arrange for stuff to happen on the AWT
    > > thread...

    >
    > Would you be good enough to enlighten me?


    Oh, yes. Sorry. I wasn't trying to be coy, I just didn't think that criticism
    (however constructively intended) would be all that welcome from a
    non-expert -- especially when it didn't actually solve (or even help with) the
    problem at hand.

    Anyway, and in no special order...

    There's no need to use invokeLater() in your button's action listener. You are
    already on the right (AWT) thread.

    In your search() method, you start threads for each URL. That means that you
    end up doing AWT/Swing operations off the AWT thread -- which is illegal (or so
    Sun have suddenly decided -- in preference to fixing their own bugs).

    Oh, BTW, the code invoked from main() will also execute on a non-AWT thread,
    which again is a no-no. But I assume that's just because this is only a simple
    test rather than production code ;-) I didn't bother to change it either...

    Those threads don't add anything anyway. The lengthy operation is downloading
    data to populate the JEditorPane, and that happens in yet another thread
    (stared internally by the implementation, as you are aware since you arrange
    for that to happen explicitly).

    Not really to do with threading, but there are several unnecessary (I think)
    calls to revalidate().

    The call to setAsynchronousLoadPriority() is unnecessary for two reasons. One
    is that it happens /after/ the lengthy call of getCocument() and the call of
    setPage() which is where it that property is used. The other is that the
    Document already has an AsynchronousLoadPriority that will cause setPage() to
    use a background thread to do the downloading.

    I'll append my own modified version of your code. It's quite a lot simpler,
    and works just as badly ;-) (I've moved some stuff around to suit my own
    tastes better; I also removed the HyperlinkListener stuff just because it was
    getting in my way and didn't help diagnose this /specific/ problem). The only
    slight oddity (apart from the fact that it doesn't work) is that I use
    invokeLater() to call the setPage() operation -- that allows the constructor to
    return quickly and so the tabs list gets populated more-or-less immediately.
    Oh, and I also changed some of the URLs since the HTML rendered was throwing
    exceptions as it tried to handle their content.

    Maybe there is a way to make this work smoothly, but I can't think of one. In
    fact I can't see how it's possible since the HTML rendering /has/ to happen on
    the AWT thread, but it's that which is (apparently) blocking input processing
    for unacceptably long periods. I could be missing something, though.

    -- chris

    ===========================
    import java.net.URL;
    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.text.*;
    import javax.swing.event.*;
    import java.beans.*;

    public class GuiFrame
    extends JFrame
    {
    private JTabbedPane tabbedPane;

    public GuiFrame()
    {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    tabbedPane = new JTabbedPane();
    tabbedPane.setPreferredSize(new Dimension(600,500));
    add(tabbedPane, BorderLayout.CENTER);

    JPanel northPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
    add(northPanel, BorderLayout.NORTH);

    JButton searchButton = new JButton("Load some pages");
    searchButton.addActionListener(searchAction);
    northPanel.add(searchButton);

    pack();
    setVisible(true);
    }

    private ActionListener searchAction
    = new ActionListener()
    {
    public void
    actionPerformed(ActionEvent evt)
    {
    search();
    }
    };

    private URL[]
    someUrls()
    {
    try
    {
    return new URL[]
    {
    new URL("http://java.sun.com"),
    new URL("http://openp2p.com"),
    new URL("http://www.slyck.com"),
    new URL("http://p2p.weblogsinc.com"),
    new URL("http://p2p-politics.org")
    };
    }
    catch(MalformedURLException ex)
    {
    ex.printStackTrace();
    return new URL[0];
    }
    }

    private void
    search()
    {
    tabbedPane.removeAll();

    int idx = 0;
    for (URL url : someUrls())
    {
    PageView view = new PageView(url);
    tabbedPane.addTab(Integer.toString(++idx), view);
    }
    }

    public static void
    main(String[] args)
    {
    new GuiFrame();
    }
    }

    class PageView
    extends JPanel
    {
    private final JScrollPane scrollPane = new JScrollPane();
    private final JEditorPane textComp = new JEditorPane();

    PageView(final URL url)
    {
    setLayout(new BorderLayout());
    add(scrollPane);

    textComp.addPropertyChangeListener
    (
    new PropertyChangeListener()
    {
    public void
    propertyChange(PropertyChangeEvent evt)
    {
    if (evt.getPropertyName().equals("page")
    && scrollPane.getViewport().getView() == null)
    {
    scrollPane.setViewportView(textComp);
    }
    }
    }
    );
    textComp.setContentType("text/html");

    // postpone setPage() so that the ctor can return without delay
    SwingUtilities.invokeLater
    (
    new Runnable()
    {
    public void
    run()
    {
    try
    {
    textComp.setPage(url);
    }
    catch(IOException ex)
    {
    ex.printStackTrace();
    }
    }
    }
    );
    }
    }
    ===========================
    Chris Uppal, Feb 22, 2006
    #4
  5. VisionSet

    VisionSet Guest

    "Chris Uppal" <-THIS.org> wrote in message
    news:43fc5d79$2$1170$...
    >
    > Oh, yes. Sorry. I wasn't trying to be coy, I just didn't think that

    criticism
    > (however constructively intended) would be all that welcome from a
    > non-expert -- especially when it didn't actually solve (or even help with)

    the
    > problem at hand.
    >


    Thanks for that Chris.

    Mike W
    VisionSet, Feb 22, 2006
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Superdude
    Replies:
    8
    Views:
    394
  2. Michael
    Replies:
    4
    Views:
    411
    Matt Hammond
    Jun 26, 2006
  3. Kenny McCormack
    Replies:
    3
    Views:
    341
    spinoza1111
    Nov 12, 2009
  4. Weng Tianxiang
    Replies:
    2
    Views:
    534
    Eric Smith
    Feb 16, 2010
  5. Robert Klemme

    With a Ruby Yell: more, more more!

    Robert Klemme, Sep 28, 2005, in forum: Ruby
    Replies:
    5
    Views:
    217
    Jeff Wood
    Sep 29, 2005
Loading...

Share This Page