Can you get any more performance out of this?

V

VisionSet

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();
}
}
});
}
}
 
C

Chris Uppal

VisionSet said:
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
 
V

VisionSet

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
 
C

Chris Uppal

VisionSet wrote:

[me:]
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();
}
}
}
);
}
}
===========================
 
V

VisionSet

Chris Uppal said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top