Skip to content

Commit 03cb017

Browse files
Tame Serial Monitor Memory & CPU Usage (Arduino issue #2233)
arduino/Arduino#2233
1 parent d8984e7 commit 03cb017

File tree

2 files changed

+94
-11
lines changed

2 files changed

+94
-11
lines changed

app/src/processing/app/SerialMonitor.java

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package processing.app;
2020

2121
import processing.app.debug.MessageConsumer;
22+
import processing.app.debug.TextAreaFIFO;
2223
import processing.core.*;
2324
import static processing.app.I18n._;
2425

@@ -32,17 +33,19 @@
3233
import java.net.*;
3334
import java.util.*;
3435

35-
public class SerialMonitor extends JFrame implements MessageConsumer {
36+
public class SerialMonitor extends JFrame implements MessageConsumer,ActionListener {
3637
private Serial serial;
3738
private String port;
38-
private JTextArea textArea;
39+
private TextAreaFIFO textArea;
3940
private JScrollPane scrollPane;
4041
private JTextField textField;
4142
private JButton sendButton;
4243
private JCheckBox autoscrollBox;
4344
private JComboBox lineEndings;
4445
private JComboBox serialRates;
4546
private int serialRate;
47+
private javax.swing.Timer updateTimer;
48+
private StringBuffer updateBuffer;
4649

4750
public SerialMonitor(String port) {
4851
super(port);
@@ -70,7 +73,9 @@ public void actionPerformed(ActionEvent e) {
7073
Font editorFont = Preferences.getFont("editor.font");
7174
Font font = new Font(consoleFont.getName(), consoleFont.getStyle(), editorFont.getSize());
7275

73-
textArea = new JTextArea(16, 40);
76+
textArea = new TextAreaFIFO(4000000);
77+
textArea.setRows(16);
78+
textArea.setColumns(40);
7479
textArea.setEditable(false);
7580
textArea.setFont(font);
7681

@@ -174,6 +179,9 @@ public void actionPerformed(ActionEvent event) {
174179
}
175180
}
176181
}
182+
183+
updateBuffer = new StringBuffer(1048576);
184+
updateTimer = new javax.swing.Timer(33, this); // redraw serial monitor at 30 Hz
177185
}
178186

179187
protected void setPlacement(int[] location) {
@@ -230,6 +238,7 @@ public void openSerialPort() throws SerialException {
230238
}
231239
}
232240
serial.addListener(this);
241+
updateTimer.start();
233242
}
234243

235244
public void closeSerialPort() {
@@ -243,15 +252,34 @@ public void closeSerialPort() {
243252
}
244253
}
245254

246-
public void message(final String s) {
247-
SwingUtilities.invokeLater(new Runnable() {
248-
public void run() {
249-
textArea.append(s);
250-
if (autoscrollBox.isSelected()) {
251-
textArea.setCaretPosition(textArea.getDocument().getLength());
252-
}
253-
}});
255+
public void message(String s) {
256+
// TODO: can we pass a byte array, to avoid overhead of String
257+
addToUpdateBuffer(s);
258+
}
259+
260+
private synchronized void addToUpdateBuffer(String s) {
261+
updateBuffer.append(s);
262+
}
263+
264+
private synchronized String consumeUpdateBuffer() {
265+
String s = updateBuffer.toString();
266+
updateBuffer.setLength(0);
267+
return s;
268+
}
269+
270+
public void actionPerformed(ActionEvent e) {
271+
final String s = consumeUpdateBuffer();
272+
if (s.length() > 0) {
273+
//System.out.println("gui append " + s.length());
274+
boolean scroll = autoscrollBox.isSelected();
275+
textArea.allowTrim(scroll);
276+
textArea.append(s);
277+
if (scroll) {
278+
textArea.setCaretPosition(textArea.getDocument().getLength());
279+
}
280+
}
254281
}
282+
255283
}
256284

257285
class FakeSerial extends Serial {
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// adapted from https://community.oracle.com/thread/1479784
2+
3+
package processing.app.debug;
4+
5+
import java.awt.*;
6+
import java.awt.event.*;
7+
import java.util.Date;
8+
import javax.swing.*;
9+
import javax.swing.event.*;
10+
import javax.swing.text.*;
11+
12+
public class TextAreaFIFO extends JTextArea implements DocumentListener
13+
{
14+
private int maxChars;
15+
private int updateCount; // limit how often we trim the document
16+
private boolean doTrim;
17+
18+
public TextAreaFIFO(int max) {
19+
maxChars = max;
20+
updateCount = 0;
21+
doTrim = true;
22+
getDocument().addDocumentListener( this );
23+
}
24+
25+
public void allowTrim(boolean trim) {
26+
doTrim = trim;
27+
}
28+
29+
public void insertUpdate(DocumentEvent e) {
30+
if (++updateCount > 150 && doTrim) {
31+
updateCount = 0;
32+
SwingUtilities.invokeLater( new Runnable() {
33+
public void run() {
34+
trimDocument();
35+
}
36+
});
37+
}
38+
}
39+
40+
public void removeUpdate(DocumentEvent e) {}
41+
public void changedUpdate(DocumentEvent e) {}
42+
43+
public void trimDocument() {
44+
int len = 0;
45+
len = getDocument().getLength();
46+
if (len > maxChars) {
47+
int n = len - maxChars;
48+
System.out.println("trimDocument: remove " + n + " chars");
49+
try {
50+
getDocument().remove(0, n);
51+
} catch(BadLocationException ble) {
52+
}
53+
}
54+
}
55+
}

0 commit comments

Comments
 (0)