Подтвердить что ты не робот

Ожидается ли медленная производительность WPF TextBlock?

Я делаю некоторый бенчмаркинг, чтобы определить, могу ли я использовать WPF для нового продукта. Однако ранние результаты работы разочаровывают. Я сделал быстрое приложение, которое использует привязку данных, чтобы отображать кучу случайного текста внутри окна списка каждые 100 мс, и он потреблял ~ 15% CPU. Поэтому я сделал еще одно быстрое приложение, которое пропустило схему привязки данных/данных и ничего не делает, кроме обновления 10 текстовых блоков, которые находятся внутри 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% CPU в соответствии с диспетчером задач или примерно до 20% от одного из ядер! Любые идеи для лучшего способа быстрого рендеринга текста?

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

4b9b3361

Ответ 1

Является ли эта медленная производительность 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 текстовых блоков, установка ItemsPanel в WrapPanel для получения данных в столбцах и уменьшение ширины TextBlock, чтобы все было на экране.

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

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

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

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

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

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

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

Ответ 2

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

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

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

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

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

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

Ответ 3

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

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

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

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

Удачи!