mirror of
https://github.com/processing/processing4.git
synced 2026-01-29 11:21:06 +01:00
Add a debug() method to Serial
This commit also turns a 100ns wait inside JSSC in a yield() and removes the invocation of serialEvent outside the synchronized block.
This commit is contained in:
@@ -48,6 +48,28 @@ public class Serial implements SerialPortEventListener {
|
||||
|
||||
volatile boolean invokeSerialAvailable = false;
|
||||
|
||||
// DEBUG
|
||||
int baudRate = 0;
|
||||
int countEvents = 0; // number of event handler invocations
|
||||
int countFuncs = 0; // number of SerialEvent invocations
|
||||
int countReads = 0; // number of read operations
|
||||
int countSyncs = 0; // number of synchronizations
|
||||
int countWrites = 0; // number of write operations
|
||||
long firstEvent = 0; // timestamp of first event handler invocation
|
||||
int maxBufferLength = 0; // maximum size of input buffer
|
||||
long maxFuncTime = 0; // maximum time spend invoking SerialEvent
|
||||
int maxRead = 0; // maximum number of bytes read
|
||||
long maxReadTime = 0; // maximum time spent on read operations
|
||||
long maxReadSyncTime = 0; // maximum time spent on a synchronization in the event handler
|
||||
long maxSyncTime = 0; // maximum time spent on a synchronization elsewhere
|
||||
long maxWriteTime = 0; // maximum time spent on a write operation
|
||||
long sumFuncTime = 0; // sum of time spent in SerialEvent
|
||||
int sumRead = 0; // sum of bytes read
|
||||
long sumReadSyncTime = 0; // sum of time spent on synchonizations in the event handler
|
||||
long sumReadTime = 0; // sum of time spent on read operations
|
||||
long sumSyncTime = 0; // sum of time spent on synchonizations elsewhere
|
||||
long sumWriteTime = 0; // sum of time spent on write operations
|
||||
|
||||
// Things we are currently not exposing:
|
||||
// * hardware flow control
|
||||
// * state of the RING, RLSD line
|
||||
@@ -79,6 +101,8 @@ public class Serial implements SerialPortEventListener {
|
||||
parent.registerMethod("dispose", this);
|
||||
parent.registerMethod("pre", this);
|
||||
|
||||
this.baudRate = baudRate;
|
||||
|
||||
// setup parity
|
||||
if (parity == 'O') {
|
||||
parity = SerialPort.PARITY_ODD;
|
||||
@@ -160,13 +184,37 @@ public class Serial implements SerialPortEventListener {
|
||||
|
||||
|
||||
public void clear() {
|
||||
long start = System.nanoTime();
|
||||
synchronized (buffer) {
|
||||
long len = System.nanoTime()-start;
|
||||
if (maxSyncTime < len) {
|
||||
maxSyncTime = len;
|
||||
}
|
||||
sumSyncTime += len;
|
||||
countSyncs++;
|
||||
inBuffer = 0;
|
||||
readOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void debug() {
|
||||
float secs = (System.nanoTime()-firstEvent)/1000000000.0f;
|
||||
System.out.println("\nSerial: test #3");
|
||||
System.out.println(port.getPortName()+" @ "+baudRate+" bps");
|
||||
System.out.println(secs+" sec receiving data:");
|
||||
System.out.println(countEvents+" events, "+(countEvents/secs)+" per sec");
|
||||
System.out.println(countReads+" reads, "+(countReads/secs)+" per sec, "+(sumReadTime/(float)countReads)+" ns avg, "+maxReadTime+" ns max");
|
||||
System.out.println((sumRead/(float)countReads)+" bytes avg per read, "+(sumRead/secs)+" per sec, "+maxRead+" bytes max");
|
||||
System.out.println("Max buffer length: "+maxBufferLength);
|
||||
System.out.println(sumReadSyncTime/(float)countReads+" ns avg read synchronizations, "+maxReadSyncTime+" ns max");
|
||||
System.out.println(countFuncs+" callbacks, "+(sumFuncTime/(float)countFuncs)+" ns avg, "+maxFuncTime+" ns max");
|
||||
System.out.println(countWrites+" writes, "+(sumWriteTime/(float)countWrites)+" ns avg, "+maxWriteTime+" ns max");
|
||||
System.out.println(countSyncs+" synchonizations, "+(sumSyncTime/(float)countSyncs)+" ns avg, "+maxSyncTime+" ns max");
|
||||
port.debug();
|
||||
}
|
||||
|
||||
|
||||
public boolean getCTS() {
|
||||
try {
|
||||
return port.isCTS();
|
||||
@@ -189,13 +237,20 @@ public class Serial implements SerialPortEventListener {
|
||||
return SerialPortList.getPortProperties(portName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public int last() {
|
||||
if (inBuffer == readOffset) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
long start = System.nanoTime();
|
||||
synchronized (buffer) {
|
||||
long len = System.nanoTime()-start;
|
||||
if (maxSyncTime < len) {
|
||||
maxSyncTime = len;
|
||||
}
|
||||
sumSyncTime += len;
|
||||
countSyncs++;
|
||||
int ret = buffer[inBuffer-1] & 0xFF;
|
||||
inBuffer = 0;
|
||||
readOffset = 0;
|
||||
@@ -221,7 +276,14 @@ public class Serial implements SerialPortEventListener {
|
||||
return -1;
|
||||
}
|
||||
|
||||
long start = System.nanoTime();
|
||||
synchronized (buffer) {
|
||||
long len = System.nanoTime()-start;
|
||||
if (maxSyncTime < len) {
|
||||
maxSyncTime = len;
|
||||
}
|
||||
sumSyncTime += len;
|
||||
countSyncs++;
|
||||
int ret = buffer[readOffset++] & 0xFF;
|
||||
if (inBuffer == readOffset) {
|
||||
inBuffer = 0;
|
||||
@@ -237,7 +299,14 @@ public class Serial implements SerialPortEventListener {
|
||||
return null;
|
||||
}
|
||||
|
||||
long start = System.nanoTime();
|
||||
synchronized (buffer) {
|
||||
long len = System.nanoTime()-start;
|
||||
if (maxSyncTime < len) {
|
||||
maxSyncTime = len;
|
||||
}
|
||||
sumSyncTime += len;
|
||||
countSyncs++;
|
||||
byte[] ret = new byte[inBuffer-readOffset];
|
||||
System.arraycopy(buffer, readOffset, ret, 0, ret.length);
|
||||
inBuffer = 0;
|
||||
@@ -252,7 +321,14 @@ public class Serial implements SerialPortEventListener {
|
||||
return 0;
|
||||
}
|
||||
|
||||
long start = System.nanoTime();
|
||||
synchronized (buffer) {
|
||||
long len = System.nanoTime()-start;
|
||||
if (maxSyncTime < len) {
|
||||
maxSyncTime = len;
|
||||
}
|
||||
sumSyncTime += len;
|
||||
countSyncs++;
|
||||
int toCopy = inBuffer-readOffset;
|
||||
if (dest.length < toCopy) {
|
||||
toCopy = dest.length;
|
||||
@@ -273,7 +349,14 @@ public class Serial implements SerialPortEventListener {
|
||||
return null;
|
||||
}
|
||||
|
||||
long start = System.nanoTime();
|
||||
synchronized (buffer) {
|
||||
long len = System.nanoTime()-start;
|
||||
if (maxSyncTime < len) {
|
||||
maxSyncTime = len;
|
||||
}
|
||||
sumSyncTime += len;
|
||||
countSyncs++;
|
||||
// look for needle in buffer
|
||||
int found = -1;
|
||||
for (int i=readOffset; i < inBuffer; i++) {
|
||||
@@ -304,7 +387,14 @@ public class Serial implements SerialPortEventListener {
|
||||
return 0;
|
||||
}
|
||||
|
||||
long start = System.nanoTime();
|
||||
synchronized (buffer) {
|
||||
long len = System.nanoTime()-start;
|
||||
if (maxSyncTime < len) {
|
||||
maxSyncTime = len;
|
||||
}
|
||||
sumSyncTime += len;
|
||||
countSyncs++;
|
||||
// look for needle in buffer
|
||||
int found = -1;
|
||||
for (int i=readOffset; i < inBuffer; i++) {
|
||||
@@ -362,41 +452,72 @@ public class Serial implements SerialPortEventListener {
|
||||
public void serialEvent(SerialPortEvent event) {
|
||||
if (event.getEventType() == SerialPortEvent.RXCHAR) {
|
||||
int toRead;
|
||||
countEvents++;
|
||||
if (firstEvent == 0) {
|
||||
firstEvent = System.nanoTime();
|
||||
}
|
||||
try {
|
||||
while (0 < (toRead = port.getInputBufferBytesCount())) {
|
||||
long start = System.nanoTime();
|
||||
// this method can be called from the context of another thread
|
||||
synchronized (buffer) {
|
||||
long len = System.nanoTime()-start;
|
||||
if (maxReadSyncTime < len) {
|
||||
maxReadSyncTime = len;
|
||||
}
|
||||
sumReadSyncTime += len;
|
||||
// enlarge buffer if necessary
|
||||
if (buffer.length < inBuffer+toRead) {
|
||||
byte temp[] = new byte[buffer.length<<1];
|
||||
System.arraycopy(buffer, 0, temp, 0, inBuffer);
|
||||
buffer = temp;
|
||||
}
|
||||
if (maxBufferLength < buffer.length) {
|
||||
maxBufferLength = buffer.length;
|
||||
}
|
||||
// read an array of bytes and copy it into our buffer
|
||||
start = System.nanoTime();
|
||||
byte[] read = port.readBytes(toRead);
|
||||
len = System.nanoTime()-start;
|
||||
if (maxReadTime < len) {
|
||||
maxReadTime = len;
|
||||
}
|
||||
sumReadTime += len;
|
||||
if (maxRead < read.length) {
|
||||
maxRead = read.length;
|
||||
}
|
||||
sumRead += read.length;
|
||||
countReads++;
|
||||
System.arraycopy(read, 0, buffer, inBuffer, read.length);
|
||||
inBuffer += read.length;
|
||||
if (serialEventMethod != null) {
|
||||
if ((0 < bufferUntilSize && bufferUntilSize <= inBuffer-readOffset) ||
|
||||
(0 == bufferUntilSize && bufferUntilByte == buffer[inBuffer-1])) {
|
||||
try {
|
||||
// serialEvent() is invoked in the context of the current (serial) thread
|
||||
// which means that serialization and atomic variables need to be used to
|
||||
// guarantee reliable operation (and better not draw() etc..)
|
||||
// serialAvailable() does not provide any real benefits over using
|
||||
// available() and read() inside draw - but this function has no
|
||||
// thread-safety issues since it's being invoked during pre in the context
|
||||
// of the Processing applet
|
||||
serialEventMethod.invoke(parent, new Object[] { this });
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error, disabling serialEvent() for "+port.getPortName());
|
||||
System.err.println(e.getLocalizedMessage());
|
||||
serialEventMethod = null;
|
||||
}
|
||||
if (serialEventMethod != null) {
|
||||
if ((0 < bufferUntilSize && bufferUntilSize <= inBuffer-readOffset) ||
|
||||
(0 == bufferUntilSize && bufferUntilByte == buffer[inBuffer-1])) {
|
||||
try {
|
||||
// serialEvent() is invoked in the context of the current (serial) thread
|
||||
// which means that serialization and atomic variables need to be used to
|
||||
// guarantee reliable operation (and better not draw() etc..)
|
||||
// serialAvailable() does not provide any real benefits over using
|
||||
// available() and read() inside draw - but this function has no
|
||||
// thread-safety issues since it's being invoked during pre in the context
|
||||
// of the Processing applet
|
||||
start = System.nanoTime();
|
||||
serialEventMethod.invoke(parent, new Object[] { this });
|
||||
long len = System.nanoTime()-start;
|
||||
if (maxFuncTime < len) {
|
||||
maxFuncTime = len;
|
||||
}
|
||||
sumFuncTime += len;
|
||||
countFuncs++;
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error, disabling serialEvent() for "+port.getPortName());
|
||||
System.err.println(e.getLocalizedMessage());
|
||||
serialEventMethod = null;
|
||||
}
|
||||
}
|
||||
invokeSerialAvailable = true;
|
||||
}
|
||||
invokeSerialAvailable = true;
|
||||
}
|
||||
} catch (SerialPortException e) {
|
||||
throw new RuntimeException("Error reading from serial port " + e.getPortName() + ": " + e.getExceptionType());
|
||||
@@ -439,7 +560,14 @@ public class Serial implements SerialPortEventListener {
|
||||
public void write(byte[] src) {
|
||||
try {
|
||||
// this might block if the serial device is not yet ready (esp. tty devices under OS X)
|
||||
long start = System.nanoTime();
|
||||
port.writeBytes(src);
|
||||
long len = System.nanoTime()-start;
|
||||
if (maxWriteTime < len) {
|
||||
maxWriteTime = len;
|
||||
}
|
||||
sumWriteTime += len;
|
||||
countWrites++;
|
||||
// we used to call flush() here
|
||||
} catch (SerialPortException e) {
|
||||
throw new RuntimeException("Error writing to serial port " + e.getPortName() + ": " + e.getExceptionType());
|
||||
@@ -449,7 +577,14 @@ public class Serial implements SerialPortEventListener {
|
||||
|
||||
public void write(int src) {
|
||||
try {
|
||||
long start = System.nanoTime();
|
||||
port.writeInt(src);
|
||||
long len = System.nanoTime()-start;
|
||||
if (maxWriteTime < len) {
|
||||
maxWriteTime = len;
|
||||
}
|
||||
sumWriteTime += len;
|
||||
countWrites++;
|
||||
} catch (SerialPortException e) {
|
||||
throw new RuntimeException("Error writing to serial port " + e.getPortName() + ": " + e.getExceptionType());
|
||||
}
|
||||
@@ -458,7 +593,14 @@ public class Serial implements SerialPortEventListener {
|
||||
|
||||
public void write(String src) {
|
||||
try {
|
||||
long start = System.nanoTime();
|
||||
port.writeString(src);
|
||||
long len = System.nanoTime()-start;
|
||||
if (maxWriteTime < len) {
|
||||
maxWriteTime = len;
|
||||
}
|
||||
sumWriteTime += len;
|
||||
countWrites++;
|
||||
} catch (SerialPortException e) {
|
||||
throw new RuntimeException("Error writing to serial port " + e.getPortName() + ": " + e.getExceptionType());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user