c# - 这种缓慢的 WPF TextBlock 性能是否符合预期?

标签 c# wpf performance textblock

我正在做一些基准测试以确定我是否可以将 WPF 用于新产品。然而,早期的业绩结果令人失望。我做了一个快速应用程序,它使用数据绑定(bind)每 100 毫秒在列表框中显示一堆随机文本,它占用了大约 15% 的 CPU。所以我制作了另一个快速应用程序,它跳过了数据绑定(bind)/数据模板方案,除了每 100 毫秒更新一次列表框内的 10 个 TextBlock 之外什么都不做(实际产品不需要 100 毫秒更新,更像是最多 500 毫秒,但是这是一个压力测试)。我仍然看到 ~5-10% 的 CPU 使用率。为什么这么高?是因为所有的垃圾字符串吗?

这是不使用绑定(bind)的版本的 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 GHz Core 2 Duo、4 GB RAM、Intel 4500 HD 集成显卡。这比我需要在实际产品中开发的硬件要强大一个数量级。

最佳答案

这种缓慢的 TextBlock 性能正常吗?

没有。如此缓慢的 TextBlock 性能绝对不正常。我的经验是 TextBlocks 比这快得多。

我使用您发布的代码进行了多次测试,将更新间隔保持在 0.1 秒,并改变了硬件和 TextBlock 的数量。这是我发现的:

 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 个 TextBlock,将 ItemsPanel 设置为 WrapPanel 以获取列中的数据,并减小 TextBlock 宽度以使所有内容适合屏幕。

我对 200MHz Pentium Pro 的测试可能与您的嵌入式硬件最相关。如果您的应用程序每 0.5 秒更新 10 个 TextBlocks,您预计将使用大约 3% 的 CPU 在 200MHz CPU 上进行更新和重绘。

如果我想让它更快怎么办?

使用数据绑定(bind) TextBlock 列表非常方便,但 WPF 还提供了较低级别的机制,可在您需要绝对最大性能时使用。

一个WPF TextBlock实际上包含一个格式化的文档而不仅仅是一个字符串,所以它是一个非常复杂的数据结构。编写您自己的 TrivialTextBlock 控件非常简单,该控件具有一个字符串参数并使用继承的 TextElement 属性(例如 FontSize、FontWeight 等)简单地绘制它。通常不会这样做,因为 TextBlock 对于几乎所有用途来说都足够快。

另一个考虑因素是,每次更改 TextBlock 中的文本时,WPF 都会重新计算布局。与旧技术不同,WPF TextBlock 的内容可以非常轻松地更改 UI 的布局。因此,每次更改文本时都必须重新测量和重新格式化。创建前面提到的 TrivialTextBlock 控件也可以通过固定控件大小来加快速度,从而避免布局传递。

第三个考虑因素是 WPF 的文本格式化程序具有高级排版功能,支持字距调整、双向文本、连字、Unicode 功能、自定义字体粗细等。要在 WPF 中获得绝对最佳性能,您可以完全绕过文本格式化程序并将您的文本绘制为一系列图像。这需要大约 20 行 XAML 和大约 40 行 C# 代码。

所有这些优化都是可能的,但在您的情况下我不会为它们操心:这样做只是为了节省 3% 的 CPU 使用率可能不值得。

关于c# - 这种缓慢的 WPF TextBlock 性能是否符合预期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2465181/

相关文章:

c# - 使用 SQLite 进行可靠的插入

c# - 什么时候使用 HttpBindNever 属性?

c# - WPF MarkupExtension 和 RowDefinition 导致 NotImplementedException

c# - 在 INotifyPropertyChanged 之后更新控件

wpf - 将参数传递给自定义控件 ViewModel、MVVM

java - Java中临时变量的效率

c# - Crystal 报表查看器未显示与在 Crystal 报表中打开的报表相同的报表布局

c# - 导出数据表时如何去除export to excel警告

javascript - 为什么 Facebook 按钮仅在所有图像加载后才出现?

javascript - 从函数返回内部变量与直接返回值之间有区别吗