viele, kurze strings in einem View zeichnen ist sehr langsam

  • Na ja, in dem Test mit dem Screenshot gibst Du den Text ja auch zwei mal aus.

    1. mit [layoutManager drawGlyphsForGlyphRange:glyphRange atPoint:NSMakePoint(0,0)]; und 2. über den BezierPath mit [pezierPath fill];

    Da ist es natürlich klar, dass es langsamer wird.

    Erstelle mal den BezierPath mit dem Code aus dem Test ohne [layoutManager drawGlyphsForGlyphRange:glyphRange atPoint:NSMakePoint(0,0)]; und gib den erstellten BezierPath dann einfach mal in der drawRect: Methode aus. Da solltest Du dann eine Geschwindigkeitssteigerung bemerken.
  • Öhm. der Screenshot zeigt doch die Situation, wenn du den Bezier-Pfad beim Zeichnen erst erzeugst!? Du sollst ihn doch vorher erzeugen und cachen.

    +++

    Scherzkeks du sollst nicht ein Bezier-Pfad-Objekt cachen, sondern ein Bezier-Pfad-Objekt mit dem erzeugten fix und foxy Pfad.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Jepp, und dann gibt es zwei Möglichkeiten:

    Entweder den View entsprechend transformieren und den Pfad reinzeichnen. Dann hat man freilich noch eine Transformation*Transformation-Operation im -drawRect:.

    Oder aber, wenn die Pfade häufig unterschiedlich sind, gleich den transformierten Pfad in den Cache schmeißen. Dann muss freilich die Transformation inverse sein.

    Da kommt vieles auf den Einzelfall an. Es gibt übrigens seit einger Zeit ein Drawing-Porformance-Guide mit Tipps & Tricks.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Das ändert nichts daran, dass du den Pfad erst im -drawRect: erzeugst. Wenn du ihn einal zeichnest, wird er bei dir im drawRect: erzeugt. Wenn du 328746283746 Mal zeichnest, wird er bei dir immer noch im -drawRect: erzeugt.

    Du sollst ihn aber cachen.

    BTW: Dein abgebildeter Code funktioniert so ganz gewiss nicht.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • ist das erstellen eines BP im drawRect etwa langsamer als sonstirgendwo?
    das ist eine sampleapp! Ich hab ein view. das alloziere ich und lass es einmal die drawmethode machen. dann wird es beendet. mehr nicht. folgich wird nur einmal gezeichnet. Warum soll ich mir bei einer testapp die mühe machen das erstellen des paths aus dem view rauszunehmen?
  • Wenn du nur eine Instanz des Views erstellen würdest, die nur einmal einen String zeichnet, hast du definitiv kein Performance-Problem.

    Du kannst den Pfad ja auch in der Klasse cachen.

    Wenn sich jedesmal der String ändert, also jeder String nur einmal gezeichnet wird, lohnt es sich in der Tat nicht. Das schrieb ich auch bereits vor etwa 5 Beiträgen.
    Wenn das ein mehr oder weniger fester Text ist, kannst du ihn in Bezier-Pfade umwandeln und diese speichern. Beim Neuzeichnen schmeißt du dann nur die PFade heraus. Das beschleunigt die Sache ungemein.

    Wenn er sich natürlich ständig ändert, bringt das nichts.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von gritsch
    ist das erstellen eines BP im drawRect etwa langsamer als sonstirgendwo?
    das ist eine sampleapp! Ich hab ein view. das alloziere ich und lass es einmal die drawmethode machen. dann wird es beendet. mehr nicht. folgich wird nur einmal gezeichnet. Warum soll ich mir bei einer testapp die mühe machen das erstellen des paths aus dem view rauszunehmen?

    Weil Du sonst nicht erkennen kannst, ob die Ausgabe eines Textes über einen vorhandenen BezierPath schneller ist als über das Text System.

    Darum ging es doch auch in der Fragestellung, oder habe ich hier das Thema verpasst? ?(
  • Original von MCDan
    Original von gritsch
    ist das erstellen eines BP im drawRect etwa langsamer als sonstirgendwo?
    das ist eine sampleapp! Ich hab ein view. das alloziere ich und lass es einmal die drawmethode machen. dann wird es beendet. mehr nicht. folgich wird nur einmal gezeichnet. Warum soll ich mir bei einer testapp die mühe machen das erstellen des paths aus dem view rauszunehmen?

    Weil Du sonst nicht erkennen kannst, ob die Ausgabe eines Textes über einen vorhandenen BezierPath schneller ist als über das Text System.

    Darum ging es doch auch in der Fragestellung, oder habe ich hier das Thema verpasst? ?(


    neine eben nicht. da ich den string nur einmal zeichne (einmal zur laufzeit des programms) kann ich nicht von einem vorhandenen pfad ausgehen. denn den muss ich 1 mal erstellen und genau das mache ich in dem fall im view ;)
  • Ich glaube nicht, dass man das so allgemein sagen kann. Ich glaube vor allem nicht, dass man nicht auf dann noch optimiren kann, wenn man sich auf LM oder BP festgelegt hat.

    Allerdings glaube ich am wenigsten, dass du in der Zwischenzeit die "Drawing Performance Guidelines" durchgearbeitet hast. ;)

    +++

    Beispiel: Bei einem Spiel musst e ich mal in vielen Feldern eine gewisse Anzahl von Symbolen zeichnen. Jedesmal war natürlich die Kombination der Symbole verschieden. Also habe ich mir die Menge aller Symbole in eine Cache gelegt und die Cell jedesmal nur entscheiden lassen, welche Symbole sie zeichnen soll. Das *war* performanter.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • So, jetzt habe ich die einzelnen BezierPaths mal über die passenden affine transformations wieder richtig positioniert. Dies scheint jedoch fast auf die Geschwindigkeit der Ausgabe über das Text System zurück zu fallen. :(

    Weiterhin gibt es noch einen Nebeneffekt, welchen ich nicht ganz verstehe.

    So wird z.B. der Text "izi" richtig umgewandelt, aber der Text "fizi" erzeugt ein zusätzliches Grafiksymbol was dort nicht hin gehört (zu sehen über dem zi von fizi). X(

    Es scheint also auch bei mir wieder auf die Verwendung des Text Systems hinaus zu laufen, da die BezierPaths nur zusäztlichen Speicher verbrauchen und ich kein Risiko bezüglich der Grafikfehler eingehen möchte.

    Mal schauen, wie CoreText unter Leopard damit zurecht kommt und ob ich es dann vielleicht alternativ verwenden kann.
  • Original von Tom9811
    Woher kommt denn das Performance-Problem einen String einmal zu zeichnen? Selbst wenn man das in Marmor meißeln würde, wäre es schnell genug.


    stell dir eine übersichtsseite für bilder/icons vor.
    du packst 200 solche dinger auf die page und unter jedes icon schreibst du dateigröße, erstellungsdatum, änderungsdatum, bildgröße, dpi etc.
    Das machst du mit einem sack voll bildern - so ergeben sich dann jede menge seiten. Diese will man als pdf haben. Folglich wird jedes draw-rect nur einmal aufgerufen.
    ja, das zeichnen der bildchen ist auch nicht gerade hammersschnell, aber immer noch schneller als das zeichnen vom text (und das irritiert mich ein wenig...)
  • Das Problem dürfte bei den Glyphen liegen. Da muss man aufpassen. Ein Zeichen = Ein Glyph geht ziemlich in die Hose.

    Bei dir lohnt es sich gewiss nicht, da nun ja wirklich in jeder Zelle etwas anderes steht und jeder einzelne Eintrag zu komplex ist, als das man mit Kombinationen etwas erzielen könnte. Andererseits würdest du ja nur einzelne Pfade ändern, wenn sich in den Zellen gerade etwas ändert. Ich weiß aber nicht, wie du wann was neu zeichnest.

    Andererseits kannst du die Genauigkeit von Bezier-Pfaden verändern. Das sieht zwar beschissen aus, ist aber etwa bei einem Live-Resize vorteilhaft.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?