Solved

CreateDIBSection, VirtualAlloc, and GDI performance

Posted on 1998-05-31
11
1,646 Views
Last Modified: 2013-12-03
I need to create a bitamp in memory, and draw to it myself without using GDI. I can create the bitmap and allocate its buffer using the following code:

    ZeroMemory(&bi,sizeof(BITMAPINFOHEADER));
    bi.biSize=sizeof(BITMAPINFOHEADER);
    bi.biWidth=width;        
    bi.biHeight=-hite; //top-down format
    bi.biPlanes=1;            
    bi.biBitCount=16;
    bi.biCompression=BI_RGB;  
    bi.biSizeImage=width*hite*2;

    dibsect=CreateDIBSection(NULL,(BITMAPINFO*)
                &bi,DIB_RGB_COLORS,
                (VOID**)(&psurface),NULL,0);

This creates a high-color DIB section, and psurface points to the start of bitmap buffer. Now I can also allocate psurface this way:

    psurface=VirtualAlloc(NULL,width*hite*2,
                 MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);

My question is, if I use GDI to copy the image onto the screen, which way of allocating the bitmap buffer will result in better performance ?

I've tried allocating the buffer both ways and timed the speed of StretchDIBits(), and there's no difference. I'm just thinking, is there any circumstance where one way of allocating the buffer will result in faster GDI performance than the other ?

When you call CreateDIBSection(), the system can know that mostly likely, you're creating a bitmap buffer which will be used by GDI in some way. Can it do something that makes GDI operations on this bitmap faster ? Of course, if CreateDIBSection() calls VirtualAlloc() internally, then there should be no performance difference.
0
Comment
Question by:byang
  • 8
  • 3
11 Comments
 
LVL 22

Expert Comment

by:nietod
ID: 1405383
answer coming.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1405384
To begin with, you really don't want to be using VirtualAlloc().  That can be used when you need  to allocate a huge amount of memory for a sparse array or some other function where you want to make sure that a big block of memory is available, but you don't need it all or don't need it right away.  That's not the case you've got.

You can allocate the memory using LocalAlloc() or GlobalAlloc().  If you are in Win32, you might as well use LocalAlloc().  There is no advantage to GlobalAlloc().  

However, your best bet is either to use "new" to allocate the memory, ot to let the OS allocate it for you.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1405385
I should be more clear.

There is not going to be a difference in the speed of the BitBlt() with any of these methods.  (potentially VirtuallAlloc() could be used to lock the memory in RAM and make things faster.  But that is a bad idea.  More often than not it will slow things down.  The difference is likely to be trivial in either case.)  The reason I said new (or malloc) is better is that the memory allocated will be part of your program and will be under the debuging control of your program.  If you forget to free the memory, your debugger will probably catch it.  If your program rashes, the memory will probably be released.  The other option is to have the CreateDIBSection() alocate the memory.  That is nice because it will figure out the size for you.  That is the only advantage there.  The memory will not be as closely associated with your program, though.  You'r debugger might not detect it if you forget to free it.  If your program crashes, the OS might never free the memory.  (Probaly will, but not necessarily.)
0
Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

 
LVL 3

Author Comment

by:byang
ID: 1405386
I guess I can take this sentence as your answer: "There is not going to be a difference in the speed of the BitBlt() with any of these methods", and the rest is just discussing memory allocation in general ?

I think new and LocalAlloc allocates from the heap, and VirtualAlloc allocates from virtual memory pool. Heaps come from virtual memory pool, so in the end everything is the same, it's just VirtualAlloc uses one segment descriptor per call on x86.

From what I read before, you should use heap for large number of small allocations, like nodes in a linked list. And you can use VirtualAlloc for big chunks. What I have here is a 960000-byte long chunk. You approach to memory allocation is certainly different.


0
 
LVL 22

Expert Comment

by:nietod
ID: 1405387
Only new and malloc allocate from a C program's  (or other high-level language) heap.  LocalAlloc and GlobalAlloc allocate from the operating system's heap, not the program's heap.  (The program's heap is one (or several) chunks from the operating system heap).  Thus you tend to want to allocate with new or malloc rather than LocalAlloc or Globalalloc, because they can make the OS's heap cumbersome.  However, if you need a few very large blocks of memory, it is best to take from from the OS's heap, using LocalAlloc().  This is so it doesn't use up your program's heap.  (Since you won't have too many of these huge blocks, it won't slow down the OS's heap too much).

All these calls are allocating from virtual memory.  VirtualAlloc() is different.  It reserves a chunk of addresses in virtual memory (just like the others), but it doesn't  necessarily provide space in memory or in the swap file for this chunk.  You can use this for huge sparse virtual arrays, like where you have potentiall millions of array entries, but almost all the entries are never used.  You can create an array using virtual alloc where the unsused entries usually won't consume memory.

You rejected my answer, but I'm not sure what you are looking for.  Haven't I answered your question?
0
 
LVL 22

Expert Comment

by:nietod
ID: 1405388
Although I didn't come out and say it.  For a 960K block, I would use LocalAlloc().
0
 
LVL 3

Author Comment

by:byang
ID: 1405389
I see your point. In fact I've seen code using VirtualAlloc to allocate memory with no page committed, then dynamically commit/decommit pages inside exception handler.

Here's how I understand memory allocation: OS has virtual memory pool, each thread has its own heap, which is created by OS using HeapCreate, which calls VirtualAlloc to get the memory, which comes from virtual memory pool. C/C++ RTL also has heaps, which is created using HeapCreate() API call by RTL initialization code.

Now we're moving away from my original question too far, I think. I guess you can give a definite answer to my question only if you know the code of Windows kernel/GDI. I was basicly thinking, when you call CreateDIBSection, OS knows this memory will be accessed by GDI somehow, so it might move it down the list of pages to be swapped out, or something like that.

0
 
LVL 22

Expert Comment

by:nietod
ID: 1405390
>> OS has virtual memory pool, each thread has its own heap,
>> which is created by OS using HeapCreate,

To the best of my knowledge that is not true.   As far as I know the OS does not create heaps for each process, much less each thread.  A high level language, like  C++ can use HeapCreate to create heaps.  But as far as I know VC's C++ only creates two heaps to be shared by all threads (in a process).  (One heap for small sized blocks and one for large.)

>> I was basicly thinking, when you call CreateDIBSection,
>> OS knows this memory will be accessed by GDI somehow,
>> so it might move it down the list of pages to be swapped out,
>> or something like that.

You can use Virtualloc to allocate memory and then lock it in memory so it is not paged out.  That appears as if it will improve performance.  Ussually it will have no effect or it will hinder performance!  The reason it can hinder performance is that paging is handled by the OS on an as needed basis.  You may think that your memory is really important and is being accessed frequently, but you don't know what else is going on in the computer.  There could be dozens of processes that need memory that you could be slowing down and that will actually end up slowing the performance of your process.  If you are right that your memory is being accessed heavily, well then there is no need to lock it because the OS isn't going to swap it out anyway.  If there is a need for the OS to bring in more heavily used memory, let it.  It is only going to do it if the memory is needed more than yours.

By the way.  in these days of 32 to 128 Meg computers, paging to disk probably happens a lot less than you might think.  Virtual memory is more of a mechanism to allow the OS to move things around in physical memory, than a mechanism for expanding RAM.  I'm not saying it doesn't happen, but it probably isn't a performance bottleneck.

Now does this answer your question?  If not, I'm not sure what you are looking for.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1405391
Please explain what it is you are looking for.

>> My question is, if I use GDI to copy the image onto the screen, which way of
>> allocating the bitmap buffer will result in better performance ?

answered.  performance doesn't depend on the way the memory is allocated.  

>> I've tried allocating the buffer both ways and timed the speed of
>> StretchDIBits(), and there's no difference. I'm just thinking, is there any
>> circumstance where one way of allocating the buffer will result in
>> faster GDI performance than the other ?

Answered.  Not in allocating the buffer.  RAM Memory is RAM memory.  You could prevent it from paging to disk, but that tends to slow things down not speed them up.

>> When you call CreateDIBSection(), the system can know that mostly likely,
>> you're creating a bitmap buffer which will be used by GDI in some way. Can
>> it do something that makes GDI operations on this bitmap faster ?

Answered.  It knows you are creating a bitmap, and it does nothing special.  There is nothing special that can be done.

Do you have other questions?
0
 
LVL 3

Author Comment

by:byang
ID: 1405392
OK, answer it again and I'll accept it.
0
 
LVL 22

Accepted Solution

by:
nietod earned 100 total points
ID: 1405393
Nothing else then?
0

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This article describes how to add a user-defined command button to the Windows 7 Explorer toolbar.  In the previous article (http://www.experts-exchange.com/A_2172.html), we saw how to put the Delete button back there where it belongs.  "Delete" is …
For a while now I'v been searching for a circular progress control, much like the one you get when first starting your Silverlight application. I found a couple that were written in WPF and there were a few written in Silverlight, but all appeared o…
This Micro Tutorial will give you a basic overview how to record your screen with Microsoft Expression Encoder. This program is still free and open for the public to download. This will be demonstrated using Microsoft Expression Encoder 4.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…

813 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now