Re: Delphi Roadmap (by David I)
- From: Lord Crc <lordcrc@xxxxxxxxxxx>
- Date: Wed, 28 Sep 2005 01:52:55 +0200
On Tue, 27 Sep 2005 22:33:31 +1000, "Oliver Townshend"
<oliveratzipdotcomdotau> wrote:
>Well I suppose that will get you the results you want. But it doesn't prove
>5x slower to me. Personally I'd rather see it demonstrated over a broad
>range of benchmarks.
I've made some small tests with code I actually use. I've tested this
with the most similar conditions I could, making sure the code does
not contain some obviously slow parts on either platform (ala the
string = string + char; issue).
The program(s) loads a bitmap, and applies a gaussian blur to it. It
displays the source and processed bitmaps in two TImages. The test
image was 4105x3182 pixels.
All runs were done outside of the IDE, and the two projects were
compiled using fully patched Delphi 2005, with optimizations on,
overflow and range checking off. Memory usage was observed using
Perfmon.
Under win32, my gaussian blur routine uses 3.0-3.1 seconds per run,
and a peak working set of about 240mb during 3 runs, dropping to 80mb
after processing had finished.
Under .net, the routine uses about 9.2-9.6 per seconds run, with a
peak working set of about 410mb during the 3 runs. After the third
run, however, the GC did not clean up memory, and it stayed at 410mb
for at least 30 seconds after processing had finished, at which time I
terminated the app.
In order to access the pixels of the bitmap, I copy the pixels into a
temporary buffer of singles. This also allows me to efficiently access
the entire image in .Net aswell. Under .Net this part took longer than
the actual pixel processing. Without copying to and from this buffer,
the .Net routine used only 4.3-4.5 seconds (vs ~2.5 for win32).
The core routine contains four similar loops looking like this (main
difference is source, dest, and count):
for i:= 0 to Count-1 do
begin
Buffer[bi].r:= (C.B * Src[si].r + (C.b1 * s1.r + C.b2 * s2.r + C.b3
* s3.r));
Buffer[bi].g:= (C.B * Src[si].g + (C.b1 * s1.g + C.b2 * s2.g + C.b3
* s3.g));
Buffer[bi].b:= (C.B * Src[si].b + (C.b1 * s1.b + C.b2 * s2.b + C.b3
* s3.b));
s3:= s2;
s2:= s1;
s1:= Buffer[bi];
inc(si, SrcDelta);
inc(bi);
end;
To me, it shows that one of the problems with .Net and speed, is when
you have to access memory in "special" ways.
If I had a native .Net bitmap loader which would allow direct access
to the pixel buffer, then the .Net code would only run ~3 times as
slow as the SSE optimized win32 code (which uses ~1.5 seconds), or
less than 2 times as slow as a "normal" win32 version.
I'd say this is a real world example. I use this code a lot, and if I
were to port my stuff to .net, it would look a lot similar to what I
used here. It is however just one :)
I'd also like to say that it was nice to see how easily I could port
the routine to .Net using VCL.Net. I had to modify my code to use
arrays instead of pointers, but thanks to SyncEdit it took no time at
all. I only had to write two small routines where I used different
code depending on platform (for copying the pixel data from and back
to a bitmap).
- Asbjørn
.
- Follow-Ups:
- Re: Delphi Roadmap (by David I)
- From: Oliver Townshend
- Re: Delphi Roadmap (by David I)
- References:
- Re: Delphi Roadmap (by David I)
- From: Atmapuri
- Re: Delphi Roadmap (by David I)
- From: Oliver Townshend
- Re: Delphi Roadmap (by David I)
- From: Atmapuri
- Re: Delphi Roadmap (by David I)
- From: Oliver Townshend
- Re: Delphi Roadmap (by David I)
- Prev by Date: Re: Delphi Roadmap (by David I)
- Next by Date: Re: Delphi Roadmap (by David I)
- Previous by thread: Re: Delphi Roadmap (by David I)
- Next by thread: Re: Delphi Roadmap (by David I)
- Index(es):
Relevant Pages
|