`
sunqi
  • 浏览: 227910 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

facebook network-connection-class初探

阅读更多

背景

      网络质量是移动端开发很关注的指标,典型场景宝贝详情展示,在网速好的时候出宝贝高清大图片,网络不好的时候出小图片,保证用户的体验和流量付出的平衡。
      Network Connection Class是一个由Facebook公司出品的Android类库,用于监听App当前网络流量以及将其按照网络质量进行分类,其是如何做到呢?

原理


     android是基于linux的,搞过服务端监控都知道,tsar等统计工具,也都是读取下内核记录的相关各种stat数据,那其实这个库也是一样的,其读取了/proc/net/xt_qtaguid/stats记录的信息



如上图例子,rx_bytes是接受到的数据字节数,tx_bytes则是发送出去的数量,其他参数可以自己看看就能明白,下面每一行代表一个用户下的流量情况。既然有这数据,那要做app对网络质量的监控,就有米了。

功能原理

1、用android的loop,hander,m
essage机制,每1秒异步的去捞取数据分析,此库还是自己去读取文件,逐行过滤用户,选取自己Process.myUid()的数据进行统计,其实Android API8 以后提供了getUidRxBytes以及getUidTxBytes,也是读取这文件。在android.net.TrafficStats里面提供了完善的数据


这样可以直接利用,也可以忽略不同平台的差异性,比如有些版本是要读取/proc/uid_stat/***(uid)/tcp_rcv和tcp_snd文件等,可以等这系统接口取不到数据的时候,再自己想办法去捞取数据。不需先自己进行复杂的文件解析,轻松可以捞取tcp、udb、总量等各个维度数据。可以自己app,和总数据等进行比对分析


2、同时可添加个实现ConnectionClassManager.ConnectionClassStateChangeListener接口的listener,当网络变化的时候去进行回调。默认规则是,连续5次以上,新采样的网络质量一直恒定新值,与当前网络质量不同,才会触发listener回调。这里其实是对网络波动的灵敏度控制。


算法

网络质量定义:
/**
   * Bandwidth under 150 kbps.
   */
  POOR,
  /**
   * Bandwidth between 150 and 550 kbps.
   */
  MODERATE,
  /**
   * Bandwidth between 550 and 2000 kbps.
   */
  GOOD,
  /**
   * EXCELLENT - Bandwidth over 2000 kbps.
   */
  EXCELLENT,
  /**
   * Placeholder for unknown bandwidth. This is the initial value and will stay at this value
   * if a bandwidth cannot be accurately found.
   */
  UNKNOWN

 
那怎么确定网络质量,因为从文件捞取的数据是字节数,因此都需要*8转换为每秒的比特位,如果每秒小于10的数据会被忽略,然后再去运算。
当app刚刚启动的时候,怎么样才能更精确反应当前的网速呢,其定义了个重要的常量

/**
   * The factor used to calculate the current bandwidth
   * depending upon the previous calculated value for bandwidth.
   *
   * The smaller this value is, the less responsive to new samples the moving average becomes.
   */
  private static final double DEFAULT_DECAY_CONSTANT = 0.05;

 

对确定了另外两个常量
double mDecayConstant=DEFAULT_DECAY_CONSTANT;
int mCutover=decayConstant == 0.0? Integer.MAX_VALUE: (int) Math.ceil(1 / decayConstant);

 

 
核心算法:

 /* * Adds a new measurement to the moving average.
   * @param measurement - Bandwidth measurement in bits/ms to add to the moving average.
   */
  public void addMeasurement(double measurement) {
    double keepConstant = 1 - mDecayConstant;
    if (mCount > mCutover) {
      mValue = Math.exp(keepConstant * Math.log(mValue) + mDecayConstant * Math.log(measurement));
    } else if (mCount > 0) {
      double retained = keepConstant * mCount / (mCount + 1.0);
      double newcomer = 1.0 - retained;
      mValue = Math.exp(retained * Math.log(mValue) + newcomer * Math.log(measurement));
    } else {
      mValue = measurement;
    }
    mCount++;
  }


看上去是否很高大上啊,还用math.exp和log,自然指数、欧拉数,还记得吗?我已经还给学校的体育老师了。自己补脑了

而计算的公式换个矮穷挫的类似写法就是


网速=之前平均值网速*旧权重比例 + 新采样的速度*新采样的权重值

那之前定义的两常量干啥呢,其实就是mDecayConstant=0.05    mCutover=20

   再看就很明了了,在统计前二十次,第一次取采样值,后续旧权重比例逐步的增加,当超过20次后,就权重比例就恒定为0.95,新采样的权重为0.05了。

   其实之前DEFAULT_DECAY_CONSTANT注释上说的很明白了,这个值越小,刚启动时候,旧权重比例会更慢的累计,当超过阀值后,新采样的权重值越小,对网络波动可能就不敏感了。因此这个值,是需要好好权衡。

  同时这个库只统计了下行,在一些特定业务需要,也可以对上行进行监控,甚至可以区分tcp ,udp等数据统计分析 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics