近期再写一个网络仿真器,里面參考了Max-MinFairness算法,这是一种比較理想、公平的带宽分配算法。其思路主要例如以下:首先是算法的准备,考察某一时刻的网络中全部的flow,因为每条flow都有其各个link,因此能够得到各个link上全部流经的flow,然后開始迭代,各个link都把capacity平均分给全部流经的flow,接着每条flow的速度就等于其最小link分配的带宽,然后每条link的剩余带宽就等于link的capacity减去全部流经的flow的速度的总和,再然后把link的剩余带宽作为capacity又一次进行上面的迭代,直至全部flow在迭代中获得的带宽都小于一个阈值时,算法结束,带宽分配完毕。

让我们来分析这个算法并考虑怎样加速该算法的运行速度。首先,对于一些bottleneck的link,流经其的flow早早就不能分配带宽了,因此假设发如今某个迭代中某条link可以分配的带宽已经小于阈值,那么在下一轮迭代,全部流经其的flow都不再考察,即使某些flow并非以该link为bottleneck,因此,算法结束的条件可以改为当全部flow都不再考察的时候。这样对不正确呢,让我们分析一下。以该link为bottleneck的flow自然不用说了,所谓的bottleneck就是可以获取的带宽最小的link,那么最小的link已经不能分配带宽了,该flow自然不再考察。但不是以该link作为bottleneck的flow呢,它们有更小带宽的link,可是假设该link不是你的bottleneck,已经不能分配带宽了,那就刚不用说更小带宽的link了,所以这些flow也应该不再考察。好,算法的解说和分析就到这儿了,以下就是算法的实现,笔者採用的Java语言。

public Map<Integer, List<TrafficState>> run() {
Map<Integer, List<TrafficState>> resultMap = new HashMap<Integer, List<TrafficState>>();
int current = 0;
// PrintWriter resultWriter = new PrintWriter(resultFileName);
while (current < runtime) {
List<Integer> runningFlowList = new ArrayList<Integer>();
// the first traverse,add the new flows and remove the shopped flow
for (int i = 0; i < graph.traffics.size(); i++) {
Traffic currentTraffic = graph.traffics.get(i);
int starttime = currentTraffic.start;
if (starttime <= current && !currentTraffic.isStopped) {
List<Integer> linksList = currentTraffic.links;
if (currentTraffic.totlesize == 0) {
// start a new flow
currentTraffic.totlesize = currentTraffic.flowsize;
currentTraffic.leftsize = currentTraffic.totlesize;
for (Integer linkno : linksList) {
graph.links.get(linkno).trafficList
.add(currentTraffic);
}
}
// calculate the transfer bytes in a epoch
currentTraffic.epochsize = currentTraffic.speed
* ((float) period / 1000);
currentTraffic.leftsize -= currentTraffic.epochsize; if (currentTraffic.leftsize <= 0
|| currentTraffic.end == current) {
// no more flowsize or time is up,stop it
currentTraffic.isStopped = true;
for (Integer linkno : linksList) {
graph.links.get(linkno).trafficList
.remove(currentTraffic);
}
} else
runningFlowList.add(i);
}
}
// print the measurement
if (printTimeSet.contains(current)) {
List<TrafficState> stateList = new ArrayList<TrafficState>();
for (Traffic traffic : graph.traffics) {
//not the stop flows and the start ones just now
if (!traffic.isStopped && traffic.totlesize != 0
&& traffic.speed != 0) {
TrafficState state = new TrafficState();
state.setBytes(traffic.epochsize);
state.setDestination(traffic.destination);
state.setSource(traffic.source);
state.setThruput(traffic.speed);
String pathString = traffic.source;
int lastNode = Integer.parseInt(traffic.source);
for (Integer linkno : traffic.links) {
if (lastNode == graph.links.get(linkno).source) {
pathString += ","
+ graph.links.get(linkno).target;
lastNode = graph.links.get(linkno).target;
} else {
pathString += ","
+ graph.links.get(linkno).source;
lastNode = graph.links.get(linkno).source;
}
// pathString += "," +
// graph.links.get(linkno).target;
}
state.setPathString(pathString);
state.setStarttime(traffic.start);
state.setFlowsize(traffic.flowsize);
state.setEndtime(traffic.end);
stateList.add(state);
}
}
resultMap.put(current, stateList);
}
// initialize all the links and traffics
for (Link link : graph.links) {
link.leftCapacity = link.capacity;
}
for (Traffic traffic : graph.traffics) {
traffic.speed = 0;
}
Set<Integer> finishedTrafficSet = new HashSet<Integer>();
// the second traverse,set the throughput of each flow in next
// iteration
while (finishedTrafficSet.size() < runningFlowList.size()) {
for (int i = 0; i < runningFlowList.size(); i++) {
if (!finishedTrafficSet.contains(runningFlowList.get(i))) {
Traffic currentTraffic = graph.traffics
.get(runningFlowList.get(i));
currentTraffic.increSpeed = Float.MAX_VALUE;
Link minLink = null;
for (Integer linkno : currentTraffic.links) {
Link currentLink = graph.links.get(linkno);
int existFlowNum = 0;// the number of exist flows
for (Traffic traffic : currentLink.trafficList) {
if (traffic.increSpeed != 0
|| traffic.speed == 0) {
existFlowNum++;
}
}
float currentLinkSpeed = (float) currentLink.leftCapacity
/ (float) existFlowNum;
if (currentLinkSpeed < currentTraffic.increSpeed) {
currentTraffic.increSpeed = currentLinkSpeed;
minLink = currentLink;
}
}
if (currentTraffic.increSpeed > 5)
currentTraffic.speed += currentTraffic.increSpeed;
else {
currentTraffic.increSpeed = 0;
if (minLink != null) {
for (Traffic traffic : minLink.trafficList) {
traffic.increSpeed = 0;
finishedTrafficSet.add(graph.traffics
.indexOf(traffic));
}
} else
finishedTrafficSet.add(runningFlowList.get(i));
}
}
}
// link left capacity decrease the traffic increase throughput
for (Link link : graph.links) {
for (Traffic traffic : link.trafficList) {
link.leftCapacity -= traffic.increSpeed;
}
}
}
current += period;
}
// resultWriter.close();
return resultMap;
}

Max-Min Fairness带宽分配算法的更多相关文章

  1. 关于STL库中的max min swap

    嗯...   不得不说c++中的STL库是一个神奇的东西   可以使你的代码显得更加简洁....   今天就只讲STL中的三个鬼畜:   max       min       swap   具体操作 ...

  2. TLFS 内存分配算法详解

    文章目录 1. DSA 背景介绍 1.1 mmheap 1.2 mmblk 2. TLFS 原理 2.1 存储结构 2.2 内存池初始化 2.3 free 2.4 malloc 参考资料 1. DSA ...

  3. webrtc中的带宽自适应算法

    转自:http://www.xuebuyuan.com/1248366.html webrtc中的带宽自适应算法分为两种: 1, 发端带宽控制, 原理是由rtcp中的丢包统计来动态的增加或减少带宽,在 ...

  4. 6.组函数(avg(),sum(),max(),min(),count())、多行函数,分组数据(group by,求各部门的平均工资),分组过滤(having和where),sql优化

     1组函数 avg(),sum(),max(),min(),count()案例: selectavg(sal),sum(sal),max(sal),min(sal),count(sal) from ...

  5. 从集合中查找最值得方法——max(),min(),nlargest(),nsmallest()

    从集合中查找最值得方法有很多,常用的方法有max(),min(),nlargest(),nsmallest()等. 一.max()和min() 1.1 入门用法 直接使用max(),min(),返回可 ...

  6. day12 max min zip 用法

    max min ,查看最大值,最小值 基础玩法 l = [1,2,3,4,5] print(max(l)) print(min(l)) 高端玩法 默认字典的取值是key的比较 age_dic={'al ...

  7. max,min,Zip函数(十一)

    zip函数,拉链,传两个有序的参数,将他们一一对应为元祖形式 max,min比较默认比较一个元素,处理的是可迭代对象,相当于for循环取出每个元素进行比较,注意:不同类型之间不可比较 #!/usr/b ...

  8. group by与avg(),max(),min(),sum()函数的关系

    数据库表: create table pay_report(     rdate varchar(8),     --日期     region_id varchar(4),    --地市      ...

  9. Kafka集群副本分配算法解析

    副本分配算法如下: 将所有N Broker和待分配的i个Partition排序. 将第i个Partition分配到第(i mod n)个Broker上. 将第i个Partition的第j个副本分配到第 ...

随机推荐

  1. python文件的操作

    文件的操作,归根结底就只有两种:打开文件.操作文件 一.打开文件:文件句柄 = open('文件路径', '模式') python中打开文件有两种方式,即:open(...) 和  file(...) ...

  2. 00089_字节输出流OutputStream

    1.字节输出流OutputStream (1)OutputStream此抽象类,是表示输出字节流的所有类的超类.操作的数据都是字节,定义了输出字节流的基本共性功能方法: (2)输出流中定义都是写wri ...

  3. 谈谈vector容器的三种遍历方法

    说明:本文仅供学习交流.转载请标明出处.欢迎转载!          vector容器是最简单的顺序容器,其用法相似于数组.实际上vector的底层实现就是採用动态数组.在编敲代码的过程中.经常会变量 ...

  4. StackExchange.Redis 官方文档(五) Keys, Values and Channels

    原文:StackExchange.Redis 官方文档(五) Keys, Values and Channels Keys, Values and Channels 在使用redis的过程中,要注意到 ...

  5. java——数组

    数组是多个同样数据类型数组组合,当中数据类型是不论什么数据类型. 数组变量是引用类型变量,数组能够作为对象,数组中的每个元素相当于对象的成员变量,所以数组元素能够默认初始化.(博客java--变量分类 ...

  6. spark算子介绍

    1.spark的算子分为转换算子和Action算子,Action算子将形成一个job,转换算子RDD转换成另一个RDD,或者将文件系统的数据转换成一个RDD 2.Spark的算子介绍地址:http:/ ...

  7. PHP回调函数--call_user_func_array

    我这是抄的 感谢 https://www.cnblogs.com/zzl-21086595/p/4547519.html 全局函数的回调 这里的全局函数的意思,是直接使用function定义的函数,它 ...

  8. java项目中VO和DTO以及Entity,各自是在什么情况下应用的

    j2ee中,经常提到几种对象(object),理解他们的含义有助于我们更好的理解面向对象的设计思维.     POJO(plain old java object):普通的java对象,有别于特殊的j ...

  9. 恢复SLAVE上的某几张表的简要方法

    同步报错是遇到最多的一个问题,如果你修复后发现还没有解决,通常的方法就是在Master上重新dump出一份,然后在slave上恢复.这个方法是针对整个库不是很大的情况下使用的,那如果是较大,全部dum ...

  10. wordpress-nas