XAML, RenderTargetBitmap - picture disappears from image after load testing

I'm developing a simple ASP.NET handler that returns image that is rendered using XAML on server side.

The problem that after stress testing picture disappears from returned image (but empty image is still returned). The picture here is XAML canvas (I put it to the bottom of the message) with different shapes and glyphs (rectangles with gradient fill, lines and text with digits).

I tested on Windows 2003 (two processors, four processors), IIS 6.0, .NET 2.0, WinFX RC (February CTP), emulated 250 concurrent users.

I have the following code:

public MemoryStream CreateImageStream(String xaml)
{
object obj = System.Windows.Markup.XamlReader.Load(new XmlTextReader(new StringReader(xaml)));
UIElement canvas = (UIElement)obj;
canvas.Arrange(new Rect(new System.Windows.Point(0, 0), new System.Windows.Size(300, 300)));
canvas.UpdateLayout();

MemoryStream mem = new MemoryStream();
System.Windows.Media.Imaging.RenderTargetBitmap bmp = new System.Windows.Media.Imaging.RenderTargetBitmap(
(int)200, (int)100, 96, 96,
System.Windows.Media.PixelFormats.Pbgra32
);
bmp.Render(canvas);

BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bmp));
encoder.Save(mem);

return mem;
}

Then I write resulting MemoryStream to Response.OutputStream in ASP.NET handler. It works fine if navigate to URL in IE.

I setup load tests for 250 users (each test is just get the same image in PNG format from the site).

After 1 - 2 minutes (I'm using IE to check this) - picture disappears from returned image.

Actions undertaked:

1. I setup remote debugging in VS 2005 and debug the code when the system comes to error state. There are no any exceptions in the code. Everything seems working fine (I went through RenderTargetBitmap, BitmapVisualManager, Renderer, some other code that is in PresentationCore, PresentationFramework and WindowsBase assemblies). Wasn't able to debug MilCore.dll because debug symbols are not available yet.

2. If AppDomain is reloaded (by modifying web.config for instance) - problem is disappeared, everything works fine again (for a while).

3. There is no memory leaks, memory is enough on the machine.

4. Set affinity... to one processor only doesn't help.

Guys from Microsoft please help! We are considering of using SVG or XAML for server side rendering and if this problem will not be resolved soon probably I'll be forced to use SVG. But I like XAML more! :)

Regards,

Andrey

Here is XAML that I used:

<Canvas Width="372" Height="64.8" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Rectangle Canvas.Left="0" Canvas.Top="0" Height="20" Width="200" >
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FF3366FF" Offset="0" />
<GradientStop Color="#FFFFFFFF" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>

<Rectangle Canvas.Left="0" Canvas.Top="5" Height="10" Width="180">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Red" Offset="0" />
<GradientStop Color="Black" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>

<Rectangle Stroke="Red" Canvas.Left="165" Canvas.Top="2" Fill="Black" Height="16" Width="5"/>

<Line Stroke="Blue" X1="0" Y1="20" X2="0" Y2="25"/>
<Line Stroke="Blue" X1="20" Y1="20" X2="20" Y2="25"/>
<Line Stroke="Blue" X1="40" Y1="20" X2="40" Y2="25"/>
<Line Stroke="Blue" X1="60" Y1="20" X2="60" Y2="25"/>
<Line Stroke="Blue" X1="80" Y1="20" X2="80" Y2="25"/>
<Line Stroke="Blue" X1="100" Y1="20" X2="100" Y2="25"/>
<Line Stroke="Blue" X1="120" Y1="20" X2="120" Y2="25"/>
<Line Stroke="Blue" X1="140" Y1="20" X2="140" Y2="25"/>
<Line Stroke="Blue" X1="160" Y1="20" X2="160" Y2="25"/>
<Line Stroke="Blue" X1="180" Y1="20" X2="180" Y2="25"/>

<TextBlock Text="0" FontFamily="Arial" FontSize="8" Canvas.Left="0" Canvas.Top="28" />
<TextBlock Text="1" FontFamily="Arial" FontSize="8" Canvas.Left="18" Canvas.Top="28" />
<TextBlock Text="2" FontFamily="Arial" FontSize="8" Canvas.Left="38" Canvas.Top="28" />
<TextBlock Text="3" FontFamily="Arial" FontSize="8" Canvas.Left="58" Canvas.Top="28" />
<TextBlock Text="4" FontFamily="Arial" FontSize="8" Canvas.Left="78" Canvas.Top="28" />
<TextBlock Text="5" FontFamily="Arial" FontSize="8" Canvas.Left="98" Canvas.Top="28" />
<TextBlock Text="6" FontFamily="Arial" FontSize="8" Canvas.Left="118" Canvas.Top="28" />
<TextBlock Text="7" FontFamily="Arial" FontSize="8" Canvas.Left="138" Canvas.Top="28" />
<TextBlock Text="8" FontFamily="Arial" FontSize="8" Canvas.Left="158" Canvas.Top="28" />
<TextBlock Text="9" FontFamily="Arial" FontSize="8" Canvas.Left="178" Canvas.Top="28" />
</Canvas>




Answer this question

XAML, RenderTargetBitmap - picture disappears from image after load testing

  • rusk50

    "Failed" I mean - picture dissapears from the image. So image is generated successfully and HTTP Request/Response is also OK.

    Image with length of 451 is just visually empty. (But it is still normal PNG image)

    I stress test application in MS VS 2005 for Testers - I use a load test with 250 concurrent users. (It just send the same HTTP GET Request to server). Average request/sec is 101. (I attached picture with Load Test results to zip file that I sent to you by mail).

    I attached the XAML code to my first message in current thread (http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=350088&SiteID=1)

    I sent to you email with attached images, statistics, load tests results and XAML file.

    Regards,

    Andrey



  • Porko

    But why this could happen Any thoughts

    Restarting of AppDomain helps - so, what kind of WPF caches/data could change to corrupted/bad state



  • stayfitsoftware

    I think I'm having the same problems you are, sometimes my png files are the right size but empty.

    I think I got lucky, I have some paths i'm saving to a file, and if I try what you are trying it comes through empty. If I put the paths in a border, measure/arrange the border as well, and render the border, everything comes through fine. Does this work for you


  • LarryWho

    Hi Andrey,



    Let’s drill into the results a bit further…



    The one where there is no picture in the image is curious to me.

    When you say “failed” in these remarks “The first couple failed requests were after 2000 requests:” and “After 17000 requests almost all of them "failed":”, what exactly do you mean Did the file get saved to the server If so, is the image blank

    When you make the 17000 requests, are any of them concurrent or are they all subsequent calls to the page

    If you wouldn’t mind sending me the code snippet of XAML that you’re rendering to the RenderTargetBitmap, that would be wonderful. I can take a look at it a bit further here. My email robertwl_at_microsoft_dot_com.

    Thanks,

    Robert.

  • venkyweb

    I don't know for sure, but it may be a similar problem to what Charles Petzold encountered here: http://www.charlespetzold.com/blog/2006/02/230940.html

    Sam


  • srinivas vasireddy

    Could the problem be in these two lines:

    canvas.Arrange(new Rect(new System.Windows.Point(0, 0), new System.Windows.Size(300, 300)));
    canvas.UpdateLayout();

    According to the docs (http://windowssdk.msdn.microsoft.com/library/default.asp url=/library/en-us/cpref28/html/M_System_Windows_UIElement_Measure_1_7183a95b.asp) you shouldn't have to call UpdateLayout. The docs seem to suggest trying a call to canvas.Measure before canvas.Arrange instead.


  • cbaldo1

    Please be aware...we have not architected WPF with the goal of running well on a server.

    -Rob Relyea
    WPF, PM
    http://longhornblogs.com/rrelyea


  • rebus

    I had posted a message concerning why I added UpdateLayout to this code. (http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=337347&SiteID=1)

    The problem was - I had memory leaks if I didn't call UpdateLayout. Documentation you provided states:

    "Layout updates happen asynchronously, such that the main thread is not waiting for every possible layout change.", "When updating layout, the Measure queue is emptied first, followed by the Arrange queue. An element in the Arrange queue will never be arranged if there is an element in the Measure queue".

    In my scenario main thread never emptied Arrange/Measure queues. Thats why I call UpdateLayout.

    Anyway, I removed UpdateLayout, added Measure call - it doesn't help...



  • saleem145

    I need to do something similar... what is the status of this

    Kevin



  • Tirumala

    Yes, sure, I'm willing to do anything that could help to solve the issue.

    What I did:

    I store all response streams (that differs by size/content) with PNG images to files. So I have 13 different files. And also I stored statistics at each 1000 requests, so for instance after 1000 requests I have:

    Length: 3803, count: 850
    Length: 3808, count: 40
    Length: 3798, count: 1
    Length: 3790, count: 2
    Length: 3804, count: 92
    Length: 3495, count: 1
    Length: 3789, count: 2
    Length: 3794, count: 7
    Length: 3786, count: 1

    Here is Length - image length, count - how many times image with this contcrete length and concrete content was generated.

    The first couple failed requests were after 2000 requests:

    Length: 3801, count: 8
    Length: 3803, count: 1676
    Length: 3808, count: 74
    Length: 3798, count: 3
    Length: 3790, count: 2
    Length: 3804, count: 211
    Length: 451, count: 2 --- there is no picture in this image.
    Length: 3495, count: 1
    Length: 3787, count: 1
    Length: 3789, count: 3
    Length: 3802, count: 1
    Length: 3794, count: 15
    Length: 3786, count: 1

    After 17000 requests almost all of them "failed":

    Length: 3801, count: 10
    Length: 3803, count: 2318
    Length: 3808, count: 107
    Length: 3798, count: 4
    Length: 3790, count: 2
    Length: 3804, count: 302
    Length: 451, count: 14220
    Length: 3495, count: 1
    Length: 3787, count: 2
    Length: 3789, count: 3
    Length: 3802, count: 2
    Length: 3794, count: 27
    Length: 3786, count: 1

    I have PNG images and statistics files ready. I didn't find how to attach the files to this message, so if you want to look at them, please tell me how I should upload them to you.

    Thank you in advance,

    Andrey



  • The Triggerman

    This is an interesting problem. I think that we need to debug this a bit more. Would it be possible for you to try saving the stream to a file on the server before sending it to the ResponseStream Please create a unique file for each request. From there, if you can look at all of the saved files and verify that there is content in them, that would be great.
  • Vincent Vouillon

    We are also investigating wether WPF can generate dynamic server side images for us. What is the status of this problem Is is solved


  • XAML, RenderTargetBitmap - picture disappears from image after load testing