<html dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style id="owaParaStyle">P {
        MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px
}
</style>
</head>
<body fPStyle="1" ocsi="0">
<div style="direction: ltr;font-family: Tahoma;color: #000000;font-size: 10pt;">
<div style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">Hi Greg,</div>
<div style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px"> </div>
<div style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">Great input. I have not gotten that far yet. Also the cache level is very naïve. Everything caches except Bypass cache which doesn't cache. To check the headers it would check the WebResponse Headers property coming
 into TryInsert in <font face="Consolas">DirectoryBackedResponseCache.cs</font> . I would combine the result of checking the header with the conditional ShouldCache which also needs work.  What we are looking for is comments like this, about what you think
 needs to be in a usable implementation, gotchas, things to look out for. Also if we are on the wrong track doing it this way I don't want to waste time doing something which will not be useful. Assuming I'm not on the wrong path, I will add the header check
 next. This is the kind of feedback we need. I only tried to make a prototype of how caching could work and then did some performance measurements. Obviously didn't add any of the details yet. If this is a viable approach I will continue to fill out the implementation
 guided by research and suggestions. Probably want to limit it to what we really need to have. Any other suggestions, comments, criticism would be greatly appreciated.</div>
<div style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px"> </div>
<div style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">Thanks,</div>
<div style="FONT-SIZE: 16px; FONT-FAMILY: Times New Roman; COLOR: #000000">
<hr tabindex="-1">
<div id="divRpF947956" style="DIRECTION: ltr"><font color="#000000" size="2" face="Tahoma"><b>From:</b> Greg Young [gregoryyoung1@gmail.com]<br>
<b>Sent:</b> Tuesday, June 04, 2013 6:49 PM<br>
<b>To:</b> Mark Lintner<br>
<b>Cc:</b> mono-devel-list@lists.ximian.com<br>
<b>Subject:</b> Re: [Mono-dev] mono WebResponse caching<br>
</font><br>
</div>
<div></div>
<div>I would expect this to look at http caching headers in response when caching such as expiration, whether something is cachable (public/private) <span></span>etc but don't see any of that code (or maybe I missed it). Can you point to where it is in your
 implementation?<br>
<br>
On Tuesday, June 4, 2013, Mark Lintner wrote:<br>
<blockquote class="gmail_quote" style="PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; BORDER-LEFT: #ccc 1px solid">
<div>
<div style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; DIRECTION: ltr">
<p>We have noticed that parts of the Mono Web functionality are not yet implemented. We are hoping to be able to add some of these missing pieces. Caching of
</p>
<p>HttpWebResponses is the first one we took a look at. It would appear that Microsoft takes advantage of the internet explorer caching. Since it would appear
</p>
<p>that an HttpWebResponse is fully populated when it is returned from the cache and the only content in the urls that are cached are the bytes that come in on
</p>
<p>the wire, Microsoft must return things from the cache at a very low level and and let the response populate the normal way. This did not seem possible to
</p>
<p>emulate when I looked at mono. I also wanted to cache to a directory so that the urls can be inspected or deleted.</p>
<p><br>
 After looking at the code for awhile I realized that I could save additional information from the response, ie: headercollection, cookiecontainer, Status
</p>
<p>code etc in the same file as the responsestream. A response can be serialized but not all of it, most importantly the responsestream is not serialized. I
</p>
<p>wrote a prototype with some helper functions, the only change to existing mono code would be in  HttpWebRequest.GetResponse. Before calling BeginGetResponse
</p>
<p>I call a function that tries to retrieve the url from the cache. If it is not there, BeginGetResponse is called as normal, the response is grabbed from
</p>
<p>EndGetResponse and passed to a method to insert into the cache. This insert method will open a filename in a directory designated as mono_cache with the name
</p>
<p>produced by calling HttpUtility.Encode so it is a legal filename. Also you can only read from the responsestream once, which means that if read from it, save
</p>
<p>it to a file, then the responsestream is no longer accessible from the WebResponse when it is returned to the calling code. If sream copy worked it could be
</p>
<p>used here. One way to fix the problem is to call GetResponseStream(), read it to the end, which produces a string, then finally convert the string to bytes.
</p>
<p>Then you can serialize the bytes to the open file, serialize the headercollection and ultimately individually add any field you want in the response when it
</p>
<p>is retrieved from the cache, then close the file. Then create a new WebConnectionData instance and populate it with headers and all the relevent fields from
</p>
<p>the old response, finally passing the bytes of data to a memory stream constructor and assign it to the WebConnectionData's stream member. Then I construct a
</p>
<p>new HttpWebResponse, passing the WebConnectionData and other arguments which are taken from the existing request and the recently retrieved response. The
</p>
<p>response is then returned to getResponse then finally to the calling code, good as new. Next time the url is requested the cached file is deserialized, one
</p>
<p>member at a time then a WebConnectionData is setup and finally, a HttpWebResponse is constructed with the info read from the file, the WebConnectionData and
</p>
<p>from the members of the new request. I concentrated on prototyping caching of HttpWebResponses. Only a simple cache algorithm, no Ftp, no File etc. No cache
</p>
<p>aging etc. There are many other things that would have to be done for this to be usable.
<br>
  Using the prototype I requested <a href="http://www.google.com" target="_blank">
www.google.com</a> and it took .1601419 sec to retrieve and cache it, including all the mechanics described above. The
</p>
<p>second time returning it from the cache, building the HttpWebResponse took .0007671. This is a 288 times speedup. That kind of performance increase, from a
</p>
<p>prototype that is not yet optimized, is compelling. I must add that I measured the same experiment with google under the .Net 4.5 implementation and the
</p>
<p>speedup is 769x. Obviously thats something to work toward. Even falling short of that level of speedup, some implementation of response caching for mono
</p>
<p>would greatly benefit the users who need better performance of services, rest etc.
</p>
<p>So far this is the only mono code that would change to support caching,</p>
<p><br>
from HttpWebRequest.cs:</p>
<p> </p>
<p>  public override WebResponse GetResponse()</p>
<p>  {</p>
<p>   WebResponse response = ResponseCache.TryRetrieve (this);</p>
<p> </p>
<p>   if (response == null)</p>
<p>   {</p>
<p>    WebAsyncResult result = (WebAsyncResult) BeginGetResponse (null, null);</p>
<p>    response = EndGetResponse (result); </p>
<p>    response.IsFromCache = false;</p>
<p>    HttpWebResponse response2 = ResponseCache.TryInsert ((HttpWebRequest)this, (HttpWebResponse)response);</p>
<p>    response.Close ();</p>
<p>    return response2;</p>
<p>   }</p>
<p> </p>
<p>   return response;</p>
<p>  }</p>
<p></p>
<p> </p>
<p>The code can stand some improvement. It is a prototype and it shows.  I have included the file ResponseCache.cs which the above
</p>
<p>code hooks into. We were wondering whether anyone has tried to implement response caching before and whether there is any intent to in the future. What are
</p>
<p>your thoughts about the approach described above and shown in the ResponseCache.cs file and the 3 other files I included. Bear in mind it
</p>
<p>would be refactored so that it fit into the mono architecture a bit better, it needs to be generalized, different strategies for different concrete response
</p>
<p>types need to be plugged in, configuration. and a plethora of things I missed. If you feel this approach has merit I can detail all that seperatly. If you
</p>
<p>feel a different approach would work better, please let us know, in the end were looking to make mono more robust in some of the ways that are expected but
</p>
<p>not yet implemented. <br>
 The main thing I want to show here is how it is possible, to wedge a cache strategy into mono's request pipeline without changing or destabilizing
</p>
<p>mono itself. The cache implementation could change also, which is one way that this is code falls short is it totally violates open-closed.  Is this a
</p>
<p>viable approach? There would of course be much more to do, that I have not even mentioned here. Your comments would be appreciated.</p>
<p><font face="Calibri, Verdana, Helvetica, Arial"><span style="FONT-SIZE: 11pt">The files can be found here.</span></font></p>
<p><font face="Calibri, Verdana, Helvetica, Arial"><span style="FONT-SIZE: 11pt"><br>
<a href="http://pastebin.com/FCefsiDx" target="_blank">http://pastebin.com/FCefsiDx</a><br>
<a href="http://pastebin.com/8qBh8mMW" target="_blank">http://pastebin.com/8qBh8mMW</a><br>
<a href="http://pastebin.com/xVKLaidG" target="_blank">http://pastebin.com/xVKLaidG</a><br>
<a href="http://pastebin.com/NMVNv30T" target="_blank">http://pastebin.com/NMVNv30T</a></span></font></p>
<p><font face="Calibri, Verdana, Helvetica, Arial"><span style="FONT-SIZE: 11pt"></span></font> </p>
<p><font face="Calibri, Verdana, Helvetica, Arial"><span style="FONT-SIZE: 11pt"></span></font> </p>
</div>
</div>
</blockquote>
<br>
<br>
-- <br>
Le doute n'est pas une condition agréable, mais la certitude est absurde.<br>
</div>
</div>
</div>
</body>
</html>