Inter-process communication

  • Thread starter Thread starter Jon Davis
  • Start date Start date
J

Jon Davis

We're looking at running a memory-intensive process for a web site as a
Windows service in isolation of IIS because IIS refuses to consume all of
the available physical RAM. Considering remoting to move data in and out of
this process. Need something that's quick and dirty and easy to implement,
but that's performant and secure at the same time. Any suggestions /
tutorials? Would prefer not to go on the TCP/IP stack (socket) as it is not
very performant, but it certainly is quick and dirty and we might go with it
anyway anyway unless there is another way with shared memory that is as easy
and more performant.

Jon
 
Jon,

I think that you might want to consider shared memory in this case,
assuming you want to be on the same machine as IIS (although, I have to
question why you would want to starve that machine, and not dedicate another
machine to performing this task, as you run the risk of starving IIS of
resources).

Are you passing massive amounts of data between the processes? If so, I
can't say remoting is a good solution. With remoting, you can marshal
objects by reference, or by value. When passing your massive data buffer
across the app domain boundary, if you pass this by value, you are going to
incur a huge cost in passing that buffer across the app domain boundary.

If your buffer has an affinity to the app domain it is in (derives from
MarshalByRefObject) then you can make calls into the object from the remote
process, but depending on how many calls you have to make to get managable
chunks of data, this might be too expensive as well.

I think that a better solution would be to have a separate machine which
is dedicated to this task, and then sending off the data buffers (or chunks
of them) to the machine to be processed. You can use MSMQ for this, or
maybe even a file drop, in which case, you have something like BizTalk pick
up the file drop. You could use WCF as well, as there is support for large
message sizes (although there is a message buffer limit there as well which
you have to tweak if the buffer is exceptionally large).

Which comes back to shared memory. If you are determined to stay on the
same machine, then you can have the IIS process write to shared memory, then
signal the service to look at a particular block of shared memory to
process. Of course, you will have to write all the coordination routines
yourself (which is going to be a pain as well).

Hope this helps.
 
The memory load could be in the range of 1GB, basically hosting indexes
in-memory for fast access to search thousands of large pieces of data. The
server has 4GB, but IIS never uses more than 1GB, which leaves us 3GB
unused, and also makes IIS vulnerable to running out of RAM if we were to
fill up its tiny 1GB rather than isolate the process.

Would love to offload to another server, but the problem there becomes the
bottleneck of 1gb/s network bandwidth which is more reserved for the other
users who are doing heavy SQL Server queries (and SQL Server is not nearly
as performant for what we are indexing, difference is like 10ms vs. 500ms).
We also then deal with TCP/IP packet encapsulation which is a huge
performance hit.

Shared memory is of course ideal. Problem is I asked about shared memory in
the .NET world a year or two ago and was told it's not possible in the C#
world, you have to use remoting. Or, use C++ (and native APIs) which I am
not privvy to, although if someone can point me to P/Invoke API tutorials
that are relevant to shared memory with C#/.NET I'd be curious.

Jon

Nicholas Paldino said:
Jon,

I think that you might want to consider shared memory in this case,
assuming you want to be on the same machine as IIS (although, I have to
question why you would want to starve that machine, and not dedicate
another machine to performing this task, as you run the risk of starving
IIS of resources).

Are you passing massive amounts of data between the processes? If so,
I can't say remoting is a good solution. With remoting, you can marshal
objects by reference, or by value. When passing your massive data buffer
across the app domain boundary, if you pass this by value, you are going
to incur a huge cost in passing that buffer across the app domain
boundary.

If your buffer has an affinity to the app domain it is in (derives from
MarshalByRefObject) then you can make calls into the object from the
remote process, but depending on how many calls you have to make to get
managable chunks of data, this might be too expensive as well.

I think that a better solution would be to have a separate machine
which is dedicated to this task, and then sending off the data buffers (or
chunks of them) to the machine to be processed. You can use MSMQ for
this, or maybe even a file drop, in which case, you have something like
BizTalk pick up the file drop. You could use WCF as well, as there is
support for large message sizes (although there is a message buffer limit
there as well which you have to tweak if the buffer is exceptionally
large).

Which comes back to shared memory. If you are determined to stay on
the same machine, then you can have the IIS process write to shared
memory, then signal the service to look at a particular block of shared
memory to process. Of course, you will have to write all the coordination
routines yourself (which is going to be a pain as well).

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Jon Davis said:
We're looking at running a memory-intensive process for a web site as a
Windows service in isolation of IIS because IIS refuses to consume all of
the available physical RAM. Considering remoting to move data in and out
of this process. Need something that's quick and dirty and easy to
implement, but that's performant and secure at the same time. Any
suggestions / tutorials? Would prefer not to go on the TCP/IP stack
(socket) as it is not very performant, but it certainly is quick and
dirty and we might go with it anyway anyway unless there is another way
with shared memory that is as easy and more performant.

Jon
 
Jon,

I think that shared memory is very viable. You will have to code it
yourself though, and use a fair amount of P/Invoke. First, I recommend
reading the section of the MSDN documentation titled "Managing Memory-Mapped
Files in Win32", located at:

http://msdn2.microsoft.com/en-us/library/ms810613.aspx

For working with MMFs in .NET, I would recommend creating a class that
derives from Stream which would allow you to work with the MMF. Basically,
you would have the file that you are using as the MMF, and then you would
call the MapViewOfFileEx API function and get the pointer at which you can
start writing. You can then take whereever the user wants to read from
/write to the stream and then offset that value by the pointer returned from
MapViewOfFileEx to find the memory location to read from/write to.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Jon Davis said:
The memory load could be in the range of 1GB, basically hosting indexes
in-memory for fast access to search thousands of large pieces of data. The
server has 4GB, but IIS never uses more than 1GB, which leaves us 3GB
unused, and also makes IIS vulnerable to running out of RAM if we were to
fill up its tiny 1GB rather than isolate the process.

Would love to offload to another server, but the problem there becomes the
bottleneck of 1gb/s network bandwidth which is more reserved for the other
users who are doing heavy SQL Server queries (and SQL Server is not nearly
as performant for what we are indexing, difference is like 10ms vs.
500ms). We also then deal with TCP/IP packet encapsulation which is a huge
performance hit.

Shared memory is of course ideal. Problem is I asked about shared memory
in the .NET world a year or two ago and was told it's not possible in the
C# world, you have to use remoting. Or, use C++ (and native APIs) which I
am not privvy to, although if someone can point me to P/Invoke API
tutorials that are relevant to shared memory with C#/.NET I'd be curious.

Jon

Nicholas Paldino said:
Jon,

I think that you might want to consider shared memory in this case,
assuming you want to be on the same machine as IIS (although, I have to
question why you would want to starve that machine, and not dedicate
another machine to performing this task, as you run the risk of starving
IIS of resources).

Are you passing massive amounts of data between the processes? If so,
I can't say remoting is a good solution. With remoting, you can marshal
objects by reference, or by value. When passing your massive data buffer
across the app domain boundary, if you pass this by value, you are going
to incur a huge cost in passing that buffer across the app domain
boundary.

If your buffer has an affinity to the app domain it is in (derives
from MarshalByRefObject) then you can make calls into the object from the
remote process, but depending on how many calls you have to make to get
managable chunks of data, this might be too expensive as well.

I think that a better solution would be to have a separate machine
which is dedicated to this task, and then sending off the data buffers
(or chunks of them) to the machine to be processed. You can use MSMQ for
this, or maybe even a file drop, in which case, you have something like
BizTalk pick up the file drop. You could use WCF as well, as there is
support for large message sizes (although there is a message buffer limit
there as well which you have to tweak if the buffer is exceptionally
large).

Which comes back to shared memory. If you are determined to stay on
the same machine, then you can have the IIS process write to shared
memory, then signal the service to look at a particular block of shared
memory to process. Of course, you will have to write all the
coordination routines yourself (which is going to be a pain as well).

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Jon Davis said:
We're looking at running a memory-intensive process for a web site as a
Windows service in isolation of IIS because IIS refuses to consume all
of the available physical RAM. Considering remoting to move data in and
out of this process. Need something that's quick and dirty and easy to
implement, but that's performant and secure at the same time. Any
suggestions / tutorials? Would prefer not to go on the TCP/IP stack
(socket) as it is not very performant, but it certainly is quick and
dirty and we might go with it anyway anyway unless there is another way
with shared memory that is as easy and more performant.

Jon
 
I forgot to mention that you will have to send signals, through
remoting, or some other technology, to tell the other process that is
sharing the memory mapped file with you when to process, when it's done,
etc, etc.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Nicholas Paldino said:
Jon,

I think that shared memory is very viable. You will have to code it
yourself though, and use a fair amount of P/Invoke. First, I recommend
reading the section of the MSDN documentation titled "Managing
Memory-Mapped Files in Win32", located at:

http://msdn2.microsoft.com/en-us/library/ms810613.aspx

For working with MMFs in .NET, I would recommend creating a class that
derives from Stream which would allow you to work with the MMF.
Basically, you would have the file that you are using as the MMF, and then
you would call the MapViewOfFileEx API function and get the pointer at
which you can start writing. You can then take whereever the user wants
to read from /write to the stream and then offset that value by the
pointer returned from MapViewOfFileEx to find the memory location to read
from/write to.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Jon Davis said:
The memory load could be in the range of 1GB, basically hosting indexes
in-memory for fast access to search thousands of large pieces of data.
The server has 4GB, but IIS never uses more than 1GB, which leaves us 3GB
unused, and also makes IIS vulnerable to running out of RAM if we were to
fill up its tiny 1GB rather than isolate the process.

Would love to offload to another server, but the problem there becomes
the bottleneck of 1gb/s network bandwidth which is more reserved for the
other users who are doing heavy SQL Server queries (and SQL Server is not
nearly as performant for what we are indexing, difference is like 10ms
vs. 500ms). We also then deal with TCP/IP packet encapsulation which is a
huge performance hit.

Shared memory is of course ideal. Problem is I asked about shared memory
in the .NET world a year or two ago and was told it's not possible in the
C# world, you have to use remoting. Or, use C++ (and native APIs) which I
am not privvy to, although if someone can point me to P/Invoke API
tutorials that are relevant to shared memory with C#/.NET I'd be curious.

Jon

Nicholas Paldino said:
Jon,

I think that you might want to consider shared memory in this case,
assuming you want to be on the same machine as IIS (although, I have to
question why you would want to starve that machine, and not dedicate
another machine to performing this task, as you run the risk of starving
IIS of resources).

Are you passing massive amounts of data between the processes? If
so, I can't say remoting is a good solution. With remoting, you can
marshal objects by reference, or by value. When passing your massive
data buffer across the app domain boundary, if you pass this by value,
you are going to incur a huge cost in passing that buffer across the app
domain boundary.

If your buffer has an affinity to the app domain it is in (derives
from MarshalByRefObject) then you can make calls into the object from
the remote process, but depending on how many calls you have to make to
get managable chunks of data, this might be too expensive as well.

I think that a better solution would be to have a separate machine
which is dedicated to this task, and then sending off the data buffers
(or chunks of them) to the machine to be processed. You can use MSMQ
for this, or maybe even a file drop, in which case, you have something
like BizTalk pick up the file drop. You could use WCF as well, as there
is support for large message sizes (although there is a message buffer
limit there as well which you have to tweak if the buffer is
exceptionally large).

Which comes back to shared memory. If you are determined to stay on
the same machine, then you can have the IIS process write to shared
memory, then signal the service to look at a particular block of shared
memory to process. Of course, you will have to write all the
coordination routines yourself (which is going to be a pain as well).

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

We're looking at running a memory-intensive process for a web site as a
Windows service in isolation of IIS because IIS refuses to consume all
of the available physical RAM. Considering remoting to move data in and
out of this process. Need something that's quick and dirty and easy to
implement, but that's performant and secure at the same time. Any
suggestions / tutorials? Would prefer not to go on the TCP/IP stack
(socket) as it is not very performant, but it certainly is quick and
dirty and we might go with it anyway anyway unless there is another way
with shared memory that is as easy and more performant.

Jon
 
Hello!
You wrote on Thu, 5 Apr 2007 10:32:44 -0700:

JD> Shared memory is of course ideal. Problem is I asked about shared
JD> memory in the .NET world a year or two ago and was told it's not
JD> possible in the C# world, you have to use remoting. Or, use C++ (and
JD> native APIs) which I am not privvy to, although if someone can point me
JD> to P/Invoke API tutorials that are relevant to shared memory with
JD> C#/.NET I'd be curious.

Check MsgConnect ( http://www.msgconnect.com ), it seems to fit your
requirements.

With best regards,
Eugene Mayevski
http://www.SecureBlackbox.com - the comprehensive component suite for
network security
 
What about System.Runtime.Remoting.Channels.Ipc (Named Pipes implementation
for .NET 2.0) .. is MMF easier or faster than Ipc?

Jon

Nicholas Paldino said:
Jon,

I think that shared memory is very viable. You will have to code it
yourself though, and use a fair amount of P/Invoke. First, I recommend
reading the section of the MSDN documentation titled "Managing
Memory-Mapped Files in Win32", located at:

http://msdn2.microsoft.com/en-us/library/ms810613.aspx

For working with MMFs in .NET, I would recommend creating a class that
derives from Stream which would allow you to work with the MMF.
Basically, you would have the file that you are using as the MMF, and then
you would call the MapViewOfFileEx API function and get the pointer at
which you can start writing. You can then take whereever the user wants
to read from /write to the stream and then offset that value by the
pointer returned from MapViewOfFileEx to find the memory location to read
from/write to.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Jon Davis said:
The memory load could be in the range of 1GB, basically hosting indexes
in-memory for fast access to search thousands of large pieces of data.
The server has 4GB, but IIS never uses more than 1GB, which leaves us 3GB
unused, and also makes IIS vulnerable to running out of RAM if we were to
fill up its tiny 1GB rather than isolate the process.

Would love to offload to another server, but the problem there becomes
the bottleneck of 1gb/s network bandwidth which is more reserved for the
other users who are doing heavy SQL Server queries (and SQL Server is not
nearly as performant for what we are indexing, difference is like 10ms
vs. 500ms). We also then deal with TCP/IP packet encapsulation which is a
huge performance hit.

Shared memory is of course ideal. Problem is I asked about shared memory
in the .NET world a year or two ago and was told it's not possible in the
C# world, you have to use remoting. Or, use C++ (and native APIs) which I
am not privvy to, although if someone can point me to P/Invoke API
tutorials that are relevant to shared memory with C#/.NET I'd be curious.

Jon

Nicholas Paldino said:
Jon,

I think that you might want to consider shared memory in this case,
assuming you want to be on the same machine as IIS (although, I have to
question why you would want to starve that machine, and not dedicate
another machine to performing this task, as you run the risk of starving
IIS of resources).

Are you passing massive amounts of data between the processes? If
so, I can't say remoting is a good solution. With remoting, you can
marshal objects by reference, or by value. When passing your massive
data buffer across the app domain boundary, if you pass this by value,
you are going to incur a huge cost in passing that buffer across the app
domain boundary.

If your buffer has an affinity to the app domain it is in (derives
from MarshalByRefObject) then you can make calls into the object from
the remote process, but depending on how many calls you have to make to
get managable chunks of data, this might be too expensive as well.

I think that a better solution would be to have a separate machine
which is dedicated to this task, and then sending off the data buffers
(or chunks of them) to the machine to be processed. You can use MSMQ
for this, or maybe even a file drop, in which case, you have something
like BizTalk pick up the file drop. You could use WCF as well, as there
is support for large message sizes (although there is a message buffer
limit there as well which you have to tweak if the buffer is
exceptionally large).

Which comes back to shared memory. If you are determined to stay on
the same machine, then you can have the IIS process write to shared
memory, then signal the service to look at a particular block of shared
memory to process. Of course, you will have to write all the
coordination routines yourself (which is going to be a pain as well).

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

We're looking at running a memory-intensive process for a web site as a
Windows service in isolation of IIS because IIS refuses to consume all
of the available physical RAM. Considering remoting to move data in and
out of this process. Need something that's quick and dirty and easy to
implement, but that's performant and secure at the same time. Any
suggestions / tutorials? Would prefer not to go on the TCP/IP stack
(socket) as it is not very performant, but it certainly is quick and
dirty and we might go with it anyway anyway unless there is another way
with shared memory that is as easy and more performant.

Jon
 
Jon,

You could use that, but in the end, you have to consider how much data
you are going to push across this pipe. MMF might be better if you have to
access that data, but for signalling between the two applications, I would
go with remoting, or, if you can use .NET 3.0 (which is 2.0 with some
additional class libraries) then, you should use WCF.
 
I see what you're saying, per your original reply. I guess I need to do some
tests to see what impact MarshalByRef implementation, for remoting, would
have. The problem is the level of effort for MMF, which isn't native to .NET
(or is it?).

We are performing search queries between the IIS process and the indexing
process, so the client/server model works fine for us (better, actually).
The compromise of ease of implementation w/ MarshalByRef for Ipc vs. the
performance overhead of TCP sockets might be legitimate enough to go with
IPC remoting over named pipes.

But if you can find a sample of MMF that's straightforward, obviously not
necessarily as straightforward as the link I just found and posted but
relatively readable, I'd be most grateful.

I'm really not interested at this time in pursuing the purchase of
third-party middleware. Free and open-source, maybe, but one would think
Microsoft would get this stuff to work right out of the .NET box.

Jon


Nicholas Paldino said:
Jon,

You could use that, but in the end, you have to consider how much data
you are going to push across this pipe. MMF might be better if you have
to access that data, but for signalling between the two applications, I
would go with remoting, or, if you can use .NET 3.0 (which is 2.0 with
some additional class libraries) then, you should use WCF.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Jon Davis said:
Erm, that's Part 2 of a two-part, rediculously straightforward article.

http://www.developer.com/net/vb/article.php/10926_3520891_1
 
The memory load could be in the range of 1GB, basically hosting indexes
in-memory for fast access to search thousands of large pieces of data.
The server has 4GB, but IIS never uses more than 1GB, which leaves us 3GB
unused, and also makes IIS vulnerable to running out of RAM if we were to
fill up its tiny 1GB rather than isolate the process.

This might be a dumb question, but...

Are you using a 64-bit version of IIS on a 64-bit version of Windows?

In 32-bit land, it wouldn't surprise me at all to find a practical limit
of around 1GB for a single process. The address space itself available to
the process is only 2GB, and with fragmentation and other issues, a
process may very well not be able to allocate more than about 1GB of large
things.

If you're running into a 32-bit Windows issue, it's not clear to me that
you'll be able to do much better than IIS is already doing for you.

If this is all under 64-bit Windows then I agree IIS should work better
than that, and none of the above is relevant.

Pete
 
Peter Duniho said:
This might be a dumb question, but...

Are you using a 64-bit version of IIS on a 64-bit version of Windows?

In 32-bit land, it wouldn't surprise me at all to find a practical limit
of around 1GB for a single process. The address space itself available to
the process is only 2GB, and with fragmentation and other issues, a
process may very well not be able to allocate more than about 1GB of large
things.

If you're running into a 32-bit Windows issue, it's not clear to me that
you'll be able to do much better than IIS is already doing for you.

If this is all under 64-bit Windows then I agree IIS should work better
than that, and none of the above is relevant.

Pete

No, but 1GB for IIS + 1GB for a service app = 2GB utilization and 1GB per
process, with another 1/2 to 1 GB physical RAM readily available on a 4GB
box. Whereas, 1GB max for IIS alone w/ the service process inside IIS = 1/2
GB for the service process and 1/2 for the web app (assuming that memory
utilization was taken up proporationately). Moving the process out seems to
be a no-brainer.

I have heard that 64-bit for IIS is pointlessly ineffective. Whereas, 64-bit
for SQL Server was a blazing improvement both for speed and for memory
scalability.

Jon
 
Jon,
In this article
http://www.eggheadcafe.com/articles/20050116.asp
I did some "proof of concept" work with MMF's using the MetalWrench Toolbox
assembly, a copy of which is in the bin/debug folder of the associated
download.

It was the only one I tested that held up consistently under heavy load.
Peter

--
Site: http://www.eggheadcafe.com
UnBlog: http://petesbloggerama.blogspot.com
Short urls & more: http://ittyurl.net




Jon Davis said:
I see what you're saying, per your original reply. I guess I need to do some
tests to see what impact MarshalByRef implementation, for remoting, would
have. The problem is the level of effort for MMF, which isn't native to .NET
(or is it?).

We are performing search queries between the IIS process and the indexing
process, so the client/server model works fine for us (better, actually).
The compromise of ease of implementation w/ MarshalByRef for Ipc vs. the
performance overhead of TCP sockets might be legitimate enough to go with
IPC remoting over named pipes.

But if you can find a sample of MMF that's straightforward, obviously not
necessarily as straightforward as the link I just found and posted but
relatively readable, I'd be most grateful.

I'm really not interested at this time in pursuing the purchase of
third-party middleware. Free and open-source, maybe, but one would think
Microsoft would get this stuff to work right out of the .NET box.

Jon


Nicholas Paldino said:
Jon,

You could use that, but in the end, you have to consider how much data
you are going to push across this pipe. MMF might be better if you have
to access that data, but for signalling between the two applications, I
would go with remoting, or, if you can use .NET 3.0 (which is 2.0 with
some additional class libraries) then, you should use WCF.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Jon Davis said:
This looks rediculously straightforward.

http://www.developer.com/net/vb/article.php/10926_3520891_2

Erm, that's Part 2 of a two-part, rediculously straightforward article.

http://www.developer.com/net/vb/article.php/10926_3520891_1
 
[...]
No, but 1GB for IIS + 1GB for a service app = 2GB utilization and 1GB
per process, with another 1/2 to 1 GB physical RAM readily available on
a 4GB
box. Whereas, 1GB max for IIS alone w/ the service process inside IIS =
1/2 GB for the service process and 1/2 for the web app (assuming that
memory
utilization was taken up proporationately). Moving the process out seems
to be a no-brainer.

Unless you run into performance and/or code maintenance problems doing
so. :)

At the very least, the fact that you're using Win32 seems to explain to me
the behavior you're seeing. It's not that IIS refuses to use more
physical RAM. It's likely simply that it can't.
I have heard that 64-bit for IIS is pointlessly ineffective. Whereas,
64-bit for SQL Server was a blazing improvement both for speed and for
memory scalability.

I have heard that people hear a lot of things about software that turn out
to not be true. :)

Seriously though, until you've tried it you won't really know whether
64-bit IIS would help you or not. Even in some tests 64-bit IIS doesn't
improve performance, that doesn't tell you very much unless you know how
those tests were run and whether they even had a theoretical chance to
consume more than one or two gigabytes of memory. I can easily see how,
for a lot of web server scenarios, virtual or physical memory just doesn't
play a big part in performance.

I don't know what your specific scenario is or what sort of resources you
have to apply to the problem. But if it were me, I'd try my application
under 64-bit Windows with 64-bit IIS to see if that was enough to gain the
benefit in performance I was looking for. I'd do that before I spent a
lot of time trying to work around apparent deficiencies in the 32-bit
paradigm, especially given that 64-bit is here now and will be dominant in
the near future (especially for server stuff).

Pete
 
Jon Davis said:
No, but 1GB for IIS + 1GB for a service app = 2GB utilization and 1GB per process, with
another 1/2 to 1 GB physical RAM readily available on a 4GB box. Whereas, 1GB max for IIS
alone w/ the service process inside IIS = 1/2 GB for the service process and 1/2 for the
web app (assuming that memory utilization was taken up proporationately). Moving the
process out seems to be a no-brainer.

I have heard that 64-bit for IIS is pointlessly ineffective. Whereas, 64-bit for SQL
Server was a blazing improvement both for speed and for memory scalability.

Jon



First of all, asp.net does NOT run in the IIS process space, each asp.net program runs in a
process separated from IIS.
Second, there is no such 1GB limit for asp.net either, to me, it looks like you are
allocating a single array of (whatever type), and here you are limited by the largest chunk
of contiguous memory available in the process space at the moment of allocation. This chunk
is ~1.7 GB when the process starts on a 32 bit version of Windows, but can easily drop to a
few MB when your allocation scheme breaks down the largest space into fragments.
In this case, the only solution is to move to 64 bit, remoting, even over shared memory, is
no solution at all, you can't guarantee to find ~1GB free contigious memory in a 32 bit
process ever.
Note that you can't allocate objects larger than 2GB in .NET, even on 64 bit.

Willy.
 
Willy Denoyette said:
First of all, asp.net does NOT run in the IIS process space, each asp.net
program runs in a process separated from IIS.

Of course; all instances of "IIS" mentioned in this thread are short-form
references the ASP.NET app we are executing.
Second, there is no such 1GB limit for asp.net either,

IIS "self-tunes" itself and avoids taking up more than roughly one quarter
of the available physical RAM, which is far less than standalone process
will allow for. We have seen OutOfMemoryExceptions frequently by stepping
above this threshhold, despite at least a gig of available physical RAM.
This does not work well for a dedicated web host machine.

Of course, we can look at experimenting more with 64-bit machines that have
gobs of RAM and see what a quarter of 8GB (2GB) would do for us, but that's
not the point. The point is I am looking in parallel at IPC and that's what
this thread is for.

Jon
 
[...]
IIS "self-tunes" itself and avoids taking up more than roughly one
quarter of the available physical RAM, which is far less than standalone
process will allow for.

Can you document the claim that "IIS 'self-tunes' itself and avoids taking
up more than roughly one quarter of the available physical RAM"? I have
never heard anything of the sort, and there's nothing about the
description of the behavior that you've given that suggests it's true.

It is false that there is any relationship between physical RAM and the
maximum allocation that a "standalone process will allow for". Under
Win32, the 2GB virtual address space limit means that even under optimal
conditions no application will ever use more than half of the installed
ram when 4GB is installed, and a typical application will only be able to
allocate some amount much less (and 1GB is not at all an uncommon upper
bound for a typical application).
We have seen OutOfMemoryExceptions frequently by stepping
above this threshhold, despite at least a gig of available physical RAM.

This means nothing. If you are running 32-bit Windows, with 4GB of RAM it
is absolutely normal for an application to not be able to allocate any
more memory even while physical RAM has 1GB or more available. With 4GB
installed, the limit on how much memory an application can allocate isn't
the physical RAM, it's the virtual address space.
This does not work well for a dedicated web host machine.

Of course, we can look at experimenting more with 64-bit machines that
have gobs of RAM and see what a quarter of 8GB (2GB) would do for us,
but that's not the point. The point is I am looking in parallel at IPC
and that's what this thread is for.

Your assumption that under 64-bit Windows you would only be able to
allocate 2GB of memory with 8GB installed is unfounded. Under 64-bit
Windows, even with only 4GB installed, you should be able to allocate as
much memory as you can use, and if that exceeds 4GB then you can be
assured of consuming all physical RAM. There's no arbitrary "1 to 4
ratio" between physical RAM and allocations allowed.

Also, your interest in IPC is predicated on an incorrect understanding of
what's going on with the memory management. Why waste time pursuing a
solution that is assured to do no better than what is already occurring?
You need to better understand the memory management issue you're dealing
with before you start tackling work-arounds to it.

Pete
 
Can you document the claim that "IIS 'self-tunes' itself

http://www.microsoft.com/technet/pr...IIS/ad56540c-2323-4316-b981-7ebb70352baa.mspx
and avoids taking up more than roughly one quarter of the available
physical RAM"?

No, this was an observation of our site.

This means nothing. If you are running 32-bit Windows, with 4GB of RAM it
is absolutely normal for an application to not be able to allocate any
more memory even while physical RAM has 1GB or more available.

That's not true; a standalone app can and will allocate RAM and will begin
using available virtual memory when unreserved physical RAM is no longer
available. IIS is FAR more likely to throw OutOfMemoryExceptions than a
standalone app. I may not be a world-class developer yet but 10 years of
experience with developing both IIS apps and Windows apps gives me enough to
go on.

IIS memory utilization in itself is not the issue here. The issue is we have
a process that we have a large process that we've decided will be
implemented as a Windows service and that will be accessible by multiple web
apps.
Your assumption that under 64-bit Windows you would only be able to
allocate 2GB of memory with 8GB installed is unfounded.

Although self-limitation of the raw memory utilization of IIS isn't
"unfounded", said ratio was stated slightly tongue-in-cheek because the
symptom was observed by us. We did already try using 64-bit Windows with no
significant memory utilization changes for IIS. But since this is still
OT--as I said, the purpose of the thread was to examine IPC--this is the
last I will speak of it. What you don't know and don't need to know is that
there is more going on here than basic IIS limitations.

Jon
 

There is nothing in that document that suggests IIS limits itself to 1/4
of available RAM. As far as "tuning" more generally goes, you'll note (I
hope) that part of the tuning that goes on is IIS ensuring that it doesn't
starve other processes of memory. Your proposed change to your setup
involves essentially doing just that, perhaps even starving IIS.
That's not true; a standalone app can and will allocate RAM and will
begin using available virtual memory when unreserved physical RAM is no
longer
available.

Wrong. And until you correct your misunderstanding of the memory
management model used by Windows, you are going to continue trying to
solve your problem the wrong way.

Quick summary (applies to 32-bit Windows, same principles apply -- mostly
-- to 64-bit Windows, but of course the actual limits are vastly higher):

* ALL memory allocations in a process go through virtual memory. ALL
of them. A normal application (this would include your service) under
Windows does not get to allocate physical RAM directly. The first part of
any memory allocation involves allocating a chunk of virtual address
space, whether or not there is sufficient physical RAM to satisfy that
allocation.

* The virtual address space for 32-bit pointers is theoretically 4GB,
but because of the way that Windows uses those pointers, only half of this
is available to the process directly (up to 3GB with a special switch
booting the OS). Thus, no process can EVER allocate more than 2GB.
Because of fragmentation, most processes will find themselves limited to
maximum total allocations somewhat less than 2GB. The larger the
individual blocks the process is trying to allocate, the more likely this
will be a problem.

* When a process references a virtual address that hasn't been
"committed", at that point physical RAM is assigned to the virtual
address. But since a process cannot address more than 2GB of virtual
address space, the process can never reference more than 2GB of physical
RAM as well. In reality, a process almost never has their entire virtual
allocation committed, and so physical RAM usage is almost always less (and
usually considerably less) than their total virtual memory allocation.
IIS is FAR more likely to throw OutOfMemoryExceptions than a
standalone app. I may not be a world-class developer yet but 10 years of
experience with developing both IIS apps and Windows apps gives me
enough to go on.

It's apparent from your lack of understanding of the Windows memory
management model that that's not true. You need to accumulate at least a
little more experience before you have "enough to go on".
IIS memory utilization in itself is not the issue here.

Then you have asked your question incorrectly. In all of your posts, how
IIS uses memory is a central part of your complaint. If IIS memory
utilization is not the issue, then I recommend you stop including it in
your queries.
The issue is we have a process that we have a large process that we've
decided will be
implemented as a Windows service and that will be accessible by multiple
web apps.

As near as I can tell, the reason you've decided to implement it as a
Windows service is that you believe you can get around the memory
allocation issues by doing so. The problem is that you can't. The same
memory allocation issues that restrict IIS will also restrict you.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top