Charts: Улучшения производительности

Созданный на 14 апр. 2015  ·  44Комментарии  ·  Источник: danielgindi/Charts

Есть ли планы улучшить производительность библиотеки так, как это сделал Филипп с MPAndroidCharts?
Благодаря его улучшениям теперь можно без проблем отображать тысячи точек данных на Android.
Я бегло ознакомился с реализацией ios-charts, и из того, что я видел, она основана на исходной реализации MPAndroidCharts без последних улучшений производительности.

То, что он будет отображать тысячи точек, будет ОГРОМНЫМ плюсом для библиотеки, поскольку он фактически сделает все коммерческие версии бесполезными (большинство из которых в любом случае являются пустой тратой времени и денег).

enhancement help wanted

Самый полезный комментарий

Я загружаю более 13000 записей в линейные диаграммы для iOS. Но графики замораживают пользовательский интерфейс во время загрузки. Кроме того, после загрузки. Если пользователь выбирает какую-либо точку, то также требуется слишком много времени, чтобы выделить выделение.

Все 44 Комментарий

Первоначальным узким местом производительности в версии Android было множество дополнительных распределений (массивов) внутри кода рендеринга. Память не должна выделяться внутри кода рендеринга. Итак, @PhilJay переместил этот код в буфер, который предварительно выделен, и делегировал вычисления рендеринга классам буфера во время рендеринга.

Я решил не переносить вычисления рендеринга в классы Buffer, а просто заранее выделить необходимую память таким же образом, но выполнял вычисления рендеринга в том же цикле, что и код рендеринга. Таким образом намного проще управлять кодом.

Также повышение производительности заключается в том, что вычисления рендеринга не выполняются внутри дополнительных функций, и данные зацикливаются внутри кода рендеринга только один раз, а не дважды.

Кстати, в Swift производительность НАМНОГО лучше, чем у Java, так что вы могли бы увидеть такой прирост производительности даже без предварительного выделения этих массивов.

Чтобы наглядно объяснить это, вот что / делалось в коде рендеринга:

  • [НАЧАТЬ ПРЕДСТАВЛЕНИЕ]
  • Цикл по DataSets
  • - Выделить массив для точек этого DataSet - Теперь предварительно выделен на обеих платформах
  • - Расчет точек для рендеринга - _Перенос в буферы в версии Android_
  • - Визуализируйте эти точки
  • [ЗАВЕРШИТЬ ПРЕДОСТАВЛЕНИЕ]

Также обратите внимание, что в Java абстракции (функции, классы, наследование) имеют большую цену. Недаром сам Google написал важную рекомендацию :

Be careful with code abstractions

Often, developers use abstractions simply as a "good programming practice," 
because abstractions can improve code flexibility and maintenance. 
However, abstractions come at a significant cost: 
    generally they require a fair amount more code that needs to be executed, 
requiring more time and more RAM for that code to be mapped into memory. 
So if your abstractions aren't supplying a significant benefit, you should avoid them.

Подводя итоги:

  • Вы можете комфортно работать с тысячами точек данных!
  • Я пытаюсь убедить Фила перенести точечные вычисления обратно в циклы рендеринга, чтобы их было проще поддерживать ;-)

Спасибо за объяснения, Даниэль. Однако я не совсем уверен, что из этого извлечь.
Что я сделал, так это настроил самый простой проект (см. Код ниже), и производительность не сравнима с версией Android, даже близко, чтобы быть полностью честной. Использование тысячи точек данных приводит к огромному количеству кадров, когда вы приближаетесь к отображению максимального количества точек данных (полное уменьшение масштаба) даже на большинстве современных устройств iOS, таких как iPad Mini3 и iPhone6. Как я уже сказал, MPAndroidcharts может визуализировать несколько тысяч на гораздо более медленных устройствах, не беспокоясь.

переопределить функцию viewDidLoad () {
super.viewDidLoad ()

    lineChart = LineChartView(frame: view.frame);
    view.addSubview(lineChart);
    lineChart.backgroundColor = UIColor.whiteColor()
    lineChart.descriptionText = "Just a test"
    lineChart.leftAxis.enabled = false
    lineChart.legend.enabled = false

    setData(20)
}

func setData(range:Float) {

    var count = 1000;
    var xVals = Array<String>();

    for(var i = 0; i<count; i++) {
        xVals.append(String(i) + "");
    }

    var yVals = Array<ChartDataEntry>();

    for (var i = 0; i<count; i++) {
        var mult = range + 1
        var val:Float = Float(random()) * mult + 3;
        yVals.append(ChartDataEntry(value: val, xIndex: i));
    }

    var lineSet:LineChartDataSet = LineChartDataSet(yVals: yVals, label: " ");
    lineSet.drawCirclesEnabled = false;
    lineSet.drawValuesEnabled = false;

    var lineData:LineChartData = LineChartData(xVals: xVals, dataSet: lineSet);
    lineChart.data = lineData;
}

Что ж, я еще не тестировал все графики на производительность, поэтому мне нужно сделать это в ближайшее время.
Узкое место , вероятно, связано с выделением памяти, которое я где-то упустил ... Я протестирую и дам вам знать! :-)

Большое спасибо, Даниэль. С нетерпением жду того, что из этого можно выжать. Было бы здорово иметь надежного компаньона для MPAndroidCharts на iOS.

Что ж, я немного поигрался с LineChartRenderer (который особенно медленный по сравнению, например, с BarChartRenderer), и Instruments говорит, что в этом виноват drawPath CGContext.
Я попытался смягчить эту проблему, используя вместо этого UIBezierPath, но производительность такая же, как только вы вызываете stroke () на пути. До этого производительность рисования была отличной, но путь заполнен относительно начальной и конечной точки, а не того, что мы хотели бы для простой линейной диаграммы.
Надеюсь, вам повезло найти решение этой проблемы.

Я тестирую это прямо сейчас, и да, похоже, что реальный CGContextStrokePath страдает от низкой производительности.
Пунктирная линия - одно из главных попаданий. При его отключении производительность ~ удваивается. Но с тысячей баллов он все еще оставляет желать лучшего.
Я читаю документацию Apple, чтобы узнать, как сделать CoreGraphics быстрее.

Да, Core Graphics определенно отрисовывает пути медленно. Похоже, это происходит из-за разрешения - разрешение на новых устройствах Apple очень высокое, а это означает, что нужно отрисовывать больше пикселей.

Я думаю, что CG отрисовывает на CPU, а не на GPU. Может быть, кто-нибудь знает, как это изменить?

CG определенно использует CPU для рендеринга, и, насколько я знаю, это никак нельзя изменить.
К сожалению, рендеринг на GPU означал бы использование OpenGL. Обидно, что CG такая медленная по сравнению с тем, как Android отрисовывает все это на CPU.

На самом деле медленные процессоры устройств. В большинстве случаев очень медленный
ЦП обеспечивает гораздо лучший опыт работы с iOS, чем быстрый ЦП с Android.

Но Apple не задумывалась о случаях, когда оптимальная ОС не подходит.
достаточно, чтобы держать это быстро.

Я полагаю, что когда мы используем много очков, мы можем просто избежать анимации - Но
Я все еще надеюсь найти способ улучшить производительность Line
графики на основе.

Кажется, что именно система рисования пути медленная, а когда
играть с Mitre и Flatness и отключать пунктирные линии и
Сглаживание - производительность становится намного лучше на 500-700 баллов на
iPhone 6, но все еще Jerky с 1000

Возможно, есть шанс использовать UIBezierPath. Как я уже сказал, эта вещь выполняется достаточно быстро, если вы не вызываете «штрих», который, по сути, сообщает системе, что путь является штрихом и не должен заполняться от начальной до конечной точки. Я понятия не имею, что с этим происходит в фоновом режиме, но это показывает, что сам по себе отрисовка графика не является проблемой.

Однако, поскольку я не смог найти способ правильно использовать UIBezierPath для линейной диаграммы, он мог бы быть жизнеспособным кандидатом для линий сетки, поскольку можно было бы обмануть путь для рисования без вызова stroke. Даже если это «неправильно» с точки зрения API, производительность должна повыситься.

UIBezierPath - это просто оболочка UIKit вокруг CGPath, CGContextDrawPath,
и т.п.
Разница в производительности, которая наблюдается в некоторых случаях, связана с
сначала настраивая CG, используя свойства UIBezierPath:
сглаживание, ограничение митры и т. д.

На самом деле нет абсолютно никаких причин использовать его, если вы знаете, как использовать
Основная графика.

И да, нам нужно вызвать «штрих», поскольку мы действительно хотим обвести этот путь ...
не заливать.
Поглаживание в большинстве случаев сложнее для системы, чем заливка сплошным
цвет, потому что нужно позаботиться о ширине линий, стыки
между линиями и формой стыков.

В пятницу, 17 апреля 2015 г., в 10:50, AlBirdie [email protected] написал:

Возможно, есть шанс использовать UIBezierPath. Как я уже сказал, эта вещь
достаточно быстро, как только вы не называете «инсульт», что по существу
сообщает системе, что путь представляет собой обводку и не должен заполняться из
от начальной точки до конечной. Я понятия не имею, что с этим происходит в
фон, но это показывает, что сам рисунок графика не
вопрос сам по себе.

Однако, поскольку я не смог найти способ правильно использовать UIBezierPath для
линейный график, это может быть жизнеспособным кандидатом для линий сетки как один
может обмануть путь для рисования, не вызывая штрих. Хотя это
«неправильный» с точки зрения API, он должен обеспечить лучшую производительность.

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/danielgindi/ios-charts/issues/29#issuecomment -93937181
.

@danielgindi , думали ли вы о том, что если анимация замедляет работу, как насчет того, чтобы нарисовать все линии без анимации и использовать маску, покрывающую ее, а затем анимировать маску, чтобы имитировать анимацию?

Что ж, отличная идея! :)

Хотя есть и обратная сторона:
Это испортит анимацию, которую вы можете с ним делать. как мы позволяем
анимация оси Y таким образом, чтобы диаграмма "увеличивалась", а также то, как линия заполняется
по оси X также отличается от обычного штриха.

Мой список вещей, которые стоит попробовать:

  1. Как-то улучшить CoreGraphics или поднять часть рендеринга до
    GPU

    1. Предварительный рендеринг всех кадров анимации - это задержит запуск анимации и

      потребляют значительный объем памяти

    2. Ваша идея маскировки, которая ограничивает виды анимации

Если есть другие идеи, я бы хотел их услышать!

Даниэль, вы еще не пробовали переложить работу на GPU?
Я очень, очень недоволен коммерческим решением, с которым мы сейчас работаем (ужасный API, ужасно закрытый, и множество ошибок, которые вызывают сбои приложения), и, имея такой большой успех с MPAndroidCharts, мы хотели бы переключиться на iOS-графики в конечном итоге, если производительность будет на уровне. Будьте уверены, ваша работа будет вознаграждена. ;)

Попробовав несколько разных техник, я дам вам обновленную информацию через несколько дней!

В понедельник, 20 апреля 2015 г., в 12:38 AlBirdie [email protected] написал:

Даниэль, вы еще не пробовали переложить работу на GPU?
Я очень, очень недоволен коммерческим решением, которое мы сейчас используем.
работа с (ужасным API, ужасно закрытым и множеством ошибок, которые вызывают
приложение к сбою), и, добившись такого большого успеха с MPAndroidCharts, мы
Люблю со временем переходить на iOS-графики, если производительность будет на уровне. Отдых
уверен, ваш труд будет вознагражден. ;)

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/danielgindi/ios-charts/issues/29#issuecomment -94408574
.

@AlBirdie, с каким узким местом вы столкнулись? В настоящее время у меня есть продукт, который рисует диаграммы так же, как диаграммы ios, у нас уже была внутренняя библиотека диаграмм. Меня также беспокоит производительность, в настоящее время мы просто загружаем 100-1000 наборов данных, сейчас все в порядке.

Я также подумываю о переходе на ios-charts, если это возможно в будущем, но в нашей библиотеке были жесты, которые могли конфликтовать с ios-charts.

Проблема с производительностью - низкая частота кадров в анимации при необходимости
нарисуйте 500-1000 линий на линейном графике.

Что касается жестов - мы используем стандартные UIGestureRecognizers, которые вы
можно отключать, изменять или работать с. Все стандартизировано. :-)

В понедельник, 20 апреля 2015 г., в 12:53 Сюань [email protected] написал:

@AlBirdie https://github.com/AlBirdie какая производительность
узкое место вы встретили? В настоящее время у меня есть продукт, который рисует только диаграммы.
как и ios-диаграммы, у нас уже была внутренняя библиотека диаграмм. Меня тоже беспокоит
насчет производительности, в настоящее время мы просто загружаем 100-1000 наборов данных, вроде нормально
сейчас.

Я также подумываю о переходе на ios-графики, если это возможно в будущем,
но в нашей библиотеке были жесты, которые могли конфликтовать с ios-диаграммами.

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/danielgindi/ios-charts/issues/29#issuecomment -94411060
.

@danielgindi ну, я думаю, мы используем представление маски, чтобы преодолеть анимацию ... Наша линейная диаграмма имеет слой градиента. В качестве вашей демонстрации ваша анимация может выполнять оба направления X + Y одновременно, в то время как мы делаем только направление X. Я не уверен, что трюк с маской может вам помочь.
Сейчас я думаю, что если бы у нас был вектор для описания вашего направления X + Y, возможно, есть шанс использовать трюк с маской ... с нетерпением жду ваших результатов!

@ liuxuan30 просто общая низкая производительность, я думаю. Анимация не проблема, потому что я с ней не работаю. Я работаю над финансовыми диаграммами, где вам нужно иметь несколько наборов данных на одной диаграмме (несколько акций + ряд индикаторов). Для диапазона данных из 250 элементов легко складывается до нескольких тысяч точек, которые необходимо визуализировать одновременно во время панорамирования и сжатия. Коммерческое решение, с которым я сейчас работаю, неплохо справляется с этим (с помощью OpenGL вы можете отображать тысячи точек без перегрузки процессора), но я не сторонник библиотек с закрытым исходным кодом, где вам нужно месяцами ждать исправления ошибок.
Мне было бы намного удобнее работать с ios-диаграммами, тем более что с API MPAndroidCharts просто невероятно легко работать.

Я вижу, финансовые данные - это катастрофа. Наш сервер заставляет просто отправлять до 1000 наборов данных на мобильное устройство, что снижает нашу перегрузку. Есть ли шанс использовать OpenGL для ios-графиков? @danielgindi

Поддержка OpenGL была бы козырной. На данный момент, вероятно, будет достаточно линейной диаграммы, отрендеренной графическим процессором.
К сожалению, я понятия не имею об OpenGL, иначе я был бы рад помочь.

В CGContextStrokeLineSegments есть улучшение по сравнению с использованием путей, поэтому вам следует попробовать это.
Все еще пытаюсь улучшить ситуацию другими способами :-)

Спасибо, Даниэль, я создам небольшое тестовое приложение, которое сравнивает две версии друг с другом, чтобы посмотреть, что к чему. Какой прирост производительности вы получили с помощью новых сегментов LineSegments?

@AlBirdie , чувствуете ли вы разницу с линейными сегментами?

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

Итак, во-первых, если вы отключите пунктирные линии на iOS, вы также получите значительный прирост!

Но я думаю, что действительно могу нарисовать его с помощью OpenGL ES на CIImage, но нужно быть очень осторожным, потому что, если одна строка GL запускается, когда приложение неактивно, она вылетает.

Также есть шанс, что я все еще могу разрешить тире путем предварительного рендеринга текстуры. Это потребует некоторой работы, и это не мой главный приоритет, но я начинаю побочный проект уровня OpenGL, который может легко заменить CGContext.

Вместо того, чтобы использовать OpenGL для рисования, вы также можете попробовать перейти на Core Animation. Может быть, класс CAShapeLayer сработает. Apple рекомендует использовать несколько CAShapeLayer при рендеринге сложного пути, поэтому вам может потребоваться разбить сегмент линии на несколько сегментов. Использование Core Animation должно переместить работу на GPU.

В течение многих лет в моей повседневной работе мы использовали коммерческий продукт, который, как отмечалось выше @AlBirdie, широко использует OpenGL и, таким образом, обходит CoreGraphics во всем, кроме аннотаций. Конечно, они, похоже, могут справиться с довольно большими наборами данных с довольно плавным рендерингом, и они утверждают, что для этого используют графический процессор. Однако их подход сопряжен с огромной головной болью, не в последнюю очередь с ошибками, которые они, по-видимому, не могут потрудиться исправить, такими как вызовы асинхронного рендеринга, которые дают сбой в OpenGL, когда приложение уходит в фоновый режим, идиотские структуры классов и безумные ограничения настраиваемости. То, что я хочу, сегодня не существует, но в iOS-Charts я вижу, что это может быть способ достичь этого. В любом случае, для меня надежность каждый раз побеждает производительность, но это с минимальным отрывом, и то, и другое очень важно.

ps на мой взгляд, пунктирные линии - это пережиток тех времен, когда на компьютерах не было возможности отображать в цвете или даже в оттенках серого - они не нужны, если мы не выполняем рендеринг в чисто черно-белый цвет и делаем что-то, что выглядит как старый Учебник высокой печати, не так ли? ;) Поэтому оптимизация для них гораздо менее важна, чем для общего случая с 10 тысячами баллов.

Абсолютно с вами @onlyforart по пунктирным линиям.
Учитывая ваше описание вашей коммерческой библиотеки диаграмм, мне интересно, использовали ли мы тот же продукт. :) Кстати, мы окончательно от этого отказались. На реализацию того, что мне потребовалось почти три месяца (даже этого было недостаточно, чтобы обойти серьезные ошибки и ограничения (например, перекрестие), с iOSCharts («идиотские структуры классов»;)) потребовалось всего две недели. Полная трата времени и денег.

@AlBirdie да, это тот самый. Даже не говоря уже о перекрестии. Сделано с использованием слишком большого количества ньюкаслского коричневого эля и, несомненно, нацелено на корпоративный рынок (где грубый API на самом деле является положительным фактором продаж, потому что он удерживает клиентов в дорогостоящем цикле поддержки / обслуживания). Вы знали историю этих парней? фактически (в своем глубоком прошлом) они были настоящими пионерами в индустрии программного обеспечения. В любом случае пора двигаться дальше и смотреть в будущее уже сейчас.
В основном мы рисуем графики свечей (это приложения для финансового сектора). Что мне действительно нужно для iOS и Android, так это то, что на самом деле очень просто с HighCharts / HighStock в мире HTML5 / Javascript:

  1. огромное количество точек данных (10К и более)
  2. автоматическое объединение данных OHLC в разумные масштабированные столбцы (например, отображение столбцов длительностью 1 час, если коэффициент масштабирования подходит, или столбцов 1 м или 1 с при уменьшении)
  3. плавное панорамирование и прокрутка
  4. ущипнуть, чтобы увеличить
  5. наложение нескольких серий данных, аннотаций и перекрестий, некоторые программно, а некоторые - при взаимодействии с пользователем, например, для установки предельной цены, все визуализируется плавно
  6. (вот кикер - HighStock с этим не помогает! хотя мне это кажется довольно очевидным) инкрементная выборка данных (с опережением), например, получение данных с низким разрешением для всего набора данных и, как и в случае с приложениями карт, получение высокого разрешения. данные (например, миллисекундные "тиковые" данные) только для просматриваемой области графика
    Мы еще не используем iOS-Charts, хотя они в моем списке дел и все ближе к вершине, поэтому я еще не так много заглядывал внутрь кода, но как только я это сделаю - вероятно, в следующем месяце - Я все это разберу.
    Вернемся к рендерингу: тенденция OpenGL давать сбой, если обстоятельства не идеальны, вызывает беспокойство. GLKit может помочь с отрисовкой на GPU; Некоторое время назад я также задавался вопросом, может ли SpriteKit помочь (рендеринг диаграмм - это не миллион миль от создания игр), но сейчас GLKit кажется лучшим кандидатом.

LOL @onlyforart , ты
Я нахожусь в той же лодке в отношении ваших требований (также работаю над финансовыми продуктами), но да, давайте вернемся к фактическому рисованию этих диаграмм. С нетерпением жду ваших открытий в будущем.

@onlyforart , @AlBirdie спасибо за понимание :-)

Действительно приятно видеть, как люди отказываются от коммерческих корпоративных продуктов в пользу нашей библиотеки, хотя мне жаль их ... Я в противоречии!

Я не решался позволить OpenGL иметь часть этого, потому что я знал, что возможны сбои, если он не управляется идеально, а это на самом деле невозможно в приложении UIKit. Если вы используете OpenGL для создания игры, все это - холст OpenGL, и вам не нужно беспокоиться о том, что вызов UIKit пытается вызвать рендеринг OpenGL в фоновом режиме.

@onlyforart ваша точка зрения о пунктирных линиях верна, но, к сожалению, у меня был опыт работы с клиентами, которые требовали пунктирных линий. Был случай на Android, когда для повышения производительности разработчик должен был изменить уровень на аппаратный уровень и сказал клиенту, что пунктирные линии станут сплошными линиями, это стоимость. И, конечно, есть возможность переместить весь код рисования в OpenGL, но тогда рисование одной линии - головная боль, но вы можете создать текстуру для пунктирной линии и работать с ней. Они не хотели платить за это, поэтому пунктирные линии, конечно, не были так критичны, но они наделали много шума по этому поводу.

На заметку: попробуйте использовать GLKit для рендеринга. Посмотри, что получится.

И если я возьму ваш список:

  1. _ "огромное количество точек данных (10К или более)" _ - мы работаем над этим :) Я не могу сказать об Android, так как перенос его на GL будет еще большим PITA, но он уже имеет довольно хорошую производительность благодаря используя аппаратный уровень, который делает все рисование на графическом процессоре.
  2. _ "автоматическое объединение данных OHLC в разумные масштабированные столбцы" _ - мы собираемся использовать фильтры аппроксимации очень скоро, так что я думаю, что это позаботится. Вместо того, чтобы иметь много 1-метровых полос, которые вы не можете прочитать, у вас будет приблизительная 1-часовая шкала и т. Д.
  3. _ "плавное панорамирование и прокрутка" _ - готово :-)
  4. _ "ущипнуть, чтобы увеличить" _ - готово :-)
  5. _ «наложение нескольких серий данных, аннотаций и перекрестия» _ - я не знаю, правильно ли я понимаю, но в настоящее время существует комбинированная диаграмма, которая может накладывать несколько типов диаграмм, и каждый тип диаграммы может принимать несколько наборов данных. Кроме того, вы всегда можете подключиться к ViewPortHandler и взять координаты, чтобы вы могли наложить все, что хотите, поверх символа.
  6. инкрементная выборка данных - мы планируем абстрагироваться от источника данных, сохраняя при этом старые API для установки статических наборов данных (это будет просто встроенный источник данных, который работает с ними). Я предполагаю, что это также будет соответствовать вашим требованиям, но мы пока не знаем, когда мы доберемся до этого

@danielgindi , не жалейте их. Если продукт, который вы разрабатываете, представляет собой тухлый помидор, но вы все равно взимаете за него серьезную плату, люди в конечном итоге перейдут на другой продукт. В этом нет ничего плохого. Я занимаюсь разработкой финансовых диаграмм в течение нескольких лет, использовал практически все решения для iOS, которые в настоящее время существуют, и фактически написал свой собственный механизм построения диаграмм на ActionScript3 еще в те дни, поэтому я чувствую себя довольно уверенно, говоря, что iOSCharts и MPAndroidCharts - фактически единственные продукты, которые я могу в настоящее время порекомендовать любому разработчику, которому нужны графики в своем приложении. Все остальное просто не подходит.

Что касается второго требования, если вы, ребята, собираетесь его реализовать, оно должно быть необязательным. У нас есть такая консолидация в одном из наших продуктов для построения графиков, и вместо этого клиенты неуклонно переходят на фиксированную частоту. Изменение частот во время масштабирования не только сбивало с толку среднего пользователя финансовых графиков, но и раздражало опытных пользователей, потому что им требовались фиксированные частоты.

Мы никогда не думали, что навязывают это пользователям! Вы можете видеть, что код уже включает фильтры, а в MPAndroidCharts вы можете увидеть, что исторически фильтры были включены с помощью свойства, устанавливающего фильтр (любой настраиваемый фильтр или встроенные фильтры), но впоследствии были удалены из-за структурных изменений.

Когда мы его реализуем, функциональность останется прежней - это будет просто еще одна крутая функция :-)

@AlBirdie Re "Что касается второго требования, если вы, ребята, собираетесь его реализовать, оно должно быть необязательным. У нас есть такая консолидация в одном из наших графических продуктов, и вместо этого клиенты неуклонно переходят на фиксированную частоту. частоты во время масштабирования оказались не только запутанными для среднего пользователя финансовых диаграмм, но и раздражали опытных пользователей, потому что они хотели фиксированные частоты ». Полностью согласен - это графики для информационных / неторговых пользователей. У торговых пользователей разные потребности.

@danielgindi Re "абстрагирование источника данных", возможно, мы могли бы внести свой вклад, если бы у нас было время. Никаких обещаний, но добавлю в наш список невыполненных обязательств.

Кто-нибудь играл с разделением кода рисования на отдельные потоки (CALayer.drawsAsynchronously)? Это может помочь, если это позволяет рисовать дополнительные элементы диаграммы, каждый набор данных, сетку и оси отдельно. Учитывая мой очень скромный опыт работы с CoreGraphics (читайте; вообще ничего ;-)), я не проводил никаких экспериментов с этим, я просто нашел его, когда искал GLKit и то, как он может улучшить производительность диаграммы.

Мне нужно было показать свечную диаграмму с 10 тыс. Точек данных, поэтому я провел несколько измерений времени на CandleStickChartRenderer.drawDataSet ().

Оказалось, что большую часть времени уходит на вызов dataSet.entryIndex (строки 76,77).

Я могу ошибаться, но похоже, что вызов dataSet.entryIndex () избыточен, поскольку значения _minX, _maxX всегда равны minx, maxx, возвращаемым из dataSet.entryIndex ()

Мне удалось сделать диаграмму из свечей с плавным панорамированием / масштабированием 10k точек данных. путем изменения
CandleStickChartRenderer.swift, строка 76,77 из:

var minx = max (dataSet.entryIndex (запись: entryFrom, isEqual: true), 0);
var maxx = min (dataSet.entryIndex (запись: entryTo, isEqual: true) + 1, entries.count);

к

var minx = max (_minX, 0);
var maxx = _maxX + 1;

Я сделал то же изменение в LineChartRenderer и смог показать комбинированный график свечей / линий с двумя сериями данных (по 10 тыс. Точек данных в каждой).

Вау, это огромное увеличение производительности @dorsoft !

Я только что проверил это и не поверил своим глазам. Даже на iPad 2 с 4 комбинированными диаграммами, показывающими до трех наборов данных каждый с 250 точками данных в каждом, и автоматическими расчетами минимума / максимума по оси y, теперь мы можем панорамировать и масштабировать все диаграммы одновременно довольно плавно. Это не 60fps, но близко. Впечатляет для такого старого устройства и НАМНОГО (!) Быстрее, чем коммерческое решение OpenGL, о котором мы говорили ранее.

Думаю, мне нужно попробовать это :) И нужно обсудить с Филом также, чтобы
поймите, есть ли какие-то последствия ...

Я только что прочитал это, выглядит очень интересно, но потребуется тщательное тестирование, чтобы убедиться, что он действительно подходит для всех сценариев :-)

Я создал PR с повышением производительности свечного графика.
Улучшение было тщательно протестировано с использованием автоматического масштабирования минимальных / максимальных значений и нулевых значений.

Я нашел возможное узкое место. В диаграмме в реальном времени. Добавляя много записей в секунду в диаграмму, я заметил, что автоматически calcMinMax набора данных вызывается сразу после КАЖДОГО values.append(e)

Функция calcMinMax определяет минимальные и максимальные значения с помощью .forEach, что приводит к тому, что ЦП тратит более 60% на цикл значений, причем в основном потоке.

Я провожу эксперимент, отключаю расчет min / max или использую собственный цикл for вместо массива .forEach

@danielgindi, пожалуйста, посмотрите, действительно ли calcMinMax для всех необходимых значений? Я вычисляю минимальные / максимальные значения Y вручную в моем коде и только для видимых значений , поэтому, возможно, вы могли бы предоставить некоторые логические значения, чтобы включить / отключить автоматическое вычисление минимального / максимального значения и повысить производительность, удалив функцию forEach и избегая вызовов функций.

```
open override func calcMinMax()
{
    guard !values.isEmpty else { return }

    _yMax = -Double.greatestFiniteMagnitude
    _yMin = Double.greatestFiniteMagnitude
    _xMax = -Double.greatestFiniteMagnitude
    _xMin = Double.greatestFiniteMagnitude

    values.forEach { calcMinMax(entry: $0) }
}

``

@samueleperricone Пожалуйста, сделайте это отдельным билетом, и я сделаю ему приоритет.

@jjatie Спасибо, просто откройте # 3166

Я загружаю более 13000 записей в линейные диаграммы для iOS. Но графики замораживают пользовательский интерфейс во время загрузки. Кроме того, после загрузки. Если пользователь выбирает какую-либо точку, то также требуется слишком много времени, чтобы выделить выделение.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

zykis picture zykis  ·  21Комментарии

danielgindi picture danielgindi  ·  61Комментарии

steprescott picture steprescott  ·  51Комментарии

cnowak7 picture cnowak7  ·  21Комментарии

sjuvvalapalem picture sjuvvalapalem  ·  24Комментарии