Click here to Skip to main content
15,887,683 members
Articles / Programming Languages / XML

Reducing Page Faults

Rate me:
Please Sign up or sign in to vote.
1.73/5 (3 votes)
25 Dec 2018CPOL1 min read 5.1K   31   1   2
Using native GDI will decrease page faults

Introduction

My application does a lot of page faults. From what I found on line, it is unlikely that it should cause any issues, but it got me interested to investigate: what is causing the huge number of page faults, and if there is a way to decrease it.

Background

Few years ago, I was trying to get my 12-year-old son interested in programming (sorry, even kept original name MyFirstGame). As a result, we designed a simple game.
Please note: This article is not about the game - I am just using the game to investigate page faults counts. While you are playing it, using standard .NET graphical objects, you get about 25000-page faults / seconds.

Using the Code

Code has a simple board (5 rows, 4 columns). Squares are randomly placed on each row, and the player should hit the black square to make it go away. If you did not click on it, and it reached the bottom, you lost, if you hit a white square, you lost. Board is drawn inside of the Form1 object, method "Draw", using standard .NET.

When you click on "Use GDI", gdi32.dll is used - in method Draw2. You can see drastic decrease in page faults as you do it.

(To make it easier to observe, I display page faults on screen every second, no need to open Task Manager.)

Also, average draw speed is ~10 times faster using GDI.

Draw method looks like this:

C#
private void Draw(Graphics g)
{
    if (checkBoxUseGDI.Checked)
    {
        Draw2(g);
        return;
    }

    graphics.Clear(Color.White);

    int left = 0;
    int top = board.Top;
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            Rectangle rect = new Rectangle(left, top, 100, 150);

            if (board.Cells[i, j] > -1)
            {
                graphics.FillRectangle(Brushes.Black, rect);
            }

            graphics.DrawRectangle(Pens.Black, rect);

            left += 100;
        }

        top += 150;
        left = 0;
    }
    g.DrawImage(bitmap, 0, 0);
}

Draw2 method looks like this:

C#
private void Draw2(Graphics g)
{
    IntPtr hdc2 = g.GetHdc();
    IntPtr hdc = GDI.CreateCompatibleDC(hdc2);
    IntPtr hBitmap = GDI.CreateCompatibleBitmap(hdc, 401, 601);
    GDI.SelectObject(hdc, hBitmap);
    IntPtr brushWhite = GDI.CreateSolidBrush(0xFFFFFF);
    GDI.FillRgn(hdc, GDI.CreateRectRgn(0, 0, 401, 601), brushWhite);
    GDI.DeleteObject(brushWhite);
    IntPtr brushBlack = GDI.CreateSolidBrush(0x0);

    int left = 0;
    int top = board.Top;
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            GDI.Rectangle(hdc, left, top, left + 101, top + 151);

            if (board.Cells[i, j] > -1)
            {
                GDI.FillRgn(hdc, GDI.CreateRectRgn(left, top, left + 101, top + 151), brushBlack);
            }

            left += 100;
        }

        top += 150;
        left = 0;
    }
    GDI.DeleteObject(brushBlack);

    GDI.BitBlt(hdc2, 0, 0, 401, 601, hdc, 0, 0, GDI.TernaryRasterOperations.SRCCOPY);
    g.ReleaseHdc(hdc2);

    GDI.DeleteDC(hdc);
    GDI.DeleteObject(hBitmap);
}

Points of Interest

I found this website to be very helpful: http://pinvoke.net/default.aspx

History

  • 26th December, 2018: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionPage faults and page faults may be different things Pin
kalberts25-Dec-18 19:33
kalberts25-Dec-18 19:33 
Disclaimer: I have not run your code to verify your figures. Comments below are general observations.

Windows memory administration implements a simplified Most Recently Used, with only a few levels. A memory sweep may remove a page not used for a while from the page tables, but the page is still in memory. When the removed page is adressed, a page fault occurs, but the handler will detect that no disk access is needed; the page is available in RAM and can be re-inserted into the page tables.

Certainly: Keeping the working set small so that the pages in use are not even wiped from the page table will will reduce the time "wasted" by the OS for finding the still valid memory page and getting it back into the page table. But the effect on the running time for the application is drastically lower than if you experienced a "hard page fault", one that actually required a page to be read in from the paging disk.

If your paging device is a flash disk, or even a spinning disk with 64 Mbytes of cache (which isn't that uncommon nowadays), even a "hard page fault" may not require waiting for positioning of the disk arm and rotation of the disk: A request to the disk is be issued, but honored in a fraction of a millisecond.

You may see a number of "real" hard page faults, in particular at application startup or when you open another data file: Executables, or data files, are memory mapped. At opening time, only the page tables are initialized, with no page brought in. The faults you see are the initial retrivals of the disk pages. They do not indicate any paging-out, but a first paging-in, and that cannot be avoided. For data files, this depends on how the application is written: If it does not use memory mapped files, the number of disk accesses are no less, but appear as file system reads/writes - which generally requires more resources!

With today's cost of RAM, for 99% of all systems (and 99,999% of all home systems) there should never be any real need for paging-out causing physical disk accesses. No application intended for private use (and very few for professional use, but there are exceptions) have an active working set in the gigabyte range. The "paged out" page will never be wiped from RAM. Even if it theoretically could happen, it is such a rare event that it has no noticable effect on the performance of your application.
AnswerRe: Page faults and page faults may be different things Pin
Fiwel26-Dec-18 4:27
Fiwel26-Dec-18 4:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.