File: s4u-io-degradation.cpp

package info (click to toggle)
simgrid 4.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 39,236 kB
  • sloc: cpp: 124,918; ansic: 66,744; python: 8,560; java: 6,773; fortran: 6,079; f90: 5,123; xml: 4,587; sh: 2,194; perl: 1,436; makefile: 111; lisp: 49; javascript: 7; sed: 6
file content (149 lines) | stat: -rw-r--r-- 6,710 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/* Copyright (c) 2017-2025. The SimGrid Team. All rights reserved.          */

/* This program is free software; you can redistribute it and/or modify it
 * under the terms of the license (GNU LGPL) which comes with this package. */

/* This example shows how to simulate a non-linear resource sharing for disk
 * operations.
 *
 * It is inspired on the paper
 * "Adding Storage Simulation Capacities to the SimGridToolkit: Concepts, Models, and API"
 * Available at : https://hal.inria.fr/hal-01197128/document
 *
 * It shows how to simulate concurrent operations degrading overall performance of IO
 * operations (specifically the effects presented in Fig. 8 of the paper).
 */

#include <simgrid/s4u.hpp>

XBT_LOG_NEW_DEFAULT_CATEGORY(disk_test, "Messages specific for this simulation");
namespace sg4 = simgrid::s4u;

/** @brief Calculates the bandwidth for disk doing async operations */
static void estimate_bw(const sg4::Disk* disk, int n_flows, bool read)
{
  unsigned long long size = 100000;
  double cur_time         = sg4::Engine::get_clock();
  std::vector<sg4::IoPtr> activities;
  for (int i = 0; i < n_flows; i++) {
    sg4::IoPtr act;
    if (read)
      act = disk->read_async(size);
    else
      act = disk->write_async(size);

    activities.push_back(act);
  }

  for (const auto& act : activities)
    act->wait();

  double elapsed_time = sg4::Engine::get_clock() - cur_time;
  double estimated_bw = static_cast<double>(size * n_flows) / elapsed_time;
  XBT_INFO("Disk: %s, concurrent %s: %d, estimated bandwidth: %lf", disk->get_cname(), read ? "read" : "write", n_flows,
           estimated_bw);
}

static void host()
{
  /* - Estimating bw for each disk and considering concurrent flows */
  for (int n = 1; n < 15; n += 2) {
    for (const auto* disk : sg4::Host::current()->get_disks()) {
      estimate_bw(disk, n, true);
      estimate_bw(disk, n, false);
    }
  }
}

/**
 * @brief Non-linear resource callback for SSD disks
 *
 * In this case, we have measurements for some resource sharing and directly use them to return the
 * correct value
 * @param disk Disk on which the operation is happening (defined by the user through the std::bind)
 * @param op read or write operation (defined by the user through the std::bind)
 * @param capacity Resource current capacity in SimGrid
 * @param n Number of activities sharing this resource
 */
static double ssd_dynamic_sharing(const sg4::Disk* /*disk*/, const std::string& op, double capacity, int n)
{
  /* measurements for SSD disks */
  using DiskCapacity                                                   = std::unordered_map<int, double>;
  static const std::unordered_map<std::string, DiskCapacity> SSD_SPEED = {{"write", {{1, 131.}}},
                                                                          {"read",
                                                                           {{1, 152.},
                                                                            {2, 161.},
                                                                            {3, 184.},
                                                                            {4, 197.},
                                                                            {5, 207.},
                                                                            {6, 215.},
                                                                            {7, 220.},
                                                                            {8, 224.},
                                                                            {9, 227.},
                                                                            {10, 231.},
                                                                            {11, 233.},
                                                                            {12, 235.},
                                                                            {13, 237.},
                                                                            {14, 238.},
                                                                            {15, 239.}}}};

  const auto& data = SSD_SPEED.at(op);
  const auto value = data.find(n);
  /* no special bandwidth for this disk sharing N flows, just returns maximal capacity */
  return value == data.end() ? capacity : value->second;
}

/**
 * @brief Non-linear resource callback for SATA disks
 *
 * In this case, the degradation for read operations is linear and we have a formula that represents it.
 *
 * @param disk Disk on which the operation is happening (defined by the user through the std::bind)
 * @param capacity Resource current capacity in SimGrid
 * @param n Number of activities sharing this resource
 */
static double sata_dynamic_sharing(const sg4::Disk* /*disk*/, double /*capacity*/, int n)
{
  return 68.3 - 1.7 * n;
}

/** @brief Creates an SSD disk, setting the appropriate callback for non-linear resource sharing */
static void create_ssd_disk(sg4::Host* host, const std::string& disk_name)
{
  auto* disk = host->add_disk(disk_name, "240MBps", "170MBps");
  disk->set_sharing_policy(sg4::Disk::Operation::READ, sg4::Disk::SharingPolicy::NONLINEAR,
                           std::bind(&ssd_dynamic_sharing, disk, "read", std::placeholders::_1, std::placeholders::_2));
  disk->set_sharing_policy(
      sg4::Disk::Operation::WRITE, sg4::Disk::SharingPolicy::NONLINEAR,
      std::bind(&ssd_dynamic_sharing, disk, "write", std::placeholders::_1, std::placeholders::_2));
  disk->set_sharing_policy(sg4::Disk::Operation::READWRITE, sg4::Disk::SharingPolicy::LINEAR);
}

/** @brief Same for a SATA disk, only read operation follows a non-linear resource sharing */
static void create_sata_disk(sg4::Host* host, const std::string& disk_name)
{
  auto* disk = host->add_disk(disk_name, "68MBps", "50MBps");
  disk->set_sharing_policy(sg4::Disk::Operation::READ, sg4::Disk::SharingPolicy::NONLINEAR,
                           std::bind(&sata_dynamic_sharing, disk, std::placeholders::_1, std::placeholders::_2));
  /* this is the default behavior, expliciting only to make it clearer */
  disk->set_sharing_policy(sg4::Disk::Operation::WRITE, sg4::Disk::SharingPolicy::LINEAR);
  disk->set_sharing_policy(sg4::Disk::Operation::READWRITE, sg4::Disk::SharingPolicy::LINEAR);
}

int main(int argc, char** argv)
{
  sg4::Engine e(&argc, argv);
  /* simple platform containing 1 host and 2 disks */
  auto* zone = e.get_netzone_root();
  auto* bob  = zone->add_host("bob", 1e6);
  create_ssd_disk(bob, "Edel (SSD)");
  create_sata_disk(bob, "Griffon (SATA II)");
  zone->seal();

  bob->add_actor("", host);

  e.run();
  XBT_INFO("Simulated time: %g", e.get_clock());

  return 0;
}