java - What is the right way to create thumbnail charts? -
i'm trying create chart of thumbnails of data using jscrollpane
, encounter performance difficulties. example has 100 thumbnails charts 5000 samples in each one. when i'm trying scroll down , multiple times, scrolling occurs delay, cpu load increasing, application memory usage reaches on 500 mb.
is there way avoid performance problem without reducing data?
import java.awt.color; import java.awt.eventqueue; import java.awt.gridlayout; import java.util.random; import javax.swing.jframe; import javax.swing.jpanel; import javax.swing.jscrollpane; import org.jfree.chart.chartfactory; import org.jfree.chart.chartpanel; import org.jfree.chart.jfreechart; import org.jfree.chart.plot.plotorientation; import org.jfree.chart.plot.thermometerplot; import org.jfree.data.general.defaultvaluedataset; import org.jfree.data.xy.xyseries; import org.jfree.data.xy.xyseriescollection; public class thumbnailchartstest extends jpanel { private static final int w = 200; private static final int h = w; private static final int n = 5000; private static final random random = new random(); private static chartpanel createpane() { final xyseries series = new xyseries("data"); (int = 0; < random.nextint(n) + n; i++) { series.add(i, random.nextgaussian()); } xyseriescollection dataset = new xyseriescollection(series); jfreechart chart = chartfactory.createxylinechart("random", "domain", "range", dataset, plotorientation.vertical, false, false, false); return new chartpanel(chart, w, h, w, h, w, h, false, true, true, true, true, true); } public static void main(final string[] args) { eventqueue.invokelater(new runnable() { @override public void run() { jframe f = new jframe("test"); f.setdefaultcloseoperation(jframe.exit_on_close); jpanel panel = new jpanel(); panel.setlayout(new gridlayout(0, 4)); (int i=0; i<100; i++){ panel.add(createpane()); } jscrollpane scrollpane = new jscrollpane(panel, jscrollpane.vertical_scrollbar_always, jscrollpane.horizontal_scrollbar_never); f.add(scrollpane); f.pack(); f.setvisible(true); } }); } }
edit: can't understand 1 thing: why in case memory usage still huge! please @ illustration.
addition: think there misunderstanding.
heap size monitor visualvm after starting applet heap size 125 mb, it's cool. i'm starting testing: scrolling , resizing multiple times, more , more -- , down, , down, smaller frame , bigger frame. heap size growing on 500 mb! suppose situation isn't normal.
addition #2
real-world example:
my data has size 2 mb , represented in 90 charts(2 series in each one), 1 series contain 3000 elements. i've implemented changing number columns slider.
but small data heap size growing on 1.5 gb!
this happens after actions, changing number columns e.g. cpu(core 2 duo 2.2ghz) every drawing table takes time 4 sec! big delay it's hard control slider.
update:
i've implemented downsampling data 100 samples per thumbnail chart. it's faster, problem huge heap size still there. on picture 1 above 700mb, , it's not record. i'm frustrated.
use flyweight pattern render visible charts. approach, used jtable
renderers, outlined here , shown in chartrenderer
seen below. illustration, dataset recreated each time cell revealed; scroll, resize , switch applications see effect. while such rendering scales tens of thousands of cells, each chart still renders n
data points. can limit number of visible cells in implementation of scrollable
method, getpreferredscrollableviewportsize()
, shown below.
how reduce memory usage small values?
there no general answer, several strategies may prove helpful:
compose charts in program initialization possible, rather @ time rendered; updated example below constructs
tablemodel
ofchartpanel
instances;chartrenderer
correspondingly simpler.charts having more few thousand points unreadable; consider truncating large datasets , displaying full data in response
listselectionevent
, illustrated here.platform activity monitors may misleading; profile verify actual results.
after starting applet it's not big, less 200 mb, after scrolling, resizing etc. memory usage reaches values more 600 mb. why?
a typical profiler view of code below shows moderate usage , expected free/used ratio after scrolling , garbage collection; results may vary.
import java.awt.component; import java.awt.dimension; import java.awt.eventqueue; import java.util.random; import javax.swing.jframe; import javax.swing.jscrollpane; import javax.swing.jtable; import javax.swing.table.defaulttablemodel; import javax.swing.table.tablecellrenderer; import org.jfree.chart.chartfactory; import org.jfree.chart.chartpanel; import org.jfree.chart.jfreechart; import org.jfree.data.xy.xyseries; import org.jfree.data.xy.xyseriescollection; /** * @see https://stackoverflow.com/a/40445144/230513 */ public class charttable { private static final random r = new random(); private static final int n = 5000; private static final int w = 200; private static final int h = w; private void display() { jframe f = new jframe("charttable"); f.setdefaultcloseoperation(jframe.exit_on_close); defaulttablemodel model = new defaulttablemodel( new string[]{"", "", "", ""}, 0) { @override public class<?> getcolumnclass(int columnindex) { return chartpanel.class; } }; (int r = 0; r < 25; r++) { chartpanel[] row = new chartpanel[4]; (int c = 0; c < row.length; c++) { final xyseries series = new xyseries("data"); int n = r.nextint(n); (int = 0; < n; i++) { series.add(i, r.nextgaussian()); } xyseriescollection dataset = new xyseriescollection(series); jfreechart chart = chartfactory.createxylinechart( "random " + series.getitemcount(), "domain", "range", dataset); chartpanel chartpanel = new chartpanel(chart) { @override public dimension getpreferredsize() { return new dimension(w, h); } }; row[c] = chartpanel; } model.addrow(row); } jtable table = new jtable(model) { @override public dimension getpreferredscrollableviewportsize() { return new dimension(4 * w, 2 * h); } }; table.setdefaultrenderer(chartpanel.class, new chartrenderer()); table.setrowheight(w); f.add(new jscrollpane(table)); f.pack(); f.setlocationrelativeto(null); f.setvisible(true); } private static class chartrenderer implements tablecellrenderer { @override public component gettablecellrenderercomponent( jtable table, object value, boolean isselected, boolean hasfocus, int row, int column) { return (chartpanel) value; } } public static void main(string[] args) { eventqueue.invokelater(new charttable()::display); } }
Comments
Post a Comment