diff --git i/doc/manual/source/events.rst w/doc/manual/source/events.rst index 5baf3b516..4d1bd00e6 100644 --- i/doc/manual/source/events.rst +++ w/doc/manual/source/events.rst @@ -190,8 +190,75 @@ context. Time **** -*To be completed* +The entire purpose of the simulator is to have a notion of time that passes and +to discover what is happening at certain moments. In simulation mode, such time +can be magnified to look in the internals: indeed, during the debugging of a +simulation, if we break into simulator functions to analyze the code +step-by-step, we are "freezing" the simulated time. That is not happening in +the emulation mode, in which the simulator tries to stay in real time. However, +in both modes, ns-3 has only one way to express the notion of time: class Time. +Each instance of Time class has a huge counter that contains integers, that +represents the ticks in a pre-defined resolution. By default, such resolution +is in nanoseconds: each tick represents a single nanosecond. So, how many +nanoseconds we can represents? The ticks are stored in a 64-bit value: +therefore, with 2^64 nanoseconds you can range from now to ~584 years in the +future. Of course, if you increase the global resolution, you also implicitly +decrease the range of your simulation. If you use picoseconds instead of +nanoseconds, the simulation range decrease to 2^64 ps = 7 months. + +It is possible to use helper functions to create a Time. For instance, to +create a time value that contains 2 seconds, we can do the following: + +:: + auto t = ns3::Seconds (2); + +That is equivalent to the following: + +:: + auto t1 = ns3::MilliSeconds (2000); + auto t2 = ns3::MicroSeconds (2000000); + +What if we want to specify a value of 20 nanoseconds? + +:: + auto t3 = ns3::NanoSeconds (20); + +For historical reasons, the API also provides the conversion from doubles when +using seconds. For instance, to indicate a value of 75 milliseconds, it is +possible to do the following: + +:: + auto t4 = ns3::Seconds (0.075); + +Even if this is allowed, you must wonder if it is the right thing to do. The +float/double representation based on IEEE 754 model is not precise (but no one +in the world has come up with a better proposal). That means that it is not +possible to represent all the values, and many of them will naturally be +rounded to the nearest representable amount. For instance, the value 0.075 +cannot be represented precisely and for this reason, if you print out the t4 +variable, you will find that internally it has stored 74999999 nanoseconds +(assuming you are using the default resolution in nanoseconds). + +It is impossible to avoid rounding problems with double and floats types: for +this reason, it is important to avoid, when possible, to use double and float. +In this specific case, ns-3 provides methods that do the hard job of converting +the values for you. So, everything you have to say is to specify the correct +unit of measure: + +:: + // auto t4 = ns3::Seconds (0.075); // Wrong + auto t4 = ns3::MilliSeconds (75); // Right + +Again, the correct ns-3 way to store times is to use the Time class. If you see +a double or a float used as a Time, that could be a bug and must be changed to +the right unit of measure. Moreover, in some places, the results of a +double-based division or multiplication will be stored as a Time. As we have +seen before, the result is often not precise: therefore, it is imperative to +switch to integer-based operations. As a pre-condition, the developer must +choose the resolution, and depending from case to case, a good option could be +to ask the simulator what is the current resolution, assuming the default value +of nanoseconds. Scheduler *********