本文介绍消息事件产生器MessageEventGenerator
及其派生类OneToEachMessageGenerator
、OneFromEachMessageGenerator
、MessageBurstGenerator
。
1. 配置文件
消息事件产生器MessageEventGenerator
根据参数产生消息创建事件,进而创建消息。消息事件产生器类型对应于消息产生类型。使用方法如下:
# 消息事件产生器类型
Events1.class = MessageEventGenerator
# 消息创建间隔,每隔(25,35)秒产生一个消息,间隔随机从(25,35)产生
Events1.interval = 25,35
# 消息大小,产生消息的大小随机从(min, max)取得,单位是字节
Events1.size = 500k,1M
# Senderaddress range, 值得注意的是,包含下限但不包含上限,即[0, 126)
Events1.hosts = 0,126
# receiver address range,同样,包含下限但不包含上限。若没有设置,被视为与hosts同
Events1.tohosts = 0, 126
# 消息名称的前缀(Message ID prefix),用于标识不同的generator产生的消息
Events1.prefix = M
# 创建消息的时间范围[min, max],默认情况是[0, Scenario.endTime],即整个仿真期间都可以创建消息
Events1.time = 500, 1000
2. 消息事件产生器类型
MessageEventGenerator
派生出3种新的消息产生器,即OneToEachMessageGenerator
、OneFromEachMessageGenerator
、MessageBurstGenerator
。The ONE目前共支持4种消息产生方式,其类图如下:
注:以下内容有些繁琐,建议直接阅读仿真报告《消息创建报告CreatedMessagesReport》,更直观。
2.1 MessageEventGenerator
产生的消息是一对一的,以上述配置文件的参数为例,在第32s
(随机从25~35选取)产生一个消息,消息大小为800kB
(随机从500k~1M选取),源节点是5
(随机从0~126选取),目的节点是100
(随机从0~126选取)。将消息放入节点5
的缓冲区。
2.2 OneToEachMessageGenerator
产生的消息是一对多的(Creates one message from source node/nodes to all destination nodes)。值得注意的是tohosts
必须指定。从字面上理解,在每隔interval
,消息的源节点从hosts
随机选取一个,创建多个消息,其目的节点涵盖所有tohosts
。但从源码看并非如此,仿真结果也验证了这一点,消息的源节点从hosts随机选取一个,并不是在单个interval
,同时创建多个消息给tohosts
,而是各个消息之间的间隔是(25,35)
。实际上,用OneToEachMessageGenerator
产生消息,整个仿真期间最多产生tohosts
个消息。源代码为证:
//OneToEachMessageGenerator.java
public ExternalEvent nextEvent() {
int responseSize = 0; // no responses requested
int from;
int to;
from = drawHostAddress(hostRange);
to = this.toIds.remove(0);
if (to == from) { // skip self
if (this.toIds.size() == 0) { // oops, no more from addresses
this.nextEventsTime = Double.MAX_VALUE;
return new ExternalEvent(Double.MAX_VALUE);
} else {
to = this.toIds.remove(0);
}
}
if (this.toIds.size() == 0) {
this.nextEventsTime = Double.MAX_VALUE; // no messages left
} else {
this.nextEventsTime += drawNextEventTimeDiff();
}
MessageCreateEvent mce = new MessageCreateEvent(from, to, getID(), drawMessageSize(), responseSize, this.nextEventsTime);
return mce;
}
2.3 OneFromEachMessageGenerator
产生的消息是多对一的(Creates one message from every source node to one of the destination nodes)。值得注意的是tohosts
必须指定。从字面上理解,在每隔interval
,hosts
每个节点产生一个消息给某个目的节点(从tohosts
随机选择)。但从源码看并非如此,仿真结果也验证了这一点,每个间隔interval
,从剩下的源节点随机选取一个,目的节点从tohosts
随机选一个。可见,用OneFromEachMessageGenerator
产生消息,整个仿真期间最多产生hosts
个消息。源代码为证:
//OneFromEachMessageGenerator.java
public ExternalEvent nextEvent() {
int responseSize = 0; // no responses requested
int from;
int to;
from = this.fromIds.remove(0);
to = drawToAddress(toHostRange, -1);
if (to == from) { //skip self
if (this.fromIds.size() == 0) { //no more from addresses
this.nextEventsTime = Double.MAX_VALUE;
return new ExternalEvent(Double.MAX_VALUE);
} else {
from = this.fromIds.remove(0);
}
}
if (this.fromIds.size() == 0) {
this.nextEventsTime = Double.MAX_VALUE; //no messages left
} else {
this.nextEventsTime += drawNextEventTimeDiff();
}
MessageCreateEvent mce = new MessageCreateEvent(from, to, getID(), drawMessageSize(), responseSize, this.nextEventsTime);
return mce;
}
2.4 MessageBurstGenerator
MessageBurstGenerator
产生的消息是多对多。每个interval
,每个源节点hosts
为每个目的节点tohosts
产生一个新消息。直接看源码注释吧:
Creates bursts of messages where every source node creates a new message to every destination node on every interval.
MessageBurstGenerator的nextEvent源代码如下:
//MessageBurstGenerator.java
public ExternalEvent nextEvent() {
int responseSize = 0; // no responses requested
int msgSize;
int interval;
int from;
int to;
boolean nextBurst = false;
from = this.hostRange[0] + nextFromOffset;
to = this.toHostRange[0] + nextToOffset;
if (to == from) {
to = this.toHostRange[0] + (++nextToOffset);
}
msgSize = drawMessageSize();
MessageCreateEvent mce = new MessageCreateEvent(from, to, getID(), msgSize, responseSize, this.nextEventsTime);
//其实类似于双重循环, for each host; for each tohosts; 产生一个消息创建事件
if (to < this.toHostRange[1] - 1) {
this.nextToOffset++;
} else {
if (from < this.hostRange[1] - 1) {
this.nextFromOffset++;
this.nextToOffset = 0;
} else {
nextBurst = true;
}
}
if (this.hostRange[0] + nextFromOffset == this.toHostRange[0] + nextToOffset) { //to and from would be same for next event
nextToOffset++;
if (nextToOffset >= toHostRange[1]) {
nextBurst = true;
}
}
//到下一个hosts
if (nextBurst) {
interval = drawNextEventTimeDiff();
this.nextEventsTime += interval;
this.nextFromOffset = 0;
this.nextToOffset = 0;
}
if (this.msgTime != null && this.nextEventsTime > this.msgTime[1]) { //next event would be later than the end time
this.nextEventsTime = Double.MAX_VALUE;
}
return mce;
}