A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
This performance difference is not reproduced anymore with Preview 5 of Visual Studio Community 2019 Version 16.8.0
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
I found a noticeable WriteableBitmap performance improvement when executing in Debug in contrast with Release.
Follow results from a simple benchmark program to move 10K Rectangles in the screen:
Debug w/ render by hardware: 185 fps with 40% CPU and 12% GPU.
Release w/ render by hardware: 150 fps with 53% CPU and 25% GPU.
Debug w/ render by software: 150 fps with 50% CPU and 0% GPU.
Release w/ render by software: 30 fps with 35% CPU and 0% GPU.
WriteableBitmap is faster, and CPU and GPU consumption are smaller in Debug than in Release.
I wonder if it is possible to request an enhancement to make WriteableBitmap Release's performance similar or even better than Debug's performance.
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
namespace WpfApp12
{
// Render : Software x Hardware (GPU-3D)
//
// BITMAP BASED
// WriteableBitmap in Image : ( 150* fps, 50% CPU, 0% GPU ) x ( 185 fps, 40% CPU, 12% GPU ) Debug mode, * = skip frames
// WriteableBitmap in Image : ( 30 fps, 35% CPU, 0% GPU ) x ( 150 fps, 53% CPU, 25% GPU ) Release mode
//
// RETAINED / VECTOR MODE
// Shapes in Canvas : ( 22 fps, 52% CPU, 0% GPU ) x ( 22* fps, 52% CPU, 3% GPU ) * = skip frames
// Drawings in Image : ( 14 fps, 48% CPU, 0% GPU ) x ( 14* fps, 52% CPU, 3% GPU ) * = skip frames
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
const int width1 = 1000;
const int height1 = 800;
Stopwatch clock1;
long t1;
int frames_counter = 0;
int num_elements_X;
int num_elements_Y;
int shift = 0;
int max_shift;
byte[] video_array;
WriteableBitmap writeableBitmap;
public MainWindow()
{
InitializeComponent();
Execute(new Size(120, 80)); // Despite number of "elements" does not affect WriteableBitmap performance
}
void Execute(Size size)
{
if (size.Width * 2 > width1) throw new Exception();
if (size.Height * 2 > height1) throw new Exception();
num_elements_X = (int)size.Width;
num_elements_Y = (int)size.Height;
var maxX = width1 - 2 * num_elements_X;
var maxY = height1 - 2 * num_elements_Y;
max_shift = (maxX < maxY) ? maxX : maxY;
SizeToContent = SizeToContent.WidthAndHeight;
ResizeMode = ResizeMode.NoResize;
RenderOptions.SetEdgeMode(this, EdgeMode.Aliased); // don't know how this affect performance.
_ = new DispatcherTimer(new TimeSpan(0, 0, 0, 1), DispatcherPriority.Background, Callback_Title, Dispatcher.CurrentDispatcher);
clock1 = Stopwatch.StartNew();
t1 = clock1.ElapsedTicks;
Content = Setup_ImageBitmap();
var d = Application.Current.Dispatcher;
while (true)
{
Update_ImageBitmap();
d.Invoke(() => 0, DispatcherPriority.Background); // Wait to empty queues to process next frame.
}
}
Image Setup_ImageBitmap()
{
video_array = new byte[width1 * height1 * 4];
writeableBitmap = new WriteableBitmap(width1, height1, 96, 96, PixelFormats.Bgr32, null);
var i = new Image()
{
Stretch = Stretch.None,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Top,
IsHitTestVisible = false,
Source = writeableBitmap
};
return i;
}
void Update_ImageBitmap()
{
Array.Fill<byte>(video_array, 255);
for (var nx = 0; nx < num_elements_X; nx++)
{
for (var ny = 0; ny < num_elements_Y; ny++)
{
var index0 = 4 * (shift + 2 * nx + (shift + 2 * ny) * width1); // B G R A {0,1,2,3}
video_array[index0] = 0; // B=0
video_array[index0 + 1] = 0; // G=1
video_array[index0 + 2] = 0; // R=2
//a1[index0 + 3] = 0; // A=3
}
}
writeableBitmap.WritePixels(new Int32Rect(0, 0, width1, height1), video_array, width1 * 4, 0, 0);
shift++;
frames_counter++;
if (shift > max_shift) shift = 0;
Show();
}
void Callback_Title(object sender, EventArgs e)
{
var t2 = clock1.ElapsedTicks;
var fps = 10000000D / (t2 - t1) * frames_counter;
Title = $"{fps:F1} fps";
frames_counter = 0;
t1 = t2;
}
}
}
I can include the simple benchmark code if necessary.
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
Answer accepted by question author
This performance difference is not reproduced anymore with Preview 5 of Visual Studio Community 2019 Version 16.8.0