Win32: Minimising desktop heap usage

Lists: pgsql-patches
From: Dave Page <dpage(at)postgresql(dot)org>
To: pgsql-patches(at)postgresql(dot)org
Subject: Win32: Minimising desktop heap usage
Date: 2007-10-23 15:08:20
Message-ID: 471E0E64.8050506@postgresql.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-patches

A discussion on -general has been ongoing in which is was discovered
that 8.3 can exhaust the desktop heap allocated to a service with ~45
connections at which point the server will crash.

Desktop heap is allocated by user32.dll and shell32 on a per-process
basis from a 512KB pool for a non-interactive logon (on XP) and 3072KB
pool for an interactive logon. The attached patch removes our direct
dependencies on these DLLs, reducing the overhead from around 9.7KB per
backend to around 3.5KB. This is back in the range we had with 8.2.

Unfortunately, there are still indirect dependencies on user32.dll which
I don't think we'll be able to do anything about. If desktop heap is
still exhausted with larger installations, the allocated heap size can
be increased in the registry.

See
http://blogs.msdn.com/ntdebugging/archive/2007/01/04/desktop-heap-overview.aspx
for more info.

Regards, Dave

Attachment Content-Type Size
desktop_heap.patch text/x-diff 3.1 KB

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Dave Page <dpage(at)postgresql(dot)org>
Cc: pgsql-patches(at)postgresql(dot)org
Subject: Re: Win32: Minimising desktop heap usage
Date: 2007-10-23 15:30:03
Message-ID: 12474.1193153403@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-patches

Dave Page <dpage(at)postgresql(dot)org> writes:
> [ get rid of wsprintf in favor of snprintf ]

+1 for not depending on nonstandard subroutines without need.
But please note the standard locution is snprintf(buf, sizeof(buf), ...
Not sizeof() - 1.

> ! char *tmppath=0;

Please use NULL not 0 ... actually, since the variable is
unconditionally assigned to just below, I'd say this should just be
"char *tmppath;". I don't like useless initializations: if the compiler
is not smart enough to discard them then they waste cycles, and they
also increase the risk of bugs-of-omission in future changes. If
someone were to change things around so that tmppath didn't get assigned
to in one code path, then the compiler would complain about use of an
uninitialized variable --- *unless* you've written a useless
initialization such as the above, in which case the mistake might pass
unnoticed for awhile. So don't initialize a local variable unless
you're giving it an actually meaningful value.

> ! /*
> ! * Note: We use getenv here because the more modern SHGetSpecialFolderPath()
> ! * will force us to link with shell32.lib which eats valuable desktop heap.
> ! */
> ! tmppath = getenv("APPDATA");

Hmm, is there any functional downside to this? I suppose
SHGetSpecialFolderPath does some things that getenv does not...

Otherwise it looks good...

regards, tom lane


From: Dave Page <dpage(at)postgresql(dot)org>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: pgsql-patches(at)postgresql(dot)org
Subject: Re: Win32: Minimising desktop heap usage
Date: 2007-10-23 15:47:33
Message-ID: 471E1795.2030207@postgresql.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-patches

Tom Lane wrote:
> Dave Page <dpage(at)postgresql(dot)org> writes:
>> [ get rid of wsprintf in favor of snprintf ]
>
> +1 for not depending on nonstandard subroutines without need.
> But please note the standard locution is snprintf(buf, sizeof(buf), ...
> Not sizeof() - 1.

Noted.

>> ! char *tmppath=0;
>
> Please use NULL not 0 ... actually, since the variable is
> unconditionally assigned to just below, I'd say this should just be
> "char *tmppath;". I don't like useless initializations: if the compiler
> is not smart enough to discard them then they waste cycles, and they
> also increase the risk of bugs-of-omission in future changes. If
> someone were to change things around so that tmppath didn't get assigned
> to in one code path, then the compiler would complain about use of an
> uninitialized variable --- *unless* you've written a useless
> initialization such as the above, in which case the mistake might pass
> unnoticed for awhile. So don't initialize a local variable unless
> you're giving it an actually meaningful value.

The downside is that we see a useless warning that, if sufficiently
multiplied, might make it hard to see something we are interested in.

In this case, not initialising it will also create the first 'accepted'
warning in VC++ in our code :-(. All the others come from Kerberos.

Modified in the attached patch however.

>> ! /*
>> ! * Note: We use getenv here because the more modern SHGetSpecialFolderPath()
>> ! * will force us to link with shell32.lib which eats valuable desktop heap.
>> ! */
>> ! tmppath = getenv("APPDATA");
>
> Hmm, is there any functional downside to this? I suppose
> SHGetSpecialFolderPath does some things that getenv does not...

A good percentage of the special folder paths you might query with
SHGetSpecialFolderPath() are not actually in the environment. APPDATA
certainly is on XP, 2K3 and Vista though, and I've found MS KB articles
referring to it being on 2K as well.

Regards, Dave.

Attachment Content-Type Size
desktop_heap2.patch text/x-diff 3.1 KB

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Dave Page <dpage(at)postgresql(dot)org>
Cc: pgsql-patches(at)postgresql(dot)org
Subject: Re: Win32: Minimising desktop heap usage
Date: 2007-10-23 15:54:16
Message-ID: 19055.1193154856@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-patches

Dave Page <dpage(at)postgresql(dot)org> writes:
> Tom Lane wrote:
>> So don't initialize a local variable unless
>> you're giving it an actually meaningful value.

> The downside is that we see a useless warning that, if sufficiently
> multiplied, might make it hard to see something we are interested in.

[ looks again... ] Actually, I think you just proved my point for me.
The ZeroMemory call should go away, no? (Does this mean that the
Windows builds fail to detect dereferencing NULL? Bad if so.)

>> Hmm, is there any functional downside to this? I suppose
>> SHGetSpecialFolderPath does some things that getenv does not...

> A good percentage of the special folder paths you might query with
> SHGetSpecialFolderPath() are not actually in the environment. APPDATA
> certainly is on XP, 2K3 and Vista though, and I've found MS KB articles
> referring to it being on 2K as well.

OK, in that case seems no problem.

regards, tom lane


From: Gregory Stark <stark(at)enterprisedb(dot)com>
To: "Tom Lane" <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: "Dave Page" <dpage(at)postgresql(dot)org>, <pgsql-patches(at)postgresql(dot)org>
Subject: Re: Win32: Minimising desktop heap usage
Date: 2007-10-23 15:54:39
Message-ID: 877ildq11c.fsf@oxford.xeocode.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-patches

"Tom Lane" <tgl(at)sss(dot)pgh(dot)pa(dot)us> writes:

>> ! /*
>> ! * Note: We use getenv here because the more modern SHGetSpecialFolderPath()
>> ! * will force us to link with shell32.lib which eats valuable desktop heap.
>> ! */
>> ! tmppath = getenv("APPDATA");
>
> Hmm, is there any functional downside to this? I suppose
> SHGetSpecialFolderPath does some things that getenv does not...

The functional difference appears to be that the environment variable is set
on startup (or login?) and doesn't necessarily have the most up to date value
if it's been changed. But it's not something you're likely to change and you
can always adjust the environment variable manually to fix the problem.

--
Gregory Stark
EnterpriseDB http://www.enterprisedb.com


From: Dave Page <dpage(at)postgresql(dot)org>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: pgsql-patches(at)postgresql(dot)org
Subject: Re: Win32: Minimising desktop heap usage
Date: 2007-10-23 16:09:42
Message-ID: 471E1CC6.1030901@postgresql.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-patches

Tom Lane wrote:
> [ looks again... ] Actually, I think you just proved my point for me.
> The ZeroMemory call should go away, no?

Yup, quite correct. v3 attached.

/D

Attachment Content-Type Size
desktop_heap3.patch text/x-diff 3.1 KB

From: Dave Page <dpage(at)postgresql(dot)org>
To: Gregory Stark <stark(at)enterprisedb(dot)com>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, pgsql-patches(at)postgresql(dot)org
Subject: Re: Win32: Minimising desktop heap usage
Date: 2007-10-23 16:15:04
Message-ID: 471E1E08.1020100@postgresql.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-patches

Gregory Stark wrote:
> "Tom Lane" <tgl(at)sss(dot)pgh(dot)pa(dot)us> writes:
>
>>> ! /*
>>> ! * Note: We use getenv here because the more modern SHGetSpecialFolderPath()
>>> ! * will force us to link with shell32.lib which eats valuable desktop heap.
>>> ! */
>>> ! tmppath = getenv("APPDATA");
>> Hmm, is there any functional downside to this? I suppose
>> SHGetSpecialFolderPath does some things that getenv does not...
>
> The functional difference appears to be that the environment variable is set
> on startup (or login?) and doesn't necessarily have the most up to date value
> if it's been changed. But it's not something you're likely to change and you
> can always adjust the environment variable manually to fix the problem.

If you're hacking the registry to change it then you've only got
yourself to blame if you don't update the environment as well imho.

I also wouldn't be at all surprised if many apps build paths containing
the value returned by SHGetSpecialFolderPath() (or %APPDATA%) at startup
and then use that value from then on rather than repeatedly calling the
API function. It's not like you'd expect the value to change at all
often, if ever.

/D


From: Magnus Hagander <magnus(at)hagander(dot)net>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Dave Page <dpage(at)postgresql(dot)org>, pgsql-patches(at)postgresql(dot)org
Subject: Re: Win32: Minimising desktop heap usage
Date: 2007-10-23 17:49:40
Message-ID: 471E3434.60306@hagander.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-patches

Tom Lane wrote:
> Dave Page <dpage(at)postgresql(dot)org> writes:
>> Tom Lane wrote:
>>> So don't initialize a local variable unless
>>> you're giving it an actually meaningful value.
>
>> The downside is that we see a useless warning that, if sufficiently
>> multiplied, might make it hard to see something we are interested in.
>
> [ looks again... ] Actually, I think you just proved my point for me.
> The ZeroMemory call should go away, no? (Does this mean that the
> Windows builds fail to detect dereferencing NULL? Bad if so.)

Windows builds don't fail to detect that in genereal. ZeroMemory,
however, has a protection specifically against being passed NULL input,
IIRC.

//Magnus


From: Magnus Hagander <magnus(at)hagander(dot)net>
To: Dave Page <dpage(at)postgresql(dot)org>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, pgsql-patches(at)postgresql(dot)org
Subject: Re: Win32: Minimising desktop heap usage
Date: 2007-10-23 18:07:41
Message-ID: 471E386D.7090102@hagander.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-patches

Dave Page wrote:
> Tom Lane wrote:
>> [ looks again... ] Actually, I think you just proved my point for me.
>> The ZeroMemory call should go away, no?
>
> Yup, quite correct. v3 attached.

Great job tracking this down!

Patch looks good from here (after the fixes per Tom).

Applied, many thanks!

//Magnus