473,406 Members | 2,769 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

WriteFile buffers in memory

Hi, I have a problem I'm hoping is not too unusual. I'm trying to push a
large file (50MB) out to the client from an ASP page. The reason I'm using
an ASP page is so I can start the reading at a particular offset. This ASP
page needs to be scaleable as it needs to support thousands of requests per
hour. I've found 2 solutions so far but both have their problems:
1) Using Response.WriteFile(filename, offset, length). This seems like the
perfect solution except that it puts the entire contents of the file in
memory per request... ouch! Anyone know of a way to put the file in some
global cache so it don't fill up my RAM per session? I could afford filling
up RAM per file as there are only a handful of files that will be
downloaded.
2) Writing the file 1K at a time to the output buffer w/ buffering disabled.
This works great; each request barely takes up any memory or CPU. However,
it seems to tie up 1 precious ASP thread per request. And it turns out that
ASP threads are very precious... they only give you 25 per processor by
default. Within a minute I'm out of threads and users get a "Server To Busy"
error. I can work around this by adding:
<httpRuntime appRequestQueueLimit="50000" /> to web.config
But all it does is make the 26th user wait for someone to finish their
download before granting access instead of giving them an error. Anyone know
how to increase the size and if so, am I treading on thin ice by increasing
it to some huge number like 1000?

Another solution I've been pursuing is to try to take the best of both
worlds. If I could create a module that uses the 1K at a time technique to
avoid memory hogging but get it return immediately by using multi-threading,
I think I could solve my problem. Unfortunately, I haven't been able to get
it to work yet.
' from my .aspx file:
Dim SendFile as New SendFile
SendFile.Response = Response
SendFile.Filename = Filename
SendFile.Offset = Offset
Dim t as New Threading.Thread(AddressOf SendFile.Go)
t.Start()

Can anyone offer any wisdom? I can't imagine I'm the first one to need to do
this. Thanks!

-- Tim
Nov 18 '05 #1
5 3458
you are stuck tying up a couple threads per request. you can bump up the i/o
and workpool thread count. asp.net sets a max i/o thread count to 100 per
cpu.

what you are dealing with

1) iis keeps a thread pool to manage i/o connections to clients
2) iis run an isapi filter that handles asp.net pages
3) the asp.net filter keeps a pool of thread to manage i/o between it and
asp.net. the filter uses named pipes to talk to the asp.net worker process.
4) the asp.net worker process keeps a pool of threads to talk to the asp.net
filter over the named pipe connection
5) the asp.net worker process keeps a pool of threads to actually process a
request.

so with a file download, you will tieup:

1) an asp.net thread (until the last i/o flush)
2) an asp.net i/o thread (until flushed to the filter)
3) an asp.net i/o filter thread (until flushed to iis)
4) an iis i/o thread. (until i/o keep alive is canceled/times out)

if you need high performance, you should look at writing your own isapi
filter.

-- bruce (sqlwork.com)
"Tim Greenfield" <ti*********@paloalto.com> wrote in message
news:u7**************@TK2MSFTNGP11.phx.gbl...
Hi, I have a problem I'm hoping is not too unusual. I'm trying to push a
large file (50MB) out to the client from an ASP page. The reason I'm using
an ASP page is so I can start the reading at a particular offset. This ASP
page needs to be scaleable as it needs to support thousands of requests per hour. I've found 2 solutions so far but both have their problems:
1) Using Response.WriteFile(filename, offset, length). This seems like the
perfect solution except that it puts the entire contents of the file in
memory per request... ouch! Anyone know of a way to put the file in some
global cache so it don't fill up my RAM per session? I could afford filling up RAM per file as there are only a handful of files that will be
downloaded.
2) Writing the file 1K at a time to the output buffer w/ buffering disabled. This works great; each request barely takes up any memory or CPU. However,
it seems to tie up 1 precious ASP thread per request. And it turns out that ASP threads are very precious... they only give you 25 per processor by
default. Within a minute I'm out of threads and users get a "Server To Busy" error. I can work around this by adding:
<httpRuntime appRequestQueueLimit="50000" /> to web.config
But all it does is make the 26th user wait for someone to finish their
download before granting access instead of giving them an error. Anyone know how to increase the size and if so, am I treading on thin ice by increasing it to some huge number like 1000?

Another solution I've been pursuing is to try to take the best of both
worlds. If I could create a module that uses the 1K at a time technique to
avoid memory hogging but get it return immediately by using multi-threading, I think I could solve my problem. Unfortunately, I haven't been able to get it to work yet.
' from my .aspx file:
Dim SendFile as New SendFile
SendFile.Response = Response
SendFile.Filename = Filename
SendFile.Offset = Offset
Dim t as New Threading.Thread(AddressOf SendFile.Go)
t.Start()

Can anyone offer any wisdom? I can't imagine I'm the first one to need to do this. Thanks!

-- Tim

Nov 18 '05 #2
Thanks for the threading info. A max of 100 threads per CPU still seems
really low... 101 users all hitting a web page that takes a long time but
uses very few resources doesn't seem all that out of the ordinary. Oh well.

How do you suppose Response.WriteFile returns immediately? If I could get my
own code to behave like .WriteFile (but not tying up memory) then I could
have the best of both worlds. Maybe?
"bruce barker" <no***********@safeco.com> wrote in message
news:e2*************@TK2MSFTNGP15.phx.gbl...
you are stuck tying up a couple threads per request. you can bump up the
i/o
and workpool thread count. asp.net sets a max i/o thread count to 100 per
cpu.

what you are dealing with

1) iis keeps a thread pool to manage i/o connections to clients
2) iis run an isapi filter that handles asp.net pages
3) the asp.net filter keeps a pool of thread to manage i/o between it and
asp.net. the filter uses named pipes to talk to the asp.net worker
process.
4) the asp.net worker process keeps a pool of threads to talk to the
asp.net
filter over the named pipe connection
5) the asp.net worker process keeps a pool of threads to actually process
a
request.

so with a file download, you will tieup:

1) an asp.net thread (until the last i/o flush)
2) an asp.net i/o thread (until flushed to the filter)
3) an asp.net i/o filter thread (until flushed to iis)
4) an iis i/o thread. (until i/o keep alive is canceled/times out)

if you need high performance, you should look at writing your own isapi
filter.

-- bruce (sqlwork.com)
"Tim Greenfield" <ti*********@paloalto.com> wrote in message
news:u7**************@TK2MSFTNGP11.phx.gbl...
Hi, I have a problem I'm hoping is not too unusual. I'm trying to push a
large file (50MB) out to the client from an ASP page. The reason I'm
using
an ASP page is so I can start the reading at a particular offset. This
ASP
page needs to be scaleable as it needs to support thousands of requests

per
hour. I've found 2 solutions so far but both have their problems:
1) Using Response.WriteFile(filename, offset, length). This seems like
the
perfect solution except that it puts the entire contents of the file in
memory per request... ouch! Anyone know of a way to put the file in some
global cache so it don't fill up my RAM per session? I could afford

filling
up RAM per file as there are only a handful of files that will be
downloaded.
2) Writing the file 1K at a time to the output buffer w/ buffering

disabled.
This works great; each request barely takes up any memory or CPU.
However,
it seems to tie up 1 precious ASP thread per request. And it turns out

that
ASP threads are very precious... they only give you 25 per processor by
default. Within a minute I'm out of threads and users get a "Server To

Busy"
error. I can work around this by adding:
<httpRuntime appRequestQueueLimit="50000" /> to web.config
But all it does is make the 26th user wait for someone to finish their
download before granting access instead of giving them an error. Anyone

know
how to increase the size and if so, am I treading on thin ice by

increasing
it to some huge number like 1000?

Another solution I've been pursuing is to try to take the best of both
worlds. If I could create a module that uses the 1K at a time technique
to
avoid memory hogging but get it return immediately by using

multi-threading,
I think I could solve my problem. Unfortunately, I haven't been able to

get
it to work yet.
' from my .aspx file:
Dim SendFile as New SendFile
SendFile.Response = Response
SendFile.Filename = Filename
SendFile.Offset = Offset
Dim t as New Threading.Thread(AddressOf SendFile.Go)
t.Start()

Can anyone offer any wisdom? I can't imagine I'm the first one to need to

do
this. Thanks!

-- Tim


Nov 18 '05 #3
Response.Writefile flushes the output to the filter, releasing the asp.net
threads, but ties up the iis threads. asp.net will not scale up if the
transactions run much more than 2-3 seconds.

-- bruce (sqlwork.com)
"Tim Greenfield" <ti*********@paloalto.com> wrote in message
news:ep**************@TK2MSFTNGP12.phx.gbl...
Thanks for the threading info. A max of 100 threads per CPU still seems
really low... 101 users all hitting a web page that takes a long time but
uses very few resources doesn't seem all that out of the ordinary. Oh well.
How do you suppose Response.WriteFile returns immediately? If I could get my own code to behave like .WriteFile (but not tying up memory) then I could
have the best of both worlds. Maybe?
"bruce barker" <no***********@safeco.com> wrote in message
news:e2*************@TK2MSFTNGP15.phx.gbl...
you are stuck tying up a couple threads per request. you can bump up the
i/o
and workpool thread count. asp.net sets a max i/o thread count to 100 per cpu.

what you are dealing with

1) iis keeps a thread pool to manage i/o connections to clients
2) iis run an isapi filter that handles asp.net pages
3) the asp.net filter keeps a pool of thread to manage i/o between it and asp.net. the filter uses named pipes to talk to the asp.net worker
process.
4) the asp.net worker process keeps a pool of threads to talk to the
asp.net
filter over the named pipe connection
5) the asp.net worker process keeps a pool of threads to actually process a
request.

so with a file download, you will tieup:

1) an asp.net thread (until the last i/o flush)
2) an asp.net i/o thread (until flushed to the filter)
3) an asp.net i/o filter thread (until flushed to iis)
4) an iis i/o thread. (until i/o keep alive is canceled/times out)

if you need high performance, you should look at writing your own isapi
filter.

-- bruce (sqlwork.com)
"Tim Greenfield" <ti*********@paloalto.com> wrote in message
news:u7**************@TK2MSFTNGP11.phx.gbl...
Hi, I have a problem I'm hoping is not too unusual. I'm trying to push a large file (50MB) out to the client from an ASP page. The reason I'm
using
an ASP page is so I can start the reading at a particular offset. This
ASP
page needs to be scaleable as it needs to support thousands of requests

per
hour. I've found 2 solutions so far but both have their problems:
1) Using Response.WriteFile(filename, offset, length). This seems like
the
perfect solution except that it puts the entire contents of the file in
memory per request... ouch! Anyone know of a way to put the file in some global cache so it don't fill up my RAM per session? I could afford

filling
up RAM per file as there are only a handful of files that will be
downloaded.
2) Writing the file 1K at a time to the output buffer w/ buffering

disabled.
This works great; each request barely takes up any memory or CPU.
However,
it seems to tie up 1 precious ASP thread per request. And it turns out

that
ASP threads are very precious... they only give you 25 per processor by
default. Within a minute I'm out of threads and users get a "Server To

Busy"
error. I can work around this by adding:
<httpRuntime appRequestQueueLimit="50000" /> to web.config
But all it does is make the 26th user wait for someone to finish their
download before granting access instead of giving them an error. Anyone

know
how to increase the size and if so, am I treading on thin ice by

increasing
it to some huge number like 1000?

Another solution I've been pursuing is to try to take the best of both
worlds. If I could create a module that uses the 1K at a time technique
to
avoid memory hogging but get it return immediately by using

multi-threading,
I think I could solve my problem. Unfortunately, I haven't been able to

get
it to work yet.
' from my .aspx file:
Dim SendFile as New SendFile
SendFile.Response = Response
SendFile.Filename = Filename
SendFile.Offset = Offset
Dim t as New Threading.Thread(AddressOf SendFile.Go)
t.Start()

Can anyone offer any wisdom? I can't imagine I'm the first one to need
to do
this. Thanks!

-- Tim



Nov 18 '05 #4
Tim,

check out this KB article:
http://support.microsoft.com/default.aspx?kbid=823409

I wonder why that new TransmitFile method, which works great for me, isn't
introduced in a ... "louder" way?
Nov 18 '05 #5
I just tried some stress testing on this method and it works perfectly! I
don't know why anyone would use .WriteFile(filename) anymore. It is however
lacking the offset & length params so I can send off just a portion of the
file. Any idea if MS will provide overloads for this function someday to
support the offset, length params? Or maybe there are already some and I'm
just unaware with how to use them? I tried Response.TransferFile(filename,
offset, length) but it didn't like that.

Thanks for the help,

-- Tim

"Alexander" <Al*******@discussions.microsoft.com> wrote in message
news:F7**********************************@microsof t.com...
Tim,

check out this KB article:
http://support.microsoft.com/default.aspx?kbid=823409

I wonder why that new TransmitFile method, which works great for me, isn't
introduced in a ... "louder" way?

Nov 18 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: dim | last post by:
Copied directly from exaple book but not working.... All i get is an empty 0 byte file Call to GetLastError directly after the call to WriteFile returns 0 (NO_ERROR) but no data sees to be written...
4
by: Henk | last post by:
Hi, I am new to the c-programming language and at the moment I am struggling with the following: I want to read a file using fread() and then put it in to memory. I want to use a (singel)...
3
by: Frank Perry | last post by:
Howdy, I'm trying to write data out the com port. I have taken the code from the sample on the MSDN Library CD and used the parts that seem relevant. I can open the com port with CreateFile...
2
by: ldawson | last post by:
From the same C++ source code, I'm attempting to generate both an unmanaged DLL and a managed assembly. This will eliminate interop as the calling code is slowly migrated to .NET. However, C++...
3
by: Sally Sally | last post by:
I have a very basic question on the two parameters shared buffers and effective cache size. I have read articles on what each is about etc. But I still think I don't quite grasp what these settings...
2
by: | last post by:
Hi, we are planning to rewrite an extisting C++ image processing application/library in C#. Now several question arouse where I hope you can help me: So far we allocated a block of memory as...
0
by: Sam Durai | last post by:
Hello, A particular select query took unusually long time to execute hence I took an app.snap to find out what happens internally and I found out that tablequeue buffers are overflowing on a...
2
by: chenxinleo | last post by:
Hi, When i use some standard library functions and fields,which return char* type(like ctime in time.h, optarg in getopt.h)and do not have to be freed after calling,i always worry about memory...
5
by: madhav001 | last post by:
Hi, I am biginner in C++ and I tried to combine two memory buffers of TIFF image data to one so that to save it as one image. ie: left half image + right half image = a full image. That was not...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.