Готов ли achartengine для построения графиков в реальном времени?

Я пытаюсь отобразить некоторые данные в реальном времени, "реальное время" здесь означает данные < 10 мс, в идеале как можно меньше. Я смог заставить Android извлекать и обрабатывать данные так быстро, но ACE выглядит так, будто он не предназначен для использования в реальном времени. Первые признаки - сборщик мусора, как будто нет завтрашнего дня и полностью убивает приложение. Я визуализирую данные в режиме "скользящего окна", поэтому я не ожидаю, что ACE построит в реальном времени сотни тысячных точек. Я взглянул на это, и onDraw для XYChart определенно выделяется очень сильно в тех случаях, когда это выглядит удобным, и, вероятно, делает код намного более читабельным, но на самом деле не обязательным. Это может быть даже хуже, чем раньше, поэтому, возможно, это еще не было замечено. Я увидел, что исправление ошибки #225 решило проблему с параллелизмом:

return mXY.subMap(start, stop);

за:

return new TreeMap<Double, Double>(mXY.subMap(start, stop));

Это создает огромные выделения (все еще поддерживаемые исходной subMap, хотя), когда, вероятно, было бы лучше ставить обновления в очередь, когда происходит onDraw, и обрабатывать их позже при атомарных обновлениях или что-то в этой строке, чтобы избежать проблем параллелизма.

Жаль, что ACE достаточно быстр для того, что мне нужно. Он может делать то, что мне нужно, на моем HW отлично, но так как он так сильно выделяется на перекрашивание Android сходит с ума от GC. Вскоре он начинает распределяться, пока GC работает, поэтому ему приходится ждать, и мое приложение начинает выглядеть как фильм с замедленным движением.

Однако реальный вопрос заключается в следующем: разумно ли ожидать возможности перерисовывать 4 или 6 линейных диаграмм (приложение для планшета) в режиме реального времени (частота обновления менее 200 мс) с помощью ACE или это просто не подготовлено для такого рода злоупотреблений? Если ответ нет. Какие-нибудь другие варианты вы бы порекомендовали?

РЕДАКТИРОВАТЬ 20130109: Revision 471 значительно улучшает вещи для небольших наборов данных. 2.000 точек / 4 графика / частота обновления 100 мс - выполнимо и плавно. Журналы по-прежнему видят, что "GC_CONCURRENT освобожден" как сумасшедший (около 10/ сек), но нет "WAIT_FOR_CONCURRENT_GC заблокирован", что является демонстрацией того, что делает ваше приложение остановленным. При 3.000 точках / 1 графике / 100 мсек это явно не гладко. Мы снова получаем лавину "WAIT_FOR_CONCURRENT_GC заблокирован" на logcat и в приложении заикания. Опять же, похоже, что у нас нет проблем со скоростью, только проблема с управлением памятью.

Может показаться, что я просил ACE творить чудеса, но я ударил эту стену после рефакторинга всего своего кода для извлечения и сохранения данных телеметрии с частотой 1 кГц. Когда я наконец увидел, что мое приложение извлекает и хранит все это в реальном времени, не вызывая GC, я попытался построить ACE, пытаясь построить график:)

3 ответа

Решение

После больших усилий по оптимизации всего остального в моем приложении, я все еще не могу заставить его отображать то, что я понимаю для "реального времени". Библиотека отличная и очень быстрая, но способ, которым каждый onDraw выделяет память, неизбежно вызывает лавину сборки мусора, которая сталкивается с ее собственным распределением и, таким образом, android замораживает ваше приложение на мгновение, вызывая заикание, которое полностью несовместимо с графикой в ​​реальном времени. Здесь "заикание" может варьироваться от 50 до 250 мс (да, миллисекунды), но этого достаточно, чтобы убить приложение реального времени.

AChartengine позволит вам создавать "динамические" графики, если вам не требуется, чтобы они были "в реальном времени" (10 кадров в секунду (частота обновления<100 мс) или то, что вы бы назвали "плавным").

Если кому-то нужна дополнительная информация об основной проблеме здесь, или почему я говорю, что библиотека достаточно быстра, но шаблоны распределения памяти в конечном итоге вызывают проблемы с производительностью, взгляните на Google I/O 2009 - Написание игр в реальном времени для Android

Прежде всего, спасибо за отличный вопрос и за вопрос, который вы подняли. Вы были совершенно правы в отношении огромного выделения памяти, которое было сделано в рамках onDraw() метод. Я исправил это и проверил код в SVN. Я также добавил синхронизированный блок внутри onDraw() такой метод, как мы надеемся, не бросит ConcurrentModificationException при добавлении новых данных в набор данных при перерисовках.

Пожалуйста, извлеките код из SVN и выполните ant dist, чтобы создать новый файл Jar AChartEngine и внедрить его в свое приложение. Пожалуйста, смотрите инструкции здесь.

Чтобы ответить на ваш вопрос: AChartEngine определенно готов к динамическому построению графиков. Проблема, о которой вы сообщили, была выставочной заглушкой, но она должна быть исправлена ​​сейчас. Я написал динамические диаграммы, используя его. Однако вам необходимо убедиться, что вы не добавили 100000 значений данных в наборы данных. Старые данные могут быть удалены из наборов данных для повышения производительности.

Разумно рисовать 5 или около того линейных графиков, если они имеют до нескольких тысячных точек.

Итак, после некоторого времени поиска другой графической библиотеки я не нашел ничего достаточно хорошего:) Это заставило меня снова взглянуть на ACE, и в итоге я сделал небольшой патч, который делает его "полезным" для меня, хотя и далеко от идеального.

На XYSeries.java я добавил новый метод:

/**
* Removes the first value from the series.
* Useful for sliding, realtime graphs where a standard remove takes up too much time.
* It assumes data is sorted on the key value (X component).
*/
public synchronized void removeFirst() {
  mXY.removeByIndex(0);
  mMinX = mXY.getXByIndex(0);
}    

Я обнаружил, что помимо проблем с памятью возникают проблемы с реальной скоростью на высокой скорости. Я тратил около 90% времени на функцию удаления, поскольку удалял точки, которые прокручивались вне поля зрения. Причина в том, что при удалении точки минимальной / максимальной точки ACE вызывает метод InitRange, который выполняет итерацию по каждой точке, чтобы пересчитать те минимальные / максимальные точки, которые он использует внутри. Так как я обрабатываю 1000 кадров телеметрии в секунду и у меня небольшой видовой экран (что вызвано стратегиями распределения памяти ACE), я очень часто бью мин / макс точки в функции удаления. Я создал новый метод, используемый для удаления первой точки ряда, который обычно вызывается, как только вы добавляете точку, которая делает эту прокрутку из области просмотра. Если ваши точки отсортированы по значению ключа (классическая серия dateTime), тогда мы можем настроить mMinX, чтобы область просмотра по-прежнему выглядела хорошо и делала это очень быстро. Мы не можем обновлять minY или maxY быстро с текущей реализацией ACE (хотя я и не рассматривал ее), но если вы установите соответствующий начальный диапазон, это может не потребоваться. Фактически я вручную настраиваю диапазон время от времени, используя дополнительную информацию, которая у меня есть, потому что я знаю, что я строю, и каковы нормальные диапазоны в разные моменты времени.

Таким образом, это может быть достаточно для кого-то другого, но я настаиваю на том, что рефакторинг выделения памяти все еще требуется для ACE для любого серьезного отображения в реальном времени.

Другие вопросы по тегам