Charts: Leistungsverbesserungen

Erstellt am 14. Apr. 2015  ·  44Kommentare  ·  Quelle: danielgindi/Charts

Gibt es Pläne, die Leistung der Bibliothek so zu verbessern, wie es Philip mit MPAndroidCharts getan hat?
Mit seinen Verbesserungen ist es jetzt möglich, Tausende von Datenpunkten auf Android reibungslos zu rendern.
Ich habe einen kurzen Blick auf die ios-chart-Implementierung geworfen und nach dem, was ich gesehen habe, basiert sie auf der ursprünglichen MPAndroidCharts-Implementierung ohne die neuesten Leistungsverbesserungen.

Es wäre ein RIESIGES Plus für die Bibliothek, wenn es auch Tausende von Punkten rendern würde, da es effektiv alle kommerziellen Versionen unbrauchbar machen würde (von denen die meisten sowieso Zeit- und Geldverschwendung sind).

enhancement help wanted

Hilfreichster Kommentar

Ich lade mehr als 13000 Datensätze in Liniendiagrammen für iOS. Diagramme frieren jedoch die Benutzeroberfläche beim Laden ein. Auch nach dem Laden Wenn der Benutzer einen Punkt auswählt, dauert es auch zu lange, um die Auswahl hervorzuheben.

Alle 44 Kommentare

Der ursprüngliche Leistungsengpass in der Android-Version bestand in vielen zusätzlichen Zuweisungen (von Arrays) innerhalb des Rendering-Codes. Der Speicher sollte nicht im Rendering-Code @PhilJay diesen Code in einen vorab zugewiesenen Puffer verschoben und die Renderberechnungen beim Rendern an die Pufferklassen delegiert.

Ich habe mich dafür entschieden, die Renderberechnungen nicht in die Pufferklassen zu verschieben, sondern nur den erforderlichen Speicher auf die gleiche Weise vorzuweisen - aber die Renderberechnungen in derselben Schleife wie der Rendercode zu haben. Auf diese Weise ist es viel einfacher, den Code zu verwalten.

Es ist auch ein Leistungsgewinn, dass die Renderberechnungen nicht innerhalb zusätzlicher Funktionen durchgeführt werden und die Daten nur einmal im Rendering-Code anstatt zweimal wiederholt werden.

Übrigens ist die Leistung in Swift ohnehin weitaus besser als in Java, sodass Sie diesen Leistungszuwachs auch ohne vorherige Zuweisung dieser Arrays gesehen hätten.

Um es grafisch zu erklären, wird / wurde im Rendering-Code Folgendes getan:

  • [RENDERING BEGINNEN]
  • Schleife über DataSets
  • - Array für Punkte dieses DataSet zuweisen. -
  • - Punkte für das Rendern berechnen - _ In der Android-Version in Puffer verschoben_
  • - Rendern Sie diese Punkte
  • [COMMIT RENDERING]

Beachten Sie auch, dass Abstraktionen (Funktionen, Klassen, Vererbung) in Java einen hohen Preis haben. Nicht umsonst hat Google selbst eine wichtige Empfehlung verfasst :

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.

Zusammenfassend:

  • Sie können mit Tausenden von Datenpunkten arbeiten!
  • Ich versuche Phil davon zu überzeugen, Punktberechnungen wieder in Rendering-Schleifen zu verschieben, um die Wartung zu vereinfachen ;-)

Danke für deine Erklärungen Daniel. Ich bin mir jedoch nicht ganz sicher, was ich daraus machen soll.
Was ich getan habe, ist das grundlegendste Projekt einzurichten (siehe den Code unten) und die Leistung ist nicht mit der Android-Version vergleichbar, nicht einmal annähernd, um ganz ehrlich zu sein. Die Verwendung von tausend Datenpunkten führt zu massiven Framedrops, sobald Sie die maximale Anzahl von Datenpunkten anzeigen (vollständig verkleinern), selbst auf den meisten aktuellen iOS-Geräten wie iPad Mini3 und iPhone6. Wie gesagt, MPAndroidcharts können mehrere Tausend auf viel langsameren Geräten rendern, ohne ins Schwitzen zu geraten.

überschreiben 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;
}

Nun, ich habe noch nicht alle Charts auf Leistung getestet - also muss ich das bald tun.
Der Engpass ist wahrscheinlich eine Zuordnung, die ich irgendwo verpasst habe ... Ich werde testen und Sie wissen lassen! :-)

Vielen Dank Daniel. Ich freue mich darauf, was Sie daraus herausholen können. Es wäre fantastisch, einen brauchbaren Begleiter für MPAndroidCharts unter iOS zu haben.

Nun, ich habe ein wenig mit dem LineChartRenderer gespielt (der im Vergleich zum Beispiel zum BarChartRenderer besonders langsam ist), und Instruments sagt, dass der drawPath des CGContext hier der Schuldige ist.
Ich habe versucht, dieses Problem zu beheben, indem ich stattdessen UIBezierPath verwendet habe. Die Leistung ist jedoch dieselbe, sobald Sie stro () auf dem Pfad aufrufen. Vorher ist die Zeichenleistung großartig, aber der Pfad ist in Bezug auf den Start- und Endpunkt gefüllt, nicht das, was wir für ein einfaches Liniendiagramm wollen.
Hoffentlich haben Sie etwas mehr Glück, eine Lösung dafür zu finden.

Ich teste dies gerade und ja, es scheint, dass das tatsächliche CGContextStrokePath unter einer schlechten Leistung leidet.
Einer der Haupttreffer ist die gestrichelte Linie. Beim Deaktivieren verdoppelt sich die Leistung ~. Aber es ist immer noch arm mit tausend Punkten.
Ich lese in Apple-Dokumenten, um herauszufinden, wie CoreGraphics schneller gemacht werden kann

Ja, Core Graphics macht die Pfade definitiv langsam. Es scheint aufgrund der Auflösung zu passieren - die Auflösung auf neueren Apple-Geräten ist sehr hoch, was bedeutet, dass mehr Pixel gerendert werden müssen.

Ich denke, der CG wird auf der CPU anstatt auf der GPU gerendert. Vielleicht weiß jemand einen Weg, das zu ändern?

CG verwendet die CPU definitiv zum Rendern, und soweit ich weiß, gibt es keine Möglichkeit, dies zu ändern.
GPU-Rendering würde leider die Verwendung von OpenGL bedeuten. Schade, dass CG so langsam ist im Vergleich dazu, wie Android dieses Zeug auf der CPU rendert.

Es sind tatsächlich die CPUs der Geräte, die langsam sind. In den meisten Fällen sehr langsam
Die CPU bietet mit iOS eine weitaus bessere Erfahrung als eine schnelle CPU mit Android.

Aber Apple hat nicht über die Fälle nachgedacht, in denen ein optimales Betriebssystem nicht vorhanden ist
ausreichend, um es schnell zu halten.

Ich denke, wenn wir viele Punkte verwenden, können wir Animationen einfach vermeiden - aber
Ich hoffe immer noch, einen Weg zu finden, um die Leistung für die Linie zu verbessern
basierte Diagramme.

Es scheint, dass speziell das Pfadzeichnungssystem langsam ist und wann
Spielen mit Mitre und Flatness und Deaktivieren von gestrichelten Linien und
Antialiasing - die Leistung wird für 500-700 Punkte auf einem viel besser
iPhone 6, aber immer noch ruckelig mit einer 1000

Bei der Verwendung von UIBezierPath besteht möglicherweise eine Chance. Wie gesagt, das Ding ist schnell genug, sobald Sie nicht "Strich" nennen, was dem System im Wesentlichen sagt, dass der Pfad ein Strich ist und nicht vom Startpunkt bis zum Endpunkt gefüllt werden sollte. Ich habe keine Ahnung, was damit im Hintergrund los ist, aber dies zeigt, dass die Grafikzeichnung selbst nicht das Problem für sich ist.

Da ich jedoch keinen Weg finden konnte, den UIBezierPath richtig für das Liniendiagramm zu verwenden, könnte es ein praktikabler Kandidat für die Gitterlinien sein, da man den Pfad zum Zeichnen austricksen könnte, ohne Strich aufzurufen. Auch wenn dies aus API-Sicht "falsch" ist, sollte es eine bessere Leistung bringen.

Der UIBezierPath ist nur ein UIKit-Wrapper um CGPath, CGContextDrawPath,
usw.
Der Leistungsunterschied, der in einigen Fällen beobachtet wird, ist darauf zurückzuführen
Richten Sie zuerst den CG mit den Eigenschaften von UIBezierPath ein
Antialiasing, Gehrungsbegrenzung usw.

Eigentlich gibt es absolut keinen Grund, es zu benutzen, wenn Sie wissen, wie man es benutzt
Kerngrafiken.

Und ja, wir müssen "Schlaganfall" nennen, da wir diesen Pfad streicheln wollen ...
es nicht zu füllen.
In den meisten Fällen ist das Streicheln für das System schwieriger als das Einfüllen von Feststoffen
Farbe, weil es auf die Breite der Linien achten muss, die Verbindungen
zwischen Linien und der Form der Verbindungen.

Am Freitag, den 17. April 2015 um 10:50 Uhr schrieb AlBirdie [email protected] :

Bei der Verwendung von UIBezierPath besteht möglicherweise eine Chance. Wie gesagt, das Ding
ist ausreichend schnell, sobald Sie nicht "Schlaganfall" nennen, was im Wesentlichen
teilt dem System mit, dass der Pfad ein Strich ist und nicht aus dem ausgefüllt werden sollte
Startpunkt zum Endpunkt. Ich habe keine Ahnung, was damit los ist
der Hintergrund, aber dies zeigt, dass die Grafikzeichnung selbst nicht die ist
Ausgabe von selbst.

Da ich jedoch keinen Weg finden konnte, den UIBezierPath richtig zu verwenden
Im Liniendiagramm könnte es ein brauchbarer Kandidat für die Gitterlinien sein
könnte den Pfad zum Zeichnen austricksen, ohne Strich aufzurufen. Auch wenn das so ist
Aus API-Sicht "falsch", sollte dies zu einer besseren Leistung führen.

- -
Antworte direkt auf diese E-Mail oder sieh sie dir auf GitHub an
https://github.com/danielgindi/ios-charts/issues/29#issuecomment -93937181
.

@danielgindi Haben Sie darüber nachgedacht, wenn die Animation die Dinge verlangsamt, wie wäre es, wenn Sie alle Linien ohne Animation zeichnen und eine Maskenansicht verwenden, die sie abdeckt, und dann die Maskenansicht animieren, um die Animation zu imitieren?

Das ist eine großartige Idee! :) :)

Obwohl es einen Nachteil gibt:
Es wird die Art von Animationen lähmen, die Sie damit machen können. wie wir erlauben
Animieren der Y-Achse, damit das Diagramm "wächst" und wie sich die Linie füllt
auf der X-Achse ist auch anders als wenn es nur einen Strich gibt.

Meine Liste der Dinge, die Sie ausprobieren sollten, sind:

  1. Verbessern Sie irgendwie CoreGraphics oder erhöhen Sie einen Teil des Renderings auf das
    GPU

    1. Rendern Sie alle Animationsframes vorab - dies verzögert den Start der Animation und

      verbrauchen eine beträchtliche Menge an Speicher

    2. Ihre Maskierungsidee, die die Art der Animationen einschränkt

Wenn es andere Ideen gibt, würde ich sie gerne hören!

Daniel, hast du schon versucht, die Arbeit auf die GPU zu verlagern?
Ich bin wirklich sehr, sehr unzufrieden mit der kommerziellen Lösung, mit der wir derzeit arbeiten (schreckliche API, schrecklich geschlossen und viele Fehler, die zum Absturz der App führen), und wir haben gerne einen so großen Erfolg mit MPAndroidCharts, zu dem wir gerne wechseln würden iOS-Charts eventuell, wenn die Leistung gleich ist. Seien Sie versichert, Ihre Arbeit würde belohnt. ;)

Ich probiere ein paar verschiedene Techniken aus und werde Ihnen in ein paar Tagen ein Update geben!

Am Montag, den 20. April 2015 um 12:38 Uhr schrieb AlBirdie [email protected] :

Daniel, hast du schon versucht, die Arbeit auf die GPU zu verlagern?
Ich bin wirklich sehr, sehr unzufrieden mit der kommerziellen Lösung, die wir derzeit sind
Arbeiten mit (schreckliche API, schrecklich geschlossen, und viele Fehler, die verursachen
die App zum Absturz bringen) und so großen Erfolg mit MPAndroidCharts hatten wir
Ich liebe es, irgendwann zu iOS-Charts zu wechseln, wenn die Leistung auf dem gleichen Niveau ist. Sich ausruhen
versichert, Ihre Arbeit würde belohnt. ;)

- -
Antworte direkt auf diese E-Mail oder sieh sie dir auf GitHub an
https://github.com/danielgindi/ios-charts/issues/29#issuecomment -94408574
.

@AlBirdie, was für einen Leistungsengpass hast du getroffen? Ich besitze derzeit ein Produkt, das Diagramme genau wie iOS-Diagramme zeichnet. Wir hatten bereits intern eine Diagrammbibliothek. Ich mache mir auch Sorgen um die Leistung, derzeit laden wir nur 100-1000 Datensätze, scheint jetzt in Ordnung zu sein.

Ich denke auch darüber nach, in Zukunft auf ios-Diagramme umzusteigen, wenn möglich, aber unsere Bibliothek hatte Gesten, die Konflikte mit ios-Diagrammen haben könnten.

Das Leistungsproblem ist eine langsame Bildrate in Animationen, wenn dies erforderlich ist
Zeichnen Sie 500-1000 Linien in ein Liniendiagramm.

In Bezug auf Gesten verwenden wir Standard-UIGesture-Erkenner, die Sie verwenden
kann deaktivieren, ändern oder damit arbeiten. Alles ist standardisiert. :-)

Am Montag, den 20. April 2015 um 12:53 Uhr schrieb Xuan [email protected] :

@AlBirdie https://github.com/AlBirdie welche Art von Leistung
Engpass, den Sie getroffen haben? Ich besitze derzeit ein Produkt, das nur Diagramme zeichnet
Wie bei iOS-Charts hatten wir bereits intern eine Chartbibliothek. Ich mache mir auch Sorgen
Über die Leistung, derzeit laden wir nur 100-1000 Datensätze, scheint in Ordnung
jetzt.

Ich denke auch darüber nach, wenn möglich in Zukunft auf ios-Charts umzusteigen.
Aber unsere Bibliothek hatte Gesten, die Konflikte mit iOS-Diagrammen haben könnten.

- -
Antworte direkt auf diese E-Mail oder sieh sie dir auf GitHub an
https://github.com/danielgindi/ios-charts/issues/29#issuecomment -94411060
.

@danielgindi Nun , ich denke, wir verwenden die
Was ich jetzt im Kopf habe, ist, dass wenn wir einen Vektor zur Beschreibung Ihrer X + Y-Richtung hätten, es vielleicht eine Chance gibt, den Maskentrick zu verwenden ... freuen Sie sich auf Ihre Ergebnisse!

@ liuxuan30 nur allgemeine langsame Leistung, denke ich. Animationen sind kein Problem, da ich nicht mit ihnen arbeite. Ich arbeite an Finanzdiagrammen, bei denen Sie mehrere Datensätze in einem einzigen Diagramm benötigen (mehrere Aktien + eine Reihe von Indikatoren). Für einen Datenbereich von 250 Elementen, der leicht mehrere tausend Punkte ergibt, die beim Schwenken und Kneifen gleichzeitig gerendert werden müssen. Die kommerzielle Lösung, mit der ich derzeit arbeite, macht das ziemlich gut (mit OpenGL können Sie Tausende von Punkten rendern, ohne die CPU zu überlasten), aber ich bin kein Freund von Closed-Source-Bibliotheken, bei denen Sie Monate auf Fehlerbehebungen warten müssen.
Ich würde mich mit iOS-Diagrammen viel wohler fühlen, zumal die API von MPAndroidCharts einfach unglaublich einfach zu handhaben ist.

Ich sehe, Finanzdaten sind eine Katastrophe. Unser Server muss nur bis zu 1000 Datensätze an das mobile Gerät senden, um die Überlastung zu verringern. Gibt es eine Möglichkeit, OpenGL für iOS-Charts zu verwenden? @ Danielgindi

OpenGL-Unterstützung wäre ein Ass. Ein GPU-gerendertes Liniendiagramm würde wahrscheinlich vorerst ausreichen.
Leider habe ich absolut keine Ahnung von OpenGL, sonst würde ich gerne helfen.

CGContextStrokeLineSegments bietet eine Verbesserung im Gegensatz zur Verwendung von Pfaden. Versuchen Sie dies daher.
Ich versuche immer noch die anderen Möglichkeiten, Dinge zu verbessern :-)

Danke Daniel, ich werde eine kleine Test-App erstellen, die die beiden Versionen gegeneinander ausrichtet, um zu sehen, was was ist. Welche Leistungssteigerungen haben Sie mit den neuen LineSegments erzielt?

@AlBirdie spürst du den Unterschied zu Liniensegmenten?

Außerdem habe ich gerade festgestellt: In Android, um die maximale Leistung zu erzielen, stellen Sie die Hardwareebene ein. In diesem Fall sind die gestrichelten Linien nicht gestrichelt, sondern alle durchgehend.

Wenn Sie also als erstes gestrichelte Linien unter iOS deaktivieren, erhalten Sie auch einen deutlichen Schub!

Aber ich denke, ich kann es tatsächlich mit einem OpenGL ES auf CIImage zeichnen, muss aber sehr vorsichtig sein, denn wenn eine GL-Linie läuft, wenn die App inaktiv ist, stürzt sie ab.

Es besteht auch die Möglichkeit, dass ich durch Vorrendern einer Textur weiterhin Bindestriche zulasse. Es wird einige Arbeit erfordern und es ist nicht meine Hauptpriorität, aber ich starte ein Nebenprojekt einer OpenGL-Ebene, die den CGContext nahtlos ersetzen kann.

Anstatt zum Zeichnen zu OpenGL zu gehen, können Sie auch versuchen, sich auf Core Animation zu reduzieren. Vielleicht könnte die CAShapeLayer- Klasse funktionieren. Apple empfiehlt, beim Rendern eines komplizierten Pfads mehrere CAShapeLayer , sodass Sie das Liniensegment möglicherweise in mehrere Segmente aufteilen müssen. Die Verwendung von Core Animation sollte die Arbeit auf die GPU verschieben.

Seit Jahren verwenden wir in meiner täglichen Arbeit ein kommerzielles Produkt, das, wie oben von @AlBirdie erwähnt, OpenGL in

ps gestrichelte Linien sind meiner Meinung nach ein Kater aus der Zeit, als Computer nicht die Möglichkeit hatten, in Farbe oder sogar Graustufen zu rendern - sie werden nicht benötigt, es sei denn, wir rendern in reines Schwarzweiß und machen etwas, das wie ein altes aussieht Buchbuch mit Buchdruck, sicher? ;) Es ist also weit weniger wichtig, für diese zu optimieren, als für den allgemeinen 10K-Punkte-Fall zu optimieren.

Absolut bei Ihnen @onlyforart bezüglich der gestrichelten Linien.
Angesichts Ihrer Beschreibung Ihrer kommerziellen Diagrammbibliothek frage ich mich, ob wir dasselbe Produkt verwendet haben. :) Wir haben es übrigens endlich über Bord geworfen. Was mich fast drei Monate gekostet hat (selbst das war nicht lang genug, um schwerwiegende Fehler und Einschränkungen (z. B. Fadenkreuz) zu umgehen, dauerte mit iOSCharts ('idiotische Klassenstrukturen';)) nur zwei Wochen. Totale Zeit- und Geldverschwendung.

@ AlBirdie ja das ist der eine. Erwähnen Sie nicht einmal das Fadenkreuz. Hergestellt mit Hilfe von zu viel Newcastle Brown Ale und zweifellos auf den Unternehmensmarkt ausgerichtet (wo eine knorrige API tatsächlich ein positiver Verkaufsfaktor ist, weil sie Kunden in einen teuren Support- / Wartungszyklus einschließt). Wussten Sie die Geschichte dieser Jungs? Tatsächlich waren sie (in ihrer tiefen Vergangenheit) echte Pioniere in der Softwareindustrie. Wie auch immer, es ist Zeit, weiterzumachen und jetzt in die Zukunft zu schauen.
Wir zeichnen hauptsächlich Candlestick-Charts (dies sind Apps für den Finanzsektor). Was ich wirklich für iOS und Android möchte, ist mit HighCharts / HighStock in der HTML5 / Javascript-Welt eigentlich sehr einfach:

  1. große Anzahl von Datenpunkten (10K oder mehr)
  2. automatische Konsolidierung von OHLC-Daten in sinnvollen skalierten Balken (z. B. 1-Stunden-Balken anzeigen, wenn der Zoomfaktor angemessen ist, oder 1-Meter- oder 1-Sekunden-Balken, wenn verkleinert)
  3. reibungsloses Schwenken und Scrollen
  4. Prise zum Zoomen
  5. Überlagern mehrerer Datenreihen und Anmerkungen und Fadenkreuze, einige programmgesteuert und einige durch Benutzerinteraktion, z. B. um einen Grenzpreis festzulegen, werden alle reibungslos wiedergegeben
  6. (Hier ist der Kicker - HighStock hilft dabei nicht! obwohl es mir ziemlich offensichtlich erscheint) Inkrementelles Abrufen von Daten (mit Lookahead), z. B. Abrufen von Daten mit niedriger Auflösung für den gesamten Datensatz und wie bei Karten-Apps das Abrufen der Hi-Rez Daten (z. B. Millisekunden-Tick-Daten) nur für den angezeigten Bereich des Diagramms
    Wir verwenden noch keine iOS-Charts, obwohl sie auf meiner "To-Do" -Liste stehen und näher an die Spitze rücken. Deshalb habe ich noch nicht so viel in den Code geschaut, aber sobald ich das tue - wahrscheinlich nächsten Monat - Ich werde das alles untersuchen.
    Zurück zum Rendern ist die Tendenz von OpenGL zum Absturz, wenn die Umstände nicht perfekt sind, besorgniserregend. GLKit könnte beim Zeichnen von GPUs helfen. Ich hatte mich vor einiger Zeit auch gefragt, ob SpriteKit helfen könnte (das Rendern von Diagrammen ist keine Million Meilen von der Erstellung von Spielen entfernt), aber im Moment scheint GLKit ein besserer Kandidat zu sein.

LOL @onlyforart , du
Ich bin in Bezug auf Ihre Anforderungen im selben Boot (arbeite auch an Finanzprodukten), aber ja, lassen Sie uns zur eigentlichen Zeichnung dieser Diagramme zurückkehren. Wir freuen uns auf Ihre Erkenntnisse in der Zukunft.

@onlyforart , @AlBirdie danke für deine Einblicke :-)

Es ist wirklich schön zu sehen, wie Leute kommerzielle Unternehmensprodukte für unsere Bibliothek fallen lassen, obwohl ich mich schlecht für sie fühle ... Ich bin in Konflikt geraten!

Ich habe gezögert, OpenGL ein Stück davon zu überlassen, weil ich wusste, dass es zu möglichen Abstürzen kommen kann, wenn es nicht perfekt verwaltet wird, und das ist in einer UIKit-App nicht wirklich möglich. Wenn Sie OpenGL zum Erstellen eines Spiels verwenden, ist das Ganze eine OpenGL-Zeichenfläche, und Sie müssen sich keine Gedanken über einen UIKit-Aufruf machen, der versucht, im Hintergrund ein OpenGL-Rendering zu verursachen.

@onlyforart Ihr Punkt über gestrichelte Linien ist richtig, aber leider habe ich Erfahrung mit Kunden, die gestrichelte Linien verlangen. Unter Android gab es einen Fall, in dem der Entwickler die Ebene in eine Hardwareebene ändern musste, um die Leistung zu steigern, und dem Client mitteilte, dass gestrichelte Linien zu durchgezogenen Linien werden. Das sind die Kosten. Und es gibt natürlich eine Option, um den gesamten Zeichencode nach OpenGL zu verschieben, aber das Zeichnen einer einzelnen Linie bereitet Kopfschmerzen, aber Sie können eine Textur für eine gestrichelte Linie erstellen und damit arbeiten. Sie wollten nicht dafür bezahlen, also waren gestrichelte Linien sicherlich nicht so kritisch, aber sie machten viel Lärm darüber.

Ein Hinweis für mich: Versuchen Sie, GLKit für das Rendern zu verwenden. Schau was passiert.

Und wenn ich Ihre Liste nehme:

  1. _ "große Anzahl von Datenpunkten (10K oder mehr)" _ - wir arbeiten daran :) Ich kann nicht über Android sagen, da das Verschieben auf GL eine noch größere PITA sein wird, aber es hat bereits eine ziemlich gute Leistung von Nutzung der Hardwareschicht, die alle Zeichnungen auf der GPU ausführt.
  2. _ "automatische Konsolidierung von OHLC-Daten in vernünftig skalierten Balken" _ - wir werden die Approximationsfilter sehr bald einsetzen, also denke ich, dass sich das darum kümmern wird. Anstatt viele 1-Meter-Balken zu haben, die Sie nicht lesen können, haben Sie einen ungefähren 1-Stunden-Balken usw.
  3. _ "reibungsloses Schwenken und Scrollen" _ - fertig :-)
  4. _ "Prise zum Zoomen" _ - fertig :-)
  5. _ "Überlagern mehrerer Datenreihen sowie Anmerkungen und Fadenkreuze" _ - Ich weiß nicht, ob ich das richtig verstehe, aber derzeit gibt es das kombinierte Diagramm, das mehrere Diagrammtypen überlagern kann, und jeder Diagrammtyp kann mehrere Datensätze akzeptieren. Darüber hinaus können Sie sich jederzeit in ViewPortHandler einbinden und Koordinaten erfassen, sodass Sie das gewünschte Zeichen überlagern können
  6. Inkrementelles Abrufen von Daten - Wir planen, die Datenquelle zu abstrahieren, während wir weiterhin über die alten APIs zum Festlegen statischer Datensätze verfügen (es handelt sich lediglich um eine integrierte Datenquelle, die mit diesen Datenmengen funktioniert). Ich denke, dass dies auch Ihren Anforderungen entspricht, aber wir wissen noch nicht, wann wir dazu kommen werden

@ Danielgindi , fühle dich nicht schlecht für sie. Wenn es sich bei dem Produkt, das Sie entwickeln, im Grunde genommen um eine faule Tomate handelt und Sie dennoch einen ernsthaften Teig dafür verlangen, werden die Leute irgendwann zu einem anderen Produkt wechseln. Daran ist nichts auszusetzen. Ich entwickle seit einigen Jahren Finanzdiagramme, habe so ziemlich alle Lösungen für iOS verwendet, die es derzeit gibt, und habe damals tatsächlich meine eigene Diagramm-Engine in ActionScript3 geschrieben, daher bin ich ziemlich zuversichtlich, das zu sagen iOSCharts und MPAndroidCharts sind in der Tat die einzigen Produkte, die ich derzeit jedem Entwickler empfehlen kann, der Diagramme in seiner App benötigt. Alles andere da draußen schneidet es einfach nicht.

In Bezug auf die zweite Anforderung muss es optional sein, wenn ihr dies implementieren wollt. Wir haben diese Art der Konsolidierung in einem unserer Charting-Produkte und die Kunden bewegen sich stattdessen stetig auf eine feste Frequenz. Das Ändern der Frequenzen während des Zooms erwies sich nicht nur als verwirrend für den durchschnittlichen Benutzer von Finanzdiagrammen, sondern auch als Hauptbenutzer, die feste Frequenzen wollten.

Wir hätten nie gedacht, dies den Benutzern aufzuzwingen! Sie können sehen, dass der Code bereits die Filter enthält, und in MPAndroidCharts können Sie sehen, dass die Filter in der Vergangenheit durch eine Eigenschaft aktiviert wurden, die den Filter festlegt (alle benutzerdefinierten oder integrierten Filter), aber später aufgrund struktureller Änderungen entfernt wurde.

Wenn wir es implementieren, bleibt die Funktionalität gleich - es wird nur ein weiteres cooles Feature sein :-)

@AlBirdie Re "Was die zweite Anforderung

@danielgindi Re "die Datenquelle abstrahieren" Vielleicht ist dies etwas, zu dem wir beitragen könnten, wenn wir Zeit haben. Keine Versprechen, aber ich werde es unserem Rückstand hinzufügen.

Hat jemand damit herumgespielt, den Zeichnungscode in separate Threads aufzuteilen (CALayer.drawsAsynchronously)? Dies kann hilfreich sein, wenn dadurch Diagramm-Extras, jeder Datensatz, das Raster und die Achsen separat gezeichnet werden können. Aufgrund meiner sehr bescheidenen Erfahrung mit CoreGraphics (lesen; überhaupt keine ;-)) habe ich keine Experimente damit durchgeführt. Ich habe es gerade gefunden, als ich nach GLKit gesucht habe und wie es die Diagrammleistung verbessern kann.

Ich musste ein Candle-Stick-Diagramm mit 10.000 Datenpunkten anzeigen, damit ich einige Zeitmessungen mit CandleStickChartRenderer.drawDataSet () durchführen konnte.

Es stellte sich heraus, dass die meiste Zeit für den Aufruf von dataSet.entryIndex (Zeilen 76, 77) aufgewendet wird.

Ich könnte mich irren, aber es sieht so aus, als ob der Aufruf von dataSet.entryIndex () redundant ist, da _minX, _maxX-Werte immer gleich dem von dataSet.entryIndex () zurückgegebenen minx, maxx sind.

Ich habe es geschafft, ein Candle-Stick-Diagramm mit 10.000 Datenpunkten zu erstellen, die reibungslos schwenken / zoomen. durch Austausch
CandleStickChartRenderer.swift, Zeile 76,77 von:

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

zu

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

Ich habe die gleiche Änderung an LineChartRenderer vorgenommen und konnte ein kombiniertes Candle Stick / Liniendiagramm mit 2 Datenreihen (jeweils 10.000 Datenpunkte) anzeigen.

Wow, das ist eine massive Leistungssteigerung @dorsoft !

Ich habe das gerade getestet und konnte meinen Augen nicht trauen. Selbst auf einem iPad 2 mit 4 CombinedCharts, das bis zu drei Datensätze mit jeweils 250 Datenpunkten und automatischen Min / Max-Berechnungen der y-Achse anzeigt, können wir jetzt alle Diagramme auf ziemlich reibungslose Weise gleichzeitig schwenken und zoomen. Es ist nicht 60fps, aber nah. Beeindruckend für solch ein altes Gerät und WAY (!) Schneller als die kommerzielle OpenGL-Lösung, über die wir zuvor gesprochen haben.

Ich denke, ich muss das versuchen :) Und ich muss auch mit Phil darüber diskutieren
verstehen, ob es irgendwelche Implikationen gibt ...

Ich habe das gerade gelesen, sieht sehr interessant aus, aber es wird einige intensive Tests erfordern, um zu sehen, ob es tatsächlich für alle Szenarien geeignet ist :-)

Ich habe eine PR mit Leistungssteigerung für Kerzendiagramme erstellt.
Die Verbesserung wurde gründlich unter Verwendung der Min / Max- und Nullwerte der automatischen Skalierung getestet.

Ich habe einen möglichen Engpass gefunden. In einem Echtzeitdiagramm Beim Hinzufügen vieler Einträge pro Sekunde zum Diagramm habe ich festgestellt, dass der calcMinMax des Datensatzes automatisch direkt nach JEDEM values.append(e) aufgerufen wird

Die Funktion calcMinMax ermittelt die Min- und Max-Werte mit .forEach, wodurch die CPU mehr als 60% der Schleifen der Werte im Hauptthread verbringt.

Ich führe ein Experiment durch, bei dem die Min / Max-Berechnung deaktiviert oder die native for-Schleife anstelle des Arrays .forEach verwendet wird

@danielgindi bitte schauen, schaut wirklich calcMinMax auf alle benötigten Werte? Ich berechne die Min / Max-Y-Werte manuell in meinem Code und nur für sichtbare Werte . Vielleicht können Sie einen Booleschen

```
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 Bitte machen Sie dies ein separates Ticket und ich werde dies priorisieren.

@jjatie Danke, öffne einfach # 3166

Ich lade mehr als 13000 Datensätze in Liniendiagrammen für iOS. Diagramme frieren jedoch die Benutzeroberfläche beim Laden ein. Auch nach dem Laden Wenn der Benutzer einen Punkt auswählt, dauert es auch zu lange, um die Auswahl hervorzuheben.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen