Why is my Clojure project slow on Raspberry Pi?

audio, clojure, raspberry-pi

Solution

Most obvious to me is that you have a lot of un-hinted interop code, leading to very expensive runtime reflection. Try running `lein check` (I think that's built in, but maybe you need a plugin) and fixing the reflection issues it points out.

Problem

I've been writing a simple Clojure framework for playing music (and later some other stuff) for my Raspberry Pi. The program parses a given music directory for songs and then starts listening for control commands (such as start, stop, next song) via a TCP interface. The code is available via GitHub: https://github.com/jvnn/raspi-framework The current version works just fine on my laptop, it starts playing music (using the JLayer library) when instructed to, changes songs, and stops just as it should. The uberjar takes a few seconds to start on the laptop as well, but when I try to run it on the Raspberry Pi, things get insanely slow. Just starting up the program so that all classes are loaded and the actual program code starts executing takes way over a minute. I tried to run it with the -verbose:class switch, and it seems the jvm spends the whole time just loading tons of classes (for Clojure and everything else). When the program finally starts, it does react to the commands given, but the playback is very laggy. There is a short sub-second sound, then a pause for almost a second, then another sound, another pause etc... So the program is trying to play something but it just can't do it fast enough. CPU usage is somewhere close to 98%. Now, having an Android phone and all, I'm sure Java can be executed on such hardware well enough to play some mp3 files without any troubles. And I know that JLayer (or parts of it) is used in the gdx game development framework (that also runs on Android) so it shouldn't be a problem either. So everything points in me being the problem. Is there something I can do either with leiningen (aot is already enabled for all files), the Raspberry Pi, or my code that could make things faster? Thanks for your time! UPDATE: I made a tiny test case to rule out some possibilities and the problems still exist with the following Clojure code: ``` (ns test.core (:import [javazoom.jl.player.advanced AdvancedPlayer]) (:gen-class)) (defn -main [] (let [filename "/path/to/a/music/file.mp3" fis (java.io.FileInputStream. filename) bis (java.io.BufferedInputStream. fis) player (AdvancedPlayer. bis)] (doto player (.play) (.close)))) ``` The project.clj: ``` (defproject test "0.0.1-SNAPSHOT" :description "FIXME: write description" :dependencies [[org.clojure/clojure "1.5.1"] [javazoom/jlayer "1.0.1"]] :javac-options ["-target" "1.6" "-source" "1.6" "-Xlint:-options"] :aot :all :main test.core) ``` So, no core.async and no threading. The playback did get a bit smoother, but it's still about 200ms music and 200ms pause.

Original source