Charts: Mejoras de rendimiento

Creado en 14 abr. 2015  ·  44Comentarios  ·  Fuente: danielgindi/Charts

¿Hay planes para mejorar el rendimiento de la biblioteca como lo hizo Philip con MPAndroidCharts?
Con sus mejoras, ahora es posible renderizar miles de puntos de datos sin problemas en Android.
He echado un vistazo rápido a la implementación de ios-charts y, por lo que he visto, se basa en la implementación original de MPAndroidCharts sin las últimas mejoras de rendimiento.

Hacer que también rinda miles de puntos sería ENORME una ventaja para la biblioteca, ya que haría inútiles todas las versiones comerciales (la mayoría de las cuales son una pérdida de tiempo y dinero de todos modos).

enhancement help wanted

Comentario más útil

Estoy cargando más de 13000 registros en gráficos de líneas para iOS. Pero los gráficos congelan la interfaz de usuario mientras se cargan. Además, después de la carga, si el usuario selecciona cualquier punto, también lleva demasiado tiempo resaltar la selección.

Todos 44 comentarios

El cuello de botella de rendimiento original en la versión de Android fueron muchas asignaciones adicionales (de matrices) dentro del código de renderizado. La memoria no debe asignarse dentro del código de renderizado. Entonces @PhilJay ha movido ese código a un búfer que está preasignado y ha delegado los cálculos de renderizado a las clases de búfer mientras se renderiza.

Elegí no mover los cálculos de renderizado a las clases Buffer, sino simplemente preasignar la memoria requerida de la misma manera, pero tener los cálculos de renderizado en el mismo ciclo que el código de renderizado. De esta forma es mucho más fácil administrar el código.

También ES una ganancia de rendimiento que los cálculos de renderizado no se realicen dentro de funciones adicionales, y los datos se repitan solo una vez dentro del código de renderizado en lugar de dos veces.

Por cierto, el rendimiento de Swift es MUCHO mejor que el de Java de todos modos, por lo que habría visto que el rendimiento aumenta incluso sin preasignar esos arreglos.

Para explicarlo gráficamente, esto es lo que se está haciendo / se estaba haciendo en el código de renderizado:

  • [COMIENZO A REPRESENTAR]
  • Bucle sobre conjuntos de datos
  • - Asignar matriz para los puntos de este DataSet - Ahora preasignado en ambas plataformas
  • - Calcular puntos para renderizar - _Moved to Buffers en la versión de Android_
  • - Renderiza esos puntos
  • [COMPROMISO DE RENDERIZACIÓN]

También tenga en cuenta que en Java, las abstracciones (funciones, clases, herencia) tienen un gran precio. No en vano los propios Google escribieron una recomendación importante :

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.

Resumiendo:

  • ¡Puede sentirse cómodo trabajando con miles de puntos de datos!
  • Estoy tratando de convencer a Phil de que vuelva a mover los cálculos de puntos a los bucles de renderizado para que sea más simple de mantener ;-)

Gracias por tus explicaciones Daniel. Sin embargo, no estoy muy seguro de qué sacar de esto.
Lo que he hecho es configurar el proyecto más básico (ver el código a continuación) y el rendimiento no es comparable con la versión de Android, ni siquiera cerca para ser completamente honesto. El uso de miles de puntos de datos da como resultado enormes gotas enmarcadas una vez que se acerca a mostrar la cantidad máxima de puntos de datos (alejar la imagen por completo) incluso en la mayoría de los dispositivos iOS actuales, como iPad Mini3 y iPhone6. Como dije, MPAndroidcharts puede renderizar varios miles en dispositivos mucho más lentos sin sudar.

anular func 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;
}

Bueno, todavía no he probado el rendimiento de todos los gráficos, así que tengo que hacerlo pronto.
El cuello de botella es probablemente una asignación que me he perdido en algún lugar ... ¡Lo probaré y te lo haré saber! :-)

Muchas gracias Daniel. Esperando lo que puedas sacar de esto. Sería increíble tener un compañero viable para MPAndroidCharts en iOS.

Bueno, he jugado un poco con LineChartRenderer (que es particularmente lento en comparación con, por ejemplo, BarChartRenderer) e Instruments dice que el drawPath de CGContext es el culpable aquí.
Intenté mitigar este problema usando UIBezierPath en su lugar, pero el rendimiento es el mismo tan pronto como llamas a stroke () en la ruta. Antes de eso, el rendimiento del dibujo es excelente, pero la ruta se llena con respecto al punto de inicio y final, no lo que queremos para un gráfico de líneas simple.
Ojalá tengas un poco más de suerte para encontrar una solución a esto.

Estoy probando esto en este momento, y sí, parece que el CGContextStrokePath real tiene un rendimiento deficiente.
Uno de los principales bateadores es la línea discontinua. Al desactivarlo, el rendimiento ~ se duplica. Pero sigue siendo pobre con mil puntos.
Estoy leyendo algunos documentos de Apple para descubrir cómo hacer que CoreGraphics sea más rápido

Sí, Core Graphics definitivamente está haciendo que los caminos sean lentos. Parece suceder debido a la resolución: la resolución en los dispositivos Apple más nuevos es muy alta, lo que significa más píxeles para renderizar.

Creo que el CG se está procesando en la CPU en lugar de en la GPU. ¿Quizás alguien sepa una forma de cambiar eso?

CG definitivamente está usando la CPU para renderizar y, hasta donde yo sé, no hay forma de cambiar eso.
La representación de GPU significaría usar OpenGL, desafortunadamente. Qué lástima que CG sea tan lento en comparación con la forma en que Android procesa estas cosas en la CPU.

En realidad, son las CPU de los dispositivos las que son lentas. En la mayoría de los casos, un muy lento
La CPU ofrece una experiencia mucho mejor con iOS que una CPU rápida con Android.

Pero Apple no pensó en los casos en los que un sistema operativo óptimo no es
suficiente para mantenerlo rápido.

Supongo que cuando usamos muchos puntos podemos evitar las animaciones, pero
Sigo esperando encontrar una forma de mejorar el rendimiento de la Línea.
gráficos basados.

Parece que específicamente el sistema de dibujo Path es lento, y cuando
jugar con Mitre y Flatness, y deshabilitar las líneas discontinuas y
Antialiasing: el rendimiento mejora mucho de 500 a 700 puntos en una
iPhone 6, pero todavía desigual con un 1000

Puede haber una posibilidad con el uso de UIBezierPath. Como dije, esa cosa es lo suficientemente rápida tan pronto como no llame a 'golpe', que esencialmente le dice al sistema que la ruta es un trazo y no debe llenarse desde el punto de inicio hasta el punto final. No tengo idea de qué está pasando con eso en segundo plano, pero esto muestra que el dibujo del gráfico en sí no es el problema en sí mismo.

Sin embargo, dado que no pude encontrar una manera de usar el UIBezierPath correctamente para el gráfico de líneas, podría ser un candidato viable para las líneas de la cuadrícula, ya que se podría engañar a la ruta para dibujar sin llamar a stroke. Aunque eso es "incorrecto" desde el punto de vista de la API, debería producir un mejor rendimiento.

UIBezierPath es solo una envoltura de UIKit alrededor de CGPath, CGContextDrawPath,
etc.
La diferencia de rendimiento que se observa en algunos casos se debe a su
configurar el CG primero, con las propiedades de UIBezierPath de
antialiasing, límite de inglete, etc.

En realidad, no hay absolutamente ninguna razón para usarlo cuando sabes cómo usarlo.
Gráficos básicos.

Y sí, necesitamos llamar "trazo", ya que queremos trazar ese camino ...
no llenarlo.
Acariciar en la mayoría de los casos es más difícil para el sistema que rellenar sólidos
color, porque necesita cuidar el ancho de las líneas, las uniones
entre líneas y la forma de las uniones.

El viernes 17 de abril de 2015 a las 10:50 a.m., AlBirdie [email protected] escribió:

Puede haber una posibilidad con el uso de UIBezierPath. Como dije, esa cosa
es lo suficientemente rápido tan pronto como no llame a 'accidente cerebrovascular', que esencialmente
le dice al sistema que la ruta es un trazo y no debe llenarse desde el
punto de inicio al punto final. No tengo idea de lo que está pasando con eso en
el fondo, pero esto muestra que el dibujo del gráfico en sí no es el
problema por sí mismo.

Sin embargo, dado que no pude encontrar una manera de usar UIBezierPath correctamente para
el gráfico de líneas, podría ser un candidato viable para las líneas de la cuadrícula como una
podría engañar a la ruta para dibujar sin llamar a stroke. Aunque eso es
"incorrecto" desde el punto de vista de la API, debería producir un mejor rendimiento.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/danielgindi/ios-charts/issues/29#issuecomment -93937181
.

@danielgindi, ¿has pensado en que si la animación ralentiza las cosas, qué tal si

¡Bueno, esa es una gran idea! :)

Aunque hay una desventaja:
Paralizará el tipo de animaciones que puedes hacer con él. como permitimos
animando el eje Y para que el gráfico "crezca", y la forma en que se llena la línea
en el eje X también es diferente que cuando solo hay un trazo.

Mi lista de cosas para probar son:

  1. Mejore de alguna manera CoreGraphics o eleve parte del renderizado al
    GPU

    1. Procesar previamente todos los cuadros de animación: retrasará el inicio de la animación y

      consume una cantidad considerable de memoria

    2. Tu idea de enmascaramiento, que limita los tipos de animaciones

¡Si hay otras ideas, me encantaría escucharlas!

Daniel, ¿ya intentaste descargar el trabajo a la GPU?
Estoy muy, muy descontento con la solución comercial con la que estamos trabajando actualmente (API terrible, terriblemente cerrada y un montón de errores que hacen que la aplicación se bloquee), y teniendo tanto éxito con MPAndroidCharts, nos encantaría cambiar a Gráficos de iOS eventualmente si el rendimiento está a la par. Tenga la seguridad de que su trabajo será recompensado. ;)

Probando algunas técnicas diferentes, ¡te daré una actualización en unos días!

El lunes 20 de abril de 2015 a las 12:38 p.m., AlBirdie [email protected] escribió:

Daniel, ¿ya intentaste descargar el trabajo a la GPU?
Estoy muy, muy descontento con la solución comercial que tenemos actualmente.
trabajando con (API terrible, terriblemente cerrada y un montón de errores que causan
la aplicación se bloquee), y teniendo tanto éxito con MPAndroidCharts,
Me encanta cambiar a gráficos de iOS eventualmente si el rendimiento está a la par. Descansar
seguro, tu trabajo será recompensado. ;)

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/danielgindi/ios-charts/issues/29#issuecomment -94408574
.

@AlBirdie, ¿qué tipo de cuello de botella de rendimiento conociste? Actualmente tengo un producto que dibuja gráficos como ios-charts, ya teníamos una biblioteca de gráficos internamente. También me preocupa el rendimiento, actualmente, solo cargamos 100-1000 conjuntos de datos, parece estar bien ahora.

También estoy considerando cambiar a ios-charts si es posible en el futuro, pero nuestra biblioteca tenía gestos que podrían tener conflictos con ios-charts.

El problema de rendimiento es una velocidad de fotogramas lenta en las animaciones cuando se tiene que
dibuja 500-1000 líneas en un gráfico de líneas.

Con respecto a los gestos, estamos utilizando UIGestureRecognizers estándar, que
puede deshabilitar, modificar o trabajar con. Todo esta estandarizado. :-)

El lunes 20 de abril de 2015 a las 12:53 p.m., Xuan [email protected] escribió:

@AlBirdie https://github.com/AlBirdie qué tipo de actuación
cuello de botella que conociste? Actualmente tengo un producto que dibuja gráficos solo
como ios-charts, ya teníamos una biblioteca de gráficos internamente. Yo tambien me preocupa
sobre el rendimiento, actualmente, solo cargamos 100-1000 conjuntos de datos, parece estar bien
ahora.

También estoy considerando cambiar a gráficos ios si es posible en el futuro,
pero nuestra biblioteca tenía gestos que podrían tener conflictos con los gráficos ios.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/danielgindi/ios-charts/issues/29#issuecomment -94411060
.

@danielgindi bueno, creo que usamos la vista de máscara para superar las animaciones ... Nuestro gráfico de líneas tiene una capa de degradado. Como demostración, su animación puede hacer ambas direcciones X + Y al mismo tiempo, mientras que nosotros solo hacemos la dirección X. No estoy seguro de que el truco de la máscara pueda ayudarte.
Lo que tengo en mente ahora es que si tuviéramos un vector para describir tu dirección X + Y, tal vez exista la posibilidad de usar el truco de la máscara ... ¡Esperamos tus resultados!

@ liuxuan30 sólo un rendimiento lento general, supongo. Las animaciones no son un problema ya que no estoy trabajando con ellas. Estoy trabajando en gráficos financieros en los que necesita tener varios conjuntos de datos en un solo gráfico (varias acciones + una gama de indicadores). Para un rango de datos de 250 elementos que se suman fácilmente a varios miles de puntos que deben procesarse a la vez durante la panorámica y el pellizco. La solución comercial con la que estoy trabajando actualmente lo hace bastante bien (usando OpenGL puedes renderizar miles de puntos sin sobrecargar la CPU), pero no soy amigo de las bibliotecas de código cerrado donde tienes que esperar meses para corregir errores.
Me sentiría mucho más cómodo con ios-charts, especialmente porque es increíblemente fácil trabajar con la API de MPAndroidCharts.

Ya veo, los datos financieros son un desastre. Nuestro servidor obliga a enviar hasta 1000 conjuntos de datos al dispositivo móvil, por lo que redujo nuestra sobrecarga. ¿Existe alguna posibilidad de utilizar OpenGL para gráficos ios? @danielgindi

El soporte de OpenGL sería un ases. Un gráfico de líneas renderizado por GPU probablemente sería suficiente por ahora.
Desafortunadamente, no tengo la menor idea sobre OpenGL, de lo contrario, estaría encantado de ayudar.

Hay una mejora con CGContextStrokeLineSegments en lugar de usar rutas, por lo que debería probar esto.
Sigo probando otras formas de mejorar las cosas :-)

Gracias Daniel, crearé una pequeña aplicación de prueba que compara las dos versiones para ver qué es qué. ¿Qué mejoras de rendimiento obtuvo con los nuevos segmentos de línea?

@AlBirdie , ¿sientes la diferencia con los segmentos de línea?

También me acabo de dar cuenta: en Android, para obtener el máximo rendimiento, lo configura en la capa de hardware, en cuyo caso las líneas discontinuas no son discontinuas, todas son sólidas.

Así que, en primer lugar, si desactivas las líneas discontinuas en iOS, ¡también obtendrás un impulso significativo!

Pero creo que puedo dibujarlo usando un OpenGL ES en CIImage, pero debo tener mucho cuidado porque si una línea GL se ejecuta cuando la aplicación está inactiva, se bloqueará.

También existe la posibilidad de que aún pueda permitir guiones al renderizar previamente una textura. Va a tomar algo de trabajo y no es mi principal prioridad, pero estoy comenzando un proyecto paralelo de una capa OpenGL que puede reemplazar sin problemas el CGContext.

En lugar de ir a OpenGL para dibujar, también puede intentar bajar a Core Animation. Quizás la clase CAShapeLayer podría funcionar. Apple recomienda usar varios CAShapeLayer s al representar una ruta complicada, por lo que es posible que deba dividir el segmento de línea en varios segmentos. El uso de Core Animation debería mover el trabajo a la GPU.

Durante años, en mi trabajo diario, hemos utilizado un producto comercial que, como se señaló anteriormente por @AlBirdie, hace un uso extensivo de OpenGL y, por lo tanto, omite CoreGraphics para todo, excepto las anotaciones. Ciertamente, parecen poder hacer frente a conjuntos de datos bastante grandes con una representación bastante fluida y afirman usar la GPU para esto. Sin embargo, su enfoque viene con dolores de cabeza masivos, entre ellos errores que aparentemente no pueden molestarse en corregir, como llamadas de renderizado asíncronas que se bloquean en OpenGL cuando la aplicación ha pasado a un segundo plano, estructuras de clases idiotas y restricciones locas en la personalización. Lo que quiero no existe hoy, pero en iOS-Charts veo que podría ser la forma de llegar allí. De todos modos, para mí la confiabilidad siempre gana sobre el rendimiento, pero es por el margen más mínimo, ambos son enormemente importantes.

ps, en mi opinión, las líneas discontinuas son una resaca de los días en que las computadoras no tenían la opción de renderizar en color o incluso en escala de grises; no son necesarias a menos que estemos renderizando en blanco y negro puro y haciendo algo que parezca un viejo libro de texto impreso en tipografía, ¿no? ;) Por lo tanto, es mucho menos importante optimizar para aquellos que optimizar para el caso general de 10K puntos.

Absolutamente contigo @onlyforart con respecto a las líneas discontinuas.
Dada su descripción sobre su biblioteca de gráficos comerciales, me pregunto si hemos estado usando el mismo producto. :) Finalmente lo abandonamos por cierto. Lo que me tomó la mayor parte de tres meses para implementarlo (incluso eso no fue lo suficientemente largo para evitar errores y restricciones severos (por ejemplo, punto de mira), tomó solo dos semanas con iOSCharts ('estructuras de clases idiotas';)). Un total desperdicio de tiempo y dinero.

@AlBirdie, sí, ese es el
Principalmente dibujamos gráficos de velas japonesas (estas son aplicaciones del sector financiero). Lo que realmente quiero para iOS y Android es algo que sea realmente muy fácil con HighCharts / HighStock en el mundo HTML5 / Javascript:

  1. gran cantidad de puntos de datos (10.000 o más)
  2. consolidación automática de datos OHLC en barras de escala sensible (por ejemplo, mostrar barras de 1 hora cuando el factor de zoom es apropiado, o barras de 1 mo 1 s cuando se aleja)
  3. desplazamiento y desplazamiento suaves
  4. pellizcar para ampliar
  5. superposición de múltiples series de datos y anotaciones y puntos de mira, algunos programáticamente y otros mediante la interacción del usuario, por ejemplo, para establecer un precio límite, todo sin problemas
  6. (aquí está el truco: ¡HighStock no ayuda con esto! aunque me parece bastante obvio) obtención incremental de datos (con anticipación), por ejemplo, obtener datos de baja resolución para todo el conjunto de datos y, al igual que con las aplicaciones de mapas, obtener la alta resolución datos (por ejemplo, datos de milisegundos "tick") solo para el área visualizada del gráfico
    Todavía no estamos usando iOS-Charts, aunque está en mi lista de "tareas pendientes" y acercándome a la parte superior, por lo que no miré mucho dentro del código todavía, pero tan pronto como lo haga, probablemente el próximo mes Investigaré todo eso.
    Volviendo al renderizado, la tendencia de OpenGL a fallar si las circunstancias no son perfectas es una preocupación. GLKit podría ayudar con el dibujo de la GPU; También me había preguntado hace un tiempo si SpriteKit podría ayudar (la representación de gráficos no está a un millón de millas de hacer juegos), pero ahora GLKit parece un mejor candidato.

LOL @onlyforart , me tuviste en Newcastle Brown Ale. : +1: :)
Estoy en el mismo barco con respecto a sus requisitos (trabajando también en productos financieros), pero sí, volvamos al dibujo real de estos gráficos. Esperamos sus hallazgos en el futuro.

@onlyforart , @AlBirdie gracias por sus ideas :-)

Es realmente agradable ver a la gente deshacerse de productos comerciales empresariales para nuestra biblioteca, aunque me siento mal por ellos ... ¡Estoy en conflicto!

Dudé en dejar que OpenGL tuviera una porción de esto porque sabía que hay posibles fallas si no se maneja a la perfección, y eso no es realmente posible en una aplicación UIKit. Si está utilizando OpenGL para crear un juego, todo es un lienzo OpenGL y no tiene que preocuparse por una llamada UIKit que intente generar una representación OpenGL mientras está en segundo plano.

@onlyforart su punto sobre las líneas discontinuas es correcto, pero desafortunadamente he tenido experiencia con clientes que exigen tener líneas discontinuas. Hubo un caso en Android en el que para mejorar el rendimiento, el desarrollador tuvo que cambiar la capa a una capa de hardware y le dijo al cliente que las líneas discontinuas se convertirían en líneas continuas, ese es el costo. Y, por supuesto, hay una opción para mover todo el código de dibujo a OpenGL, pero luego dibujar una sola línea es un dolor de cabeza, pero puede crear una textura para una línea discontinua y trabajar con ella. No querían pagar por ello, así que las líneas discontinuas no eran tan críticas, pero hicieron mucho ruido al respecto.

Una nota para mí: intente usar GLKit para el renderizado. Mira qué pasa.

Y si tomo tu lista:

  1. _ "gran cantidad de puntos de datos (10.000 o más)" _ - estamos trabajando en ello :) No puedo decir sobre Android, ya que moverlo a GL será un PITA aún mayor, pero ya está teniendo un rendimiento bastante bueno por aprovechando la capa de hardware, que está haciendo todo el dibujo en la GPU.
  2. _ "consolidación automática de datos OHLC en barras de escala sensible" _ - vamos a poner en uso los filtros de aproximación muy pronto, así que creo que eso se encargará de eso. En lugar de tener muchas barras de 1 m que no puede leer, tendrá una barra aproximada de 1 hora, etc.
  3. _ "panorámica y desplazamiento suaves" _ - hecho :-)
  4. _ "pellizcar para ampliar" _ - hecho :-)
  5. _ "superposición de varias series de datos y anotaciones y puntos de mira" _ - No sé si lo entiendo correctamente, pero actualmente existe el gráfico combinado que puede superponer varios tipos de gráficos, y cada tipo de gráfico puede aceptar varios conjuntos de datos. Además, siempre puede conectarse a ViewPortHandler y tomar coordenadas para que pueda superponer lo que quiera sobre el char
  6. Recuperación incremental de datos: estamos planeando abstraer la fuente de datos, sin dejar de tener las API antiguas para establecer conjuntos de datos estáticos (solo será una fuente de datos incorporada que funcione con ellos). Supongo que esto también se ajustará a sus requisitos, pero aún no sabemos cuándo lo haremos.

@danielgindi , no te sientas mal por ellos. Si el producto que está desarrollando es básicamente un tomate podrido y, sin embargo, todavía cobra bastante dinero por él, la gente finalmente cambiará a un producto diferente. No hay nada de malo en eso. He estado desarrollando gráficos financieros durante varios años, he utilizado prácticamente todas las soluciones para iOS que existen actualmente y, de hecho, he escrito mi propio motor de gráficos en ActionScript3 en el pasado, así que me siento bastante seguro al decir eso. iOSCharts y MPAndroidCharts son, de hecho, los únicos productos que puedo recomendar actualmente a cualquier desarrollador que necesite crear gráficos en su aplicación. Todo lo demás no es suficiente.

En cuanto al segundo requisito, si van a implementar esto, tiene que ser opcional. Tenemos este tipo de consolidación en uno de nuestros productos de gráficos y los clientes se están moviendo constantemente hacia una frecuencia fija. El cambio de frecuencias durante el zoom resultó no solo confuso para el usuario promedio de gráficos financieros, sino que los usuarios avanzados se molestaron porque querían frecuencias fijas.

¡Nunca imaginamos forzar esto a los usuarios! Puede ver que el código ya incluye los filtros, y en MPAndroidCharts puede ver que históricamente los filtros fueron habilitados por una propiedad que establece el filtro (cualquier filtro personalizado o los incorporados), pero eliminados más tarde debido a cambios estructurales.

Cuando lo implementemos, la funcionalidad seguirá siendo la misma, será solo otra característica interesante :-)

@AlBirdie Re "Con respecto al segundo requisito, si van a implementar esto, tiene que ser opcional. Tenemos este tipo de consolidación en uno de nuestros productos de gráficos y los clientes se están moviendo constantemente a una frecuencia fija en su lugar. Cambiando las frecuencias durante el zoom resultaron no solo confusas para el usuario promedio de gráficos financieros, sino que los usuarios avanzados se molestaron porque querían frecuencias fijas ". Totalmente de acuerdo: esto es para gráficos para usuarios informativos / no comerciales. Los usuarios comerciales tienen diferentes necesidades.

@danielgindi Re "abstraer la

¿Alguien jugó con la división del código de dibujo en hilos separados (CALayer.drawsAsynchronously)? Eso podría ayudar en caso de que esto permita dibujar gráficos adicionales, cada conjunto de datos, la cuadrícula y los ejes por separado. Dada mi muy humilde experiencia con CoreGraphics (leer; ninguno en absoluto ;-)), no he hecho ningún experimento con esto, lo encontré cuando estaba buscando GLKit y cómo podría mejorar el rendimiento del gráfico.

Necesitaba mostrar un gráfico de velas con 10k puntos de datos, así que ejecuté algunas mediciones de tiempo en CandleStickChartRenderer.drawDataSet ().

Resultó que la mayor parte del tiempo se dedica a llamar a dataSet.entryIndex (líneas 76,77).

Podría estar equivocado, pero parece que la llamada dataSet.entryIndex () es redundante como _minX, los valores _maxX son siempre iguales al minx, maxx devuelto por dataSet.entryIndex ()

Me las arreglé para hacer un gráfico de velas con 10k puntos de datos de panorámica / zoom sin problemas. cambiando
CandleStickChartRenderer.swift, línea 76,77 de:

var minx = max (dataSet.entryIndex (entrada: entryFrom, isEqual: true), 0);
var maxx = min (dataSet.entryIndex (entrada: entryTo, isEqual: true) + 1, entradas.count);

a

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

Hice el mismo cambio en LineChartRenderer y pude mostrar un gráfico combinado de velas / líneas con 2 series de datos (10k puntos de datos cada una)

¡Vaya, eso es un aumento de rendimiento masivo @dorsoft !

Acabo de probar esto y no podía creer lo que veía. Incluso en un iPad 2 con 4 CombinedCharts que muestran hasta tres conjuntos de datos cada uno con 250 puntos de datos cada uno y cálculos automáticos mínimos / máximos del eje y, ahora podemos desplazar y hacer zoom en todos los gráficos simultáneamente de una manera bastante suave. No es de 60 fps, pero está cerca. Impresionante para un dispositivo tan antiguo y MUCHO (!) Más rápido que la solución comercial OpenGL de la que hablamos anteriormente.

Supongo que tengo que probar esto :) Y necesito discutir con Phil también para
entender si hay alguna implicación ...

Acabo de leer esto, parece muy interesante pero necesitará algunas pruebas intensas para ver si es realmente adecuado para todos los escenarios :-)

He creado un PR con la mejora del rendimiento del gráfico de velas.
La mejora se probó minuciosamente utilizando valores mínimos / máximos y nulos de escala automática.

Encontré un posible cuello de botella. En un gráfico en tiempo real Al agregar muchas entradas por segundo al gráfico, noté que automáticamente se llama a calcMinMax del conjunto de datos justo después de CADA values.append(e)

La función calcMinMax determina los valores mínimo y máximo usando .forEach que está causando que la CPU gaste más del 60% en bucle de los valores, además en el hilo principal.

Estoy realizando un experimento que deshabilita el cálculo mínimo / máximo o uso el bucle for nativo en lugar de la matriz .forEach

@danielgindi, por favor, eche un vistazo, ¿realmente se necesita calcMinMax en todos los valores? Calculo los valores mínimos / máximos de Y manualmente en mi código y solo en valores visibles , por lo que tal vez pueda exponer algunos

```
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 Por favor, haga de esto un ticket por separado y le daré prioridad a esto.

@jjatie Gracias, solo abre # 3166

Estoy cargando más de 13000 registros en gráficos de líneas para iOS. Pero los gráficos congelan la interfaz de usuario mientras se cargan. Además, después de la carga, si el usuario selecciona cualquier punto, también lleva demasiado tiempo resaltar la selección.

¿Fue útil esta página
0 / 5 - 0 calificaciones