我正在做一些基准测试以确定我是否可以将 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/