在开始正文之前,请帮忙为当前排名前 10 唯一的 .Net 开源软件 FineUI 投一票:

投票地址: https://code.csdn.net/2013OSSurvey/gitop/codevote/vote_num

目前排名前 10 ,只有 FineUI 是 .Net 项目,也希望大家能够多多支持这唯一的 .Net 项目!!!!!

=======================

-->

不管是第一次使用 FineUI 控件库的网友,还是有着 3 年以上使用经验的网友,都对 FineUI 的简单印象深刻。当然,“一切为了简单”也是 FineUI 一句响亮的口号,不仅如此,一个开源项目要想立足并长久发展下去,光凭着简单是不行,还要有自己的特色,这个特色就是创新。

从 FineUI 的官网(http://fineui.com/)我们明显看到 FineUI 的三个大特性“一切为了简单”、“用心实现80%的功能”、“创新所以独一无二”:

而今天要讲的就是“创新”的范畴。

FineUI 的 XState 机制

我们都知道 ViewState 是 ASP.NET WebForms 的一个重要的基础,用来在页面回发过程中维护控件的服务器端状态,这样我们就能方便的在回发事件处理函数中随意使用控件属性了,比如下面代码:

   1:  Label1.Text = TextBox1.Text;

但是在 AJAX 的应用环境中,ViewState 会代码下载数据的冗余,所以 FineUI 很早就在其内部实现了适合 AJAX 的 XState 机制,从而减少下载数据的冗余,加快页面的呈现速度。

但是请注意,FineUI 使用 XState 并非启用 ViewState,传统的 ASP.NET 控件仍然使用 ViewState,大家也仍然可以在 ViewState 中保存少量的数据,比如如下代码依然有效:

   1:  if (ViewState["BindGrid1"] != null && Convert.ToBoolean(ViewState["BindGrid1"]))
   2:   {
   3:          BindGrid();
   4:          ViewState["BindGrid1"] = false;
   5:  }

之前有一篇详细的文章来对比 ViewState 和 XState 对使用 FineUI 控件库的印象:http://www.cnblogs.com/sanshi/archive/2013/01/08/2850459.html

这里我们简单把结论列一下:

对于如下这个页面,我们分别比较页面第一次加载和点击按钮回发两个过程中下载的数据量:

使用 ViewState 的版本: 第一次页面加载下载数据(5068 bytes)     点击按钮回发下载数据(1251 bytes)

使用 XState 的版本:       第一次页面加载下载数据(4922 bytes)     点击按钮回发下载数据(709 bytes)

可见,XState 带来了一个很大的优势,那就是减少数据的下载量。

现在,开始关心数据上传量

之前一直很关心数据下载量,而忽视了数据上传量。其实我们所处的网络环境是一个上行下行不对称的网络,一般上行速度是下行速度的 1/2,甚至更少。来引用一篇文章中的一段:

Why Upload and Download Speeds Differ

  • Upload speed is usually slower than download speed because Internet providers have designed their systems to optimize download speeds. This is because most Internet users spend more time downloading than uploading. In other words, Internet providers give priority to downloading since it's more frequently done than uploading.

换句话说,因为人们对下载的需求更旺盛,所以网络提供商一般会分配给下载更高的传输速度。

我一直没有向这个方向考虑,直到有论坛网友提出了这个问题:http://fineui.com/bbs/forum.php?mod=viewthread&tid=3166

看到这篇帖子的时候,我就意识到了,FineUI 是做出改变的时候了!

因为我们需要在服务器和客户端之前持久化数据,对于这个网友的例子而言,就是表格中那些已经渲染后的HTML代码。通用的办法就是对客户端提交的数据进行压缩,但是在客户端使用 JavaScript 实现类似 Gzip 的压缩简直就是天方夜谭(浏览器性能受不了)!

怎么办?

均衡下载量和上传量

既然无法在客户端进行压缩,就只好在服务器端进行压缩了。所以思路如下:

1. 在页面加载时在服务器端压缩需要持久化的状态,并写入页面中;

2. 下载 AJAX 提交时,提交压缩后的持久化数据;

3. 在 AJAX 提交过程中,重新生成新的压缩后的持久化数据,并写入页面中;

4. 如此下去….

基于如下几点考虑,这部分新增的压缩数据不会对下载量造成很大的影响:

1. 下行带宽一般都比较充足;

2. 经过压缩后的持久化数据一般比较小;

3. 下载数据一般都会经过 GZIP 压缩。

具体到 FineUI 中的实现,也很简单,首先定义 GZIP 压缩和解压函数:

   1:  public static string Gzipped(string source)
   2:  {
   3:      using (var outStream = new MemoryStream())
   4:      {
   5:          using (var gzipStream = new GZipStream(outStream, CompressionMode.Compress))
   6:          {
   7:              using (var mStream = new MemoryStream(Encoding.UTF8.GetBytes(source)))
   8:              {
   9:                  mStream.WriteTo(gzipStream);
  10:              }
  11:          }
  12:   
  13:          return StringUtil.EncodeTo64(outStream.ToArray());
  14:      }
  15:  }
  16:   
  17:  public static string Ungzipped(string source)
  18:  {
  19:      byte[] bytes = Convert.FromBase64String(source);
  20:   
  21:      using (GZipStream stream = new GZipStream(new MemoryStream(bytes), CompressionMode.Decompress))
  22:      {
  23:          const int size = 512;
  24:          byte[] buffer = new byte[size];
  25:          using (MemoryStream memory = new MemoryStream())
  26:          {
  27:              int count = 0;
  28:              do
  29:              {
  30:                  count = stream.Read(buffer, 0, size);
  31:                  if (count > 0)
  32:                  {
  33:                      memory.Write(buffer, 0, count);
  34:                  }
  35:              } while (count > 0);
  36:   
  37:              return System.Text.Encoding.UTF8.GetString(memory.ToArray());
  38:          }
  39:      }
  40:  }

然后为控件基类添加一个需要对哪些属性进行 GZIP 压缩的属性:

   1:  private List<string> _gzippedAjaxProperties = new List<string>();
   2:   
   3:  internal List<string> GzippedAjaxProperties
   4:  {
   5:      get { return _gzippedAjaxProperties; }
   6:      set { _gzippedAjaxProperties = value; }
   7:  }

最后,在页面第一次加载和 AJAX 过程中压缩这个属性:

   1:  bool propertyGzippped = _gzippedAjaxProperties.Contains(property);
   2:  string propertyGzippedValue = String.Empty;
   3:   
   4:  object propertyValue = GetPropertyJSONValue(property);
   5:   
   6:  JToken tokenValue = propertyValue as JToken;
   7:  jo.Add(property, tokenValue);
   8:   
   9:  if (propertyGzippped)
  10:  {
  11:      propertyGzippedValue = tokenValue.ToString(Newtonsoft.Json.Formatting.None);
  12:  }
  13:   
  14:  if (propertyGzippped && !String.IsNullOrEmpty(propertyGzippedValue))
  15:  {
  16:      jo.Add(property + "_GZ", StringUtil.Gzipped( propertyGzippedValue));
  17:  }

测试优化结果

为了进行测试,我们创建了一个表格页面,页面效果如下:

这个页面总共有 22 行数据,我们来比较页面第一次加载和点击“选中了哪些行”两个操作在优化前后的结果。

优化前,页面第一次加载(UP:0   DOWN:30684):

优化前,页面回发(UP:33202   DOWN:186):

优化后,页面第一次加载(UP:0   DOWN:34366):

优化后,页面回发(UP:6016   DOWN:186):

经过优化后,页面第一次加载时下载数据由 30684 bytes 增加为 34366 bytes,增加了 12%,而这个增加量不会对下载造成多大的影响。

而上传量却有大幅减少,AJAX 回发时上传数据由原来的 33202 bytes 减少为 6016,减少了 82%,对于上行带宽不足的现实,这个改变带来的影响确实巨大的!

结论

优化后的 FineUI 控件库会稍微增加下载数据量,但是考虑到下行带宽一般比较充裕,并且下行数据一般会经过 GZIP 压缩,所以这个改变影响不大。现实的好处是上传数据大幅减少了 80%,这个改变带来的影响确实巨大的!

注:这个特性会加 FineUI 下个版本中去(FineUI v3.3.1)。

喜欢这篇文章,就不要忘记点击页面右下角的【推荐】按钮哦。

如何优化 FineUI 控件库的性能,减少 80% 的数据上传量!的更多相关文章

  1. 用jQuery File Upload做的上传控件demo,支持同页面多个上传按钮

    需求 有这么一个需求,一个form有多个文件要上传,但又不是传统的图片批量上传那种,是类似下图这种需求,一开始是用的swfupload做的上传,但是问题是如果有多个按钮的话,就要写很多重复的代码,于为 ...

  2. 关于附件控件隐藏后,在IE下不能上传,报“拒绝访问”

    报错时的使用: @Html.TextBoxFor(m => m.FileName, new { style = "width:457px;", @readonly = &qu ...

  3. FineUIPro控件库深度解析

    FineUIPro控件库 FineUIPro是一套基于jQuery的专业ASP.NET控件库,始于2008年的开源版FineUI控件库. 当年为了提升项目的开发效率,降低代码复杂度,减少对CSS和Ja ...

  4. Win10 UWP开发系列——开源控件库:UWPCommunityToolkit

    在开发应用的过程中,不可避免的会使用第三方类库.之前用过一个WinRTXamlToolkit.UWP,现在微软官方发布了一个新的开源控件库—— UWPCommunityToolkit 项目代码托管在G ...

  5. 开源WPF控件库MaterialDesignInXAML推荐

    今天介绍一个开源的C# WPF开源控件库,非常漂亮,重点是开源哦 WPF做桌面开发是很有优势的,除了微软自带的控件外,还有很多第三方的控件库,比如收费的Dev Express For WPF.Tele ...

  6. 《Dotnet9》系列-开源C# WPF控件库1《MaterialDesignInXAML》强力推荐

    时间如流水,只能流去不流回! 点赞再看,养成习惯,这是您给我创作的动力! 本文 Dotnet9 https://dotnet9.com 已收录,站长乐于分享dotnet相关技术,比如Winform.W ...

  7. FineUI 基于 ExtJS 的专业 ASP.NET 控件库

    FineUI 基于 ExtJS 的专业 ASP.NET 控件库 http://www.fineui.com/

  8. Android 性能优化——之控件的优化

    Android 性能优化——之控件的优化 前面讲了图像的优化,接下来分享一下控件的性能优化,这里主要是面向自定义View的优化. 1.首先先说一下我们在自定义View中可能会犯的3个错误: 1)Use ...

  9. 反爬虫:利用ASP.NET MVC的Filter和缓存(入坑出坑) C#中缓存的使用 C#操作redis WPF 控件库——可拖动选项卡的TabControl 【Bootstrap系列】详解Bootstrap-table AutoFac event 和delegate的分别 常见的异步方式async 和 await C# Task用法 c#源码的执行过程

    反爬虫:利用ASP.NET MVC的Filter和缓存(入坑出坑)   背景介绍: 为了平衡社区成员的贡献和索取,一起帮引入了帮帮币.当用户积分(帮帮点)达到一定数额之后,就会“掉落”一定数量的“帮帮 ...

随机推荐

  1. input的file 控件及美化

    在一些网站进行上传时,当单击了“浏览”按钮之后会弹出[选择文件]的对话框.想要实现这一功能,用input的file控件来实现就好啦~ <!doctype html> <html la ...

  2. CDC 2013 北京站手记

    受搜狐畅游的邀请,这次能够有机会参与2013中国开发者大会北京站的活动. 本次大会的主题是“游戏”和“移动”,因此上午的峰会安排了5个主讲,分别就搜索.云存储服务器.游戏媒体.移动应用和游戏渠道等多方 ...

  3. Solr页面查询各个字段参数解释

    q:查询的关键字,此参数最为重要,例如,q=id:1,默认为q=*:*,类似于sql中的where 1=1. fq(filter query):过滤查询,提供一个可选的筛选器查询.返回在q查询符合结果 ...

  4. HTTP协议小结

    HTTP/0.9已过时.只接受GET一种请求方法,没有在通讯中指定版本号,且不支持请求头.由于该版本不支持POST方法,因此客户端无法向服务器传递太多信息. HTTP/1.0 这是第一个在通讯中指定版 ...

  5. ES6函数剩余参数(Rest Parameters)

    我们知道JS函数内部有个arguments对象,可以拿到全部实参.现在ES6给我们带来了一个新的对象,可以拿到除开始参数外的参数,即剩余参数(废话好多 O(∩_∩)O~). 这个新的对象和argume ...

  6. MYSQL:使用\G参数改变输出结果集的显示方式

    在mysql命令行工具中执行查询时,当表的列很多的时候显示很乱. 上面的显示你肯定看不清楚吧.以上方式是默认以列(表格)形式显示的.那怎么以行(表单)的方式显示呢,请看下面 OK,搞定. 参考文档:h ...

  7. js中的继承

    js中继承的实现方式很多,此处给出两种常用方式. <!DOCTYPE html> <html> <head> <meta charset='UTF-8'> ...

  8. python 缩进语法,优缺点

    Python的语法比较简单——采用缩进方式 缩进有利有弊: 好处之一是强迫你写出格式化的代码,但没有规定缩进是几个空格还是Tab.按照约定俗成的管理,应该始终坚持使用4个空格的缩进. 其二是强迫你写出 ...

  9. 用FineReport报表系统构建资金监管平台

    一.应用背景 计算机的应用已经渗透到日常工作的许多方面,无论是其自身还是所发挥的作用,计算机都标志着一种高科技,使工作高效率和高水平.为了能更方便,更轻松,更好的管理,信息化建设正在日益发展壮大,更加 ...

  10. .Net程序员之Python基础教程学习----字符串的使用 [Second Day]

         在The FirstDay 里面学习了列表的元组的使用,今天开始学习字符串的使用.字符串的使用主要要掌握,字符串的格式化(C语言中我们应该都知道,Python和C语言差别不大),字符串的基本 ...