convex.gui.manager.windows.peer.StressPanel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of convex-gui Show documentation
Show all versions of convex-gui Show documentation
Convex desktop GUI and test applications
package convex.gui.manager.windows.peer;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.net.InetSocketAddress;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import convex.api.Convex;
import convex.core.Result;
import convex.core.crypto.AKeyPair;
import convex.core.data.ACell;
import convex.core.data.AVector;
import convex.core.data.Address;
import convex.core.data.Strings;
import convex.core.lang.Reader;
import convex.core.transactions.ATransaction;
import convex.core.transactions.Invoke;
import convex.core.transactions.Multi;
import convex.core.util.Text;
import convex.core.util.Utils;
import convex.gui.components.ActionPanel;
import convex.gui.manager.PeerGUI;
import convex.gui.utils.Toolkit;
@SuppressWarnings("serial")
public class StressPanel extends JPanel {
static final Logger log = LoggerFactory.getLogger(StressPanel.class.getName());
protected Convex peerConvex;
private ActionPanel actionPanel;
private JButton btnRun;
private JSpinner requestCountSpinner;
private JSpinner transactionCountSpinner;
private JSpinner opCountSpinner;
private JSpinner clientCountSpinner;
private JCheckBox syncCheckBox;
private JCheckBox distCheckBox;
public StressPanel(Convex peerView) {
this.peerConvex = peerView;
this.setLayout(new BorderLayout());
actionPanel = new ActionPanel();
add(actionPanel, BorderLayout.SOUTH);
btnRun = new JButton("Run Test");
actionPanel.add(btnRun);
btnRun.addActionListener(e -> {
btnRun.setEnabled(false);
SwingUtilities.invokeLater(() -> runStressTest());
});
splitPane = new JSplitPane();
add(splitPane, BorderLayout.CENTER);
JPanel panel = new JPanel();
splitPane.setLeftComponent(panel);
FlowLayout flowLayout = (FlowLayout) panel.getLayout();
flowLayout.setAlignment(FlowLayout.LEFT);
flowLayout.setAlignOnBaseline(true);
// =========================================
// Option Panel
JPanel optionPanel = new JPanel();
panel.add(optionPanel);
optionPanel.setLayout(new GridLayout(0, 2, 0, 0));
JLabel lblClients = new JLabel("Clients");
optionPanel.add(lblClients);
clientCountSpinner = new JSpinner();
// Note: about 300 max number of clients before hitting juice limits for account creation
clientCountSpinner.setModel(new SpinnerNumberModel(100, 1, 300, 1));
optionPanel.add(clientCountSpinner);
JLabel lblRequests = new JLabel("Requests per client");
optionPanel.add(lblRequests);
requestCountSpinner = new JSpinner();
requestCountSpinner.setModel(new SpinnerNumberModel(100, 1, 1000000, 10));
optionPanel.add(requestCountSpinner);
JLabel lblTrans = new JLabel("Transactions per Request");
optionPanel.add(lblTrans);
transactionCountSpinner = new JSpinner();
transactionCountSpinner.setModel(new SpinnerNumberModel(10, 1, 1000, 1));
optionPanel.add(transactionCountSpinner);
JLabel lblOps = new JLabel("Ops per Transaction");
optionPanel.add(lblOps);
opCountSpinner = new JSpinner();
opCountSpinner.setModel(new SpinnerNumberModel(1, 1, 1000, 10));
optionPanel.add(opCountSpinner);
JLabel lblSync=new JLabel("Sync Requests?");
optionPanel.add(lblSync);
syncCheckBox=new JCheckBox();
optionPanel.add(syncCheckBox);
syncCheckBox.setSelected(true);
JLabel lblDist=new JLabel("Distribute over Peers?");
optionPanel.add(lblDist);
distCheckBox=new JCheckBox();
optionPanel.add(distCheckBox);
distCheckBox.setSelected(false);
// =========================================
// Result Panel
resultPanel = new JPanel();
splitPane.setRightComponent(resultPanel);
resultPanel.setLayout(new BorderLayout(0, 0));
resultArea = new JTextArea();
resultArea.setText("No results yet");
resultArea.setLineWrap(true);
resultArea.setEditable(false);
resultPanel.add(resultArea);
resultArea.setFont(Toolkit.SMALL_MONO_FONT);
}
long errors = 0;
long values = 0;
private JSplitPane splitPane;
private JPanel resultPanel;
private JTextArea resultArea;
NumberFormat formatter = new DecimalFormat("#0.000");
private synchronized void runStressTest() {
errors = 0;
values = 0;
Address address=peerConvex.getAddress();
AKeyPair kp=peerConvex.getKeyPair();
int transCount = (Integer) transactionCountSpinner.getValue();
int requestCount = (Integer) requestCountSpinner.getValue();
int opCount = (Integer) opCountSpinner.getValue();
// TODO: enable multiple clients
int clientCount = (Integer) clientCountSpinner.getValue();
new SwingWorker() {
@Override
protected String doInBackground() throws Exception {
StringBuilder sb = new StringBuilder();
try {
resultArea.setText("Connecting clients...");
InetSocketAddress sa = peerConvex.getHostAddress();
// Use client store
// Stores.setCurrent(Stores.CLIENT_STORE);
ArrayList> frs=new ArrayList<>();
Convex pc = Convex.connect(sa, address,kp);
ArrayList kps=new ArrayList<>(clientCount);
for (int i=0; i v=ccr.getValue();
ArrayList ccs=new ArrayList<>(clientCount);
for (int i=0; i> cfutures=Utils.threadMap (cc->{
try {
for (int i = 0; i < requestCount; i++) {
StringBuilder tsb = new StringBuilder();
tsb.append("(def a (do ");
for (int j = 0; j < opCount; j++) {
tsb.append(" (* 10 " + i + ")");
}
tsb.append("))");
String source = tsb.toString();
Address origin=cc.getAddress();
ATransaction t = Invoke.create(origin,-1, Reader.read(source));
if (transCount!=1) {
ATransaction[] trxs=new ATransaction[transCount];
for (int k=0; k fr;
if (syncCheckBox.isSelected()) {
Result r=cc.transactSync(t);
fr=CompletableFuture.completedFuture(r);
} else {
fr = cc.transact(t);
}
synchronized(frs) {
// synchronised so we don't collide with other threads
frs.add(fr);
}
}
} catch (Exception e) {
throw Utils.sneakyThrow(e);
}
return null;
},ccs);
// wait for everything to be sent
for (int i=0; i results = Utils.completeAll(frs).get();
long endTime = Utils.getCurrentTimestamp();
HashMap errorMap=new HashMap<>();
for (Result r : results) {
if (r.isError()) {
errors++;
Utils.histogramAdd(errorMap,r.getErrorCode());
} else {
values++;
}
}
for (int i=0; i0) {
sb.append(errorMap);
sb.append("\n");
}
sb.append("\n");
sb.append("Total time: " + formatter.format((endTime - startTime) * 0.001) + "s\n");
sb.append("\n");
sb.append("Approx TPS: " + Text.toFriendlyIntString(totalCount/((endTime - startTime) * 0.001)) + "\n");
} catch (Throwable e) {
log.warn("Stress test worker terminated unexpectedly",e);
resultArea.setText("Test Error: "+e);
} finally {
btnRun.setEnabled(true);
}
String report = sb.toString();
return report;
}
@Override
protected void done() {
try {
resultArea.setText(get());
} catch (Exception e) {
resultArea.setText(e.getMessage());
}
}
}.execute();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy