知乎周源微信_每周源代码35-Zip压缩ASP.NET会话和缓存状态

本文主要是介绍知乎周源微信_每周源代码35-Zip压缩ASP.NET会话和缓存状态,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

知乎周源微信

知乎周源微信

Recently while talking to Jeff Atwood and his development team about StackOverflow he mentioned that he compresses the Cache or Session data in ASP.NET which enables him to store about 5-10x more data. They do it with some helper methods but I thought it'd be interesting to try it myself.

最近,在与Jeff Atwood及其开发团队讨论StackOverflow时,他提到他在ASP.NET中压缩了Cache或Session数据,这使他可以存储大约5-10倍的数据。 他们使用一些辅助方法来完成此操作,但我认为自己尝试一下会很有趣。

There's a lot of options and thoughts and quasi-requirements on how to pull this off:

关于如何实现这一目标,有很多选择,想法和准要求:

  • I could create my own SessionStateModule, basically replacing the default Session state mechanism completely.

    我可以创建自己的SessionStateModule,基本上完全替换默认的Session状态机制。
  • I could create a number of extension methods to HttpSessionState.

    我可以为HttpSessionState创建许多扩展方法。
  • I could just use helper methods, but that means I have to remember to use them on the in and the out and it doesn't feel like the way I'd use it day to day. However, the benefit to this approach is that it's very VERY simple and I can zip up whatever I want, whenever, and put it wherever.

    我可以只使用辅助方法,但是这意味着我必须记住在和外出使用他们在和它不觉得喜欢的方式我会用它每一天。 但是,这种方法的好处是非常简单,我可以随时随地压缩任何内容,然后放在任何地方。

  • I didn't want to accidentally put something in zipped and take it out unzipped. I want to avoid collisions.

    我不想意外地将某些东西放进拉链,然后将其解压缩。 我想避免碰撞。
  • I'm primarily concerned about storing strings (read: angle brackets), rather than binary serialization and compression of objects.

    我主要关心的是存储字符串(阅读:尖括号),而不是二进制序列化和对象压缩。
  • I want to be able to put zipped stuff in the Session, Application and Cache. I realized that this was the primary requirement. I didn't realize it until I started writing code from the outside. Basically, TDD, using the non-existent library in real websites.

    我希望能够将压缩后的内容放入会话,应用程序和缓存中。 我意识到这是主要要求。 直到我开始从外部编写代码时,我才意识到这一点 基本上,TDD使用实际网站中不存在的库。

我的错误开始 (My False Start)

I initially thought I wanted it to look and work like this:

我最初以为我希望它看起来像这样工作:

Session.ZippedItems["foo"] = someLargeThing;
someLargeThing = Session.ZippedItems["foo"]; //string is implied

But you can't do extension properties (rather than extension methods) or operator overloading.

但是您不能执行扩展属性(而不是扩展方法)或运算符重载。

Then I though I'd do it like this:

然后,尽管我会这样做:

public static class ZipSessionExtension
{
public static object GetZipItem(this HttpSessionState s, string key)
{
//go go go
}
}

And have GetThis and SetThat all over...but that didn't feel right either.

到处都有GetThis和SetThat ...但是感觉也不对。

它应该如何工作 (How It Should Work)

So I ended up with this once I re-though the requirements. I realized I'd want it to work like this:

因此,一旦我重新考虑了要求,我就结束了。 我意识到我希望它像这样工作:

Session["foo"] = "Session: this is a test of the emergency broadcast system.";
Zip.Session["foo"] = "ZipSession this is a test of the emergency broadcast system.";
string zipsession = Zip.Session["foo"];
Cache["foo"] = "Cache: this is a test of the emergency broadcast system.";
Zip.Cache["foo"] = "ZipCache: this is a test of the emergency broadcast system.";
string zipfoo = Zip.Cache["foo"];

Once I realized how it SHOULD work, I wrote it. There's a few interesting things I used and re-learned.

一旦我意识到它应该如何工作,我就写了它。 我使用并重新学习了一些有趣的东西。

I initially wanted the properties to be indexed properties and I wanted to be able to type "Zip." and get intellisense. I named the class Zip and made it static. There's two static properties name Session and Cache respectively. They each have an indexer, which makes Zip.Session[""] and Zip.Cache[""] work. I prepended the word "zip" to the front of the key in order to avoid collisions with uncompressed content, and to create the illusion there were two different places.

我最初希望该属性成为索引属性,并且希望能够键入“ Zip”。 并获得智慧。 我将类命名为Zip并使其变为静态。 有两个静态属性,分别为Session和Cache。 它们每个都有一个索引器,使Zip.Session [“”]和Zip.Cache [“”]工作。 为了避免与未压缩的内容发生冲突,我在键的前面加上了“ zip”一词,为了营造一种错觉,这里有两个不同的地方。

using System.IO;
using System.IO.Compression;
using System.Diagnostics;
using System.Web;

namespace HanselZip
{
public static class Zip
{
public static readonly ZipSessionInternal Session = new ZipSessionInternal();
public static readonly ZipCacheInternal Cache = new ZipCacheInternal();

public class ZipSessionInternal
{
public string this[string index]
{
get
{
return GZipHelpers.DeCompress(HttpContext.Current.Session["zip" + index] as byte[]);
}
set
{
HttpContext.Current.Session["zip" + index] = GZipHelpers.Compress(value);
}
}
}

public class ZipCacheInternal
{
public string this[string index]
{
get
{
return GZipHelpers.DeCompress(HttpContext.Current.Cache["zip" + index] as byte[]);
}
set
{
HttpContext.Current.Cache["zip" + index] = GZipHelpers.Compress(value);
}
}
}

public static class GZipHelpers
{
public static string DeCompress(byte[] unsquishMe)
{
using (MemoryStream mem = new MemoryStream(unsquishMe))
{
using (GZipStream gz = new GZipStream(mem, CompressionMode.Decompress))
{
var sr = new StreamReader(gz);
return sr.ReadToEnd();
}
}
}

public static byte[] Compress(string squishMe)
{
Trace.WriteLine("GZipHelper: Size In: " + squishMe.Length);
byte[] compressedBuffer = null;
using (MemoryStream stream = new MemoryStream())
{
using (GZipStream zip = new GZipStream(stream, CompressionMode.Compress))
{
using (StreamWriter sw = new StreamWriter(zip))
{
sw.Write(squishMe);
}
//Dont get the MemoryStream data before the GZipStream is closed since it doesn’t yet contain complete compressed data.
//GZipStream writes additional data including footer information when its been disposed
}
compressedBuffer = stream.ToArray();
Trace.WriteLine("GZipHelper: Size Out:" + compressedBuffer.Length);
}
return compressedBuffer;
}
}
}
}

Note that if the strings you put in are shorter than about 300 bytes, they will probably get LARGER. So, you'll probably only want to use these if have strings of more than a half K. More likely you'll use these if you have a few K or more. I figure these would be used for caching large chunks of HTML.

请注意,如果您输入的字符串短于大约300个字节,则它们可能会变得更大。 因此,如果字符串的长度大于K的一半,您可能只想使用它们。如果K的数量大于或等于K,则更有可能使用它们。 我认为这些将用于缓存大量HTML。

As an aside, I used Trace.WriteLine to show the size in and the size out. Then, in the web.config I added this trace listener to make sure my Trace output from my external assembly showed up in the ASP.NET Tracing:

顺便说一句,我使用了Trace.WriteLine来显示大小和大小。 然后,在web.config中,我添加了此跟踪侦听器,以确保来自外部程序集的跟踪输出显示在ASP.NET跟踪中:

<system.diagnostics>
<trace>
<listeners>
<add name="WebPageTraceListener"
type="System.Web.WebPageTraceListener, System.Web,
Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
</listeners>
</trace>
</system.diagnostics>
<system.web>
<trace pageOutput="true" writeToDiagnosticsTrace="true" enabled="true"/>
...

The resulting trace output is:

结果跟踪输出为:

image

何时压缩 (When To Compress)

See how the first zipped string got bigger? I shouldn't have put it in there, it was initially too small. The second one went from 1137 bytes to 186, so that was reasonably useful. Again, IMHO, this probably won't matter unless you were storing thousands of strings in cache that were grater than 1k, but as you get towards 10k or more, I suspect you'd get some more value.

看看第一个压缩的弦如何变大? 我不应该把它放在那里,它最初太小了。 第二个从1137字节增加到186个字节,因此相当有用。 同样,恕我直言,除非您在缓存中存储数千个大于1k的字符串,否则这可能无关紧要,但是当您达到10k或更多时,我怀疑您会获得更多价值。

For example, if I put 17k of basic HTML in the cache, it squishes it 3756 bytes, a 78% savings. It all depends on how repetitive the markup is and how many visitors you have. If you had a thousand visitors on a machine simultaneously, and you were caching, say, 20 chunks of 100k each, times 1000 users, you'd use about 244 megs for your cache. When I was working in banking, we might have tens of thousands of users online at a time, and we'd be caching historical checking or savings data, and that data might get to 500k or more of XML. Four savings accounts * 70,000 users * 500k of XML history might be 16gigs of RAM (across many servers, so maybe a gig or half-gig per server.) Squishing that 500k to 70k would reduce the hit to 2gigs total. It all depends on how much you're storing, how much it'll compress (how repetitive it is) and how often it's accessed.

例如,如果我将17k基本HTML放入缓存中,它将压缩3756字节,节省了78%。 这完全取决于标记的重复性以及您拥有多少访问者。 如果您同时在一台机器上有一千个访问者,并且您要缓存20个块(每个100k,乘以1000个用户),则将使用约244兆作为缓存。 当我在银行工作时,我们一次可能有成千上万的用户在线,并且我们将缓存历史检查或储蓄数据,并且该数据可能达到500k或更多的XML。 四个储蓄帐户* 70,000个用户* 500,000个XML历史记录可能是16 gig的RAM(在许多服务器上,因此每个服务器可能是一个gig或半gig。)将500k减少到70k会将命中总数减少到2 gig。 这完全取决于您要存储多少,压缩多少(重复性如何)以及访问频率。

Memcached 2 includes a setCompressThreshold that lets you adjust the minimum savings you want before it'll compress. I suspect Velocity will have some similar setting. 

Memcached 2包含一个setCompressThreshold,可让您调整压缩前所需的最低节省量。 我怀疑Velocity会有类似的设置。

Ultimately, however, this all means nothing unless you measure. For example, all this memory savings might be useless if the data is being read and written constantly. You'd be trading any savings from squishing for other potential problems like the memory you need hold the decompressed values as well as memory fragmentation. Point is, DON'T just turn this stuff on without measuring.

但是,最终,除非您进行测量,否则所有这些都没有任何意义。 例如,如果不断地读取和写入数据,那么所有这些内存节省都可能是无用的。 压缩其他潜在问题(例如需要保留解压缩后的值的内存以及内存碎片)可节省任何节省。 重点是,不要随便测量这些东西。

Nate Davis had a great comment on the StackOverflow show I wanted to share here:

Nate Davis对我想在这里分享的StackOverflow节目发表了很好的评论:

If they are caching final page output in this way and they are already sending HTTP responses across the wire as gzip,
then gzipping the output cache would make great sense. But only if they are NOT first unzipping when taking the page out of cache and then re-zipping it up again before sending the response.
If they check the 'Accept-Encoding' header to make sure gzip is supported, then they can just send the gzipped output cache directly into the response stream and set the Encoding header with 'gzip'. If Accept-Encoding doesn't include gzip, then the cache would have to be unzipped, but this is a very small percentage of browsers.

如果他们以这种方式缓存最终页面输出,并且已经以gzip的形式通过网络发送了HTTP响应, 那么gziping输出缓存将非常有意义。 但是,只有在将页面从缓存中移出时,他们没有首先解压缩,然后在发送响应之前再次将其重新压缩时,才行。 如果他们检查“ Accept-Encoding”标头以确保支持gzip,则他们可以将gzip压缩的输出缓存直接发送到响应流中,并用“ gzip”设置Encoding标头。 如果Accept-Encoding不包含gzip,则必须解压缩缓存,但这只是很小一部分的浏览器。

Nate is pointing out that one should think about HOW this data will be used. Are you caching and entire page or iFrame? If so, you might be able to send it right back out, still compressed to the browser.

Nate指出,应该考虑如何使用这些数据。 您要缓存整个页面还是iFrame? 如果是这样,您可以直接将其发送回,但仍压缩到浏览器中。

However, if you've got IIS7 and you want to cache a whole page rather than just a per user fragment, consider using IIS7's Dynamic Compression. You've already got this feature, and along with ASP.NET's OutputCaching, the system already knows about gzip compression. It'll store the gzipp'ed version and serve it directly.

但是,如果您拥有IIS7,并且想要缓存整个页面而不是每个用户片段,请考虑使用IIS7的Dynamic Compression 。 您已经具有此功能,并且与ASP.NET的OutputCaching一起,系统已经了解gzip压缩。 它将存储gzipp版本并直接提供。

我的结论? (My Conclusion?)

  • I might use something like this if I was storing large string fragments in a memory constrained situation.

    如果我在内存受限的情况下存储大型字符串片段,则可能会使用类似的内容。
  • I always turn compression on at the Web Server level. It's solving a different problem, but there's really NO reason for your web server to be serving uncompressed content. It's wasteful not to turn it on.

    我总是在Web服务器级别打开压缩功能。 它正在解决一个不同的问题,但实际上没有理由让您的Web服务器提供未压缩的内容。 不打开它很浪费。

Thoughts? What is this missing? Useful? Not useful?

有什么想法吗? 这缺少什么? 有用? 没用?

翻译自: https://www.hanselman.com/blog/the-weekly-source-code-35-zip-compressing-aspnet-session-and-cache-state

知乎周源微信

这篇关于知乎周源微信_每周源代码35-Zip压缩ASP.NET会话和缓存状态的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/515940

相关文章

java向微信服务号发送消息的完整步骤实例

《java向微信服务号发送消息的完整步骤实例》:本文主要介绍java向微信服务号发送消息的相关资料,包括申请测试号获取appID/appsecret、关注公众号获取openID、配置消息模板及代码... 目录步骤1. 申请测试系统2. 公众号账号信息3. 关注测试号二维码4. 消息模板接口5. Java测试

解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题

《解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题》:本文主要介绍解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4... 目录未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘打开pom.XM

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

Python基于微信OCR引擎实现高效图片文字识别

《Python基于微信OCR引擎实现高效图片文字识别》这篇文章主要为大家详细介绍了一款基于微信OCR引擎的图片文字识别桌面应用开发全过程,可以实现从图片拖拽识别到文字提取,感兴趣的小伙伴可以跟随小编一... 目录一、项目概述1.1 开发背景1.2 技术选型1.3 核心优势二、功能详解2.1 核心功能模块2.

IIS 7.0 及更高版本中的 FTP 状态代码

《IIS7.0及更高版本中的FTP状态代码》本文介绍IIS7.0中的FTP状态代码,方便大家在使用iis中发现ftp的问题... 简介尝试使用 FTP 访问运行 Internet Information Services (IIS) 7.0 或更高版本的服务器上的内容时,IIS 将返回指示响应状态的数字代

Java实现本地缓存的常用方案介绍

《Java实现本地缓存的常用方案介绍》本地缓存的代表技术主要有HashMap,GuavaCache,Caffeine和Encahche,这篇文章主要来和大家聊聊java利用这些技术分别实现本地缓存的方... 目录本地缓存实现方式HashMapConcurrentHashMapGuava CacheCaffe

SpringBoot实现文件记录日志及日志文件自动归档和压缩

《SpringBoot实现文件记录日志及日志文件自动归档和压缩》Logback是Java日志框架,通过Logger收集日志并经Appender输出至控制台、文件等,SpringBoot配置logbac... 目录1、什么是Logback2、SpringBoot实现文件记录日志,日志文件自动归档和压缩2.1、

如何基于Python开发一个微信自动化工具

《如何基于Python开发一个微信自动化工具》在当今数字化办公场景中,自动化工具已成为提升工作效率的利器,本文将深入剖析一个基于Python的微信自动化工具开发全过程,有需要的小伙伴可以了解下... 目录概述功能全景1. 核心功能模块2. 特色功能效果展示1. 主界面概览2. 定时任务配置3. 操作日志演示

如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)

《如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)》:本文主要介绍如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)问题,具有很好的参考价值,希望对大家有所帮助,如有... 目录先在你打算存放的地方建四个文件夹更改这四个路径就可以修改默认虚拟内存分页js文件的位置接下来从高级-

PyCharm如何更改缓存位置

《PyCharm如何更改缓存位置》:本文主要介绍PyCharm如何更改缓存位置的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录PyCharm更改缓存位置1.打开PyCharm的安装编程目录2.将config、sjsystem、plugins和log的路径