on July 1, 2010 at 4:09 AM PDT
I have found a performance problem with RowSorter that might be a
potential flaw in its design, that I would like to post here to get some
comments before making an attempt at submitting a complete bug report.
I have a JTable, with a DefaultTableModel with getColumnClass overriden
to return String.class. It uses a TableRowSorter, and is sorted by the
only column in the model.
Adding 20.000 rows to this model takes 3600 ms.
Next, I select the first 10.000 rows with a call to setSelectionInterval.
Then I delete 10.000 rows from the model, one by one(*). This takes a
staggering 61000 ms.
Note that the selection interval is essential to see this performance
problem clearly. Keeping it up-to-date is proving very costly.
(*) The one-by-one deletes are triggered externally (files being deleted
on a filesystem) which takes far less time than the 61000 ms to keep the
model updated...... for the purpose of the test though it is simply a
The TableRowSorter is doing a full sort of the model after each removal,
and for each removal returns an array the same size as the model (ie,
10000-20000 items) with view-to-model indices for internal processing by
JTable (mainly to update the indices of the selected items). Just these
arrays produce around ~550 MB of heap traffic during this process.
This is inherent to the RowSorter interface specification, which
requires these arrays to be returned in RowSorterEvent objects. Not
complying with this requirement results in the selection not being
This means that writing a more efficient RowSorter implementation will
not solve this performance problem as to generate proper RowSorterEvent
objects one must provide an array with the (old) view-to-model mapping
-- something that would be cumbersome for an implementation that does
not rely on arrays internally for example.
As I was sure that keeping a large list sorted while many inserts and
removes occur is a fairly trivial task given the correct algorithms, I
made an attempt to resolve this issue. As stated, writing a new
RowSorter implementation is pointless as the performance issues are
inherent to the interface.
Instead, I opted to write a sorted TableModel, of which numerous
examples are available from the days when RowSorter did not exist.
After creating the proper data structures (most importantly was a List
structure with fast insert/removal performance) I did some tests:
Insert 20.000 rows: 900 ms
Remove 10.000 rows: 580 ms
The gain in performance is primarily because the view is not resorted,
but simply updated.
Since the JTable is NOT using any RowSorter it is not using the code
paths where the selection indices are updated. This presents a problem
as the selection needs to be maintained properly as well.
Therefore, to keep the selection correct even when the table is
resorted, a special selection model is used which keeps track of the
selection in terms of the model (normally it is kept track of in terms
of the view). This means that it only needs to be updated when rows are
inserted or removed (which is fast), and simply stays the same when any
sorting or filtering occurs. Changes in the selection by the user are
simply translated from view to model as needed.
The solution is fairly transparent and can be easily used as an
alternative to RowSorter. It however will translate some events in
several seperate events or into more generic ones (ie, removing 100
consecutive rows can be one event from the view point of the model, but
could be 100 seperate events or even a full-change from the perspective
of a sorted model as the rows are not necessarily consecutive).
It is also much more scalable than RowSorter, as the underlying
structures have O(log n) performance for insertion, removal and retrieval.
Of course, not using RowSorter means the support for clicking on column
headers and having them reflect the sort status is not working either.
This can be solved, and I already solved it partially, but it is proving
a bit cumbersome.
I'm hoping the underlying problem could somehow be fixed in Swing
directly or that API's could be provided to make avoiding the use of
RowSorter easier (it would be nice if the sorting functionality for the
column headers would be seperate from RowSorter for example).
Comments welcome, I'm also happy to share any code that I used to
resolve this problem and the performance test code.
To unsubscribe, e-mail: firstname.lastname@example.org
For additional commands, e-mail: email@example.com