Skip to content

Commit

Permalink
perf(gui): reduce updates count for memory usage bar (#1000)
Browse files Browse the repository at this point in the history
- disabled by default
- update only if label changed
- skip updates if app window becomes inactive
  • Loading branch information
skylot committed Oct 27, 2020
1 parent 12dc4fd commit 9277341
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 33 deletions.
8 changes: 6 additions & 2 deletions jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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;
Expand Down Expand Up @@ -436,6 +436,10 @@ private void upgradeSettings(int fromVersion) {
if (fromVersion == 8) {
fromVersion++;
}
if (fromVersion == 9) {
showHeapUsageBar = false;
fromVersion++;
}
settingsVersion = CURRENT_SETTINGS_VERSION;
sync();
}
Expand Down
120 changes: 89 additions & 31 deletions jadx-gui/src/main/java/jadx/gui/ui/HeapUsageBar.java
Original file line number Diff line number Diff line change
@@ -1,79 +1,137 @@
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());
}
}
});
}

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;
}
}
}
1 change: 1 addition & 0 deletions jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -1116,6 +1116,7 @@ private void closeWindow() {
settings.setMainWindowExtendedState(getExtendedState());
cancelBackgroundJobs();
wrapper.close();
heapUsageBar.reset();
dispose();

FileUtils.deleteTempRootDir();
Expand Down

0 comments on commit 9277341

Please sign in to comment.