Solved

CreateDIBSection, VirtualAlloc, and GDI performance

Posted on 1998-05-31
11
1,625 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
 
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
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
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

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

This article shows how to make a Windows 7 gadget that extends its U/I with a flyout panel -- a window that pops out next to the gadget.  The example gadget shows several additional techniques:  How to automatically resize a gadget or flyout panel t…
Entering time in Microsoft Access can be difficult. An input mask often bothers users more than helping them and won't catch all typing errors. This article shows how to create a textbox for 24-hour time input with full validation politely catching …
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…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

746 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

12 Experts available now in Live!

Get 1:1 Help Now