BOINC /
boinc
| 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
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
|
|||||||
| 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
|
|||||||
| 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
|
|||||||
| 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
|
|||||||
| 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 batch_stats: %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
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
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 batch_stats: %s\n", time_str(time())); |
||||||
| 201 | } |
||||||
| 202 | |||||||
| 203 | main(); |
||||||
| 204 | ?> |
||||||
| 205 |