зеркало из https://github.com/mono/mail-archives.git
339 строки
16 KiB
HTML
339 строки
16 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<HTML>
|
|
<HEAD>
|
|
<TITLE> [Mono-dev] mono WebResponse caching
|
|
</TITLE>
|
|
<LINK REL="Index" HREF="index.html" >
|
|
<LINK REL="made" HREF="mailto:mono-devel-list%40lists.ximian.com?Subject=Re%3A%20%5BMono-dev%5D%20mono%20WebResponse%20caching&In-Reply-To=%3CCAB1r_%2BXfEHXtixb%3D-pALu9%2BCmUm_pvwJRmb9tfNbkUb5RMeTGQ%40mail.gmail.com%3E">
|
|
<META NAME="robots" CONTENT="index,nofollow">
|
|
<style type="text/css">
|
|
pre {
|
|
white-space: pre-wrap; /* css-2.1, curent FF, Opera, Safari */
|
|
}
|
|
</style>
|
|
<META http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
|
<LINK REL="Previous" HREF="040497.html">
|
|
<LINK REL="Next" HREF="040513.html">
|
|
</HEAD>
|
|
<BODY BGCOLOR="#ffffff">
|
|
<H1>[Mono-dev] mono WebResponse caching</H1>
|
|
<B>Daniel Lo Nigro</B>
|
|
<A HREF="mailto:mono-devel-list%40lists.ximian.com?Subject=Re%3A%20%5BMono-dev%5D%20mono%20WebResponse%20caching&In-Reply-To=%3CCAB1r_%2BXfEHXtixb%3D-pALu9%2BCmUm_pvwJRmb9tfNbkUb5RMeTGQ%40mail.gmail.com%3E"
|
|
TITLE="[Mono-dev] mono WebResponse caching">lists at dan.cx
|
|
</A><BR>
|
|
<I>Sun Jun 9 12:36:24 UTC 2013</I>
|
|
<P><UL>
|
|
<LI>Previous message: <A HREF="040497.html">[Mono-dev] mono WebResponse caching
|
|
</A></li>
|
|
<LI>Next message: <A HREF="040513.html">[Mono-dev] mono WebResponse caching
|
|
</A></li>
|
|
<LI> <B>Messages sorted by:</B>
|
|
<a href="date.html#40509">[ date ]</a>
|
|
<a href="thread.html#40509">[ thread ]</a>
|
|
<a href="subject.html#40509">[ subject ]</a>
|
|
<a href="author.html#40509">[ author ]</a>
|
|
</LI>
|
|
</UL>
|
|
<HR>
|
|
<!--beginarticle-->
|
|
<PRE>There'd be some code for output caching in Mono's ASP.NET implementation, I
|
|
wonder if any of it could be reused here. They're different concepts (
|
|
ASP.NET is using output caching at the server-side whereas this is request
|
|
caching at the client-side) but maybe some of the code could be reused,
|
|
especially around cache header parsing.
|
|
|
|
A caching implementation would definitely have to take into account, at the
|
|
minimum:
|
|
|
|
- Cacheability (public / private)
|
|
- Max age and expiry dates
|
|
|
|
And revalidation using ETags and Last-Modified dates would be a
|
|
nice-to-have (doing the request with the old ETag and Last-Modified date
|
|
and getting a 304 Not Modified back if the page hasn't been modified) but
|
|
isn't entirely necessary with a basic implementation (don't both
|
|
revalidating, just clear the cache when the max age is met)
|
|
|
|
I'd personally cache the results in memory using
|
|
System.Runtime.Caching<<A HREF="http://msdn.microsoft.com/en-us/library/system.runtime.caching.aspx">http://msdn.microsoft.com/en-us/library/system.runtime.caching.aspx</A>>rather
|
|
than on disk, as on-disk caching can get slow. I haven't checked if
|
|
Mono supports this, though.
|
|
|
|
|
|
On Wed, Jun 5, 2013 at 11:32 AM, Mark Lintner <<A HREF="http://lists.ximian.com/mailman/listinfo/mono-devel-list">mlintner at sinenomine.net</A>>wrote:
|
|
|
|
><i> Hi Greg,
|
|
</I>><i>
|
|
</I>><i>
|
|
</I>><i>
|
|
</I>><i> Great input. I have not gotten that far yet. Also the cache level is very
|
|
</I>><i> naïve. Everything caches except Bypass cache which doesn't cache. To check
|
|
</I>><i> the headers it would check the WebResponse Headers property coming
|
|
</I>><i> into TryInsert in DirectoryBackedResponseCache.cs . I would combine the
|
|
</I>><i> result of checking the header with the conditional ShouldCache which also
|
|
</I>><i> needs work. What we are looking for is comments like this, about what you
|
|
</I>><i> think needs to be in a usable implementation, gotchas, things to look out
|
|
</I>><i> for. Also if we are on the wrong track doing it this way I don't want to
|
|
</I>><i> waste time doing something which will not be useful. Assuming I'm not on
|
|
</I>><i> the wrong path, I will add the header check next. This is the kind of
|
|
</I>><i> feedback we need. I only tried to make a prototype of how caching could
|
|
</I>><i> work and then did some performance measurements. Obviously didn't add any
|
|
</I>><i> of the details yet. If this is a viable approach I will continue to fill
|
|
</I>><i> out the implementation guided by research and suggestions. Probably want to
|
|
</I>><i> limit it to what we really need to have. Any other suggestions, comments,
|
|
</I>><i> criticism would be greatly appreciated.
|
|
</I>><i>
|
|
</I>><i>
|
|
</I>><i>
|
|
</I>><i> Thanks,
|
|
</I>><i>
|
|
</I>><i> Mark
|
|
</I>><i> ------------------------------
|
|
</I>><i> *From:* Greg Young [<A HREF="http://lists.ximian.com/mailman/listinfo/mono-devel-list">gregoryyoung1 at gmail.com</A>]
|
|
</I>><i> *Sent:* Tuesday, June 04, 2013 6:49 PM
|
|
</I>><i> *To:* Mark Lintner
|
|
</I>><i> *Cc:* <A HREF="http://lists.ximian.com/mailman/listinfo/mono-devel-list">mono-devel-list at lists.ximian.com</A>
|
|
</I>><i> *Subject:* Re: [Mono-dev] mono WebResponse caching
|
|
</I>><i>
|
|
</I>><i> I would expect this to look at http caching headers in response when
|
|
</I>><i> caching such as expiration, whether something is cachable (public/private) etc
|
|
</I>><i> but don't see any of that code (or maybe I missed it). Can you point to
|
|
</I>><i> where it is in your implementation?
|
|
</I>><i>
|
|
</I>><i> On Tuesday, June 4, 2013, Mark Lintner wrote:
|
|
</I>><i>
|
|
</I>>><i> We have noticed that parts of the Mono Web functionality are not yet
|
|
</I>>><i> implemented. We are hoping to be able to add some of these missing pieces.
|
|
</I>>><i> Caching of
|
|
</I>>><i>
|
|
</I>>><i> HttpWebResponses is the first one we took a look at. It would appear that
|
|
</I>>><i> Microsoft takes advantage of the internet explorer caching. Since it would
|
|
</I>>><i> appear
|
|
</I>>><i>
|
|
</I>>><i> that an HttpWebResponse is fully populated when it is returned from the
|
|
</I>>><i> cache and the only content in the urls that are cached are the bytes that
|
|
</I>>><i> come in on
|
|
</I>>><i>
|
|
</I>>><i> the wire, Microsoft must return things from the cache at a very low level
|
|
</I>>><i> and and let the response populate the normal way. This did not seem
|
|
</I>>><i> possible to
|
|
</I>>><i>
|
|
</I>>><i> emulate when I looked at mono. I also wanted to cache to a directory so
|
|
</I>>><i> that the urls can be inspected or deleted.
|
|
</I>>><i>
|
|
</I>>><i>
|
|
</I>>><i> After looking at the code for awhile I realized that I could save
|
|
</I>>><i> additional information from the response, ie: headercollection,
|
|
</I>>><i> cookiecontainer, Status
|
|
</I>>><i>
|
|
</I>>><i> code etc in the same file as the responsestream. A response can be
|
|
</I>>><i> serialized but not all of it, most importantly the responsestream is not
|
|
</I>>><i> serialized. I
|
|
</I>>><i>
|
|
</I>>><i> wrote a prototype with some helper functions, the only change to existing
|
|
</I>>><i> mono code would be in HttpWebRequest.GetResponse. Before calling
|
|
</I>>><i> BeginGetResponse
|
|
</I>>><i>
|
|
</I>>><i> I call a function that tries to retrieve the url from the cache. If it is
|
|
</I>>><i> not there, BeginGetResponse is called as normal, the response is grabbed
|
|
</I>>><i> from
|
|
</I>>><i>
|
|
</I>>><i> EndGetResponse and passed to a method to insert into the cache. This
|
|
</I>>><i> insert method will open a filename in a directory designated as mono_cache
|
|
</I>>><i> with the name
|
|
</I>>><i>
|
|
</I>>><i> produced by calling HttpUtility.Encode so it is a legal filename. Also
|
|
</I>>><i> you can only read from the responsestream once, which means that if read
|
|
</I>>><i> from it, save
|
|
</I>>><i>
|
|
</I>>><i> it to a file, then the responsestream is no longer accessible from the
|
|
</I>>><i> WebResponse when it is returned to the calling code. If sream copy worked
|
|
</I>>><i> it could be
|
|
</I>>><i>
|
|
</I>>><i> used here. One way to fix the problem is to call GetResponseStream(),
|
|
</I>>><i> read it to the end, which produces a string, then finally convert the
|
|
</I>>><i> string to bytes.
|
|
</I>>><i>
|
|
</I>>><i> Then you can serialize the bytes to the open file, serialize the
|
|
</I>>><i> headercollection and ultimately individually add any field you want in the
|
|
</I>>><i> response when it
|
|
</I>>><i>
|
|
</I>>><i> is retrieved from the cache, then close the file. Then create a new
|
|
</I>>><i> WebConnectionData instance and populate it with headers and all the
|
|
</I>>><i> relevent fields from
|
|
</I>>><i>
|
|
</I>>><i> the old response, finally passing the bytes of data to a memory stream
|
|
</I>>><i> constructor and assign it to the WebConnectionData's stream member. Then I
|
|
</I>>><i> construct a
|
|
</I>>><i>
|
|
</I>>><i> new HttpWebResponse, passing the WebConnectionData and other arguments
|
|
</I>>><i> which are taken from the existing request and the recently retrieved
|
|
</I>>><i> response. The
|
|
</I>>><i>
|
|
</I>>><i> response is then returned to getResponse then finally to the calling
|
|
</I>>><i> code, good as new. Next time the url is requested the cached file is
|
|
</I>>><i> deserialized, one
|
|
</I>>><i>
|
|
</I>>><i> member at a time then a WebConnectionData is setup and finally, a
|
|
</I>>><i> HttpWebResponse is constructed with the info read from the file, the
|
|
</I>>><i> WebConnectionData and
|
|
</I>>><i>
|
|
</I>>><i> from the members of the new request. I concentrated on prototyping
|
|
</I>>><i> caching of HttpWebResponses. Only a simple cache algorithm, no Ftp, no File
|
|
</I>>><i> etc. No cache
|
|
</I>>><i>
|
|
</I>>><i> aging etc. There are many other things that would have to be done for
|
|
</I>>><i> this to be usable.
|
|
</I>>><i> Using the prototype I requested www.google.com and it took .1601419
|
|
</I>>><i> sec to retrieve and cache it, including all the mechanics described above.
|
|
</I>>><i> The
|
|
</I>>><i>
|
|
</I>>><i> second time returning it from the cache, building the HttpWebResponse
|
|
</I>>><i> took .0007671. This is a 288 times speedup. That kind of performance
|
|
</I>>><i> increase, from a
|
|
</I>>><i>
|
|
</I>>><i> prototype that is not yet optimized, is compelling. I must add that I
|
|
</I>>><i> measured the same experiment with google under the .Net 4.5 implementation
|
|
</I>>><i> and the
|
|
</I>>><i>
|
|
</I>>><i> speedup is 769x. Obviously thats something to work toward. Even falling
|
|
</I>>><i> short of that level of speedup, some implementation of response caching for
|
|
</I>>><i> mono
|
|
</I>>><i>
|
|
</I>>><i> would greatly benefit the users who need better performance of services,
|
|
</I>>><i> rest etc.
|
|
</I>>><i>
|
|
</I>>><i> So far this is the only mono code that would change to support caching,
|
|
</I>>><i>
|
|
</I>>><i>
|
|
</I>>><i> from HttpWebRequest.cs:
|
|
</I>>><i>
|
|
</I>>><i>
|
|
</I>>><i>
|
|
</I>>><i> public override WebResponse GetResponse()
|
|
</I>>><i>
|
|
</I>>><i> {
|
|
</I>>><i>
|
|
</I>>><i> WebResponse response = ResponseCache.TryRetrieve (this);
|
|
</I>>><i>
|
|
</I>>><i>
|
|
</I>>><i>
|
|
</I>>><i> if (response == null)
|
|
</I>>><i>
|
|
</I>>><i> {
|
|
</I>>><i>
|
|
</I>>><i> WebAsyncResult result = (WebAsyncResult) BeginGetResponse (null,
|
|
</I>>><i> null);
|
|
</I>>><i>
|
|
</I>>><i> response = EndGetResponse (result);
|
|
</I>>><i>
|
|
</I>>><i> response.IsFromCache = false;
|
|
</I>>><i>
|
|
</I>>><i> HttpWebResponse response2 = ResponseCache.TryInsert
|
|
</I>>><i> ((HttpWebRequest)this, (HttpWebResponse)response);
|
|
</I>>><i>
|
|
</I>>><i> response.Close ();
|
|
</I>>><i>
|
|
</I>>><i> return response2;
|
|
</I>>><i>
|
|
</I>>><i> }
|
|
</I>>><i>
|
|
</I>>><i>
|
|
</I>>><i>
|
|
</I>>><i> return response;
|
|
</I>>><i>
|
|
</I>>><i> }
|
|
</I>>><i>
|
|
</I>>><i>
|
|
</I>>><i>
|
|
</I>>><i> The code can stand some improvement. It is a prototype and it shows. I
|
|
</I>>><i> have included the file ResponseCache.cs which the above
|
|
</I>>><i>
|
|
</I>>><i> code hooks into. We were wondering whether anyone has tried to implement
|
|
</I>>><i> response caching before and whether there is any intent to in the future.
|
|
</I>>><i> What are
|
|
</I>>><i>
|
|
</I>>><i> your thoughts about the approach described above and shown in the
|
|
</I>>><i> ResponseCache.cs file and the 3 other files I included. Bear in mind it
|
|
</I>>><i>
|
|
</I>>><i> would be refactored so that it fit into the mono architecture a bit
|
|
</I>>><i> better, it needs to be generalized, different strategies for different
|
|
</I>>><i> concrete response
|
|
</I>>><i>
|
|
</I>>><i> types need to be plugged in, configuration. and a plethora of things I
|
|
</I>>><i> missed. If you feel this approach has merit I can detail all that
|
|
</I>>><i> seperatly. If you
|
|
</I>>><i>
|
|
</I>>><i> feel a different approach would work better, please let us know, in the
|
|
</I>>><i> end were looking to make mono more robust in some of the ways that are
|
|
</I>>><i> expected but
|
|
</I>>><i>
|
|
</I>>><i> not yet implemented.
|
|
</I>>><i> The main thing I want to show here is how it is possible, to wedge a
|
|
</I>>><i> cache strategy into mono's request pipeline without changing or
|
|
</I>>><i> destabilizing
|
|
</I>>><i>
|
|
</I>>><i> mono itself. The cache implementation could change also, which is one way
|
|
</I>>><i> that this is code falls short is it totally violates open-closed. Is this
|
|
</I>>><i> a
|
|
</I>>><i>
|
|
</I>>><i> viable approach? There would of course be much more to do, that I have
|
|
</I>>><i> not even mentioned here. Your comments would be appreciated.
|
|
</I>>><i>
|
|
</I>>><i> The files can be found here.
|
|
</I>>><i>
|
|
</I>>><i>
|
|
</I>>><i> <A HREF="http://pastebin.com/FCefsiDx">http://pastebin.com/FCefsiDx</A>
|
|
</I>>><i> <A HREF="http://pastebin.com/8qBh8mMW">http://pastebin.com/8qBh8mMW</A>
|
|
</I>>><i> <A HREF="http://pastebin.com/xVKLaidG">http://pastebin.com/xVKLaidG</A>
|
|
</I>>><i> <A HREF="http://pastebin.com/NMVNv30T">http://pastebin.com/NMVNv30T</A>
|
|
</I>>><i>
|
|
</I>>><i>
|
|
</I>>><i>
|
|
</I>>><i>
|
|
</I>>><i>
|
|
</I>><i>
|
|
</I>><i>
|
|
</I>><i> --
|
|
</I>><i> Le doute n'est pas une condition agréable, mais la certitude est absurde.
|
|
</I>><i>
|
|
</I>><i> _______________________________________________
|
|
</I>><i> Mono-devel-list mailing list
|
|
</I>><i> <A HREF="http://lists.ximian.com/mailman/listinfo/mono-devel-list">Mono-devel-list at lists.ximian.com</A>
|
|
</I>><i> <A HREF="http://lists.ximian.com/mailman/listinfo/mono-devel-list">http://lists.ximian.com/mailman/listinfo/mono-devel-list</A>
|
|
</I>><i>
|
|
</I>><i>
|
|
</I>-------------- next part --------------
|
|
An HTML attachment was scrubbed...
|
|
URL: <<A HREF="http://lists.ximian.com/pipermail/mono-devel-list/attachments/20130609/7303c7df/attachment-0001.html">http://lists.ximian.com/pipermail/mono-devel-list/attachments/20130609/7303c7df/attachment-0001.html</A>>
|
|
</PRE>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!--endarticle-->
|
|
<HR>
|
|
<P><UL>
|
|
<!--threads-->
|
|
<LI>Previous message: <A HREF="040497.html">[Mono-dev] mono WebResponse caching
|
|
</A></li>
|
|
<LI>Next message: <A HREF="040513.html">[Mono-dev] mono WebResponse caching
|
|
</A></li>
|
|
<LI> <B>Messages sorted by:</B>
|
|
<a href="date.html#40509">[ date ]</a>
|
|
<a href="thread.html#40509">[ thread ]</a>
|
|
<a href="subject.html#40509">[ subject ]</a>
|
|
<a href="author.html#40509">[ author ]</a>
|
|
</LI>
|
|
</UL>
|
|
|
|
<hr>
|
|
<a href="http://lists.ximian.com/mailman/listinfo/mono-devel-list">More information about the Mono-devel-list
|
|
mailing list</a><br>
|
|
</body></html>
|