提交 92773417 编写于 作者: S Skylot

perf(gui): reduce updates count for memory usage bar (#1000)

- disabled by default
- update only if label changed
- skip updates if app window becomes inactive
上级 12dc4fde
......@@ -35,7 +35,7 @@ public class JadxSettings extends JadxCLIArgs {
private static final Path USER_HOME = Paths.get(System.getProperty("user.home"));
private static final int RECENT_PROJECTS_COUNT = 15;
private static final int CURRENT_SETTINGS_VERSION = 9;
private static final int CURRENT_SETTINGS_VERSION = 10;
private static final Font DEFAULT_FONT = new RSyntaxTextArea().getFont();
......@@ -57,7 +57,7 @@ public class JadxSettings extends JadxCLIArgs {
protected String excludedPackages = "";
private boolean autoSaveProject = false;
private boolean showHeapUsageBar = true;
private boolean showHeapUsageBar = false;
private Map<String, WindowLocation> windowPos = new HashMap<>();
private int mainWindowExtendedState = JFrame.NORMAL;
......@@ -436,6 +436,10 @@ public class JadxSettings extends JadxCLIArgs {
if (fromVersion == 8) {
fromVersion++;
}
if (fromVersion == 9) {
showHeapUsageBar = false;
fromVersion++;
}
settingsVersion = CURRENT_SETTINGS_VERSION;
sync();
}
......
package jadx.gui.ui;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import javax.swing.*;
import javax.swing.FocusManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import hu.akarnokd.rxjava2.swing.SwingSchedulers;
import io.reactivex.Flowable;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import jadx.gui.utils.NLS;
import jadx.gui.utils.UiUtils;
public class HeapUsageBar extends JProgressBar implements ActionListener {
private static final Logger LOG = LoggerFactory.getLogger(HeapUsageBar.class);
public class HeapUsageBar extends JProgressBar {
private static final long serialVersionUID = -8739563124249884967L;
private static final double TWO_TO_20 = 1048576d;
private static final Logger LOG = LoggerFactory.getLogger(HeapUsageBar.class);
private static final double GB = 1024 * 1024 * 1024;
private static final Color GREEN = new Color(0, 180, 0);
private static final Color RED = new Color(200, 0, 0);
private final transient Runtime runtime = Runtime.getRuntime();
private final transient Timer timer;
private final transient FocusManager focusManager = FocusManager.getCurrentManager();
private final double maxGB;
private final long limit;
private final String labelTemplate;
private transient Disposable timer;
private transient Color currentColor;
public HeapUsageBar() {
setBorderPainted(false);
setStringPainted(true);
setValue(10);
int maxKB = (int) (runtime.maxMemory() / 1024);
setMaximum(maxKB);
maxGB = maxKB / TWO_TO_20;
update();
timer = new Timer(2000, this);
long maxMemory = runtime.maxMemory();
maxGB = maxMemory / GB;
limit = maxMemory - UiUtils.MIN_FREE_MEMORY;
labelTemplate = NLS.str("heapUsage.text");
setMaximum((int) (maxMemory / 1024));
setColor(GREEN);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
Runtime.getRuntime().gc();
update();
HeapUsageBar.this.update();
if (LOG.isDebugEnabled()) {
LOG.debug("Memory used: {}", UiUtils.memoryInfo());
}
......@@ -49,31 +64,74 @@ public class HeapUsageBar extends JProgressBar implements ActionListener {
});
}
public void update() {
long used = runtime.totalMemory() - runtime.freeMemory();
int usedKB = (int) (used / 1024);
setValue(usedKB);
setString(NLS.str("heapUsage.text", (usedKB / TWO_TO_20), maxGB));
if ((used + UiUtils.MIN_FREE_MEMORY) > runtime.maxMemory()) {
setForeground(RED);
@Override
public void setVisible(boolean enabled) {
super.setVisible(enabled);
if (enabled) {
startTimer();
} else {
setForeground(GREEN);
reset();
}
}
@Override
public void actionPerformed(ActionEvent e) {
private static class UpdateData {
int value;
String label;
Color color;
}
private static final UpdateData SKIP_UPDATE = new UpdateData();
private void startTimer() {
if (timer != null) {
return;
}
update();
timer = Flowable.interval(2, TimeUnit.SECONDS, Schedulers.newThread())
.map(i -> prepareUpdate())
.filter(update -> update != SKIP_UPDATE)
.distinctUntilChanged((a, b) -> Objects.equals(a.label, b.label)) // pass only if label changed
.subscribeOn(SwingSchedulers.edt())
.subscribe(this::applyUpdate);
}
@Override
public void setVisible(boolean aFlag) {
super.setVisible(aFlag);
if (aFlag) {
timer.start();
} else {
timer.stop();
public UpdateData prepareUpdate() {
if (focusManager.getActiveWindow() == null) {
// skip update if app window not active
return SKIP_UPDATE;
}
UpdateData updateData = new UpdateData();
long used = runtime.totalMemory() - runtime.freeMemory();
updateData.value = (int) (used / 1024);
updateData.label = String.format(labelTemplate, used / GB, maxGB);
updateData.color = used > limit ? RED : GREEN;
return updateData;
}
public void applyUpdate(UpdateData update) {
setValue(update.value);
setString(update.label);
setColor(update.color);
}
private void setColor(Color color) {
if (currentColor != color) {
setForeground(color);
currentColor = color;
}
}
private void update() {
UpdateData update = prepareUpdate();
if (update != SKIP_UPDATE) {
applyUpdate(update);
}
}
public void reset() {
if (timer != null) {
timer.dispose();
timer = null;
}
}
}
......@@ -1116,6 +1116,7 @@ public class MainWindow extends JFrame {
settings.setMainWindowExtendedState(getExtendedState());
cancelBackgroundJobs();
wrapper.close();
heapUsageBar.reset();
dispose();
FileUtils.deleteTempRootDir();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册