По какой-то странной причине вызов функции WinAPI ExtTextOutW для рисования обрезанного текста на растровом изображении с высоким разрешением (2560x1440/3840x2160) приводит к падению производительности ~x50 после обновления Windows 10 с помощью обновления Creators Edition. Из журналов тестирования и отладки моего пользователя видно, что небольшая разница в растровом изображении или, возможно, в размере шрифта может привести к снижению производительности.
Вот журнал отладки, показывающий падение производительности:
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
Как видно из лога, один вызов ExtTextgOutW занимает ~9,5 мс, в то время как этот же вызов занимал менее 1 мс до обновления создателей.
Вот фактический код, который вы можете сравнить с выводом отладки выше:
{$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}
Этот код создает очень простой эффект тени, дважды отображая один и тот же текст с небольшой разницей в Y-смещении и цвете.
Вот полное обсуждение с пользователями моего форума, где мы пытаемся отладить проблему на самых разных аппаратных средствах (дополнительные журналы отладки включены в пост): http://forum.inmatrix.com/index.php?showtopic=14995&page=2
Мы тестировали с DPI, установленным на 100%, чтобы убедиться, что триггер не связан с изменениями DPI, представленными в Creators Edition.
Кто-нибудь знает, что вызывает это? и есть ли обходной путь?
***** обновление 1 *****
По крайней мере, при первоначальном тестировании на "DrawTextExW" также повлияла потеря производительности. Во время тестирования используется шрифт Arial, и проблемы с производительностью, по-видимому, связаны с размером шрифта, поскольку пользователь сообщил, что добавление на экран большего количества строк меньшего размера (больше текста отображается с более низким разрешением) значительно повышает производительность.
***** обновление 2 *****
Я написал небольшой инструмент для профилирования этой проблемы, который вы можете найти в этом репозитории GitHub: https://github.com/bLightZP/WindowsTextRenderingProfiler
Кажется, проблема зависит от размера шрифта, например, на экране 2560x1440 рендеринг строки текста шрифта «Arial» с размером «35» занимает 21 мс, а при размере «34» — 2 мс.
Это визуализируется в HDC Delphi TBitmap с 32-битным форматом пикселей, и отключение отсечения оказывает лишь незначительное влияние на производительность.
***** обновление 3 *****
Ответ Себастьяна Зи ниже действительно восстанавливает уровень производительности версии до создателей, и я обновил пример кода на GitHub, чтобы отразить его ответ, но с тех пор я смог воспроизвести проблему с 64-битной Windows 7 и на экране 1920x1080, так что это не ограничивается выпуском Windows 10 Creators Edition или дисплеями с высоким разрешением, просто порог срабатывания выше, когда для качества шрифта установлено значение ANTIALIASED. В моем тесте под Windows 7 с использованием шрифта Arial точкой срабатывания был размер шрифта «109» (быстрый) по сравнению с размером шрифта «110» (в 10 раз медленнее или хуже производительность). И этот же порог срабатывания существует в Windows 10 после использования ответа Себастьяна З. для отключения прозрачного типа.