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
150
151
152
153
154
155
156
157
158
159
160
161
162
|
open SimulTypes
open SimulGraphes
type trace_event =
Peers of int
| Days of int * int
| Peer of int * float * string
| Round of int
| On of int
| Off of int
| Dead of int
| End
| Exponential
let trace_output oc trace_event =
output_string oc (match trace_event with
Peers npeers -> Printf.sprintf "Peers %d\n" npeers
| Days (ndays, day) -> Printf.sprintf "Days %d %d\n" ndays day
| Peer (i,avail,s) ->
Printf.sprintf "Peer %d %.3f %s\n" i avail s
| Round round -> Printf.sprintf "Round %d\n" round
| On i -> Printf.sprintf "On %d\n" i
| Off i -> Printf.sprintf "Off %d\n" i
| Dead i -> Printf.sprintf "Dead %d\n" i
| End -> "End\n"
| Exponential -> "Exponential\n"
)
let trace_input ic =
let line = input_line ic in
match String2.split line ' ' with
["Peers"; npeers] -> Peers (int_of_string npeers)
| ["Days"; ndays] -> Days (int_of_string ndays, 24 * 60)
| ["Days"; ndays; day] -> Days (int_of_string ndays, int_of_string day)
| "Peer" :: i :: avail :: tail ->
Peer (int_of_string i, float_of_string avail, String2.unsplit tail ' ')
| ["End"] -> End
| ["Exponential"] -> Exponential
| ["Round"; round] -> Round (int_of_string round)
| ["On"; i] -> On (int_of_string i)
| ["Dead"; i] -> Dead (int_of_string i)
| ["Off"; i] -> Off (int_of_string i)
| _ -> failwith (Printf.sprintf "Bad line [%s]" (String.escaped line))
let print_distribution = ref false
(* gnuplot> plot exp(1-log(2+65*x)), 1.0/12 *)
let exponential = ref false
let distribution = ref []
let availability = ref []
let trace_read filename =
let ic = open_in filename in
let npeers = match trace_input ic with
Peers npeers -> npeers
| _ -> assert false
in
let (ndays, day) = match trace_input ic with
Days (ndays, day) -> ndays, day
| _ -> assert false
in
let rec read_peer ii =
match trace_input ic with
Exponential -> exponential := true;
read_peer ii
| Peer (i, avail, s) ->
assert (i=ii);
(*
let x = float_of_int avail /. 900000. in
let avail = (if !exponential then
max 0.02 (min 1. (exp(1. -. log(2. +. 65. *. x))))
else
0.02 +. 0.98 *. x
)
in
if !print_distribution then begin
distribution := x :: !distribution;
availability := avail :: !availability;
end;
let lambda = float_of_int decs /. (60. *. 24.) in
let mu = avail *. lambda /. (1. -. avail) in
*)
let p = {
i = i;
avail = avail;
descr = s;
session = 0;
day = true;
state = OFF;
real_avail = 0;
real_decs = 0;
} in
p
| _ -> assert false
in
let peers = Array.init npeers read_peer in
let event = ref None in
let get_event () =
let ev = trace_input ic in
event := Some ev
in
let next_day = ref 0 in
let begin_time = (Int64.of_float (Unix.gettimeofday ())) in
let rec iter_round round =
match !event with
None ->
next_event round
| Some ev ->
match ev with
Round rr ->
if rr = round then begin
if !next_day = round then begin
let time = Unix.gettimeofday () in
let time = Int64.of_float time in
Printf.printf "Day %d (%Ld)\n%!" (round / day)
(Int64.sub time begin_time);
next_day := !next_day + day
end;
next_event round
end else
assert (rr > round)
| On i ->
event := None;
let p = peers.(i) in
p.state <- ON;
next_event round
| Off i ->
event := None;
let p = peers.(i) in
p.state <- OFF;
p.real_decs <- p.real_decs + 1;
next_event round
| Dead i ->
event := None;
let p = peers.(i) in
p.state <- DEAD;
peers.(i) <- {
p with state = OFF;
};
next_event round
| End -> ()
| _ -> assert false
and next_event round =
get_event ();
iter_round round
in
if !print_distribution then begin
cdf_of_list string_of_float "dist_random" !distribution
"set yrange [0:1]" "CDF of peers" "Distribution"
" title 'random'";
cdf_of_list string_of_float "dist_availability" !availability
"set yrange [0:1]" "CDF of peers" "Distribution"
" title 'avail'";
distribution := [];
availability := [];
end;
peers, ndays * day, iter_round
|