Skip to content

Commit 8128525

Browse files
committed
Improve performance on serial monitor 'Show timestamp'
This patch dramatically reduce pressure on heap memory: - use a StringTokenizer instead of the very slow String.split(...) method to decode newlines. This avoid allocation/deallocation of big strings array and use of regexp. - pre allocate as many object as possible to avoid new allocation while streaming data. - the "timestamp" string is calculated only once per iteration. - use StringBuilder instead of inline temporary strings (that are, again, allocated and deallocated on each iteration)
1 parent 13c3750 commit 8128525

File tree

1 file changed

+34
-11
lines changed

1 file changed

+34
-11
lines changed

app/src/processing/app/AbstractTextMonitor.java

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.awt.event.WindowEvent;
1313
import java.text.SimpleDateFormat;
1414
import java.util.Date;
15+
import java.util.StringTokenizer;
1516

1617
import javax.swing.Box;
1718
import javax.swing.BoxLayout;
@@ -177,21 +178,43 @@ public void onSerialRateChange(ActionListener listener) {
177178

178179
public void message(final String s) {
179180
SwingUtilities.invokeLater(new Runnable() {
181+
// Pre-allocate all objects used for streaming data
182+
Date t = new Date();
183+
String now;
184+
StringBuilder out = new StringBuilder(16384);
185+
180186
public void run() {
181187
if (addTimeStampBox.isSelected()) {
182-
String[] lines = s.split("(?<=\\n)");
183-
Document doc = textArea.getDocument();
184-
for (String currentLine : lines) {
185-
try {
186-
if (doc.getLength() == 0 || ((int) doc.getText(doc.getLength() - 1, 1).charAt(0) == 10)) {
187-
textArea.append(logDateFormat.format(new Date()) + " -> " + currentLine);
188-
} else {
189-
textArea.append(currentLine);
190-
}
191-
} catch (BadLocationException e) {
192-
e.printStackTrace();
188+
t.setTime(System.currentTimeMillis());
189+
now = logDateFormat.format(t);
190+
out.setLength(0);
191+
192+
boolean isStartingLine;
193+
try {
194+
Document doc = textArea.getDocument();
195+
isStartingLine = doc.getLength() == 0 || ((int) doc.getText(doc.getLength() - 1, 1).charAt(0) == 10);
196+
} catch (BadLocationException e) {
197+
// Should not happen but...
198+
e.printStackTrace();
199+
return;
200+
}
201+
202+
StringTokenizer tokenizer = new StringTokenizer(s, "\n", true);
203+
while (tokenizer.hasMoreTokens()) {
204+
if (isStartingLine) {
205+
out.append(now);
206+
out.append(" -> ");
207+
}
208+
out.append(tokenizer.nextToken());
209+
210+
// Check if we have a "\n" token
211+
if (tokenizer.hasMoreTokens()) {
212+
out.append(tokenizer.nextToken());
213+
isStartingLine = true;
193214
}
194215
}
216+
217+
textArea.append(out.toString());
195218
} else {
196219
textArea.append(s);
197220
}

0 commit comments

Comments
 (0)