View | Details | Raw Unified | Return to bug 252
Collapse All | Expand All

(-)a/src/simulator/simulator.cc (-42 lines)
 Lines 62-69   public: Link Here 
62
  ~SimulatorPrivate ();
62
  ~SimulatorPrivate ();
63
63
64
  void Destroy ();
64
  void Destroy ();
65
66
  void EnableLogTo (char const *filename);
67
65
68
  bool IsFinished (void) const;
66
  bool IsFinished (void) const;
69
  Time Next (void) const;
67
  Time Next (void) const;
 Lines 95-103   private: Link Here 
95
  uint32_t m_uid;
93
  uint32_t m_uid;
96
  uint32_t m_currentUid;
94
  uint32_t m_currentUid;
97
  uint64_t m_currentTs;
95
  uint64_t m_currentTs;
98
  std::ofstream m_log;
99
  std::ifstream m_inputLog;
100
  bool m_logEnable;
101
  // number of events that have been inserted but not yet scheduled,
96
  // number of events that have been inserted but not yet scheduled,
102
  // not counting the "destroy" events; this is used for validation
97
  // not counting the "destroy" events; this is used for validation
103
  int m_unscheduledEvents;
98
  int m_unscheduledEvents;
 Lines 133-139   SimulatorPrivate::SimulatorPrivate () Link Here 
133
  m_uid = 4; 
128
  m_uid = 4; 
134
  // before ::Run is entered, the m_currentUid will be zero
129
  // before ::Run is entered, the m_currentUid will be zero
135
  m_currentUid = 0;
130
  m_currentUid = 0;
136
  m_logEnable = false;
137
  m_currentTs = 0;
131
  m_currentTs = 0;
138
  m_unscheduledEvents = 0;
132
  m_unscheduledEvents = 0;
139
}
133
}
 Lines 182-194   SimulatorPrivate::GetScheduler (void) co Link Here 
182
}
176
}
183
177
184
void
178
void
185
SimulatorPrivate::EnableLogTo (char const *filename)
186
{
187
  m_log.open (filename);
188
  m_logEnable = true;
189
}
190
191
void
192
SimulatorPrivate::ProcessOneEvent (void)
179
SimulatorPrivate::ProcessOneEvent (void)
193
{
180
{
194
  EventId next = m_events->RemoveNext ();
181
  EventId next = m_events->RemoveNext ();
 Lines 199-208   SimulatorPrivate::ProcessOneEvent (void) Link Here 
199
  TRACE ("handle " << nextEv);
186
  TRACE ("handle " << nextEv);
200
  m_currentTs = next.GetTs ();
187
  m_currentTs = next.GetTs ();
201
  m_currentUid = next.GetUid ();
188
  m_currentUid = next.GetUid ();
202
  if (m_logEnable) 
203
    {
204
      m_log << "e "<<next.GetUid () << " " << next.GetTs () << std::endl;
205
    }
206
  EventImpl *event = next.PeekEventImpl ();
189
  EventImpl *event = next.PeekEventImpl ();
207
  event->Invoke ();
190
  event->Invoke ();
208
}
191
}
 Lines 239-245   SimulatorPrivate::Run (void) Link Here 
239
  // consistency test to check that we didn't lose any events along the way.
222
  // consistency test to check that we didn't lose any events along the way.
240
  NS_ASSERT(!m_events->IsEmpty () || m_unscheduledEvents == 0);
223
  NS_ASSERT(!m_events->IsEmpty () || m_unscheduledEvents == 0);
241
224
242
  m_log.close ();
243
}
225
}
244
226
245
227
 Lines 262-272   SimulatorPrivate::Schedule (Time const & Link Here 
262
  NS_ASSERT (time >= TimeStep (m_currentTs));
244
  NS_ASSERT (time >= TimeStep (m_currentTs));
263
  uint64_t ts = (uint64_t) time.GetTimeStep ();
245
  uint64_t ts = (uint64_t) time.GetTimeStep ();
264
  EventId id (event, ts, m_uid);
246
  EventId id (event, ts, m_uid);
265
  if (m_logEnable) 
266
    {
267
      m_log << "i "<<m_currentUid<<" "<<m_currentTs<<" "
268
            <<m_uid<<" "<<time.GetTimeStep () << std::endl;
269
    }
270
  m_uid++;
247
  m_uid++;
271
  ++m_unscheduledEvents;
248
  ++m_unscheduledEvents;
272
  m_events->Insert (id);
249
  m_events->Insert (id);
 Lines 276-286   SimulatorPrivate::ScheduleNow (const Ptr Link Here 
276
SimulatorPrivate::ScheduleNow (const Ptr<EventImpl> &event)
253
SimulatorPrivate::ScheduleNow (const Ptr<EventImpl> &event)
277
{
254
{
278
  EventId id (event, m_currentTs, m_uid);
255
  EventId id (event, m_currentTs, m_uid);
279
  if (m_logEnable) 
280
    {
281
      m_log << "i "<<m_currentUid<<" "<<m_currentTs<<" "
282
            <<m_uid<<" "<<m_currentTs << std::endl;
283
    }
284
  m_uid++;
256
  m_uid++;
285
  ++m_unscheduledEvents;
257
  ++m_unscheduledEvents;
286
  m_events->Insert (id);
258
  m_events->Insert (id);
 Lines 291-301   SimulatorPrivate::ScheduleDestroy (const Link Here 
291
{
263
{
292
  EventId id (event, m_currentTs, 2);
264
  EventId id (event, m_currentTs, 2);
293
  m_destroyEvents.push_back (id);
265
  m_destroyEvents.push_back (id);
294
  if (m_logEnable) 
295
  {
296
    m_log << "id " << m_currentUid << " " << Now ().GetTimeStep () << " "
297
          << m_uid << std::endl;
298
  }
299
  m_uid++;
266
  m_uid++;
300
  return id;
267
  return id;
301
}
268
}
 Lines 341-351   SimulatorPrivate::Remove (const EventId Link Here 
341
  m_events->Remove (ev);
308
  m_events->Remove (ev);
342
  Cancel (ev);
309
  Cancel (ev);
343
310
344
  if (m_logEnable) 
345
    {
346
      m_log << "r " << m_currentUid << " " << m_currentTs << " "
347
            << ev.GetUid () << " " << ev.GetTs () << std::endl;
348
    }
349
  --m_unscheduledEvents;
311
  --m_unscheduledEvents;
350
}
312
}
351
313
 Lines 410-419   void Simulator::SetScheduler (Ptr<Schedu Link Here 
410
void Simulator::SetScheduler (Ptr<Scheduler> scheduler)
372
void Simulator::SetScheduler (Ptr<Scheduler> scheduler)
411
{
373
{
412
  GetPriv ()->SetScheduler (scheduler);
374
  GetPriv ()->SetScheduler (scheduler);
413
}
414
void Simulator::EnableLogTo (char const *filename)
415
{
416
  GetPriv ()->EnableLogTo (filename);
417
}
375
}
418
376
419
#ifdef NS3_LOG_ENABLE
377
#ifdef NS3_LOG_ENABLE
(-)a/src/simulator/simulator.h (-15 lines)
 Lines 63-83   public: Link Here 
63
   * before we start to use it.
63
   * before we start to use it.
64
   */
64
   */
65
  static void SetScheduler (Ptr<Scheduler> scheduler);
65
  static void SetScheduler (Ptr<Scheduler> scheduler);
66
67
  /**
68
   * Enable logging to the file identified by filename. If the file
69
   * does not exist, it is created. If it exists, it is destroyed and
70
   * re-created. Every scheduling event is logged to this file in a
71
   * simple text format which can be read back by the event replay
72
   * utility. This allows you to record the scheduling behavior of
73
   * a simulation, and measure the exact overhead related to
74
   * event scheduling with the event replay utility. It is also possible
75
   * to compare the performance of every scheduling algorithms on this
76
   * specific scheduling load.
77
   * This method must be invoked before any call to Simulator::run
78
   * @param filename the name of the file to log to 
79
   */
80
  static void EnableLogTo (char const *filename);
81
66
82
  /**
67
  /**
83
   * Every event scheduled by the Simulator::insertAtDestroy method is
68
   * Every event scheduled by the Simulator::insertAtDestroy method is
(-)a/utils/bench-simulator.cc (-6 lines)
 Lines 130-136   PrintHelp (void) Link Here 
130
  std::cout << "      --list: use std::list scheduler"<<std::endl;
130
  std::cout << "      --list: use std::list scheduler"<<std::endl;
131
  std::cout << "      --map: use std::map cheduler"<<std::endl;
131
  std::cout << "      --map: use std::map cheduler"<<std::endl;
132
  std::cout << "      --heap: use Binary Heap scheduler"<<std::endl;
132
  std::cout << "      --heap: use Binary Heap scheduler"<<std::endl;
133
  std::cout << "      --log=filename: log scheduler events for the event replay utility."<<std::endl;
134
  std::cout << "      --debug: enable some debugging"<<std::endl;
133
  std::cout << "      --debug: enable some debugging"<<std::endl;
135
}
134
}
136
135
 Lines 173-183   int main (int argc, char *argv[]) Link Here 
173
        {
172
        {
174
          g_debug = true;
173
          g_debug = true;
175
        } 
174
        } 
176
      else if (strncmp ("--log=", argv[0],strlen ("--log=")) == 0) 
177
        {
178
          char const *filename = argv[0] + strlen ("--log=");
179
          Simulator::EnableLogTo (filename);
180
        }
181
      else if (strncmp ("--total=", argv[0], strlen("--total=")) == 0) 
175
      else if (strncmp ("--total=", argv[0], strlen("--total=")) == 0) 
182
        {
176
        {
183
          total = atoi (argv[0]+strlen ("--total="));
177
          total = atoi (argv[0]+strlen ("--total="));
(-)a/utils/replay-simulation.cc (-330 lines)
Removed Link Here 
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
 * Copyright (c) 2006 INRIA
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as
7
 * published by the Free Software Foundation;
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19
 */
20
21
#include "ns3/simulator-module.h"
22
#include "ns3/core-module.h"
23
#include <vector>
24
#include <deque>
25
#include <fstream>
26
#include <iostream>
27
#include <string.h>
28
29
using namespace ns3;
30
31
class LogReader {
32
public:
33
  void ReadFromFilename (char const *filename);
34
  void Run (void);
35
  void PrintStats (void);
36
private:
37
  struct Command {
38
      enum {
39
          REMOVE = 100,
40
          INSERT,
41
          INSERT_LATER,
42
          INSERT_REMOVE
43
      } m_type;
44
      // uid at which this command is supposed to be executed.
45
      uint32_t m_uid;
46
      union {
47
          struct {
48
            // time at which the event is supposed to expire
49
            uint64_t m_evNs;
50
            uint32_t m_evUid;
51
          } insert;
52
          struct {
53
            // location in the array of events to remove where
54
            // to insert this event once it is inserted in 
55
            // the scheduler.
56
            uint32_t m_evLoc; 
57
            // time at which the event is supposed to expire
58
            uint64_t m_evNs;
59
          } insertRemove;
60
      };
61
  };
62
  void ExecuteLogCommands (uint32_t uid);
63
64
  typedef std::vector<struct Command> Commands;
65
  typedef std::vector<struct Command>::iterator CommandsI;
66
  typedef std::vector<EventId> RemoveEvents;
67
  typedef std::vector<EventId>::iterator RemoveEventsI;
68
  
69
70
  Commands m_commands;
71
  CommandsI m_command;
72
  RemoveEvents m_removeEvents;
73
  uint32_t m_uid;
74
};
75
76
typedef std::vector<std::pair<uint32_t, uint32_t> > Removes;
77
typedef std::vector<std::pair<uint32_t, uint32_t> >::iterator RemovesI;
78
79
void
80
LogReader::ReadFromFilename (char const *filename)
81
{
82
  std::ifstream log;
83
  std::cout << "read log..." << std::endl;
84
  Removes removes;
85
  log.open (filename);
86
  while (!log.eof ()) 
87
    {
88
      std::string type;
89
      log >> type;
90
      if (type == "i") 
91
        {
92
          uint32_t nowUid, evUid;
93
          uint64_t nowNs, evNs;
94
          log >> nowUid >> nowNs >> evUid >> evNs;
95
          struct Command cmd;
96
          cmd.m_type = Command::INSERT;
97
          cmd.m_uid = nowUid;
98
          cmd.insert.m_evNs = evNs;
99
          cmd.insert.m_evUid = evUid;
100
          m_commands.push_back (cmd);
101
        } 
102
      else if (type == "r") 
103
        {
104
          uint32_t nowUid, evUid;
105
          uint64_t nowNs, evNs;
106
          log >> nowUid >> nowNs >> evUid >> evNs;
107
          struct Command cmd;
108
          cmd.m_type = Command::REMOVE;
109
          cmd.m_uid = nowUid;
110
          m_commands.push_back (cmd);
111
          removes.push_back (std::make_pair (nowUid, evUid));
112
        } 
113
      else if (type == "il") 
114
        {
115
          uint32_t nowUid, evUid;
116
          uint64_t nowNs, evNs;
117
          log >> nowUid >> nowNs >> evUid >> evNs;
118
          struct Command cmd;
119
          cmd.m_type = Command::INSERT_LATER;
120
          cmd.m_uid = nowUid;
121
          m_commands.push_back (cmd);
122
        }
123
    }
124
  log.close ();
125
126
  std::cout << "gather insert/removes, commands="<<m_commands.size () 
127
            << ", removes=" << removes.size () << "..." << std::endl;
128
  for (CommandsI i = m_commands.begin (); i != m_commands.end (); i++) 
129
    {
130
      if (i->m_type == Command::INSERT) 
131
        {
132
          for (RemovesI j = removes.begin (); j != removes.end (); j++) 
133
            {
134
              if (j->second == i->insert.m_evUid) 
135
                {
136
                  // this insert will be removed later.
137
                  uint64_t ns = i->insert.m_evNs;
138
                  uint32_t uid = i->m_uid;
139
                  i->m_type = Command::INSERT_REMOVE;
140
                  i->m_uid = uid;
141
                  i->insertRemove.m_evNs = ns;
142
                  i->insertRemove.m_evLoc = j->first;
143
                  break;
144
                }
145
            }
146
        }
147
    }
148
  std::cout << "calculate remove locations..." << std::endl;
149
  // calculate the final insert/remove location.
150
  for (CommandsI i = m_commands.begin (); i != m_commands.end (); i++) 
151
    {
152
      if (i->m_type == Command::INSERT_REMOVE) 
153
        {
154
          uint32_t loc = 0;
155
          for (CommandsI tmp = i; tmp != m_commands.end (); tmp++) 
156
            {
157
              if (tmp->m_type == Command::REMOVE) 
158
                {
159
                  if (tmp->m_uid == i->insertRemove.m_evLoc) 
160
                    {
161
                      i->insertRemove.m_evLoc = loc;
162
                      break;
163
                    }
164
                  loc++;
165
                }
166
            }
167
        }
168
    }
169
}
170
void
171
LogReader::ExecuteLogCommands (uint32_t uid)
172
{
173
  if (m_command == m_commands.end ()) 
174
    {
175
      return;
176
    }
177
  //std::cout << "one event, uid=" <<m_uid<< std::endl;
178
  struct Command cmd = *m_command;
179
  //std::cout << "cmd uid=" <<cmd.m_uid<< std::endl;
180
  while (cmd.m_uid == uid) 
181
    {
182
      m_command++;
183
      switch (cmd.m_type) {
184
      case Command::INSERT:
185
        //std::Cout << "exec insert now=" << Simulator::Now ().GetNanoSeconds ()
186
        //<< ", time=" << cmd.insert.m_evNs << std::endl;
187
        Simulator::Schedule (NanoSeconds (cmd.insert.m_evNs) - Now (), 
188
                             &LogReader::ExecuteLogCommands, this, m_uid);
189
        m_uid++;
190
        break;
191
      case Command::INSERT_LATER:
192
          //std::cout << "exec insert later" << std::endl;
193
          Simulator::ScheduleNow (&LogReader::ExecuteLogCommands, this, m_uid);
194
          m_uid++;
195
          break;
196
      case Command::REMOVE: 
197
        {
198
          //std::cout << "exec remove" << std::endl;
199
          EventId id = m_removeEvents.back ();
200
          m_removeEvents.pop_back ();
201
          Simulator::Remove (id);
202
        } break;
203
      case Command::INSERT_REMOVE: 
204
        {
205
          //std::cout << "exec insert remove" << std::endl;
206
          EventId id = Simulator::Schedule (NanoSeconds (cmd.insertRemove.m_evNs) - Now (),
207
                                            &LogReader::ExecuteLogCommands, this, m_uid);
208
          NS_ASSERT (id.GetUid () == m_uid);
209
          if (cmd.insertRemove.m_evLoc + 1 > m_removeEvents.size ())
210
            {
211
              uint32_t missing = cmd.insertRemove.m_evLoc + 1 - m_removeEvents.size ();
212
              m_removeEvents.insert (m_removeEvents.begin (),
213
                                     missing, id);
214
            }
215
          uint32_t index = m_removeEvents.size () - cmd.insertRemove.m_evLoc - 1;
216
          m_removeEvents[index] = id;
217
          m_uid++;
218
        } break;
219
      default:
220
        NS_ASSERT (false);
221
        break;
222
      }
223
      cmd = *m_command;
224
  }
225
}
226
227
void
228
LogReader::PrintStats (void)
229
{
230
  uint32_t nInserts = 0;
231
  uint32_t nRemoves = 0;
232
  for (CommandsI i = m_commands.begin (); i != m_commands.end (); i++) 
233
    {
234
      switch (i->m_type) {
235
      case Command::INSERT:
236
          nInserts++;
237
          break;
238
      case Command::INSERT_LATER:
239
          nInserts++;
240
          break;
241
      case Command::INSERT_REMOVE:
242
          nInserts++;
243
          break;
244
      case Command::REMOVE:
245
          nRemoves++;
246
          break;
247
      }
248
    }
249
  std::cout << "inserts="<<nInserts<<", removes="<<nRemoves<<std::endl;
250
  std::cout << "run simulation..."<<std::endl;
251
}
252
253
void
254
LogReader::Run (void)
255
{
256
  m_uid = 1;
257
  SystemWallClockMs time;
258
  time.Start ();
259
  m_command = m_commands.begin ();
260
  ExecuteLogCommands (0);
261
  Simulator::Run ();
262
  unsigned long long delta = time.End ();
263
  double delay = ((double)delta)/1000;
264
  std::cout << "runtime="<<delay<<"s"<<std::endl;
265
}
266
267
268
int main (int argc, char *argv[])
269
{
270
  char const *input = 0;
271
  uint32_t n = 1;
272
  bool is_map = false;
273
  bool is_list = false;
274
  bool is_heap = false;
275
  while (argc > 0) 
276
    {
277
      if (strcmp ("--list", argv[0]) == 0) 
278
        {
279
          is_list = true;
280
        } 
281
      else if (strcmp ("--heap", argv[0]) == 0) 
282
        {
283
          is_heap = true;
284
        } 
285
      else if (strcmp ("--map", argv[0]) == 0) 
286
        {
287
          is_map = true;
288
        } 
289
      else if (strncmp ("--n=", argv[0], strlen("--n=")) == 0) 
290
        {
291
          n = atoi (argv[0]+strlen ("--n="));
292
        } 
293
      else if (strncmp ("--input=", argv[0],strlen ("--input=")) == 0) 
294
        {
295
          input = argv[0] + strlen ("--input=");
296
        } 
297
      else if (strncmp ("--log=", argv[0],strlen ("--log=")) == 0) 
298
        {
299
          char const *filename = argv[0] + strlen ("--log=");
300
          Simulator::EnableLogTo (filename);
301
        }
302
      argc--;
303
      argv++;
304
    }
305
  if (input == 0) 
306
    {
307
      std::cerr << "need --input=[filename] option" << std::endl;
308
      return 1;
309
    }
310
  LogReader log;
311
  log.ReadFromFilename (input);
312
  std::cout << "start runs..." << std::endl;
313
  for (uint32_t i = 0; i < n; i++) 
314
    {
315
      if (is_map)
316
        {
317
          Simulator::SetScheduler (CreateObject<MapScheduler> ());
318
        }
319
      else if (is_list)
320
        {
321
          Simulator::SetScheduler (CreateObject<ListScheduler> ());
322
        }
323
      else if (is_heap)
324
        {
325
          Simulator::SetScheduler (CreateObject<HeapScheduler> ());
326
        }
327
      log.Run ();
328
      Simulator::Destroy ();
329
    }
330
}
(-)a/utils/wscript (-3 lines)
 Lines 24-32   def build(bld): Link Here 
24
    obj = bld.create_ns3_program('bench-packets', ['common'])
24
    obj = bld.create_ns3_program('bench-packets', ['common'])
25
    obj.source = 'bench-packets.cc'
25
    obj.source = 'bench-packets.cc'
26
26
27
    obj = bld.create_ns3_program('replay-simulation', ['simulator'])
28
    obj.source = 'replay-simulation.cc'
29
30
    obj = bld.create_ns3_program('print-introspected-doxygen',
27
    obj = bld.create_ns3_program('print-introspected-doxygen',
31
                                 ['internet-stack', 'csma-cd', 'point-to-point'])
28
                                 ['internet-stack', 'csma-cd', 'point-to-point'])
32
    obj.source = 'print-introspected-doxygen.cc'
29
    obj.source = 'print-introspected-doxygen.cc'

Return to bug 252