Resumable pipeline, Async handlers and URI matching. It was simple. Kinda

35 views
Skip to first unread message

Sebastien Lambla

unread,
Sep 6, 2009, 7:43:50 PM9/6/09
to open...@googlegroups.com

Hi boys and girls,

 

So, if you remember a couple of days ago we talked about making the pipeline “resumable”, aka make it so the pipeline can stop execution and simply restart when re-executed a second time.

 

As far as I can tell, my code works and openbastard doesn’t have any issues with it, so it’s in. It’s not been integrated to the aspnet module yet, I’m waiting to get the asp.net integration for openbastard working before I enable it. All this is RC / RTM work, what follows is for 2.1.

 

Now the interesting challenge is the following. The first step of execution can simply try and match the uri (aka execute until KnownStages.IUriResolving or whatnot), return, and the http module will know if the URI is something OR should process or not.

 

If yes, the module does the rewrite, the handler goes and execute the rest of the pipeline.

 

Now if we think about async handlers, there’s a slight problem. We don’t know for sure which method will be executed until it’s time to execute the operation, which will have received all of its data from the request already. That means that the reading codec will still be synchronous. I don’t think it’s a problem, because you can stream the content yourself if and when required for codecs that support streaming (aka multipart when using IEnumerable<IHttpMultipartEntity> and App/octet-stream when using any stream of data).

 

Enough of the boring details. Now we have two choices when it comes to making the operation asynchronous.

 

Option 1, we manage the execution by queuing the request in the thread pool. This is the typical one you see in other frameworks when they annotate with an [Async] attribute. The issue with this is that you just take work items from the thread pool, which is the same one the asp.net requests get processed from. You end up hitting the cpu in both instances, playing with the same threads as asp.net and potentially end-up with threadpool starvation, which kills asp.net performance completely. I just don’t think there’s a valid use-case for this.

 

Option 2, we let the operation control the asynchronous call, aka have a signature of the form IAsyncResult BeginGet(), and have an EndGet() method that matches. Considering the only reason you should want to use async is when hitting APIs that hit IO threads rather than threadpool threads, this seems like the correct approach.

 

Option 3 is to create a type for async handling that encapsulates somehow the begin and end, but at that stage I wonder if it’s not simple over-engineering.

 

Comments?

 

Seb

 

Ryan Riley

unread,
Sep 6, 2009, 11:06:17 PM9/6/09
to open...@googlegroups.com
Sounds like a job for ... Super Reactive Framework! Well, that's a bit extreme, but it is the perfect solution for elegance. I'm trying to do some of that in F# right now to get a feel for it, in addition to the monadic codec composition. I'm actually getting close, even though I have nothing for OpenRasta itself yet. I'm also not sure how all this will play with .NET 2.0 as most of it relies on LINQ.

Nevertheless, I think option 2 is sound if we don't go Reactive (which I think is option 3). I'm happy to help on this. I'm trying to get through it anyway for my own amusement. If you want resources, try:

I'm also curious, any objections to F# for certain pieces of the system where it makes sense? There are certain things (such as Async processing) that are generally much simpler in F# than C# and still accessible from an F# library in C#.

Ryan

Sebastien Lambla

unread,
Sep 7, 2009, 4:45:24 AM9/7/09
to open...@googlegroups.com

Well, any Fsharp will have to stay out of the core to preserve .net 2 compat. Other than that, I have no major issues with it, it just can’t be used for the core API.

 

Seb

Victor Kornov

unread,
Sep 7, 2009, 1:08:52 PM9/7/09
to open...@googlegroups.com
On Mon, Sep 7, 2009 at 3:43 AM, Sebastien Lambla <s...@serialseb.com> wrote:

Option 1, we manage the execution by queuing the request in the thread pool. This is the typical one you see in other frameworks when they annotate with an [Async] attribute. The issue with this is that you just take work items from the thread pool, which is the same one the asp.net requests get processed from. You end up hitting the cpu in both instances, playing with the same threads as asp.net and potentially end-up with threadpool starvation, which kills asp.net performance completely. I just don’t think there’s a valid use-case for this.

Valid use case is easy long running tasks. Which are not hit very often. Then you can execute it on the UI (asp.net/thread pool) thread and return some results to the client while keeping the connection open. But I don't think it's anything important to support.
 

Option 2, we let the operation control the asynchronous call, aka have a signature of the form IAsyncResult BeginGet(), and have an EndGet() method that matches. Considering the only reason you should want to use async is when hitting APIs that hit IO threads rather than threadpool threads, this seems like the correct approach.

#2 Looks like reasonable way to go.
 

 Option 3 is to create a type for async handling that encapsulates somehow the begin and end, but at that stage I wonder if it’s not simple over-engineering.


May be... in case of dynamic actions a-la Monorail.
Reply all
Reply to author
Forward
0 new messages