WriteFile buffers in memory

Discussion in 'ASP .Net' started by Tim Greenfield, Oct 4, 2004.

  1. 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
    Tim Greenfield, Oct 4, 2004
    #1
    1. Advertising

  2. Tim Greenfield

    bruce barker Guest

    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" <> wrote in message
    news:...
    > 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
    >
    >
    bruce barker, Oct 5, 2004
    #2
    1. Advertising

  3. 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" <> wrote in message
    news:...
    > 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" <> wrote in message
    > news:...
    >> 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
    >>
    >>

    >
    >
    Tim Greenfield, Oct 5, 2004
    #3
  4. Tim Greenfield

    bruce barker Guest

    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" <> wrote in message
    news:...
    > 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" <> wrote in message
    > news:...
    > > 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" <> wrote in message
    > > news:...
    > >> 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
    > >>
    > >>

    > >
    > >

    >
    >
    bruce barker, Oct 5, 2004
    #4
  5. =?Utf-8?B?QWxleGFuZGVy?=, Oct 5, 2004
    #5
  6. 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" <> wrote in message
    news:...
    > 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?
    Tim Greenfield, Oct 5, 2004
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jerry J
    Replies:
    2
    Views:
    752
    Jerry J
    Jul 20, 2003
  2. Robert Hanson
    Replies:
    3
    Views:
    647
    Steve C. Orr [MVP, MCSD]
    Nov 21, 2003
  3. Earl Teigrob
    Replies:
    0
    Views:
    905
    Earl Teigrob
    Jan 20, 2004
  4. Replies:
    6
    Views:
    302
    Chris Torek
    Jan 19, 2005
  5. Henk
    Replies:
    4
    Views:
    836
Loading...

Share This Page