Wednesday, July 1, 2015

Proper serial logging with arduino

In microelectronics, everything you do takes considerable time.
Sending data over serial link is quite heavy by itself.

Not only it takes CPU cycles. Serial.write() can block if the sending buffer is full. That's not okay.

My idea was to monitor output buffer and log only if it doesn't block.

Arduino documentation mentions that serial transmission is asynchronous, but doesn't hint how to deal with the output buffer. Searching web & stackoverflow didn't help. I even cloned the whole repository only to discover later the simple function in HardwareSerial.h:
int availableForWrite(void);
which tells how much bytes you can put in without blocking. Together with SERIAL_TX_BUFFER_SIZE that's just the right thing to know how much is enqueued.

As the result, I wrote the following little program:

unsigned char i = 1;

void setup() {
  Serial.begin(115200);
  Serial.print("start\n");
}

void loop() {  
  int inQueue = SERIAL_TX_BUFFER_SIZE - Serial.availableForWrite();

  if (inQueue < 8) {
    Serial.print(i); // that's heavy
    Serial.write('\n');
    i = 0;
  }

  i = i + 1;
}

Arduino Mega outputs ~22. Make it unsigned int and the output becomes 20. With unsigned long it's 18.

Saturday, January 19, 2013

SSH and performance overhead

One of the first things I do when I come home – I open a port on the router with upnpc, log into my office's PC and set up a reverse ssh connection to my notebook, then I use sshfs to mount the remote filesystem.

I know that ssh uses encryption (thanks, Cap) and that comes at the price of CPU time. I guess, modern CPUs have instructions to accelerate encryption.

What's the price?

So, let's begin the experiment

$ dd if=/dev/urandom of=bigfile bs=8M count=50

gives me a big (400M) file. By the way, it took 107.675 s (3.9 MB/s) on i7-2630QM (only 1 core was loaded).

Let's just read it. First time, after a reboot:
$ dd if=bigfile of=/dev/null bs=8M
50+0 records in
50+0 records out
419430400 bytes (419 MB) copied, 1.7027 s, 246 MB/s


Consecutive runs:
$ dd if=bigfile of=/dev/null bs=8M
50+0 records in
50+0 records out
419430400 bytes (419 MB) copied, 0.0819643 s, 5.1 GB/s


Let's read that via ssh:
$ sudo sshfs -o allow_other,uid=1000 user@localhost:/home/user/ /home/user/self/
$ dd if=self/bigfile of=/dev/null bs=8M
50+0 records in
50+0 records out
419430400 bytes (419 MB) copied, 6.985 s, 60.0 MB/s


The same experiment, on an old AMD Athlon(tm) 64 Processor 3000+ (1 Ghz): 38.663 s, 10.8 MB/s

Ok, here is the price.