我一直在为Raspberry Pi编写一个简单的Clojure框架,用于播放音乐(以及后来的其他内容)。该程序解析给定音乐目录中的歌曲,然后开始通过TCP接口(interface)监听控制命令(例如开始,停止,下一首歌曲)。

该代码可通过GitHub获得:
https://github.com/jvnn/raspi-framework

当前版本可以在我的笔记本电脑上正常工作,可以在得到指示时开始播放音乐(使用JLayer库),更改歌曲并按应有的方式停止播放。 uberjar也需要花费几秒钟才能在笔记本电脑上启动,但是当我尝试在Raspberry Pi上运行它时,事情变得异常缓慢。

只需启动程序,以便加载所有类并开始执行实际的程序代码,需要一分钟的时间。我试图用-verbose:class开关运行它,看来jvm花费了整个时间来加载大量的类(对于Clojure和其他所有东西)。

当程序最终启动时,它确实会响应给定的命令,但是播放非常缓慢。会发出一秒钟以下的声音,然后停顿将近一秒钟,然后发出另一个声音,再出现一次暂停等。因此,该程序正在尝试播放某些内容,但它做得不够快。 CPU使用率接近98%。

现在,有了Android手机和其他所有设备,我相信Java可以在这样的硬件上很好地执行,从而可以播放一些mp3文件而没有任何麻烦。而且我知道在gdx游戏开发框架(也可以在Android中运行)中使用了JLayer(或它的一部分),所以也不应该成为问题。

所以一切都说明我是问题所在。我可以使用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))))

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)

因此,没有core.async也没有线程。播放确实更流畅了一些,但仍然是大约200毫秒的音乐和200毫秒的暂停时间。

最佳答案

对我而言,最明显的是,您有许多未提示的互操作代码,从而导致非常昂贵的运行时反射。尝试运行lein check(我认为它是内置的,但也许您需要一个插件)并修复其指出的反射问题。

10-07 19:27
查看更多