<Swing Dev> Extension method for AbstractDocument.Content?
Paulo Levi
i30817 at gmail.com
Wed Jul 11 13:55:49 UTC 2012
Tried to do a performance and memory test; they fail or pass depending on
the order the Documents are tested.
Could someone more experienced tell me what am i doing wrong? The
performance test i expected to fail (since reflection is much slower than
override), but the memory test i did not expect to depend on order.
import java.io.BufferedReader;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.ThreadMXBean;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import javax.swing.event.DocumentEvent;
import javax.swing.event.UndoableEditEvent;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.DefaultStyledDocument.ElementSpec;
import javax.swing.text.GapContent;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class DocumentTest {
public DocumentTest() {
}
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
OldTestDocument oldDoc = new OldTestDocument();
NewTestDocument newDoc = new NewTestDocument();
/**
* Test of insert method performance and memory
*/
@Test
public void testInsert() throws Exception {
System.out.println("insert");
List<ElementSpec> l = new ArrayList<>();
try (BufferedReader r = Files.newBufferedReader(Paths.get("War and
Peace.txt"), Charset.forName("us-ascii"))) {
while (r.ready()) {
String line = r.readLine();
l.add(new ElementSpec(null, ElementSpec.StartTagType));
l.add(new ElementSpec(null, ElementSpec.ContentType,
line.toCharArray(), 0, line.length()));
l.add(new ElementSpec(null, ElementSpec.EndTagType));
}
}
//every styled document must end with a 'implied newline'
l.add(new ElementSpec(null, ElementSpec.ContentType, new
char[]{'\n'}, 0, 1));
ElementSpec[] arr = (ElementSpec[]) l.toArray(new ElementSpec[0]);
long time, mem, elapsedTime1, elapsedTime2, memory1, memory2;
ThreadMXBean t = ManagementFactory.getThreadMXBean();
MemoryMXBean m = ManagementFactory.getMemoryMXBean();
//using non-heap memory because we are testing the memory impact of
the stringbuilder
//inside DefaultStyledDocument.insert(int offset, ElementSpec[]
data)
//to switch the order exchange the next 6 lines of code with the
other six lines below
m.gc();
mem = m.getNonHeapMemoryUsage().getUsed();
time = t.getCurrentThreadCpuTime();
oldDoc.insert(0, arr);
elapsedTime2 = t.getCurrentThreadCpuTime() - time;
memory2 = m.getNonHeapMemoryUsage().getUsed() - mem;
m.gc();
mem = m.getNonHeapMemoryUsage().getUsed();
time = t.getCurrentThreadCpuTime();
newDoc.insert(0, arr);
elapsedTime1 = t.getCurrentThreadCpuTime() - time;
memory1 = m.getNonHeapMemoryUsage().getUsed() - mem;
System.out.println("new style insert time : " + elapsedTime1 + "
memory used : " + memory1);
System.out.println("old style insert time : " + elapsedTime2 + "
memory used : " + memory2);
assert memory1 < memory2 : "old style insert took less memory than
new style insert!";
assert elapsedTime1 < elapsedTime2 : "old style insert took less
time than new style insert!";
}
class OldTestDocument extends DefaultStyledDocument {
@Override
public void insert(int offset, ElementSpec[] data) throws
BadLocationException {
super.insert(offset, data);
}
}
final class NewTestDocument extends DefaultStyledDocument {
private final Method replace;
private final Object[] bulkArgs = new Object[4];
public NewTestDocument() {
super();
try {
Class[] args = new Class[]{Integer.TYPE, Integer.TYPE,
Object.class, Integer.TYPE};
replace =
GapContent.class.getSuperclass().getDeclaredMethod("replace", args);
replace.setAccessible(true);
} catch (Exception ex) {
throw new AssertionError(ex);
}
}
@Override
public void insert(int offset, ElementSpec[] data) throws
BadLocationException {
if (offset > getLength() || offset < 0) {
throw new BadLocationException("Invalid insert", offset);
}
if (data == null || data.length == 0) {
return;
}
writeLock();
try {
Content content = getContent();
//since instead of doing normal string insert we are going
to use the gapvector directly, we don't do this
//UndoableEdit cEdit = content.insertString(offset,
sb.toString());
int charArraysSize = 0;
int index = offset;
for (ElementSpec e : data) {
if (e.getLength() > 0) {
charArraysSize += e.getLength();
bulkArgs[0] = index;
bulkArgs[1] = e.getOffset();
bulkArgs[2] = e.getArray();
bulkArgs[3] = e.getLength();
index += e.getLength();
try {
replace.invoke(content, bulkArgs);
} catch (Exception ex) {
throw new AssertionError(ex);
}
}
}
if (charArraysSize == 0) {
return;
}
//created the undoable edit corresponding to the whole
inserted string
//this can't be created since it is package default in
GapContent
//UndoableEdit cEdit = new InsertUndo(offset,
charArraysSize);
DefaultDocumentEvent evnt = new
DefaultDocumentEvent(offset, charArraysSize,
DocumentEvent.EventType.INSERT);
//evnt.addEdit(cEdit);
buffer.insert(offset, charArraysSize, data, evnt);
// update bidi (possibly)
super.insertUpdate(evnt, null);
// notify the listeners
evnt.end();
fireInsertUpdate(evnt);
fireUndoableEditUpdate(new UndoableEditEvent(this, evnt));
} finally {
writeUnlock();
}
}
}
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/swing-dev/attachments/20120711/2c6ec606/attachment.html>
More information about the swing-dev
mailing list