Faster byte and word to hex string
I was alarmed to discover just how slow `String.format()` is for doing integer to hex conversions. Now that a trace window has been added to Symon, it became especially clear that I needed a more efficient way to handle it. I looked into using `Integer.toHexString()`, but I would have had to wrap it to do zero-padding, so I decided to just bite the bullet and do my own with a lookup table. The implementation in `HexUtil` is just as fast as `Integer.toHexString()`, but also zero-pads appropriately. Combined with Java's `+` String concatenation, it seems perfectly adequate. For yet better performance with the trace window, it would make a lot of sense to special-case stepping so that it just pops the top line off the log, and appends to the bottom, rather than re-stringifying the entire trace log each time. This will be a future enhancement.
This commit is contained in:
1 parent
bc3de80892
commit
807a43ce6f
5 files changed
+225
-56
No files matched your search
@@ -31,54 +31,99 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* This frame displays a trace of CPU execution. The most recent TRACE_LENGTH lines
|
||||
* This frame displays a trace of CPU execution. The most recent <code>TRACE_LENGTH</code> lines
|
||||
* are captured in a buffer and rendered to the JFrame's main text area upon request.
|
||||
*/
|
||||
public class TraceLog {
|
||||
|
||||
private FifoRingBuffer<Cpu.CpuState> traceLog;
|
||||
private JFrame traceLogWindow;
|
||||
private JTextArea logArea;
|
||||
private JFrame traceLogFrame;
|
||||
private JTextArea traceLogTextArea;
|
||||
|
||||
private static final Dimension SIZE = new Dimension(640, 480);
|
||||
private static final int MAX_LOG_LENGTH = 10000;
|
||||
private static final Dimension MIN_SIZE = new Dimension(320, 200);
|
||||
private static final Dimension PREFERRED_SIZE = new Dimension(640, 480);
|
||||
private static final int MAX_LOG_LENGTH = 50000;
|
||||
|
||||
public TraceLog() {
|
||||
traceLog = new FifoRingBuffer<Cpu.CpuState>(MAX_LOG_LENGTH);
|
||||
traceLogWindow = new JFrame();
|
||||
traceLogWindow.setPreferredSize(SIZE);
|
||||
traceLogWindow.setResizable(true);
|
||||
traceLogFrame = new JFrame();
|
||||
traceLogFrame.setMinimumSize(MIN_SIZE);
|
||||
traceLogFrame.setPreferredSize(PREFERRED_SIZE);
|
||||
traceLogFrame.setResizable(true);
|
||||
traceLogFrame.setTitle("Trace Log");
|
||||
|
||||
traceLogWindow.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
||||
traceLogFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
||||
|
||||
logArea = new JTextArea();
|
||||
logArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
|
||||
traceLogTextArea = new JTextArea();
|
||||
traceLogTextArea.setFont(new Font(Font.MONOSPACED, Font.BOLD, 12));
|
||||
traceLogTextArea.setEditable(false);
|
||||
|
||||
JScrollPane scrollableView = new JScrollPane(logArea);
|
||||
JScrollPane scrollableView = new JScrollPane(traceLogTextArea);
|
||||
|
||||
traceLogWindow.getContentPane().add(scrollableView);
|
||||
traceLogWindow.pack();
|
||||
traceLogFrame.getContentPane().add(scrollableView);
|
||||
traceLogFrame.pack();
|
||||
// Don't show the frame. That action is controlled by the Simulator.
|
||||
}
|
||||
|
||||
/**
|
||||
* Redraw the display with the most recent <code>MAX_LOG_LENGTH</code>
|
||||
* trace events. <strong>CAUTION</strong>: This can be a very expensive
|
||||
* call.
|
||||
*/
|
||||
public void refresh() {
|
||||
StringBuilder logString = new StringBuilder();
|
||||
for (Cpu.CpuState state : traceLog) {
|
||||
logString.append(state.toString());
|
||||
logString.append("\n");
|
||||
synchronized (this) {
|
||||
StringBuilder logString = new StringBuilder();
|
||||
for (Cpu.CpuState state : traceLog) {
|
||||
logString.append(state.toTraceEvent());
|
||||
}
|
||||
traceLogTextArea.setText(logString.toString());
|
||||
}
|
||||
logArea.setText(logString.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the log area.
|
||||
*/
|
||||
public void reset() {
|
||||
synchronized (this) {
|
||||
traceLog.reset();
|
||||
traceLogTextArea.setText("");
|
||||
traceLogTextArea.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a CPU State to the trace log.
|
||||
*
|
||||
* @param state The CPU State to append.
|
||||
*/
|
||||
public void append(Cpu.CpuState state) {
|
||||
traceLog.push(new Cpu.CpuState(state));
|
||||
synchronized(this) {
|
||||
traceLog.push(new Cpu.CpuState(state));
|
||||
}
|
||||
}
|
||||
|
||||
public void simulatorDidStart() {
|
||||
traceLogTextArea.setEnabled(false);
|
||||
}
|
||||
|
||||
public void simulatorDidStop() {
|
||||
traceLogTextArea.setEnabled(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the Trace Log window is currently visible.
|
||||
* @return ture if the Trace Log window is currently visible.
|
||||
*/
|
||||
public boolean isVisible() {
|
||||
return traceLogWindow.isVisible();
|
||||
return traceLogFrame.isVisible();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the visibility of the Trace Log window.
|
||||
*
|
||||
* @param b True to make the Trace Log window visible, false to hide it.
|
||||
*/
|
||||
public void setVisible(boolean b) {
|
||||
traceLogWindow.setVisible(b);
|
||||
traceLogFrame.setVisible(b);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user