Я писал простую основу Clojure для воспроизведения музыки (а затем и некоторых других вещей) для моей малины Pi. Программа анализирует данный музыкальный каталог для композиций, а затем начинает прослушивание команд управления (таких как запуск, остановка, следующая песня) через интерфейс TCP.Почему мой проект Clojure медленный на малине Pi?
код доступен через GitHub: https://github.com/jvnn/raspi-framework
Текущая версия прекрасно работает на моем ноутбуке, он начинает играть музыку (с помощью библиотеки JLayer), когда проинструктированы, изменяет песни, и останавливается, как должно , Убержар занимает несколько секунд, чтобы начать работу с ноутбуком, но когда я пытаюсь запустить его на малиновом Pi, все становится безумно медленным.
Просто запустите программу, чтобы все классы были загружены, а фактический программный код начинает выполняться более чем через минуту. Я попытался запустить его с помощью переключателя -verbose: class, и кажется, что jvm тратит все время, просто загружая тонны классов (для Clojure и всего остального).
Когда программа, наконец, начинается, она реагирует на приведенные команды, но воспроизведение очень лаги. Существует короткий субсекундный звук, затем пауза в течение почти секунды, затем другой звук, другая пауза и т. Д. Итак, программа пытается что-то сыграть, но просто не может сделать это достаточно быстро. Использование процессора где-то близко к 98%.
Теперь, имея телефон Android и все, я уверен, что Java может быть выполнен на таком оборудовании достаточно хорошо, чтобы воспроизводить некоторые mp3-файлы без каких-либо проблем. И я знаю, что JLayer (или его части) используется в платформе разработки игр gdx (которая также работает на Android), поэтому это тоже не должно быть проблемой.
Так что все указывает на то, что я являюсь проблемой. Есть ли что-то, что я могу сделать с leiningen (aot уже включен для всех файлов), Raspberry Pi или мой код, который может ускорить работу?
Спасибо за ваше время!
UPDATE: Я сделал крошечный тест, чтобы исключить некоторые возможности и проблемы все еще существуют со следующим кодом 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 мс.
Я думаю, что это может быть связано с меньшим размером кеша на процессоре pi. Clojure велик, но идиоматический Clojure гораздо более требователен с точки зрения сбоя кеша, чем большинство других языков (в частности, из-за его интенсивного использования неизменяемых структур данных). – noisesmith
Я думаю, что это не объяснит проблемы с воспроизведением (и не очень медленное время запуска, как я предполагаю). Поскольку (по крайней мере, если код работает так, как я имел в виду, что он работает) во время воспроизведения, который обрабатывается библиотекой java, весь код Clojure должен стоять на стоянке и ждать ввода асинхронного канала. –
Эта парковка, вероятно, связана с переключением контекста. Переключение контекста разбивает ваш кеш, что дорого (особенно с медленной шиной).Когда у вас есть медиапоток, который поступает непосредственно из ОЗУ (или даже диска) в устройство вывода без изменений, то, что пропускает его, - это переключение контекста, и чем больше кеша требуется контекстному коммутатору, тем более экстремальные проблемы пропуска будет. – noisesmith