Win32: Minimising desktop heap usage

Started by Dave Pagealmost 19 years ago9 messagespatches
Jump to latest
#1Dave Page
dpage@pgadmin.org

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

Attachments:

desktop_heap.patchtext/x-diff; name=desktop_heap.patchDownload+16-16
#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Dave Page (#1)
Re: Win32: Minimising desktop heap usage

Dave Page <dpage@postgresql.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

#3Dave Page
dpage@pgadmin.org
In reply to: Tom Lane (#2)
Re: Win32: Minimising desktop heap usage

Tom Lane wrote:

Dave Page <dpage@postgresql.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.

Attachments:

desktop_heap2.patchtext/x-diff; name=desktop_heap2.patchDownload+16-16
#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Dave Page (#3)
Re: Win32: Minimising desktop heap usage

Dave Page <dpage@postgresql.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

#5Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#2)
Re: Win32: Minimising desktop heap usage

"Tom Lane" <tgl@sss.pgh.pa.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

#6Dave Page
dpage@pgadmin.org
In reply to: Tom Lane (#4)
Re: Win32: Minimising desktop heap usage

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

Attachments:

desktop_heap3.patchtext/x-diff; name=desktop_heap3.patchDownload+16-16
#7Dave Page
dpage@pgadmin.org
In reply to: Bruce Momjian (#5)
Re: Win32: Minimising desktop heap usage

Gregory Stark wrote:

"Tom Lane" <tgl@sss.pgh.pa.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

#8Magnus Hagander
magnus@hagander.net
In reply to: Tom Lane (#4)
Re: Win32: Minimising desktop heap usage

Tom Lane wrote:

Dave Page <dpage@postgresql.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

#9Magnus Hagander
magnus@hagander.net
In reply to: Dave Page (#6)
Re: Win32: Minimising desktop heap usage

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