Z jakiegoś dziwnego powodu wywołanie funkcji ExtTextOutW w WinAPI w celu narysowania przyciętego tekstu w bitmapie o wysokiej rozdzielczości (2560x1440/3840x2160) skutkuje uzyskaniem wydajności ~ x50 po aktualizacji systemu Windows 10 z aktualizacją edycji Creators. Z dzienników testowania i debugowania mojego użytkownika wynika, że niewielka różnica w bitmapach lub rozmiar czcionki może spowodować wzrost wydajności.Zmniejszenie wydajności ExtTextOutW x50 na ekranach QHD/4K po aktualizacji edycji Windows Creators
Oto dziennik debugowania pokazujący spadek wydajności:
10/05/2017 15:51:50 [ 63227,186] : Calculate Rect
10/05/2017 15:51:50 [ 63227,190] : Rect : Left=263, Top=504, Right=3561, Bottom=2155
10/05/2017 15:51:50 [ 63227,193] : Set Shadow Color
10/05/2017 15:51:50 [ 63227,198] : Render Text Shadow
10/05/2017 15:51:50 [ 63236,650] : Set Text Color
10/05/2017 15:51:50 [ 63236,661] : Render Text "Kingdom come Deliverance"
10/05/2017 15:51:50 [ 63246,062] : Rendering complete
Jak widać z dziennika, pojedyncze wywołanie ExtTextgOutW trwa ~ 9.5ms podczas gdy ta sama rozmowa wziął również pod 1ms przed twórcami aktualizacja.
Oto rzeczywisty kod, który można porównać do wyjścia debugowania powyżej:
{$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:\log\.TextRender.txt','Calculate Rect');{$ENDIF}
cRect := Rect(X,Y,Width+X,MainForm.Monitor.Height-(1+(MainForm.Monitor.Height div 540)));
{$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:\log\.TextRender.txt','Rect : Left='+IntToStr(cRect.Left)+', Top='+IntToStr(cRect.Top)+', Right='+IntToStr(cRect.Right)+', Bottom='+IntToStr(cRect.Bottom));{$ENDIF}
{$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:\log\.TextRender.txt','Set Shadow Color');{$ENDIF}
srcColor := txtCanvas.Font.Color;
txtCanvas.Font.Color := OutLineColor;
{$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:\log\.TextRender.txt','Render Text Shadow');{$ENDIF}
Windows.ExtTextOutW(txtCanvas.Handle,X ,Y+(MainForm.Monitor.Height div 540),ETO_CLIPPED,@cRect,@S[1],I,nil);
{$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:\log\.TextRender.txt','Set Text Color');{$ENDIF}
txtCanvas.Font.Color := srcColor;
{$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:\log\.TextRender.txt','Render Text "'+S+'"');{$ENDIF}
Windows.ExtTextOutW(txtCanvas.Handle,X ,Y ,ETO_CLIPPED,@cRect,@S[1],I,nil);
{$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:\log\.TextRender.txt','Rendering complete'+CRLF);{$ENDIF}
Kod ten ma bardzo prosty efekt drop-cień pełniąc ten sam tekst dwukrotnie nieznacznej różnicy w Y- Przesunięcie i kolor.
Oto pełna dyskusja z moich użytkowników forum, na którym staramy się debugować problem na szerokiej gamie sprzętu (dodatkowe dzienników debugowania są zawarte w poście): http://forum.inmatrix.com/index.php?showtopic=14995&page=2
Przetestowaliśmy z DPI ustawione na 100 %, aby upewnić się, że wyzwalacz nie jest powiązany ze zmianami DPI wprowadzonymi w edycji Creators.
Czy ktoś wie, co to powoduje? i czy istnieje obejście?
***** Aktualizacja 1 *****
Przynajmniej w początkowym testowaniu „DrawTextExW” również wydaje się mieć wpływ na utratę wydajności. Czcionka używana podczas testowania to Arial, a problemy z wydajnością wydają się być związane z rozmiarem czcionki, ponieważ użytkownik zgłosił, że dodanie do ekranu mniejszych linii (więcej tekstu jest renderowane w niższej rozdzielczości) znacznie poprawia wydajność.
***** Aktualizacja 2 *****
napisałem małe narzędzie do profilu tego problemu, które można znaleźć w repozytorium GitHub: https://github.com/bLightZP/WindowsTextRenderingProfiler
Wydaje się, że kwestia zależy rozmiar czcionki, na przykład, na ekranie 2560x1440, renderowanie linii tekstu czcionki "Arial" o rozmiarze "35" 21 ms w celu renderowania w rozmiarze "34" zajęło 2 ms.
Jest to renderowane do HDC mapy TBit Delphi w formacie 32-bitowym, a wyłączenie przycinania ma jedynie niewielki wpływ na wydajność.
***** Aktualizacja 3 *****
odpowiedźSebastiana Z. poniżej powoduje przywrócenie wstępnie twórcom poziom wydania wydajności i I zostały zaktualizowane przykładowy kod na GitHub, aby odzwierciedlić jego odpowiedź, ale mam ponieważ udało się odtworzyć problem w systemie Windows 7 64bit i na ekranie 1920x1080, więc nie jest ograniczony do edycji programów dla twórców systemu Windows 10 lub wyświetlaczy o wysokiej rozdzielczości, po prostu próg wyzwalacza jest wyższy, gdy jakość czcionki jest ustawiona na ANTYZONOWANĄ. W moim teście pod Windows 7, używając czcionki Arial, punktem wyzwalania był rozmiar czcionki "109" (szybki) a rozmiar czcionki "110" (x 10 wolniej lub gorzej). Ten sam próg wyzwalania istnieje w systemie Windows 10 po użyciu odpowiedzi Sebastiana Z w celu wyłączenia funkcji cleartype.
Czy spadek wydajności po usunięciu flagi ETO_CLIPPED jest taki sam? Jaką głębią koloru jest bitmapa (np. 24bpp lub 32bpp)? Czy to DIB czy DDB? Najlepiej, jeśli dodasz [mcve], aby użytkownicy SO mogli próbować odtworzyć. – zett42
Zaktualizowałem oryginalny post z linkiem do projektu GitHub, który zawiera kod źródłowy i plik wykonywalny, którego można użyć do przetestowania tego. Aktualizacja zawiera inne szczegóły. – bLight