|
1 @node RealTime |
|
2 @chapter Real-Time Scheduler |
|
3 @anchor{chap:RealTime} |
|
4 |
|
5 ns-3 has been designed for integration into testbed and virtual machine |
|
6 environments. To integrate with real network stacks and emit/consume |
|
7 packets, a real-time scheduler is needed to try to lock the simulation |
|
8 clock with the hardware clock. We describe here a component of this: |
|
9 the RealTime scheduler. |
|
10 |
|
11 The purpose of the realtime scheduler is to cause the progression of |
|
12 the simulation clock to occur synchronously with respect to some |
|
13 external time base. Without the presence of an external time base |
|
14 (wall clock), simulation time jumps instantly from one simulated time to |
|
15 the next. |
|
16 |
|
17 @section Behavior |
|
18 |
|
19 When using a non-realtime scheduler (the default in ns-3), the simulator |
|
20 advances the simulation time to the next scheduled event. During event |
|
21 execution, simulation time is frozen. With the realtime scheduler, the |
|
22 behavior is similar from the perspective of simulation models (i.e., |
|
23 simulation time is frozen during event execution), but between events, |
|
24 the simulator will attempt to keep the simulation clock aligned with |
|
25 the machine clock. |
|
26 |
|
27 When an event is finished executing, and the scheduler moves to the next |
|
28 event, the scheduler compares the next event execution time with the |
|
29 machine clock. If the next event is scheduled for a future time, |
|
30 the simulator sleeps until that realtime is reached and then executes |
|
31 the next event. |
|
32 |
|
33 It may happen that, due to the processing inherent in the execution |
|
34 of simulation events, that the simulator cannot keep up with realtime. |
|
35 In such a case, it is up to the user configuration what to do. There |
|
36 are two ns-3 attributes that govern the behavior. The first is |
|
37 @code{ns3::RealTimeSimulatorImpl::SynchronizationMode}. The two |
|
38 entries possible for this attribute are @code{BestEffort} (the default) |
|
39 or @code{HardLimit}. In "BestEffort" mode, the simulator will just |
|
40 try to catch up to realtime by executing events until it reaches |
|
41 a point where the next event is in the (realtime) future, or else |
|
42 the simulation ends. In BestEffort mode, then, it is possible for |
|
43 the simulation to consume more time than the wall clock time. The |
|
44 other option "HardLimit" will cause the simulation to abort if the tolerance |
|
45 threshold is exceeded. This attribute is |
|
46 @code{ns3::RealTimeSimulatorImpl::HardLimit} and the default is 0.1 seconds. |
|
47 |
|
48 A different mode of operation is one in which simulated time is @strong{not} |
|
49 frozen during an event execution. This mode of realtime simulation was |
|
50 implemented but removed from the ns-3 tree because of questions of whether |
|
51 it would be useful. If users are interested in a realtime simulator |
|
52 for which simulation time does not freeze during event execution (i.e., |
|
53 every call to @code{Simulator::Now()} returns the current wall clock time, |
|
54 not the time at which the event started executing), please contact the |
|
55 ns-developers mailing list. |
|
56 |
|
57 @section Usage |
|
58 |
|
59 The usage of the realtime simulator is straightforward, from a scripting |
|
60 perspective. Users just need to set the attribute |
|
61 @code{SimulatorImplementationType} to the Realtime simulator, such as follows: |
|
62 @verbatim |
|
63 GlobalValue::Bind ("SimulatorImplementationType", |
|
64 StringValue ("ns3::RealtimeSimulatorImpl")); |
|
65 @end verbatim |
|
66 |
|
67 There is a script in @code{examples/realtime-udp-echo.cc} that has an |
|
68 example of how to configure the realtime behavior. Try: |
|
69 @verbatim |
|
70 ./waf --run realtime-udp-echo |
|
71 @end verbatim |
|
72 |
|
73 Whether the simulator will work in a best effort or hard limit policy |
|
74 fashion is governed by the attributes explained in the previous section. |
|
75 |
|
76 @section Implementation |
|
77 |
|
78 The implementation is contained in the following files: |
|
79 @itemize @bullet |
|
80 @item @code{src/simulator/realtime-simulator-impl.{cc,h}} |
|
81 @item @code{src/simulator/wall-clock-synchronizer.{cc,h}} |
|
82 @end itemize |
|
83 |
|
84 In order to create a realtime scheduler, to a first approximation you |
|
85 just want to cause simulation time jumps to consume real time. We propose |
|
86 doing this using a combination of sleep- and busy- waits. Sleep-waits cause |
|
87 the calling process (thread) to yield the processor for some amount of time. |
|
88 Even though this specified amount of time can be passed to nanosecond |
|
89 resolution, it is actually converted to an OS-specific granularity. |
|
90 In Linux, the granularity is called a Jiffy. Typically this resolution is |
|
91 insufficient for our needs (on the order of a ten milliseconds), so we |
|
92 round down and sleep for some smaller number of Jiffies. The process is |
|
93 then awakened after the specified number of Jiffies has passed. At this |
|
94 time, we have some residual time to wait. This time is generally smaller |
|
95 than the minimum sleep time, so we busy-wait for the remainder of the time. |
|
96 This means that the thread just sits in a for loop consuming cycles until |
|
97 the desired time arrives. After the combination of sleep- and busy-waits, |
|
98 the elapsed realtime (wall) clock should agree with the simulation time |
|
99 of the next event and the simulation proceeds. |
|
100 |