Skip to content

Commit

Permalink
Merge pull request #5795 from chimp1984/optimize-dao-charts-7
Browse files Browse the repository at this point in the history
Optimize DAO charts [7]
  • Loading branch information
ripcurlx authored Nov 9, 2021
2 parents 07f4074 + 2eae94e commit 60526cc
Show file tree
Hide file tree
Showing 11 changed files with 321 additions and 168 deletions.
2 changes: 1 addition & 1 deletion common/src/main/java/bisq/common/ClockWatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public void start() {
}
}

public void stop() {
public void shutDown() {
timer.stop();
timer = null;
counter = 0;
Expand Down
19 changes: 2 additions & 17 deletions common/src/main/java/bisq/common/app/Log.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

public class Log {
private static Logger logbackLogger;
public static final Level DEFAULT_LOG_LEVEL = Level.INFO;

public static void setLevel(Level logLevel) {
logbackLogger.setLevel(logLevel);
Expand Down Expand Up @@ -67,23 +68,7 @@ public static void setup(String fileName) {

logbackLogger = loggerContext.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
logbackLogger.addAppender(appender);
logbackLogger.setLevel(Level.INFO);

// log errors in separate file
// not working as expected still.... damn logback...
/* FileAppender errorAppender = new FileAppender();
errorAppender.setEncoder(encoder);
errorAppender.setName("Error");
errorAppender.setContext(loggerContext);
errorAppender.setFile(fileName + "_error.log");
LevelFilter levelFilter = new LevelFilter();
levelFilter.setLevel(Level.ERROR);
levelFilter.setOnMatch(FilterReply.ACCEPT);
levelFilter.setOnMismatch(FilterReply.DENY);
levelFilter.start();
errorAppender.addFilter(levelFilter);
errorAppender.start();
logbackLogger.addAppender(errorAppender);*/
logbackLogger.setLevel(DEFAULT_LOG_LEVEL);
}

public static void setCustomLogLevel(String pattern, Level logLevel) {
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/bisq/core/app/BisqExecutable.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

import bisq.network.p2p.P2PService;

import bisq.common.ClockWatcher;
import bisq.common.UserThread;
import bisq.common.app.AppModule;
import bisq.common.config.BisqHelpFormatter;
Expand Down Expand Up @@ -228,6 +229,7 @@ public void gracefulShutDown(ResultHandler resultHandler) {
}

try {
injector.getInstance(ClockWatcher.class).shutDown();
injector.getInstance(OpenBsqSwapOfferService.class).shutDown();
injector.getInstance(PriceFeedService.class).shutDown();
injector.getInstance(ArbitratorManager.class).shutDown();
Expand Down
56 changes: 39 additions & 17 deletions desktop/src/main/java/bisq/desktop/components/chart/ChartView.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Stream;

import lombok.Setter;
Expand Down Expand Up @@ -107,8 +108,9 @@ public abstract class ChartView<T extends ChartViewModel<? extends ChartDataMode
private int maxDataPointsForShowingSymbols = 100;
private ChangeListener<Number> yAxisWidthListener;
private EventHandler<MouseEvent> dividerMouseDraggedEventHandler;
private StringProperty fromProperty = new SimpleStringProperty();
private StringProperty toProperty = new SimpleStringProperty();
private final StringProperty fromProperty = new SimpleStringProperty();
private final StringProperty toProperty = new SimpleStringProperty();
private boolean dataApplied;


///////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -219,19 +221,14 @@ public void initialize() {
@Override
public void activate() {
timelineNavigation.setDividerPositions(model.getDividerPositions()[0], model.getDividerPositions()[1]);
UserThread.execute(this::applyTimeLineNavigationLabels);
UserThread.execute(this::onTimelineChanged);

TemporalAdjuster temporalAdjuster = model.getTemporalAdjuster();
applyTemporalAdjuster(temporalAdjuster);
findTimeIntervalToggleByTemporalAdjuster(temporalAdjuster).ifPresent(timeIntervalToggleGroup::selectToggle);

defineAndAddActiveSeries();
applyData();
initBoundsForTimelineNavigation();

updateChartAfterDataChange();

// Apply listeners and handlers
root.widthProperty().addListener(widthListener);
xAxis.getChildrenUnmodifiable().addListener(nodeListChangeListener);
Expand Down Expand Up @@ -555,15 +552,25 @@ protected void activateSeries(XYChart.Series<Number, Number> series) {
chart.getData().add(series);
activeSeries.add(series);
legendToggleBySeriesName.get(getSeriesId(series)).setSelected(true);
updateChartAfterDataChange();
applyDataAndUpdate();
}


///////////////////////////////////////////////////////////////////////////////////////////
// Data
///////////////////////////////////////////////////////////////////////////////////////////

protected abstract void applyData();
protected abstract CompletableFuture<Boolean> applyData();

private void applyDataAndUpdate() {
long ts = System.currentTimeMillis();
applyData().whenComplete((r, t) -> {
log.debug("applyData took {}", System.currentTimeMillis() - ts);
long ts2 = System.currentTimeMillis();
updateChartAfterDataChange();
log.debug("updateChartAfterDataChange took {}", System.currentTimeMillis() - ts2);
});
}

/**
* Implementations define which series will be used for setBoundsForTimelineNavigation
Expand All @@ -589,16 +596,14 @@ private void onTimeIntervalChanged(Toggle newValue) {
TemporalAdjusterModel.Interval interval = (TemporalAdjusterModel.Interval) newValue.getUserData();
applyTemporalAdjuster(interval.getAdjuster());
model.invalidateCache();
applyData();
updateChartAfterDataChange();
applyDataAndUpdate();
}

private void onTimelineChanged() {
updateTimeLinePositions();

model.invalidateCache();
applyData();
updateChartAfterDataChange();
applyDataAndUpdate(); //3
}

private void updateTimeLinePositions() {
Expand Down Expand Up @@ -636,8 +641,7 @@ private void onSelectLegendToggle(XYChart.Series<Number, Number> series) {
if (isSelected) {
chart.getData().add(series);
activeSeries.add(series);
//model.invalidateCache();
applyData();
applyDataAndUpdate();

if (isRadioButtonBehaviour) {
// We support different y-axis formats only if isRadioButtonBehaviour is set, otherwise we would get
Expand All @@ -647,9 +651,8 @@ private void onSelectLegendToggle(XYChart.Series<Number, Number> series) {
} else if (!isRadioButtonBehaviour) { // if isRadioButtonBehaviour we have removed it already via the code above
chart.getData().remove(series);
activeSeries.remove(series);

updateChartAfterDataChange();
}
updateChartAfterDataChange();
}

///////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -771,4 +774,23 @@ private Optional<Toggle> findTimeIntervalToggleByTemporalAdjuster(TemporalAdjust
protected String getSeriesId(XYChart.Series<Number, Number> series) {
return series.getName();
}

protected void mapToUserThread(Runnable command) {
UserThread.execute(() -> {
command.run();
onDataApplied();
});
}

// For the async handling we need to wait until we get the data applied and then still delay a bit otherwise
// the UI does not get rendered at first start
protected void onDataApplied() {
if (!dataApplied) {
dataApplied = true;
UserThread.execute(() -> {
applyTimeLineNavigationLabels();
updateTimeLinePositions();
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

import bisq.core.locale.Res;

import bisq.common.util.CompletableFutureUtils;

import javax.inject.Inject;

import javafx.scene.chart.XYChart;
Expand All @@ -29,16 +31,20 @@
import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;

import javafx.collections.ObservableList;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class PriceChartView extends ChartView<PriceChartViewModel> {
private XYChart.Series<Number, Number> seriesBsqUsdPrice, seriesBsqBtcPrice, seriesBtcUsdPrice;
private DoubleProperty averageBsqUsdPriceProperty = new SimpleDoubleProperty();
private DoubleProperty averageBsqBtcPriceProperty = new SimpleDoubleProperty();
private final DoubleProperty averageBsqUsdPriceProperty = new SimpleDoubleProperty();
private final DoubleProperty averageBsqBtcPriceProperty = new SimpleDoubleProperty();

@Inject
public PriceChartView(PriceChartViewModel model) {
Expand Down Expand Up @@ -121,38 +127,80 @@ protected void defineAndAddActiveSeries() {
onSetYAxisFormatter(seriesBsqUsdPrice);
}

@Override
protected void activateSeries(XYChart.Series<Number, Number> series) {
super.activateSeries(series);

String seriesId = getSeriesId(series);
if (seriesId.equals(getSeriesId(seriesBsqUsdPrice))) {
seriesBsqUsdPrice.getData().setAll(model.getBsqUsdPriceChartData());
} else if (seriesId.equals(getSeriesId(seriesBsqBtcPrice))) {
seriesBsqBtcPrice.getData().setAll(model.getBsqBtcPriceChartData());
} else if (seriesId.equals(getSeriesId(seriesBtcUsdPrice))) {
seriesBtcUsdPrice.getData().setAll(model.getBtcUsdPriceChartData());
}
}


///////////////////////////////////////////////////////////////////////////////////////////
// Data
///////////////////////////////////////////////////////////////////////////////////////////

@Override
protected void applyData() {
protected CompletableFuture<Boolean> applyData() {
List<CompletableFuture<Boolean>> allFutures = new ArrayList<>();

if (activeSeries.contains(seriesBsqUsdPrice)) {
seriesBsqUsdPrice.getData().setAll(model.getBsqUsdPriceChartData());
CompletableFuture<Boolean> task1Done = new CompletableFuture<>();
allFutures.add(task1Done);
applyBsqUsdPriceChartDataAsync(task1Done);
}
if (activeSeries.contains(seriesBsqBtcPrice)) {
seriesBsqBtcPrice.getData().setAll(model.getBsqBtcPriceChartData());
CompletableFuture<Boolean> task2Done = new CompletableFuture<>();
allFutures.add(task2Done);
applyBsqBtcPriceChartData(task2Done);
}
if (activeSeries.contains(seriesBtcUsdPrice)) {
seriesBtcUsdPrice.getData().setAll(model.getBtcUsdPriceChartData());
CompletableFuture<Boolean> task3Done = new CompletableFuture<>();
allFutures.add(task3Done);
applyBtcUsdPriceChartData(task3Done);
}

averageBsqBtcPriceProperty.set(model.averageBsqBtcPrice());
averageBsqUsdPriceProperty.set(model.averageBsqUsdPrice());
CompletableFuture<Boolean> task4Done = new CompletableFuture<>();
allFutures.add(task4Done);
model.averageBsqBtcPrice()
.whenComplete((data, t) ->
mapToUserThread(() -> {
averageBsqBtcPriceProperty.set(data);
task4Done.complete(true);
}));

CompletableFuture<Boolean> task5Done = new CompletableFuture<>();
allFutures.add(task5Done);
model.averageBsqUsdPrice()
.whenComplete((data, t) ->
mapToUserThread(() -> {
averageBsqUsdPriceProperty.set(data);
task5Done.complete(true);
}));

return CompletableFutureUtils.allOf(allFutures).thenApply(e -> {
return true;
});
}

private void applyBsqUsdPriceChartDataAsync(CompletableFuture<Boolean> completeFuture) {
model.getBsqUsdPriceChartData()
.whenComplete((data, t) ->
mapToUserThread(() -> {
ObservableList<XYChart.Data<Number, Number>> data1 = seriesBsqUsdPrice.getData();
data1.setAll(data);
completeFuture.complete(true);
})
);
}

private void applyBtcUsdPriceChartData(CompletableFuture<Boolean> completeFuture) {
model.getBtcUsdPriceChartData()
.whenComplete((data, t) ->
mapToUserThread(() -> {
seriesBtcUsdPrice.getData().setAll(data);
completeFuture.complete(true);
}));
}

private void applyBsqBtcPriceChartData(CompletableFuture<Boolean> completeFuture) {
model.getBsqBtcPriceChartData()
.whenComplete((data, t) ->
mapToUserThread(() -> {
seriesBsqBtcPrice.getData().setAll(data);
completeFuture.complete(true);
}));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import java.text.DecimalFormat;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;

import lombok.extern.slf4j.Slf4j;
Expand All @@ -53,29 +54,30 @@ public PriceChartViewModel(PriceChartDataModel dataModel) {
// Average price from timeline selection
///////////////////////////////////////////////////////////////////////////////////////////

double averageBsqUsdPrice() {
return dataModel.averageBsqUsdPrice();
CompletableFuture<Double> averageBsqUsdPrice() {
return CompletableFuture.supplyAsync(() -> dataModel.averageBsqUsdPrice());
}

double averageBsqBtcPrice() {
return dataModel.averageBsqBtcPrice();
CompletableFuture<Double> averageBsqBtcPrice() {
return CompletableFuture.supplyAsync(() -> dataModel.averageBsqBtcPrice());
}


///////////////////////////////////////////////////////////////////////////////////////////
// Chart data
///////////////////////////////////////////////////////////////////////////////////////////

List<XYChart.Data<Number, Number>> getBsqUsdPriceChartData() {
return toChartDoubleData(dataModel.getBsqUsdPriceByInterval());

CompletableFuture<List<XYChart.Data<Number, Number>>> getBsqUsdPriceChartData() {
return CompletableFuture.supplyAsync(() -> toChartDoubleData(dataModel.getBsqUsdPriceByInterval()));
}

List<XYChart.Data<Number, Number>> getBsqBtcPriceChartData() {
return toChartDoubleData(dataModel.getBsqBtcPriceByInterval());
CompletableFuture<List<XYChart.Data<Number, Number>>> getBsqBtcPriceChartData() {
return CompletableFuture.supplyAsync(() -> toChartDoubleData(dataModel.getBsqBtcPriceByInterval()));
}

List<XYChart.Data<Number, Number>> getBtcUsdPriceChartData() {
return toChartDoubleData(dataModel.getBtcUsdPriceByInterval());
CompletableFuture<List<XYChart.Data<Number, Number>>> getBtcUsdPriceChartData() {
return CompletableFuture.supplyAsync(() -> toChartDoubleData(dataModel.getBtcUsdPriceByInterval()));
}


Expand Down
Loading

0 comments on commit 60526cc

Please sign in to comment.