Johnny-five: REPL Unresponsive

Created on 12 Sep 2018  路  23Comments  路  Source: rwaldron/johnny-five

When running in REPL mode on a Raspberry Pi B+ the command line input becomes slow and unresponsive after ~1 minute.

What is the recommended path to improve performance?

rasp-io stale

Most helpful comment

Check out my guide to debugging at https://github.com/nebrius/raspi-io/wiki/Getting-a-Raspberry-Pi-ready-for-NodeBots#debugging-your-code. You don't have to use the GUI to get full visual debugging in an IDE ;-)

All 23 comments

Can we see your code?

Here is one version I've been using to test / debug.

```const raspio = require('raspi-io')
const five = require('johnny-five')
const board = new five.Board({ io: new raspio() })

board.on('ready', function() { // Can't use anonymous function with 'this' keyword
let led = new five.Led('P1-16') // Create an Led on pin 13
let led2 = new five.Led('P1-18') // Create an Led on pin 13

this.repl.inject({
led: led,
led2: led2
})

})

This is the bit I would like to use in production

```const express = require('express')
const app = express()
const cors = require('cors')

const raspio = require('raspi-io')
const five = require('johnny-five')
const board = new five.Board({ io: new raspio() })

board.on("ready", () => {

let server = app.listen(process.env.PORT || 8077, () => { // Initialize server
let port = server.address().port
console.log("App now running on localhost:", port)
})

const corsOptions = {
allowedHeaders: [
'Access-Control-Allow-Origin', 'Content-Type', 'Authorization', 'X-Content-Type-Option'
],
credentials: true,
optionsSuccessStatus: 200,
origin: '*',
preflightContinue: true
}

app.use((req, res, next) => { // Enable Cross-Origin Resource Sharing (CORS)
res.header("Access-Control-Allow-Origin", "*")
res.header("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS")
res.header("Access-Control-Allow-Headers", "Accept, Access-Control-Allow-Headers, Authorization, Content-Type, Origin, X-Content-Type-Option")
next()
})

// Initialize pins

five.Led('P1-7').on()
five.Led('P1-11').on()
five.Led('P1-13').on()
five.Led('P1-15').on()
five.Led('P1-29').on()
five.Led('P1-31').on()
five.Led('P1-33').on()
five.Led('P1-24').on()
five.Led('P1-37').on()
five.Led('P1-12').on()
five.Led('P1-16').on()
five.Led('P1-18').on()
five.Led('P1-22').on()
five.Led('P1-36').on()
five.Led('P1-38').on()
five.Led('P1-40').on()

// Main controls

app.get('/on/:i', (req, res) => {
let pin = map(req.params.i)
let led = new five.Led('P1-' + pin)
led.off(500) // on-off is inverted
res.json({
input: req.params.i,
map: pin,
type: 'on'
})
})

app.get('/off/:i', (req, res) => {
let pin = map(req.params.i)
let led = new five.Led('P1-' + pin)
led.on(500) // on-off is inverted
res.json({
input: req.params.i,
map: pin,
type: 'off'
})
})

})

// Map pin numbers on Raspberry Pi

function map(pin) {
switch(pin) {
case '1': return '7'
case '2': return '11'
case '3': return '13'
case '4': return '15'
case '5': return '29'
case '6': return '31'
case '7': return '33'
case '8': return '24'
case '9': return '37'
case '10': return '12'
case '11': return '16'
case '12': return '18'
case '13': return '22'
case '14': return '36'
case '15': return '38'
case '16': return '40'
default: return '28'
}
}

The first case runs interactively in REPL.

And when I boot up the second bit of code with nodemon it logs out the following upon boot:

``[nodemon] 1.18.4 [nodemon] to restart at any time, enterrs [nodemon] watching: *.* [nodemon] startingnode server.js`
1536783439764 Available RaspberryPi-IO
1536783440085 Connected RaspberryPi-IO
1536783440093 Repl Initialized

App now running on localhost: 8077

After doing some more testing on the Express code, it becomes unresponsive even when disabling REPL. Taking 4 - 10 seconds to respond to a command.

I should also add that I am running the API from nodemon via a samba server via macOS and also hosting a Polymer site to run the controls. (So it's possible that the Raspberry Pi can't handle the workload). Although the controller does become unresponsive when running REPL alone.

```
const board = new five.Board({
io: new raspio(),
repl: false
})

So you've taken the REPL out of the picture and it's still slow, correct? I'd take J5 out of the picture altogether and see if you still have performance problems.

I would worry a bit about running and serving things up over SAMBA. That seems like the most likely source of performance problems.

When I set REPL to false it is responsive for about minute then it becomes very slow and unresponsive. Sometimes the console logging happens immediately and the switching is delayed considerably.

So looking at the task manager, the Express code loads ~15 MB into RAM every 3 seconds and gets capped at 841 / 927 MB. There seems to be a memory leak somewhere... and the unresponsiveness happens when the Pi is in a low free memory state.

When I exit the program from the command line the memory is freed back up to 94 / 927 MB in use.

The REPL code has the same leaky memory behavior. When running the code from the command line. The program becomes unresponsive when ~500 MB memory is in use.

This was run on the Raspberry Pi with Samba disabled.

I think the board.on() function is likely causing the problem. Or perhaps how the raspi-io plug-in is interfacing with the board.on() function.

```const five = require('johnny-five')
const board = new five.Board({ io: new raspio() })

board.on('ready', function() { // Can't use anonymous function with 'this' keyword
let led = new five.Led('P1-16') // Create an Led on pin 13
let led2 = new five.Led('P1-18') // Create an Led on pin 13

this.repl.inject({
led: led,
led2: led2
})

})

I was doing some performance testing just the other day and memory usage was stable around ~400mb after 5 minutes, so it's not as simple as being an issue with board.on.

Can you answer/confirm the following:

  • Are you running Raspbian or Raspbian lite?
  • If you sudo apt-get remove samba, do you see the same behavior?
  • Do you see the same behavior when running the application normally outside of nodemon?
  • When you run the code listed in https://github.com/rwaldron/johnny-five/issues/1504#issuecomment-421067686 and _only that code_, do you see the memory leak?
  • When you exit the above application, via ctrl+c or other mechanism, does the memory usage drop back down to normal?
  1. OS Version
    NAME="Raspbian GNU/Linux"
    VERSION_ID="9"
    VERSION="9 (stretch)"

  2. I get this behavior when running directly on the Raspberry Pi without Samba.

  3. Yes, I see the same behavior when running just with sudo node app.js

  4. Yes, the code run with sudo node app.js is from #1504.

  5. Yes, when I exit the application the memory is released, and drops to 65 - 90 MB from peak ~810 MB.

More notes:

Node version 8.11.4
Raspberry Pi B+
Processor model name: ARMv7 Processor rev 4 (v71)

Raspberry Pi hooked up to ethernet
Raspberry Pi hooked up to external keyboard
Raspberry Pi connect to 7" touch interface via ribbon cable.
20 GPIO pins are wired to a breakout relay switch
4 GPIO pins are wired to a breakout INA219

Can you let me know if you're running Raspbian or Raspbian Lite? (this information isn't included in the above).

How can I check?

I got the OS version above from running cat /etc/os-release

lsb_release -a returns

Distributor ID: Raspbian
Description: Raspbian GNU/Linux 9.4 (stretch)
Release: 9.4
Codename: stretch

Based on this post: https://medium.com/@timcase/raspbian-vs-raspbian-lite-8fa54cc79805

I think I have the full version of Raspbian since the install included Libre Office, Wolfram, etc.

Rebuilding the Express architecture with rpio (https://www.npmjs.com/package/rpio)

  • When running directly on the Pi the app is stable at 107 MB / 927 MB
  • When running via ssh and connected with Samba the app is stable at 108 / 927 MB

How can I check?

Normally I just know myself, since you have to select it when you download the OS from rasbian.org. Do you have a GUI? If so, then it's the full version. If not, it's the Lite version.

I'm glad you got it working with rpio!

Yes, I have a GUI - it's running connected to a 7" touchscreen.

It's the full version then. I'm not saying this is the issue to the memory leak you noticed, but generally speaking it's a good idea to run the Lite version of Raspbian unless you definitely _need_ a GUI. It saves a lot on system resources.

Yes. I am new to Raspberry Pi, so the GUI is nice for debugging...

Check out my guide to debugging at https://github.com/nebrius/raspi-io/wiki/Getting-a-Raspberry-Pi-ready-for-NodeBots#debugging-your-code. You don't have to use the GUI to get full visual debugging in an IDE ;-)

That looks like very nice work!

The GUI is nice for continuous polling of CPU and memory usage, and is doubling as a graphical controller (touch buttons) for the API...

Note that you can use the command-line top command to also get continuous polling of CPU and memory usage.

UI for the app is usually what I classify as "need" though for a GUI

Awesome. Thanks for the tip!

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

IainIsCreative picture IainIsCreative  路  10Comments

cannehag picture cannehag  路  12Comments

ntatko picture ntatko  路  11Comments

danielhep picture danielhep  路  4Comments

peetj picture peetj  路  7Comments