Schlechte Leistung mit DrawText auf Win7 x64

8

Ich habe bemerkt, dass ich in einer MFC-Anwendung entwickle, während ich die Bildlaufleiste ziehe, um sanft das Dokument herunterzuscrollen, die Bildrate fällt ab, wenn ein Block mit einem Textabschnitt auf dem Bildschirm ist, aber seidig glatt, wenn er ist Offscreen. Bei der Untersuchung der Leistung fand ich den einzelnen CDC::DrawText -Aufruf für den Textabschnitt verantwortlich. Dies ist in einem optimierten Release-Build.

Ich habe QueryPerformanceCounter verwendet, um eine hohe Auflösung von nur dem DrawText-Aufruf zu erhalten, wie folgt:

%Vor%

Der Text ist Unicode, lorem-ipsum Stil Filler, 865 Zeichen lang und umschließt 7-und-ein-Bit-Linien mit dem Rechteck und der Schriftart (Segoe UI, lfHeight = -12, eine Standard-Textgröße) . Von meinen Messungen benötigt dieser Aufruf allein durchschnittlich 7,5 ms, mit dem ungeraden Peak bei 21 ms. (Hinweis, um mit einem 60Hz-Monitor Schritt zu halten, erhalten Sie etwa 16 ms, um jedes Update zu rendern.)

Ich habe versucht, einige Änderungen vorzunehmen, um die Leistung zu verbessern:

  • Durch das Entfernen von DT_WORDBREAK wird die Leistung auf etwa 1 ms erhöht (etwa 7 mal schneller), aber wenn nur eine Textzeile auf dem Bildschirm angezeigt wird, gibt es etwas mehr als 7 Zeilen mit Wortbruch, woran es zu liegen scheint Ich bin der Flaschenhals woanders.
  • Ich zeichnete Text im transparenten Modus ( SetBkMode(TRANSPARENT) ). Also habe ich den undurchsichtigen Modus mit einer durchgehenden Hintergrundfüllung versucht. Keine Verbesserung.
  • Ich dachte, ClearType-Rendering könnte schuld sein. Ich habe die Schriftart lfQuality von CLEARTYPE_QUALITY in NONANTIALIASED_QUALITY geändert. Es sah aus wie Mist mit scharfen Kanten und allem, und keine Verbesserung.
  • Laut einem Kommentarvorschlag habe ich eine CMemDC verwendet, aber ich habe sie losgeworden und direkt gezeichnet. Es flackerte wie verrückt, und keine Besserung.

Dies läuft auf einem Windows 7 64-Bit-Laptop mit einem Intel Core 2 Duo P8400 @ 2,26 GHz und 4 GB RAM - ich glaube nicht, dass es als ein langsames System zählt.

Ich rufe DrawText () jedes Mal an, wenn es zeichnet, und das hemmt offensichtlich die Performance mit einer so langsamen Funktion, besonders wenn mehrere dieser Textblöcke gleichzeitig sichtbar sind. Es ist genug, um die Erfahrung träge zu machen. Allerdings kann Firefox eine Seite wie diese in ClearType mit viel mehr Text rendern und scheint damit gut zurecht zu kommen. Was mache ich falsch? Wie kann ich die schlechte Leistung eines tatsächlichen DrawText-Aufrufs umgehen?

    
AshleysBrain 25.11.2010, 20:54
quelle

5 Antworten

6

Das Zeichnen des Textes bei jeder Aktualisierung ist verschwenderisch. Verwenden Sie double buffering , dh, zeichnen Sie eine Offscreen-Bitmap und blit sie einfach auf den Bildschirm. Dann scrollen Sie einfach zum Scrollen den größten Teil der Bitmap nach oben oder unten oder seitwärts und zeichnen dann nur den ungültigen Bereich (bevor Sie das Ergebnis auf den Bildschirm blitzen).

Wenn sich das sogar als zu langsam herausstellt, behalten Sie den gezeichneten Text in einer Offscreen-Bitmap und blit anstelle von draw.

Prost & amp; hth.,

    
Cheers and hth. - Alf 29.11.2010, 15:32
quelle
2

Nach dieser deutsche Blogpost , das Problem hat mit der Unterstützung asiatischer Fonts zu tun. Wenn Sie diese in XP aktivieren, erhalten Sie den gleichen Perf-Treffer. In Vista / 7 sind sie standardmäßig aktiviert und Sie können sie nicht deaktivieren.

BEARBEITEN: Vielleicht hilft vielleicht eine andere Schriftart .. (eine, die keine asiatischen Zeichen enthält).

    
user180326 25.11.2010 21:27
quelle
2

Benutzer können Text in 7 Zeilen in 7 Millisekunden nicht lesen, daher ist der Anruf selbst schnell genug.

Die 60 Hz Bildwiederholfrequenz des Monitors ist völlig irrelevant. Sie müssen nicht denselben Text für jeden Frame neu rendern. Die Grafikkarte sendet glücklich die gleichen Pixel wieder auf den Bildschirm.

Also, ich denke, Sie haben ein anderes Problem. Fragen Sie sich vielleicht über Scroll-Text? Bitte frage nach dem Problem, das du wirklich hast, anstatt anzunehmen, dass DrawText der Schuldige ist.

    
MSalters 26.11.2010 13:26
quelle
1

Um den Text bei Wortumbrüchen zu brechen, muss DrawText immer wieder versuchen, die Breite eines Textblocks zu ermitteln, um zu sehen, ob er passt, und dann den Rest übernehmen und fertigstellen. Dies muss bei jedem Anruf erfolgen. Wenn sich Ihr Text nicht ändert, ist dies ein unnötiger Overhead. Um dieses Problem zu umgehen, können Sie den Text selbst messen und temporäre Zeilenumbrüche einfügen und das DT_WORDBREAK-Flag entfernen.

    
Mark Ransom 27.11.2010 07:01
quelle
0

Haben Sie Direct2D / DirectWrite in Betracht gezogen?

Wie auch immer, es sollte besser funktionieren, wenn Sie den Text einfach einmal auf sein eigenes Mem zeichnen und ihn mit jeder Iteration auf die gewünschte DC-Karte übertragen.

    
Rune Aamodt 30.11.2010 12:55
quelle

Tags und Links