zoukankan      html  css  js  c++  java
  • Volley1--为什么说Volley适合数据量小,通信频繁的网络操作

    前言

    网络编程对于客户端来说是一块及其重要的地方,使用高效的网络请求框架将为你的系统产生很大的影响。而Volley作为谷歌的一个开源项目,炙手可热。有很多中小型公司的安卓移动客户端的网络程序都是基于volley的。 Volley的优点很多,光可扩展性这一条优点就值得我们称赞。但是我想针对的是在 Google I/O 2013 大会上发布Volley的时候的一句话:a burst or emission of many things or a large amount at once(爆炸性的事件在很短的时间内发生),意思就是:Volley特别适合数据量小,通信量大的客户端。同为网络请求框架,为什么Volley会有这样的特点?接下来,我就用我的理解来解释一下。

    ByteArrayPool产生背景

    根据类名,知道这是一个字节数组缓存池。没错,就是用来缓存 网络请求获得的数据。 当网络请求得到返回数据以后,我们需要在内存开辟出一块区域来存放我们得到的网络数据,不论是json还是图片,都会存在于内存的某一块区域,然后拿到UI显示,然而客户端请求是相当频繁的操作,想一下我们平时使用知乎等一些客户端,几乎每一个操作都要进行网络请求(虽然知乎大部分是WebView)。那么问题来了:这么频繁的数据请求,获得数据以后我们先要在堆内存开辟存储空间,然后显示,等到时机成熟,GC回收这块区域,如此往复,那么GC的负担就相当的重,然而Android客户端处理能力有限,频繁GC对客户端的性能有直接影响。我们能不能减少GC和内存的分配呢?我想这个问题就是这个类的产生背景。

    实现原理(怎么实现缓存从而减少GC)

    在ByteArrayPool中维护了两个List集合。

    从缓冲区取空间

    当请求数据返回以后,我们不是急于在内存开辟空间,而是从ByteArrayPool中取出一块已经分配的内存区域。此时会调用ByteArrayPool的getBuf(int)方法,来得到一块参数大小的区域,源码如下:

     1 public synchronized byte[] getBuf(int len) {
     2     for (int i = 0; i < mBuffersBySize.size(); i++) {
     3         byte[] buf = mBuffersBySize.get(i);
     4         if (buf.length >= len) {
     5             mCurrentSize -= buf.length;
     6             mBuffersBySize.remove(i);
     7             mBuffersByLastUse.remove(buf);
     8             return buf;
     9         }
    10     }
    11     return new byte[len];
    12 }

    ①方法的第2行代码,遍历mBuffersBySize,找到最适合len大小的byte[]。第6 ~8行更新缓存池中数据

    ②此方法主要的功能: 不必每次存数据都要进行内存分配,而是先查找缓冲池中有无适合的内存区域

    ③有的条件不需循环 if(len<=mSizeLimit)、

    将空间返回给缓存池

    如果只是拿数据,缓存区的只会越来越小,我们还需要向缓冲区中加入存储空间。这个时候涉及到一个方法
     1 public synchronized void returnBuf(byte[] buf) {
     2     if (buf == null || buf.length > mSizeLimit) {
     3         return;
     4     }
     5     mBuffersByLastUse.add(buf);
     6     int pos = Collections.binarySearch(mBuffersBySize, buf, BUF_COMPARATOR);
     7     if (pos < 0) {
     8         pos = -pos - 1;
     9     }
    10     mBuffersBySize.add(pos, buf);
    11     mCurrentSize += buf.length;
    12     trim();
    13 }
    方法首先检查 要插入的数据大小有没有超出边界,如果没有,利用二分法找到插入位置,将数据插入到上述的两个集合,完成排序。然后更新缓冲池的大小,以方便从缓冲区中取存储空间。

    结语

    ByteArrayPool利用getBuf和returnBuf以及mBuffersByLastUse和mBuffersBySize完成字节数组的缓存。当需要使内存区域的时候,先从已经分配的区域中获得以减少内存分配次数。当空间用完以后,在将数据返回给此缓冲区。
    这样,就会减少内存区域堆内存的波动和减少GC的回收,让CPU把更多的性能留给页面的渲染,提高性能。通过这个类发现,谷歌对技术的细节十分考究。



     http://www.codekk.com/open-source-project-analysis/detail/Android/grumoon/Volley%20%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90

  • 相关阅读:
    Entity Framework Core 2.0 新特性
    asp.net core部署时自定义监听端口,提高部署的灵活性
    asp.net core使用jexus部署在linux无法正确 获取远程ip的解决办法
    使用xshell连接服务器,数字键盘无法使用解决办法
    使用Jexus 5.8.2在Centos下部署运行Asp.net core
    【DevOps】DevOps成功的八大炫酷工具
    【Network】Calico, Flannel, Weave and Docker Overlay Network 各种网络模型之间的区别
    【Network】UDP 大包怎么发? MTU怎么设置?
    【Network】高性能 UDP 应该怎么做?
    【Network】golang 容器项目 flannel/UDP相关资料
  • 原文地址:https://www.cnblogs.com/ganchuanpu/p/7625504.html
Copyright © 2011-2022 走看看