gpt4 book ai didi

java - 创建缩略图的正确方法是什么?

转载 作者:行者123 更新时间:2023-11-30 06:51:12 25 4
gpt4 key购买 nike

我正在尝试使用 JScrollPane 创建一些数据的缩略图图表,但遇到性能问题。此示例有大约 100 个缩略图,每个缩略图有 5000 个样本。当我尝试向下滚动并返回向上多次时,滚动会出现延迟,CPU 负载增加,应用程序内存使用量达到超过 500 Mb。

有没有办法在不减少数据的情况下避免此性能问题?

enter image description here

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");
for (int i = 0; i < 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));
for (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);
}
});

}
}

编辑:我不明白一件事:为什么在这种情况下内存使用量仍然非常巨大!请看这个插图。

image

添加:我认为这其中存在一些误解。

监视器 VisualVM 的堆大小 enter image description here启动applet后堆大小只有125 Mb,很酷。但随后我开始测试:多次滚动和调整大小,越来越多——上下,上下,更小的框架和更大的框架。堆大小增长超过 500 Mb!我认为这种情况不正常。

添加#2

现实世界的例子:

我的数据大小约为 2 Mb,以 90 个图表表示(每个图表 2 个系列),一个系列包含 3000 个元素。我已经实现了通过 slider 更改数字列。 enter image description here

但是对于这个小数据堆大小增长超过 1.5 GB!

enter image description here

这种情况发生在一些操作之后,更改数字列,例如对于我的 CPU(core 2 duo 2.2GHz),每个绘图表大约需要 4 秒!由于延迟很大,很难控制 slider 。

更新:

我已将数据下采样为每个缩略图图表 100 个样本。现在它肯定更快了,但是巨大的堆大小问题仍然存在。图片上是700Mb以上,而且还不是记录。我很沮丧。 enter image description here

最佳答案

使用flyweight pattern仅渲染可见图表。 JTable renderers 使用的方法,概述here并显示在下面的 ChartRenderer 中。为了便于说明,每次显示单元格时都会重新创建数据集;滚动、调整大小和切换应用程序以查看效果。虽然这种渲染可以很好地扩展到数万个单元格,但每个图表仍然渲染 N 个数据点。您可以在 Scrollable 方法 getPreferredScrollableViewportSize() 的实现中限制可见单元格的数量,如下所示。

How to reduce memory usage to small values?

没有通用的答案,但有几种策略可能会有所帮助:

  • 在程序初始化时尽早构建图表,而不是在渲染图表时; updated下面的示例构造了 ChartPanel 实例的 TableModelChartRenderer 相应地更简单。

  • 超过几千个点的图表实际上是不可读的;考虑截断大型数据集并仅在响应 ListSelectionEvent 时显示完整数据,如图 here 所示.

  • 平台 Activity 监视器可能会产生误导; profile验证实际结果。

image

After starting applet it's not big, less than 200 Mb, but after scrolling, resizing etc. memory usage reaches values more than 600 Mb. Why?

典型的profiler下面的代码 View 仅显示中等使用情况和预期的 free/used ratio滚动后 garbage collection ;您的结果可能会有所不同。

profile

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;
}
};
for (int r = 0; r < 25; r++) {
ChartPanel[] row = new ChartPanel[4];
for (int c = 0; c < row.length; c++) {
final XYSeries series = new XYSeries("Data");
int n = R.nextInt(N);
for (int i = 0; i < 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);
}
}

关于java - 创建缩略图的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40441186/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com