Disposable Canvas?

  • Thread starter Thread starter Jon Davis
  • Start date Start date
Jon Davis said:
Exactly. It also lacks 3D capabilities. For that matter, Silverlight isn't
even the same rendering codebase; in fact it has nothing in common with
WPF except shared linguistics, but even the XAML parser is different.

Yep, the rendering of WPF uses MIL in top of Direct3D, not something that is
available cross-browser and cross platform. The current WPF stack is just to
heavy weight to be usable server side.
Silverlight is also COM-based on the outset, which is how/why it supports
being driven by JScript, although I'm not sure that matters if one can
avoid touching its COM interfaces.

SilverLight v1.1 (currently in pre-beta) supports C#, Ruby, Python and VB in
addition to JScript, the version for MAC isn't COM based at all, while on
windows it's only used to interface with the JScript engine.

Willy.
 
Willy Denoyette said:
Yep, the rendering of WPF uses MIL in top of Direct3D, not something that
is available cross-browser and cross platform. The current WPF stack is
just to heavy weight to be usable server side.

You continue to make some pretty blanket pronouncements about this not being
usable on a server. Have you ever heard of a queue?!

Jon
 
Jon Davis said:
Once again, I had already posted in this thread that I learned that
instantiating a thread in STA context was not enough, but AspCompat="true"
behaved differently. That said, thank you for explaining what was going on
behind what I had already posted.

Jon



I ran nearly the same code [1] from a console application (in a non pumping
STA thread) and the handle count around 153, while the memory consumption
shows a saw tooth pattern as expected.

// ---[ 1 ] ----
class Program
{
[STAThread]
static void Main(string[] args)
{
Program pr = new Program();
for (int i = 0; i < 100000; i++)
{
pr.GenImageStream();
}
}
private static string GetXaml()
{
string xaml = null;
using (StreamReader sr = new StreamReader(@"..\..\Canvas.xaml"))
{
xaml = sr.ReadToEnd();
}
return xaml;
}

protected void GenImageStream()
{
string xaml = GetXaml();

using (MemoryStream ms = new MemoryStream(xaml.Length))
{
using (StreamWriter sw = new StreamWriter(ms))
{
sw.Write(xaml);
sw.Flush();

ms.Seek(0, SeekOrigin.Begin);

Canvas canvas = (Canvas)XamlReader.Load(ms);
canvas.Background = Brushes.Yellow;
canvas.Measure(new Size(640d, 480d));
canvas.Arrange(new Rect(0d, 0d, 640d, 480d));
RenderTargetBitmap rtb = new RenderTargetBitmap(
640, 480, 96d, 96d, PixelFormats.Default);
rtb.Render(canvas);
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(rtb));
using (Stream outstream = new MemoryStream())
encoder.Save(outstream);
}
}
}
}

Willy.
 
Jon Davis said:
You continue to make some pretty blanket pronouncements about this not
being usable on a server. Have you ever heard of a queue?!

Jon



When I'm talking about "server side" I mean within a "service process"
running on a Server , don't know what queue you mean here though, but if
you think about queuing requests to another service using some IPC
mechanism, the problem remains the same, that service needs to handle all
WPF stuff from a STA thread. Just face it, WPF is client side technology in
V3, just like WIndows.Forms (which is not supported server side!) is in V2,
both are designed to be used from a interactive session running a desktop
like application.
The presentationcore and presentationframework managed libraries libraries,
do load the DWM (Destop Window Manager), the MIL 5Media Integration Layer)
the codecs (windowscodesc.dll) library and a couple of other native
libraries, a number of these libraries are loaded in the middle of the
Virtual address space, cutting the free space available for the GC heap in
pieces (fragmentation!), that means that the largest contiguous space is
less than 500MB on 32 bit Windows. But there is more, it loads also GDI and
USER32, and consumes GDI handles and USER objects and uses extra memory from
both the paged and non paged pooled memory pages, these resources are quite
expensive, on anything lower than Vista, the non paged pool space is shared
among all sessions (interactive or not), on Vista, services run in Session
0, and here this space is even more restricted (Services should not have
UI's on Vista, that is - should not hold into HWND's, should not require
space for the clipboard etc...).
And this whole stuff needs an STA to run in, when used in a service context
like ASP.NET it means that it doesn't scale, this is nothing new, this is
one of the reason asp.net was invented and STA threading abandoned in this
context (aspcompat is for backwards compatibility). Also, the memory
footprint is way to large, your simple sample consumes from ~70MB up to
~135MB committed private bytes (the console version) , this quite some
memory just to render (a nearly empty) XAML as jpeg.
Anyway, if you think you can use this "server side", I won't stop you, but I
won't do it, nor will I ever suggest this as possible solution for the
problem at hand, when I need to render something like this, I will simply
call the windowscodecs library (WIC) from unmanaged code or from mixed mode
C++/CLI code.

Willy.
 

The queue comment was only a least-useful example of usefulness of a
service, where only one image gets generated at a time. It's most certainly
doable.
When I'm talking about "server side" I mean within a "service process"
running on a Server , don't know what queue you mean here though, but if
you think about queuing requests to another service using some IPC
mechanism, the problem remains the same, that service needs to handle all
WPF stuff from a STA thread. Just face it, WPF is client side technology
in V3, just like WIndows.Forms (which is not supported server side!) is in
V2, both are designed to be used from a interactive session running a
desktop like application.
The presentationcore and presentationframework managed libraries
libraries, do load the DWM (Destop Window Manager), the MIL 5Media
Integration Layer) the codecs (windowscodesc.dll) library and a couple of
other native libraries, a number of these libraries are loaded in the
middle of the Virtual address space, cutting the free space available for
the GC heap in pieces (fragmentation!), that means that the largest
contiguous space is less than 500MB on 32 bit Windows. But there is more,
it loads also GDI and USER32, and consumes GDI handles and USER objects
and uses extra memory from both the paged and non paged pooled memory
pages, these resources are quite expensive, on anything lower than Vista,
the non paged pool space is shared among all sessions (interactive or
not), on Vista, services run in Session 0, and here this space is even
more restricted (Services should not have UI's on Vista, that is - should
not hold into HWND's, should not require space for the clipboard etc...).
And this whole stuff needs an STA to run in, when used in a service
context like ASP.NET it means that it doesn't scale, this is nothing new,
this is one of the reason asp.net was invented and STA threading abandoned
in this context (aspcompat is for backwards compatibility). Also, the
memory footprint is way to large, your simple sample consumes from ~70MB
up to ~135MB committed private bytes (the console version) , this quite
some memory just to render (a nearly empty) XAML as jpeg.
Anyway, if you think you can use this "server side", I won't stop you, but
I won't do it, nor will I ever suggest this as possible solution for the
problem at hand, when I need to render something like this, I will simply
call the windowscodecs library (WIC) from unmanaged code or from mixed
mode C++/CLI code.

I conceded from the beginning that executing WPF on a server process was
costly, even to the extent that feasibility was questionable. You don't have
to evidence why WPF isn't supported on the server. We all know this. You
missed the point. Calling it *unusable* as a service is too broad and
blanket a statement. Of course it's usable, if only within very, very
defined limits. Heck, you can use Microsoft Excel's or Word's COM interface
on the server. Would that be scalable? Not very. But it most certainly is
usable. But then you say "I'm not going to stop you" from trying to use it,
well, no, of course you're not, because you can't. Neither will Microsoft.
They have to hold a position on the basis of their intentions; they're
legally required to on the basis of warranting their operating system and
APIs. They cannot support awkward possibilities. My whole life's pattern is
to find things that aren't supposed to work but would be nice if they did,
and see if I can pound that square peg into the round hole.

In the end, I am pretty confident that one can get WPF rendering of XAML to
JPEGs running on a server at 50 nicely rendered images per second with
memory leaks dealt with on a single web server. On some sites that could
support thousands of web users at any given time. The server might require
16 GB of RAM and a couple quad core processors. I might need to scale out,
with multiple machines. That price might be expensive. But don't call WPF
"useless" on the server, because that notion will be disproven 50 times per
second.

Or, heck, "I'm not going to stop you" from making such statements, all they
will do is challenge me and get me motivated to see this through.

Jon
 
... incidentally, one must measure and weigh the cost of such positions. Five
load balancing web servers costing $10,000 each using a quickly constructed
WPF-based image renderer that accepts XAML and spits out very pretty images
at, say, as few as 20 images per second, would cost $50,000 plus, say,
$2,500 (a week or two for one man) to engineer, and only the cost of Adobe
Illustrator artists to maintain and customize the images--say, $75,000 per
year. Whereas, to do it the "right" way, the performant way, using unmanaged
code and C++/CLI, running on a single server, generating 100 images per
second, would cost more like $50,000 to engineer, plus the cost of
engineers' salaries to maintain and customize the images, say $150,000 per
year. And out of that you get crappy output because you didn't leave the
artwork to the artists.
 
I think the crash could be because the Bitmap object isn't disposed off
automatically after it is no longer in use.
 
Back
Top