Passed
Pull Request — master (#6643)
by David
15:30 queued 06:17
created

add_ntt()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 9
nc 2
nop 2
dl 0
loc 11
rs 9.9666
c 1
b 0
f 0
1
#!/usr/bin/env php
2
<?php
3
// This file is part of BOINC.
4
// https://boinc.berkeley.edu
5
// Copyright (C) 2025 University of California
6
//
7
// BOINC is free software; you can redistribute it and/or modify it
8
// under the terms of the GNU Lesser General Public License
9
// as published by the Free Software Foundation,
10
// either version 3 of the License, or (at your option) any later version.
11
//
12
// BOINC is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
// See the GNU Lesser General Public License for more details.
16
//
17
// You should have received a copy of the GNU Lesser General Public License
18
// along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
19
// process turnaround time stats files
20
21
// compute stats for batch acceleration
22
//
23
// - classify hosts as low turnaround time (LTT)
24
//      host.error_rate = 1
25
// - classify apps as 'accelerable' if there are sufficient LTT hosts
26
//      app.n_size_classes = 1
27
// - compute median TT of batches
28
//      batch.expire_time
29
//
30
// Details: https://github.com/BOINC/boinc/wiki/Batch-acceleration
31
32
require_once("../inc/util.inc");
33
require_once("../inc/boinc_db.inc");
34
require_once("../inc/submit_db.inc");
35
require_once("../inc/common_defs.inc");
36
37
ini_set('display_errors', true);
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type string expected by parameter $value of ini_set(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

37
ini_set('display_errors', /** @scrutinizer ignore-type */ true);
Loading history...
38
39
// global data structures
40
//
41
$apps = [];
42
    // $apps[id] is a list of IDs of hosts that have completed jobs
43
$hosts = [];
44
    // $hosts[id] is a struct
45
    //  ntt_n
46
    //  ntt_sum
47
    
48
// compute the median TT for the batch;
49
// compute normalized TT for hosts w/ jobs
50
// classify apps as accelerable or not
51
//
52
function do_batch($batch) {
53
    echo "processing batch $batch->id\n";
54
    $results = BoincResult::enum_fields(
55
        'sent_time, received_time, hostid',
56
        sprintf('batch=%d and outcome=%d',
57
            $batch->id, RESULT_OUTCOME_SUCCESS
58
        )
59
    );
60
    $tts = [];
61
    foreach ($results as $r) {
62
        $r->tt = $r->received_time - $r->sent_time;
63
        $tts[] = $r->tt;
64
    }
65
    $n = count($tts);
66
    echo "$n success results\n";
67
    if ($n < 100) {
68
        // not enough for a meaningful median
69
        $batch->update("expire_time=0");
70
        return;
71
    }
72
    sort($tts);
73
    $median = $tts[intdiv($n, 2)];
74
    echo "median TT: $median\n";
75
    foreach ($results as $r) {
76
        add_ntt($r->hostid, $r->tt/$median);
77
        add_host($batch->app_id, $r->hostid);
78
    }
79
80
    $results = BoincResult::enum_fields(
81
        'hostid',
82
        sprintf('batch=%d and outcome=%d',
83
            $batch->id, RESULT_OUTCOME_NO_REPLY
84
        )
85
    );
86
    echo sprintf("%d timeout results\n", count($results));
87
    foreach ($results as $r) {
88
        add_ntt($r->hostid, 10.);
89
    }
90
91
    $batch->update("expire_time=$median");
92
}
93
94
// increment TT counts in hosts array; add host if needed
95
//
96
function add_ntt($hostid, $tt) {
97
    global $hosts;
98
    if (!array_key_exists($hostid, $hosts)) {
99
        $x = new StdClass;
100
        $x->ntt_n = 0;
101
        $x->ntt_sum = 0;
102
        $hosts[$hostid] = $x;
103
    }
104
    $h = $hosts[$hostid];
105
    $h->ntt_n += 1;
106
    $h->ntt_sum += $tt;
107
}
108
109
function add_host($appid, $hostid) {
110
    global $apps;
111
    $x = $apps[$appid];
112
    if (array_key_exists($hostid, $x)) {
113
        $x[$hostid] += 1;
114
    } else {
115
        $x[$hostid] = 1;
116
    }
117
    $apps[$appid] = $x;
118
}
119
120
function update_db() {
121
    global $hosts, $apps;
122
123
    // identify LTT hosts
124
125
    echo "Updating host LTT flags\n";
126
    BoincHost::update_aux("error_rate=0");
127
    $ltts = [];
128
    foreach ($hosts as $id=>$x) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "=>"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space after "=>"; 0 found
Loading history...
129
        $avg = $x->ntt_sum / $x->ntt_n;
130
        if ($avg < 1) {
131
            $ltts[] = $id;
132
        }
133
    }
134
    if ($ltts) {
135
        $ltts = implode(',', $ltts);
136
        BoincHost::update_aux(
137
            'error_rate=1',
138
            sprintf('id in (%s)', $ltts)
139
        );
140
    }
141
142
    // identify accelerable apps
143
144
    echo "Updating app accelerable flags\n";
145
    foreach ($apps as $id=>$hlist) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "=>"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space after "=>"; 0 found
Loading history...
146
        $app = BoincApp::lookup_id($id);
147
        $accel = false;
148
        $n = count($hlist);
149
        if ($n > 100) {
150
            $nfast = 0;
151
            foreach ($hlist as $id=>$count) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "=>"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space after "=>"; 0 found
Loading history...
Comprehensibility Bug introduced by
$id is overwriting a variable from outer foreach loop.
Loading history...
152
                $x = $hosts[$id];
153
                $avg = $x->ntt_sum / $x->ntt_n;
154
                if ($avg < 1) {
155
                    $nfast++;
156
                }
157
            }
158
            echo "app $app->name $n hosts, $nfast are LTT\n";
159
            if ($nfast > $n*.25) {
160
                echo "marking $app->name as accelerable\n";
161
                $accel = true;
162
            }
163
        } else {
164
            echo "app $app->name not enough hosts: $n\n";
165
        }
166
167
        $app->update(
168
            sprintf('n_size_classes=%d', $accel?1:0)
169
        );
170
    }
171
}
172
173
function show_hosts() {
174
    global $hosts;
175
    foreach ($hosts as $id=>$h) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "=>"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space after "=>"; 0 found
Loading history...
176
        echo sprintf("host %d: %d jobs, avg NTT %f\n",
177
            $id, $h->ntt_n, $h->ntt_sum/$h->ntt_n
178
        );
179
    }
180
}
181
182
function main() {
183
    global $apps;
184
    echo sprintf("starting: %s\n", time_str(time()));
185
    $as = BoincApp::enum('');
186
    foreach ($as as $a) {
187
        $apps[$a->id] = [];
188
    }
189
    $start = time()-30*86400;
190
    $batches = BoincBatch::enum(
191
        sprintf(
192
            'create_time>%d and state in (%d, %d)',
193
            $start, BATCH_STATE_IN_PROGRESS, BATCH_STATE_COMPLETE
194
        )
195
    );
196
    foreach($batches as $batch) {
197
        do_batch($batch);
0 ignored issues
show
Bug introduced by
The call to do_batch() has too few arguments starting with wus. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

197
        /** @scrutinizer ignore-call */ 
198
        do_batch($batch);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
198
    }
199
    update_db();
200
    echo sprintf("finished: %s\n", time_str(time()));
201
}
202
203
main();
204
?>
205