Ожидается ли такая низкая производительность WPF TextBlock? - PullRequest
18 голосов
/ 17 марта 2010

Я делаю несколько тестов, чтобы определить, могу ли я использовать WPF для нового продукта. Тем не менее, первые результаты производительности разочаровывают. Я сделал быстрое приложение, которое использует привязку данных для отображения случайного текста внутри поля списка каждые 100 мс, и оно потребляло ~ 15% ресурсов процессора. Поэтому я сделал другое быстрое приложение, которое пропустило схему привязки данных / шаблонов данных и ничего не делает, кроме обновления 10 TextBlocks, которые находятся внутри ListBox каждые 100 мс (для реального продукта не потребуется обновления 100 мс, более как 500 мс, но это стресс тест). Я до сих пор вижу ~ 5-10% загрузки процессора. Почему это так высоко? Это из-за всех мусорных строк?

Вот XAML для версии, которая не использует привязку:

<Grid>
    <ListBox x:Name="numericsListBox">
        <ListBox.Resources>
            <Style TargetType="TextBlock">
                <Setter Property="FontSize" Value="48"/>
                <Setter Property="Width" Value="300"/>
            </Style>
        </ListBox.Resources>

        <TextBlock/>
        <TextBlock/>
        <TextBlock/>
        <TextBlock/>
        <TextBlock/>
        <TextBlock/>
        <TextBlock/>
        <TextBlock/>
        <TextBlock/>
        <TextBlock/>
    </ListBox>
</Grid>

Вот код:

public partial class Window1 : Window
{
    private int _count = 0;

    public Window1()
    {
        InitializeComponent();
    }

    private void OnLoad(object sender, RoutedEventArgs e)
    {
        var t = new DispatcherTimer(TimeSpan.FromSeconds(0.1), DispatcherPriority.Normal, UpdateNumerics, Dispatcher);
        t.Start();
    }

    private void UpdateNumerics(object sender, EventArgs e)
    {
        ++_count;
        foreach (object textBlock in numericsListBox.Items)
        {
            var t = textBlock as TextBlock;
            if (t != null)
                t.Text = _count.ToString();
        }
    }
}

Это потребляет ~ 5-10% ЦП в соответствии с диспетчером задач, или примерно до 20% одного из ядер! Любые идеи для лучшего способа быстрого рендеринга текста?

Мой компьютер: XP SP3, 2,26 ГГц Core 2 Duo, 4 ГБ ОЗУ, интегрированная графика Intel 4500 HD. И это на порядок выше, чем оборудование, которое мне нужно было бы разработать для реального продукта.

Ответы [ 3 ]

41 голосов
/ 18 марта 2010

Является ли эта медленная производительность TextBlock нормальной?

Нет. Такая медленная производительность TextBlock определенно не нормальная . Мой опыт показывает, что TextBlocks гораздо быстрее.

Я провел несколько тестов, используя опубликованный вами код, оставив интервал обновления равным 0,1 с и изменив аппаратное обеспечение и количество текстовых блоков. Вот что я нашел:

 10 TextBlocks, 2.16GHz Core 2 Duo, Radeon 4100 GPU:     CPU Usage "0%"
 10 TextBlocks, 2.16GHz Core 2 Duo, Software rendering:  CPU Usage 1%
100 TextBlocks, 2.16GHz Core 2 Duo, Radeon 4100 GPU:     CPU Usage 8%
100 TextBlocks, 2.16GHz Core 2 Duo, Software rendering:  CPU Usage 18%
 10 TextBlocks, 200MHz Pentium Pro, Software rendering:  CPU Usage 35%
 10 TextBlocks, 200MHz Pentium Pro, No rendering:        CPU Usage 7%

Каждый из этих тестов предполагает, что WPF примерно в 10 раз быстрее, чем показывают ваши измерения. Если ваш код так прост, как кажется, я подозреваю, что с вашим GPU или драйверами DirectX происходит что-то странное.

Обратите внимание, что для 100 тестов TextBlock мне пришлось внести три изменения: добавление 90 TextBlocks, установка ItemsPanel в WrapPanel для получения данных в столбцах и уменьшение ширины TextBlock, чтобы все помещалось на экране.

Мой тест на 200 МГц Pentium Pro, вероятно, наиболее актуален для вашего встроенного оборудования. Если ваше приложение обновляет 10 TextBlocks каждые 0,5 с , вы можете рассчитывать на использование приблизительно 3% ЦП для обновления и перерисовки на 200 МГц ЦП.

Что если я хочу сделать это еще быстрее?

Использование списка связанных с данными TextBlocks очень удобно, но WPF также предоставляет механизмы более низкого уровня, которые можно использовать, когда вам нужна абсолютная максимальная производительность.

Текстовый блок WPF на самом деле содержит отформатированный документ, а не просто строку, поэтому это очень сложная структура данных. Довольно просто написать свой собственный элемент управления TrivialTextBlock, который имеет строковый параметр и просто рисует его, используя унаследованные свойства TextElement (такие как FontSize, FontWeight и т. Д.). Обычно этого не делается, потому что TextBlock достаточно быстр для почти всех целей.

Еще одним соображением является то, что каждый раз, когда вы изменяете текст в TextBlock, WPF пересчитывает макет. В отличие от старых технологий, содержимое текстового блока WPF может очень легко изменить макет вашего пользовательского интерфейса. Таким образом, текст должен быть переоценен и переформатирован каждый раз, когда вы меняете его. Создание вышеупомянутого TrivialTextBlock элемента управления также может ускорить это, фиксируя размер элемента управления и тем самым избегая проходов макета.

Третье соображение заключается в том, что форматировщик текста WPF имеет расширенные функции типографики, поддерживающие такие вещи, как кернинг, двунаправленный текст, лигатуры, функции юникода, настраиваемые веса шрифтов и т. Д. Чтобы получить абсолютную максимальную производительность в WPF, вы можете полностью обойти форматировщик текста и нарисуйте свой текст в виде серии изображений. Для этого требуется около 20 строк XAML и около 40 строк кода C #.

Все эти оптимизации возможны, но в вашем случае я не стал бы с ними беспокоиться: сделать это, чтобы сэкономить всего лишь 3% использования ЦП, вероятно, не стоит.

4 голосов
/ 18 марта 2010

В WPF многое можно сделать неправильно, если говорить о производительности. Многие люди воспринимают это как приложение win form, веб-страницу html или какую-то гибридную атаку на разработку приложения, и из-за этого существует много плохих оценок WPF.

Я понимаю, что вы пытаетесь провести тестирование производительности, чтобы увидеть, может ли WPF работать на вашей платформе, и хороший пример того, как заставить ваш элемент управления WPF работать для ожидаемого типа нагрузки, можно найти на ниже ссылка.

http://msdn.microsoft.com/en-us/magazine/dd483292.aspx

Petzold проведет вас через процесс оптимизации элемента управления для оптимальной визуализации для загрузки данных, отображаемых в пользовательском интерфейсе.

Чтобы провести честный тест, я бы написал пример приложения, которое будет иметь дело с образцом данных, с которыми вы собираетесь иметь дело, и затем проверите производительность этого кода. Существует большое количество оптимизаций, которые можно применить, чтобы заставить приложение WPF кричать и использовать меньше ресурсов ЦП, но все они зависят от вашего приложения и от того, как оно представляет ваши данные.

Надеюсь, это поможет.

3 голосов
/ 01 февраля 2011

Я бы использовал WPF только для нового продукта, если вы уверены, что ваше оборудование для развертывания достаточно хорошее. С практической точки зрения я думаю, что выделенная видеокарта является минимальным требованием.

Моя команда выбрала WPF для проекта, ориентированного на процессорную платформу Atom, потому что встроенная графика GMA 500 требовала рендеринга WPF уровня 2. Однако по какой-то причине производительность GMA 500 очень низкая, и мы отключили аппаратный рендеринг лучшая производительность. Даже тогда платформа Atom недостаточно мощна для разумной производительности. Я не советую использовать WPF, если нетбуки или что-либо с Intel Atom является частью вашей клиентской базы.

Вот ссылка на открытый у меня вопрос о производительности WPF на GMA 500.

Как предполагает Роб Перкинс, вам может быть лучше с Silverlight 4 для лучшей производительности.

Удачи!

...