zoukankan      html  css  js  c++  java
  • Volley之ByteArrayPool

    前言

    网络编程对于客户端来说是一块及其重要的地方,使用高效的网络请求框架将为你的系统产生很大的影响。而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)方法,来得到一块参数大小的区域,源码如下:

    public synchronized byte[] getBuf(int len) {
        for (int i = 0; i < mBuffersBySize.size(); i++) {
            byte[] buf = mBuffersBySize.get(i);
            if (buf.length >= len) {
                mCurrentSize -= buf.length;
                mBuffersBySize.remove(i);
                mBuffersByLastUse.remove(buf);
                return buf;
            }
        }
        return new byte[len];
    }
    

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

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

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

    将空间返回给缓存池

    如果只是拿数据,缓存区的只会越来越小,我们还需要向缓冲区中加入存储空间。这个时候涉及到一个方法

    public synchronized void returnBuf(byte[] buf) {
        if (buf == null || buf.length > mSizeLimit) {
            return;
        }
        mBuffersByLastUse.add(buf);
        int pos = Collections.binarySearch(mBuffersBySize, buf, BUF_COMPARATOR);
        if (pos < 0) {
            pos = -pos - 1;
        }
        mBuffersBySize.add(pos, buf);
        mCurrentSize += buf.length;
        trim();
    }
    

    方法首先检查 要插入的数据大小有没有超出边界,如果没有,利用二分法找到插入位置,将数据插入到上述的两个集合,完成排序。然后更新缓冲池的大小,以方便从缓冲区中取存储空间。

    结语

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

    http://www.codekk.com/open-source-project-analysis/detail/Android/grumoon/Volley 源码解析

    本文转自:https://www.cnblogs.com/ganchuanpu/p/7625504.html

  • 相关阅读:
    java基础之接口和多态
    JAVA随笔三
    java基础之多线程
    JAVA随笔二
    java基础之继承补充和抽象类
    java基础之面向对象和继承
    java基础 之IO流随笔
    Java 基础之String随笔
    JAVA随笔一
    python文件处理指针的移动
  • 原文地址:https://www.cnblogs.com/sishuiliuyun/p/14781466.html
Copyright © 2011-2022 走看看