Audio 为什么我的Clojure项目在Raspberry Pi上进展缓慢?

Audio 为什么我的Clojure项目在Raspberry Pi上进展缓慢?,audio,clojure,raspberry-pi,Audio,Clojure,Raspberry Pi,我一直在为我的Raspberry Pi编写一个简单的Clojure框架,用于播放音乐(后来还有其他东西)。程序解析给定音乐目录中的歌曲,然后通过TCP接口开始监听控制命令(如开始、停止、下一首歌曲) 代码可通过GitHub获得: 当前版本在我的笔记本电脑上运行良好,它在接到指示时开始播放音乐(使用JLayer库),更改歌曲,并按其应有的方式停止播放。uberjar也需要几秒钟才能在笔记本电脑上启动,但当我尝试在Raspberry Pi上运行它时,速度会变得异常缓慢 只需启动程序,以便加载所有类

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

代码可通过GitHub获得:

当前版本在我的笔记本电脑上运行良好,它在接到指示时开始播放音乐(使用JLayer库),更改歌曲,并按其应有的方式停止播放。uberjar也需要几秒钟才能在笔记本电脑上启动,但当我尝试在Raspberry Pi上运行它时,速度会变得异常缓慢

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

当程序最终启动时,它确实会对给定的命令做出反应,但播放非常缓慢。有一个短的亚秒的声音,然后是一个停顿几乎一秒钟,然后是另一个声音,另一个停顿等等。。。因此,该程序试图播放一些内容,但速度不够快。CPU使用率接近98%

现在,有了安卓手机,我相信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))))
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
(我认为这是内置的,但可能需要一个插件)并修复它指出的反射问题。

谢谢您的回答。lein check没有告诉我任何事情,唯一的输出是“编译名称空间…”。但我想,即使反射会使程序在运行时变慢,也不能成为启动时间过长的原因?重新启动时间…Clojure很大,raspberry pi很小。如果您在启动时看到大量时间花在加载类上,那可能是因为有很多类要加载。我想你的jar文件是相当大的,与pi想要看到的相比。好吧,这是我害怕听到的。我希望可以做一些事情(优化、不同的java版本等),使事情变得更好。我认为这可能与pi的CPU上较小的缓存大小有关。Clojure很棒,但是惯用Clojure在缓存搅动方面比大多数其他语言要求更高(特别是因为它大量使用不可变的数据结构)。我认为这并不能解释播放问题(我猜也不能解释启动时间太慢)。因为在java库处理的回放过程中(至少如果代码像我想的那样工作),所有Clojure代码都应该停驻并等待异步通道输入。停驻可能涉及一些上下文切换。上下文切换会破坏缓存,这非常昂贵(尤其是在总线速度较慢的情况下)。一旦你有一个媒体流直接从RAM(甚至是磁盘)传输到输出设备而无需修改,它就会跳过上下文切换,而上下文切换需要的缓存越多,跳过问题就越严重。我用一个最小的测试用例更新了这个问题。我添加的代码现在是唯一正在进行的事情,但它仍然很不顺利。我还通过使用gstreamer播放音乐文件来检查sound是否在Pi上工作,并且没有问题。如果代码跳过,那么问题要么是javazoom类,要么是JVM。我正在写一个答案,但是我查看了javazoom文档,没有找到输出设备上缓冲区大小的选项。如果它不允许您调整缓冲区大小,那么您应该使用另一个库(考虑到代码的精简程度,我看不出除了更改输出缓冲区大小之外还有什么可以提高性能)。