Charts: Améliorations des performances

Créé le 14 avr. 2015  ·  44Commentaires  ·  Source: danielgindi/Charts

Existe-t-il des plans pour améliorer les performances de la bibliothèque comme Philip l'a fait avec MPAndroidCharts?
Avec ses améliorations, il est désormais possible de rendre des milliers de points de données en douceur sur Android.
J'ai jeté un coup d'œil rapide à l'implémentation d'ios-charts et d'après ce que j'ai vu, elle est basée sur l'implémentation originale de MPAndroidCharts sans les dernières améliorations de performances.

Le rendre également des milliers de points serait un énorme plus pour la bibliothèque car cela rendrait toutes les versions commerciales inutiles (dont la plupart sont une perte de temps et d'argent de toute façon).

enhancement help wanted

Commentaire le plus utile

Je charge plus de 13000 enregistrements dans des graphiques linéaires pour iOS. Mais, les graphiques gèlent l'interface utilisateur lors du chargement. De plus, après le chargement Si l'utilisateur sélectionne un point, cela prend également trop de temps pour mettre la sélection en surbrillance.

Tous les 44 commentaires

Le goulot d'étranglement des performances d'origine dans la version Android était de nombreuses allocations supplémentaires (de tableaux) dans le code de rendu. La mémoire ne doit pas être allouée à l' intérieur du code de rendu. Ainsi @PhilJay a déplacé ce code dans un Buffer préalloué et délégué les calculs de rendu aux classes Buffer lors du rendu.

J'ai choisi de ne pas déplacer les calculs de rendu vers les classes Buffer, mais simplement de préallouer la mémoire requise de la même manière - mais de placer les calculs de rendu dans la même boucle que le code de rendu. De cette façon, il est beaucoup plus facile de gérer le code.

C'est aussi un gain de performance que les calculs de rendu ne sont pas effectués dans des fonctions supplémentaires, et les données ne sont bouclées qu'une seule fois dans le code de rendu au lieu de deux.

Btw, dans Swift, les performances sont de toute façon BEAUCOUP meilleures que Java, vous auriez donc vu ce gain de performances même sans pré-allouer ces tableaux.

Afin de l'expliquer graphiquement, voici ce qui est / était en cours dans le code de rendu:

  • [COMMENCER LE RENDU]
  • Boucle sur les ensembles de données
  • - Allouer un tableau pour les points de ce DataSet - Désormais préalloué dans les deux plates-formes
  • - Calculer les points pour le rendu - _ Déplacé vers les tampons dans la version Android_
  • - Rendre ces points
  • [COMMIT RENDERING]

Notez également qu'en Java, les abstractions (fonctions, classes, héritage) ont un prix très intéressant. Ce n'est pas pour rien que Google lui-même a écrit une recommandation 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.

Pour résumer:

  • Vous pouvez être à l'aise avec des milliers de points de données!
  • J'essaie de convaincre Phil de ramener les calculs de points aux boucles de rendu pour le rendre plus simple à maintenir ;-)

Merci pour vos explications Daniel. Je ne sais pas trop quoi en retenir, cependant.
Ce que j'ai fait, c'est configurer le projet le plus basique (voir le code ci-dessous) et les performances ne sont pas comparables à la version Android, pas même proches pour être tout à fait honnête. L'utilisation d'un millier de points de données entraîne des chutes de cadre massives une fois que vous vous approchez de l'affichage du nombre maximal de points de données (zoom arrière complet), même sur la plupart des appareils iOS actuels tels que l'iPad Mini3 et l'iPhone6. Comme je l'ai dit, MPAndroidcharts peut rendre plusieurs milliers sur des appareils beaucoup plus lents sans transpirer.

remplacer la fonction 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;
}

Eh bien, je n'ai pas encore testé tous les graphiques pour les performances - donc je dois le faire bientôt.
Le goulot d'étranglement est probablement une allocation que j'ai manquée quelque part ... Je vais tester et vous le faire savoir! :-)

Merci beaucoup Daniel. Dans l'attente de ce que vous pouvez en tirer. Ce serait génial d'avoir un compagnon viable pour MPAndroidCharts sur iOS.

Eh bien, j'ai un peu joué avec le LineChartRenderer (qui est particulièrement lent par rapport au BarChartRenderer par exemple) et Instruments dit que le drawPath de CGContext est ici le coupable.
J'ai essayé d'atténuer ce problème en utilisant UIBezierPath à la place, mais les performances sont les mêmes dès que vous appelez stroke () sur le chemin. Avant cela, les performances de dessin sont excellentes, mais le chemin est rempli en ce qui concerne le point de départ et d'arrivée, pas ce que nous voulons pour un simple graphique en courbes.
J'espère que vous avez un peu plus de chance pour trouver une solution à ce problème.

Je teste cela en ce moment, et oui, il semble que le CGContextStrokePath souffre de mauvaises performances.
L'un des principaux frappeurs est la ligne pointillée. Lors de sa désactivation, les performances ~ doublent. Mais il est encore pauvre avec mille points.
Je suis en train de lire dans la documentation Apple pour savoir comment rendre CoreGraphics plus rapide

Oui, Core Graphics rend définitivement les chemins lents. Cela semble être dû à la résolution - la résolution sur les nouveaux appareils Apple est très élevée, ce qui signifie plus de pixels à rendre.

Je pense que le CG est rendu sur le CPU plutôt que sur le GPU. Peut-être que quelqu'un connaît un moyen de changer cela?

CG utilise très certainement le processeur pour le rendu et pour autant que je sache, il n'y a aucun moyen de changer cela.
Le rendu GPU signifierait l'utilisation d'OpenGL, malheureusement. Dommage que CG soit aussi lent par rapport à la façon dont Android rend ces choses sur le processeur.

Ce sont en fait les processeurs des appareils qui sont lents. Dans la plupart des cas, un
Le processeur offre une bien meilleure expérience avec iOS qu'un processeur rapide avec un Android.

Mais Apple n'a pas pensé aux cas où un système d'exploitation optimal n'est pas
suffisant pour le garder rapide.

Je suppose que lorsque nous utilisons beaucoup de points, nous pouvons simplement éviter les animations - mais
J'espère toujours trouver un moyen d'améliorer les performances de la ligne
graphiques basés.

Il semble que le système de dessin de chemin soit lent, et quand
jouer avec l'onglet et la planéité, et désactiver les lignes pointillées et
Anticrénelage - les performances sont bien meilleures pour 500 à 700 points sur un
iPhone 6, mais toujours saccadé avec un 1000

Il peut y avoir une chance d'utiliser UIBezierPath. Comme je l'ai dit, cette chose est suffisamment rapide dès que vous n'appelez pas «course», ce qui indique essentiellement au système que le chemin est un trait et ne doit pas être rempli du point de départ au point final. Je n'ai aucune idée de ce qui se passe avec cela en arrière-plan, mais cela montre que le dessin du graphique lui-même n'est pas le problème en soi.

Cependant, comme je ne pouvais pas trouver un moyen d'utiliser correctement UIBezierPath pour le graphique en courbes, cela pourrait être un bon choix pour les lignes de la grille, car on pourrait tromper le chemin pour dessiner sans appeler stroke. Même si cela est «faux» du point de vue de l'API, cela devrait donner de meilleures performances.

UIBezierPath est juste un wrapper UIKit autour de CGPath, CGContextDrawPath,
etc.
La différence de performance observée dans certains cas est due à sa
configurer d'abord le CG, avec les propriétés de UIBezierPath de
anti-crénelage, limite d'onglet, etc.

En fait, il n'y a absolument aucune raison de l'utiliser lorsque vous savez comment l'utiliser
Graphiques de base.

Et oui, nous devons appeler "AVC", car nous voulons tracer ce chemin ...
de ne pas le remplir.
La caresse dans la plupart des cas est plus difficile pour le système que le remplissage de solide
couleur, car il faut prendre soin de la largeur des lignes, des jointures
entre les lignes et la forme des jointures.

Le vendredi 17 avril 2015 à 10 h 50, AlBirdie [email protected] a écrit:

Il peut y avoir une chance d'utiliser UIBezierPath. Comme je l'ai dit, cette chose
est suffisamment rapide dès que vous n'appelez pas `` AVC '', ce qui
indique au système que le chemin est un trait et ne doit pas être rempli à partir du
point de départ au point final. Je n'ai aucune idée de ce qui se passe avec ça
l'arrière-plan, mais cela montre que le graphique lui-même n'est pas le
problème par lui-même.

Cependant, comme je ne pouvais pas trouver un moyen d'utiliser correctement UIBezierPath pour
le graphique en courbes, cela pourrait être un bon choix pour les lignes de la grille en tant qu'un
pourrait tromper le chemin pour dessiner sans appeler stroke. Même si c'est
«faux» du point de vue de l'API, cela devrait donner de meilleures performances.

-
Répondez directement à cet e-mail ou affichez-le sur GitHub
https://github.com/danielgindi/ios-charts/issues/29#issuecomment -93937181
.

@danielgindi avez-vous pensé que si l'animation ralentissait les choses, que diriez-vous de dessiner toutes les lignes sans animation et d'utiliser une vue de masque la recouvrant, puis d'animer la vue de masque pour imiter l'animation?

Eh bien, c'est une excellente idée! :)

Bien qu'il y ait un inconvénient:
Cela paralysera le type d'animations que vous pouvez en faire. comme nous le permettons
animer l'axe Y pour que le graphique "grandisse" et la façon dont la ligne se remplit
sur l'axe X est également différent de celui où il n'y a qu'un trait.

Ma liste de choses à essayer est:

  1. Améliorez d'une manière ou d'une autre CoreGraphics ou élevez une partie du rendu au
    GPU

    1. Pré-rendre toutes les images d'animation - cela retardera le début de l'animation, et

      consomme une quantité considérable de mémoire

    2. Votre idée de masquage - qui limite les types d'animations

S'il y a d'autres idées, j'aimerais les entendre!

Daniel, avez-vous déjà essayé de décharger le travail sur le GPU?
Je suis vraiment, vraiment mécontent de la solution commerciale avec laquelle nous travaillons actuellement (API terrible, terriblement fermée et plein de bugs qui provoquent le plantage de l'application), et ayant un si grand succès avec MPAndroidCharts, nous aimerions passer à Les graphiques iOS éventuellement si les performances sont à la hauteur. Rassurez-vous, votre travail serait récompensé. ;)

En essayant quelques techniques différentes, je vous donnerai une mise à jour dans quelques jours!

Le lundi 20 avril 2015 à 12 h 38, AlBirdie [email protected] a écrit:

Daniel, avez-vous déjà essayé de décharger le travail sur le GPU?
Je suis vraiment, vraiment mécontent de la solution commerciale que nous sommes actuellement
travailler avec (API terrible, terriblement fermée, et des tas de bogues qui causent
l'application à planter), et ayant un tel succès avec MPAndroidCharts, nous
J'adore passer éventuellement aux graphiques iOS si les performances sont à la hauteur. Du repos
assuré, votre travail serait récompensé. ;)

-
Répondez directement à cet e-mail ou affichez-le sur GitHub
https://github.com/danielgindi/ios-charts/issues/29#issuecomment -94408574
.

@AlBirdie quel genre de goulot d'étranglement de performance avez-vous rencontré? Je possède actuellement un produit qui dessine des graphiques tout comme ios-charts, nous avions déjà une bibliothèque de graphiques en interne. Je suis également préoccupé par les performances, actuellement, nous ne chargeons que 100-1000 ensembles de données, cela semble correct maintenant.

J'envisage également de passer aux graphiques ios si possible à l'avenir, mais notre bibliothèque avait des gestes qui pourraient avoir des conflits avec les graphiques ios.

Le problème des performances est une fréquence d'images lente dans les animations lorsque vous devez
dessinez entre 500 et 1000 lignes dans un graphique en courbes.

En ce qui concerne les gestes - nous utilisons des UIGestureRecognizers standard - que vous
peut désactiver, modifier ou utiliser. Tout est standardisé. :-)

Le lundi 20 avril 2015 à 12h53, Xuan [email protected] a écrit:

@AlBirdie https://github.com/AlBirdie quel genre de performance
goulot d'étranglement que vous avez rencontré? Je possède actuellement un produit qui dessine des graphiques uniquement
comme ios-charts, nous avions déjà une bibliothèque de graphiques en interne. Je concerne aussi
à propos des performances, actuellement, nous ne chargeons que 100-1000 ensembles de données, cela semble correct
à présent.

J'envisage également de passer aux cartes ios si possible à l'avenir,
mais notre bibliothèque avait des gestes qui pourraient avoir des conflits avec les graphiques ios.

-
Répondez directement à cet e-mail ou affichez-le sur GitHub
https://github.com/danielgindi/ios-charts/issues/29#issuecomment -94411060
.

@danielgindi eh bien, je pense que nous utilisons la vue masque pour surmonter les animations ... Notre graphique en
Ce que j'ai à l'esprit maintenant, c'est que si nous avions un vecteur pour décrire votre direction X + Y, il y a peut-être une chance d'utiliser l'astuce du masque ... attendez avec impatience vos résultats!

@ liuxuan30 juste des performances lentes générales, je suppose. Les animations ne sont pas un problème car je ne travaille pas avec celles-ci. Je travaille sur des graphiques financiers où vous devez avoir plusieurs ensembles de données dans un seul graphique (plusieurs actions + une gamme d'indicateurs). Pour une plage de données de 250 éléments qui ajoute facilement jusqu'à plusieurs milliers de points qui doivent être rendus à la fois pendant le panoramique et le pincement. La solution commerciale avec laquelle je travaille actuellement le fait assez bien (en utilisant OpenGL, vous pouvez rendre des milliers de points sans surcharger le processeur), mais je ne suis pas un ami des bibliothèques à source fermée où vous devez attendre des mois pour corriger les bogues.
Je me sentirais beaucoup plus à l'aise avec les graphiques ios, d'autant plus que l'API de MPAndroidCharts est incroyablement facile à utiliser.

Je vois, les données financières sont un désastre. Notre serveur force à envoyer jusqu'à 1000 ensembles de données à l'appareil mobile, ce qui a réduit notre surcharge. Y a-t-il une chance d'utiliser OpenGL pour les graphiques iOS? @danielgindi

Le support d'OpenGL serait un atout. Un graphique en courbes rendu par GPU suffirait probablement pour l'instant.
Malheureusement, je n'ai absolument aucune idée d'OpenGL, sinon je serais ravi de vous aider.

Il y a une amélioration avec CGContextStrokeLineSegments par opposition à l'utilisation de chemins, vous devriez donc essayer ceci.
J'essaie toujours les autres moyens d'améliorer les choses :-)

Merci Daniel, je vais créer une petite application de test qui compare les deux versions l'une à l'autre pour voir quoi. Quels gains de performances avez-vous obtenus avec les nouveaux LineSegments?

@AlBirdie sentez -vous la différence avec les segments de ligne?

Aussi, je viens de réaliser: dans Android pour obtenir les performances maximales, vous le définissez sur la couche matérielle - auquel cas les lignes en pointillés ne sont pas en pointillés, elles sont toutes solides.

Donc, première chose, si vous désactivez les lignes pointillées sur iOS, vous obtenez également un coup de pouce significatif!

Mais je pense que je peux en fait le dessiner en utilisant un OpenGL ES sur CIImage, mais je dois être très prudent car si une ligne GL s'exécute lorsque l'application est inactive, elle plantera.

Il y a aussi une chance que je puisse toujours autoriser les tirets en pré-rendant une texture. Cela va prendre du travail et ce n'est pas ma priorité principale, mais je démarre un projet parallèle d'une couche OpenGL qui peut remplacer de manière transparente le CGContext.

Plutôt que d'aller à OpenGL pour dessiner, vous pouvez également essayer de descendre à Core Animation. Peut-être que la classe CAShapeLayer pourrait fonctionner. Apple recommande d'utiliser plusieurs CAShapeLayer s lors du rendu d'un chemin compliqué, vous devrez peut-être diviser le segment de ligne en plusieurs segments. L'utilisation de Core Animation devrait déplacer le travail vers le GPU.

Pendant des années dans mon travail quotidien, nous avons utilisé un produit commercial qui, comme indiqué ci-dessus par @AlBirdie, utilise largement OpenGL, et contourne ainsi CoreGraphics pour tout sauf les annotations. Certes, ils semblent être capables de gérer des ensembles de données assez volumineux avec un rendu assez fluide et ils prétendent utiliser le GPU pour cela. Cependant, leur approche s'accompagne d'énormes maux de tête, notamment des bogues qu'ils ne peuvent apparemment pas prendre la peine de corriger, tels que les appels de rendu asynchrones qui plantent dans OpenGL lorsque l'application est passée en arrière-plan, des structures de classe idiotes et des restrictions insensées sur la personnalisation. Ce que je veux n'existe pas aujourd'hui, mais dans les graphiques iOS, je vois que c'est peut-être le moyen d'y arriver. Quoi qu'il en soit, pour moi, la fiabilité l'emporte sur les performances à chaque fois, mais c'est par la moindre marge, les deux sont extrêmement importants.

ps à mon avis, les lignes pointillées sont une gueule de bois de l'époque où les ordinateurs n'avaient pas la possibilité de rendre en couleur ou même en niveaux de gris - elles ne sont pas nécessaires à moins que nous ne rendions en noir et blanc pur et que nous fassions quelque chose qui ressemble à un vieux manuel imprimé typographique, sûrement? ;) Il est donc beaucoup moins important d'optimiser pour ceux-ci que d'optimiser pour le cas général de 10K points.

Absolument avec vous @onlyforart concernant les lignes pointillées.
Compte tenu de votre description de votre bibliothèque de graphiques commerciaux, je me demande si nous utilisons le même produit. :) Nous l'avons finalement abandonné au fait. Ce qui m'a pris plus de trois mois à mettre en œuvre (même si ce n'était pas assez long pour contourner les bogues et les restrictions sévères (par exemple, le réticule), n'a pris que deux semaines avec iOSCharts ('structures de classe idiotes';)). Perte totale de temps et d'argent.

@AlBirdie oui c'est celui-là. Ne parlez même pas du réticule. Fabriqué avec l'aide de trop de Newcastle Brown Ale et sans aucun doute destiné au marché des entreprises (où une API géniale est en fait un facteur de vente positif, car elle enferme les clients dans un cycle de support / maintenance coûteux). Connaissiez-vous l'histoire de ces gars-là? en fait (dans leur passé profond), ils étaient de véritables pionniers dans l'industrie du logiciel. Quoi qu'il en soit, il est temps de passer à autre chose et de regarder vers l'avenir maintenant.
Nous dessinons principalement des graphiques en chandeliers (ce sont des applications du secteur financier). Ce que je veux vraiment pour iOS et Android, c'est quelque chose de très simple avec HighCharts / HighStock dans le monde HTML5 / Javascript:

  1. un grand nombre de points de données (10K ou plus)
  2. consolidation automatique des données OHLC en barres sensibles à l'échelle (par exemple, afficher des barres de 1h lorsque le facteur de zoom est approprié, ou des barres de 1m ou 1s lors d'un zoom arrière)
  3. panoramique et défilement fluides
  4. pincer pour zoomer
  5. superposition de plusieurs séries de données et annotations et réticules, certaines par programmation et d'autres par interaction de l'utilisateur, par exemple pour définir un prix limite, le tout rendu en douceur
  6. (voici le kicker - HighStock n'aide pas avec cela! bien que cela me semble assez évident) extraction incrémentielle de données (avec anticipation), par exemple récupérer des données basse résolution pour l'ensemble de données et, comme avec les applications de cartes, récupérer le hi-rez données (par exemple, données en millisecondes "tick") uniquement pour la zone visualisée du graphique
    Nous n'utilisons pas encore iOS-Charts bien qu'il soit sur ma liste de choses à faire et que je me rapproche du sommet, donc je n'ai pas encore beaucoup regardé à l'intérieur du code, mais dès que je le ferai - probablement le mois prochain - Je vais examiner tout cela.
    De retour au rendu, la tendance d'OpenGL à planter si les circonstances ne sont pas parfaites est un souci. GLKit pourrait aider avec le dessin GPU; Je m'étais également demandé il y a quelque temps si SpriteKit pouvait aider (le rendu des graphiques n'est pas à un million de kilomètres de la création de jeux), mais pour le moment, GLKit semble un meilleur candidat.

LOL @onlyforart , vous m'avez eu à la Newcastle Brown Ale. : +1: :)
Je suis dans le même bateau en ce qui concerne vos besoins (je travaille également sur les produits financiers), mais oui, revenons au dessin réel de ces graphiques. Dans l'attente de vos découvertes à l'avenir.

@onlyforart , @AlBirdie merci pour vos idées :-)

C'est vraiment agréable de voir des gens abandonner des produits commerciaux pour notre bibliothèque, même si je me sens mal pour eux ... Je suis en conflit!

J'ai hésité à laisser OpenGL avoir une part de cela parce que je savais qu'il y avait des plantages possibles si ce n'était pas géré parfaitement, et ce n'est pas vraiment possible dans une application UIKit. Si vous utilisez OpenGL pour créer un jeu, le tout est un canevas OpenGL et vous n'avez pas à vous soucier d'un appel UIKit essayant de provoquer un rendu OpenGL en arrière-plan.

@onlyforart votre point sur les lignes pointillées est correct, mais malheureusement, j'ai eu de l'expérience avec des clients exigeant des lignes pointillées. Il y avait un cas sur Android où pour améliorer les performances, le développeur a dû changer la couche en couche matérielle et a dit au client que les lignes pointillées deviendraient des lignes pleines, c'est le coût. Et il y a bien sûr une option pour déplacer tout le code de dessin vers OpenGL, mais dessiner une seule ligne est un casse-tête, mais vous pouvez créer une texture pour une ligne en pointillé et travailler avec elle. Ils ne voulaient pas payer pour cela, donc les lignes pointillées n'étaient certainement pas si critiques, mais ils en faisaient beaucoup de bruit.

Une note pour moi-même: essayez d'utiliser GLKit pour le rendu. Voyez ce qui se passe.

Et si je prends votre liste:

  1. _ "un grand nombre de points de données (10K ou plus)" _ - nous y travaillons :) Je ne peux pas dire à propos d'Android, car le déplacer vers GL sera un PITA encore plus grand, mais il a déjà de très bonnes performances en tirer parti de la couche matérielle, qui fait tout le dessin sur le GPU.
  2. _ "consolidation automatique des données OHLC dans des barres d'échelle sensibles" _ - nous allons mettre en service les filtres d'approximation très prochainement, donc je pense que cela réglera cela. Au lieu d'avoir de nombreuses barres de 1 m que vous ne pouvez pas lire, vous aurez une barre d'environ 1 heure, etc.
  3. _ "panoramique et défilement en douceur" _ - terminé :-)
  4. _ "pincer pour zoomer" _ - terminé :-)
  5. _ "superposition de plusieurs séries de données, annotations et réticules" _ - Je ne sais pas si je comprends bien, mais il existe actuellement le graphique combiné qui peut superposer plusieurs types de graphiques, et chaque type de graphique peut accepter plusieurs ensembles de données. De plus, vous pouvez toujours vous connecter à ViewPortHandler et prendre des coordonnées afin de pouvoir superposer ce que vous voulez sur le caractère
  6. extraction incrémentielle des données - nous prévoyons d'abstraire la source de données, tout en ayant toujours les anciennes API pour définir des ensembles de données statiques (ce sera juste une source de données intégrée qui fonctionne avec ceux-ci). Je suppose que cela répondra également à vos besoins, mais nous ne savons pas quand nous y arriverons encore

@danielgindi , ne vous sentez pas mal pour eux. Si le produit que vous développez est essentiellement une tomate pourrie et que vous facturez encore une pâte sérieuse pour cela, les gens finiront par passer à un produit différent. Il n'y a rien de mal à cela. Je développe des graphiques financiers depuis plusieurs années maintenant, j'ai utilisé à peu près toutes les solutions pour iOS qui existent actuellement et j'ai en fait écrit mon propre moteur de création de graphiques dans ActionScript3 à l'époque, donc je suis assez confiant en disant que iOSCharts et MPAndroidCharts sont en fait les seuls produits que je peux actuellement recommander à tout développeur qui a besoin de graphiques dans son application. Tout le reste ne suffit pas.

En ce qui concerne la deuxième exigence, si vous voulez l'implémenter, elle doit être facultative. Nous avons ce type de consolidation dans l'un de nos produits de cartographie et les clients passent progressivement à une fréquence fixe à la place. Changer les fréquences pendant le zoom s'est avéré non seulement déroutant pour l'utilisateur moyen des graphiques financiers, mais les utilisateurs expérimentés ont été ennuyés parce qu'ils voulaient des fréquences fixes.

Nous n'avons jamais imaginé imposer cela aux utilisateurs! Vous pouvez voir que le code inclut déjà les filtres, et dans MPAndroidCharts, vous pouvez voir que les filtres étaient historiquement activés par une propriété qui définit le filtre (tout filtre personnalisé ou ceux intégrés), mais supprimés plus tard en raison de changements structurels.

Lorsque nous l'implémenterons, la fonctionnalité restera la même - ce ne sera qu'une autre fonctionnalité intéressante :-)

@AlBirdie Re "En ce qui concerne la deuxième exigence, si vous voulez l'implémenter, elle doit être facultative. Nous avons ce type de consolidation dans l'un de nos produits de cartographie et les clients passent régulièrement à une fréquence fixe à la place. Changement les fréquences pendant le zoom se sont révélées non seulement déroutantes pour l'utilisateur moyen des graphiques financiers, mais les utilisateurs expérimentés ont été ennuyés parce qu'ils voulaient des fréquences fixes. " Tout à fait d'accord - c'est pour les graphiques pour les utilisateurs informatifs / non commerciaux. Les utilisateurs de trading ont des besoins différents.

@danielgindi Re "faire abstraction de la source de données" c'est peut-être quelque chose

Quelqu'un a-t-il joué avec le fractionnement du code de dessin pour séparer les threads (CALayer.drawsAsynchronously)? Cela pourrait aider au cas où cela permettrait de dessiner des extras de graphique, chaque jeu de données, la grille et les axes séparément. Compte tenu de ma très humble expérience avec CoreGraphics (lire; rien du tout ;-)), je n'ai fait aucune expérience avec cela, je l'ai juste trouvé lorsque je cherchais GLKit et comment il pourrait améliorer les performances du graphique.

J'avais besoin de montrer un graphique en chandelier avec 10k points de données, j'ai donc effectué des mesures de temps sur CandleStickChartRenderer.drawDataSet ().

Il s'est avéré que la plupart du temps est passé à appeler dataSet.entryIndex (lignes 76,77).

Je me trompe peut-être, mais il semble que l'appel dataSet.entryIndex () est redondant car _minX, les valeurs _maxX sont toujours égales au minx, maxx renvoyé par dataSet.entryIndex ()

J'ai réussi à créer un graphique en chandelier avec 10k points de données pan / zoom en douceur. en changeant
CandleStickChartRenderer.swift, ligne 76,77 de:

var minx = max (dataSet.entryIndex (entrée: entryFrom, isEqual: true), 0);
var maxx = min (dataSet.entryIndex (entrée: entryTo, isEqual: true) + 1, entries.count);

à

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

J'ai apporté la même modification à LineChartRenderer et j'ai pu afficher un graphique combiné bougie / ligne avec 2 séries de données (10k points de données chacune)

Wow, c'est une augmentation massive des performances @dorsoft !

Je viens de tester ça et je n'en croyais pas mes yeux. Même sur un iPad 2 avec 4 CombinedCharts affichant jusqu'à trois ensembles de données chacun avec 250 points de données chacun et des calculs automatiques min / max de l'axe y, nous pouvons maintenant effectuer un panoramique et un zoom sur tous les graphiques simultanément de manière assez fluide. Ce n'est pas 60fps, mais proche. Impressionnant pour un appareil aussi ancien et BIEN (!) Plus rapide que la solution commerciale OpenGL dont nous avons parlé plus tôt.

Je suppose que je dois essayer ceci :) Et que je dois discuter avec Phil aussi pour
comprendre s'il y a des implications ...

Je viens de lire ceci, ça a l'air très intéressant mais ça va nécessiter des tests intensifs pour voir si cela convient réellement à tous les scénarios :-)

J'ai créé un PR avec une amélioration des performances du graphique en bougies.
L'amélioration a été testée de manière approfondie en utilisant des valeurs min / max et nil d'échelle automatique.

J'ai trouvé un goulot d'étranglement possible. Dans un graphique en temps réel En ajoutant de nombreuses entrées par seconde au graphique, j'ai remarqué que automatiquement le calcMinMax de l'ensemble de données est appelé juste après CHAQUE values.append(e)

La fonction calcMinMax détermine les valeurs min et max à l'aide de .forEach, ce qui fait que le processeur passe plus de 60% à boucler les valeurs, de plus dans le thread principal.

J'effectue une expérience en désactivant le calcul min / max ou en utilisant la boucle for native au lieu du tableau .forEach

@danielgindi s'il vous plaît jeter un oeil, est-ce vraiment calcMinMax sur toutes les valeurs nécessaires? Je calcule manuellement les valeurs min / max Y dans mon code et uniquement sur les valeurs visibles , vous pourriez donc peut-être exposer des

```
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 Veuillez en faire un ticket séparé et je

@jjatie Merci, il suffit d'ouvrir le # 3166

Je charge plus de 13000 enregistrements dans des graphiques linéaires pour iOS. Mais, les graphiques gèlent l'interface utilisateur lors du chargement. De plus, après le chargement Si l'utilisateur sélectionne un point, cela prend également trop de temps pour mettre la sélection en surbrillance.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

newbiebie picture newbiebie  ·  3Commentaires

coop44483 picture coop44483  ·  3Commentaires

BrandonShega picture BrandonShega  ·  4Commentaires

anhltse03448 picture anhltse03448  ·  3Commentaires

guoyutaog picture guoyutaog  ·  3Commentaires