我一直在为我的 Raspberry Pi 编写一个简单的 Clojure 框架来播放音乐(以及后来的一些其他东西)。该程序解析给定的音乐目录中的歌曲,然后通过 TCP 接口(interface)开始监听控制命令(例如开始、停止、下一首歌曲)。
该代码可通过 GitHub 获得:
https://github.com/jvnn/raspi-framework
当前版本在我的笔记本电脑上运行良好,它在收到指示时开始播放音乐(使用 JLayer 库),更改歌曲,然后按原样停止。 uberjar 在笔记本电脑上也需要几秒钟才能启动,但是当我尝试在 Raspberry Pi 上运行它时,事情变得异常缓慢。
只需启动程序以加载所有类并开始执行实际程序代码就需要一分钟多的时间。我尝试使用 -verbose:class 开关运行它,似乎 jvm 整个时间都在加载大量的类(对于 Clojure 和其他所有内容)。
当程序最终启动时,它确实会对给定的命令使用react,但播放非常滞后。有一个亚秒级的短声,然后是几乎一秒钟的停顿,然后是另一个声音,另一个停顿等等......所以程序正在尝试播放一些东西,但它做的不够快。 CPU 使用率接近 98%。
现在,有了 Android 手机和所有设备,我确信 Java 可以在这样的硬件上很好地执行,可以毫无问题地播放一些 mp3 文件。而且我知道 JLayer(或其中的一部分)用于 gdx 游戏开发框架(也可以在 Android 上运行),所以它也不应该成为问题。
所以一切都指向我是问题所在。我可以用 leiningen(所有文件都已启用 aot)、Raspberry Pi 或我的代码做些什么来让事情变得更快吗?
谢谢你的时间!
更新:
我做了一个小测试用例来排除一些可能性,但以下 Clojure 代码仍然存在问题:
(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))))
项目.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)
所以,没有 core.async 也没有线程。播放确实变得更流畅了,但仍然是大约 200 毫秒的音乐和 200 毫秒的暂停。
最佳答案
对我来说最明显的是你有很多没有提示的互操作代码,导致非常昂贵的运行时反射。尝试运行 lein check
(我认为这是内置的,但也许你需要一个插件)并修复它指出的反射问题。
关于audio - 为什么我的 Clojure 项目在 Raspberry Pi 上运行缓慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21706497/