source: libcfa/src/concurrency/stats.cfa@ 1d5deea

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 1d5deea was d2fadeb, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Changed stats to make sense with relaxed fifo and work stealing

  • Property mode set to 100644
File size: 14.1 KB
Line 
1#include <stdint.h>
2#include <stdlib.hfa>
3
4#include <unistd.h> // STDERR_FILENO
5#include <inttypes.h>
6#include "bits/debug.hfa"
7#include "bits/locks.hfa"
8#include "stats.hfa"
9
10#if !defined(__CFA_NO_STATISTICS__)
11 void __init_stats( struct __stats_t * stats ) {
12 stats->ready.push.local.attempt = 0;
13 stats->ready.push.local.success = 0;
14 stats->ready.push.share.attempt = 0;
15 stats->ready.push.share.success = 0;
16 stats->ready.push.extrn.attempt = 0;
17 stats->ready.push.extrn.success = 0;
18 stats->ready.pop.local .attempt = 0;
19 stats->ready.pop.local .success = 0;
20 stats->ready.pop.local .elock = 0;
21 stats->ready.pop.local .eempty = 0;
22 stats->ready.pop.local .espec = 0;
23 stats->ready.pop.help .attempt = 0;
24 stats->ready.pop.help .success = 0;
25 stats->ready.pop.help .elock = 0;
26 stats->ready.pop.help .eempty = 0;
27 stats->ready.pop.help .espec = 0;
28 stats->ready.pop.steal .attempt = 0;
29 stats->ready.pop.steal .success = 0;
30 stats->ready.pop.steal .elock = 0;
31 stats->ready.pop.steal .eempty = 0;
32 stats->ready.pop.steal .espec = 0;
33 stats->ready.pop.search.attempt = 0;
34 stats->ready.pop.search.success = 0;
35 stats->ready.pop.search.elock = 0;
36 stats->ready.pop.search.eempty = 0;
37 stats->ready.pop.search.espec = 0;
38 stats->ready.threads.migration = 0;
39 stats->ready.threads.threads = 0;
40 stats->ready.sleep.halts = 0;
41 stats->ready.sleep.cancels = 0;
42 stats->ready.sleep.wakes = 0;
43 stats->ready.sleep.exits = 0;
44
45 #if defined(CFA_HAVE_LINUX_IO_URING_H)
46 stats->io.alloc.fast = 0;
47 stats->io.alloc.slow = 0;
48 stats->io.alloc.fail = 0;
49 stats->io.alloc.revoke = 0;
50 stats->io.alloc.block = 0;
51 stats->io.submit.fast = 0;
52 stats->io.submit.slow = 0;
53 stats->io.flush.external = 0;
54 stats->io.calls.flush = 0;
55 stats->io.calls.submitted = 0;
56 stats->io.calls.drain = 0;
57 stats->io.calls.completed = 0;
58 stats->io.calls.errors.busy = 0;
59 stats->io.poller.sleeps = 0;
60 #endif
61
62 #if defined(CFA_STATS_ARRAY)
63 stats->array.values = alloc(CFA_STATS_ARRAY);
64 stats->array.cnt = 0;
65 #endif
66 }
67
68 void __tally_stats( struct __stats_t * cltr, struct __stats_t * proc ) {
69 __atomic_fetch_add( &cltr->ready.push.local.attempt, proc->ready.push.local.attempt, __ATOMIC_SEQ_CST ); proc->ready.push.local.attempt = 0;
70 __atomic_fetch_add( &cltr->ready.push.local.success, proc->ready.push.local.success, __ATOMIC_SEQ_CST ); proc->ready.push.local.success = 0;
71 __atomic_fetch_add( &cltr->ready.push.share.attempt, proc->ready.push.share.attempt, __ATOMIC_SEQ_CST ); proc->ready.push.share.attempt = 0;
72 __atomic_fetch_add( &cltr->ready.push.share.success, proc->ready.push.share.success, __ATOMIC_SEQ_CST ); proc->ready.push.share.success = 0;
73 __atomic_fetch_add( &cltr->ready.push.extrn.attempt, proc->ready.push.extrn.attempt, __ATOMIC_SEQ_CST ); proc->ready.push.extrn.attempt = 0;
74 __atomic_fetch_add( &cltr->ready.push.extrn.success, proc->ready.push.extrn.success, __ATOMIC_SEQ_CST ); proc->ready.push.extrn.success = 0;
75 __atomic_fetch_add( &cltr->ready.pop.local .attempt, proc->ready.pop.local .attempt, __ATOMIC_SEQ_CST ); proc->ready.pop.local .attempt = 0;
76 __atomic_fetch_add( &cltr->ready.pop.local .success, proc->ready.pop.local .success, __ATOMIC_SEQ_CST ); proc->ready.pop.local .success = 0;
77 __atomic_fetch_add( &cltr->ready.pop.local .elock , proc->ready.pop.local .elock , __ATOMIC_SEQ_CST ); proc->ready.pop.local .elock = 0;
78 __atomic_fetch_add( &cltr->ready.pop.local .eempty , proc->ready.pop.local .eempty , __ATOMIC_SEQ_CST ); proc->ready.pop.local .eempty = 0;
79 __atomic_fetch_add( &cltr->ready.pop.local .espec , proc->ready.pop.local .espec , __ATOMIC_SEQ_CST ); proc->ready.pop.local .espec = 0;
80 __atomic_fetch_add( &cltr->ready.pop.help .attempt, proc->ready.pop.help .attempt, __ATOMIC_SEQ_CST ); proc->ready.pop.help .attempt = 0;
81 __atomic_fetch_add( &cltr->ready.pop.help .success, proc->ready.pop.help .success, __ATOMIC_SEQ_CST ); proc->ready.pop.help .success = 0;
82 __atomic_fetch_add( &cltr->ready.pop.help .elock , proc->ready.pop.help .elock , __ATOMIC_SEQ_CST ); proc->ready.pop.help .elock = 0;
83 __atomic_fetch_add( &cltr->ready.pop.help .eempty , proc->ready.pop.help .eempty , __ATOMIC_SEQ_CST ); proc->ready.pop.help .eempty = 0;
84 __atomic_fetch_add( &cltr->ready.pop.help .espec , proc->ready.pop.help .espec , __ATOMIC_SEQ_CST ); proc->ready.pop.help .espec = 0;
85 __atomic_fetch_add( &cltr->ready.pop.steal .attempt, proc->ready.pop.steal .attempt, __ATOMIC_SEQ_CST ); proc->ready.pop.steal .attempt = 0;
86 __atomic_fetch_add( &cltr->ready.pop.steal .success, proc->ready.pop.steal .success, __ATOMIC_SEQ_CST ); proc->ready.pop.steal .success = 0;
87 __atomic_fetch_add( &cltr->ready.pop.steal .elock , proc->ready.pop.steal .elock , __ATOMIC_SEQ_CST ); proc->ready.pop.steal .elock = 0;
88 __atomic_fetch_add( &cltr->ready.pop.steal .eempty , proc->ready.pop.steal .eempty , __ATOMIC_SEQ_CST ); proc->ready.pop.steal .eempty = 0;
89 __atomic_fetch_add( &cltr->ready.pop.steal .espec , proc->ready.pop.steal .espec , __ATOMIC_SEQ_CST ); proc->ready.pop.steal .espec = 0;
90 __atomic_fetch_add( &cltr->ready.pop.search.attempt, proc->ready.pop.search.attempt, __ATOMIC_SEQ_CST ); proc->ready.pop.search.attempt = 0;
91 __atomic_fetch_add( &cltr->ready.pop.search.success, proc->ready.pop.search.success, __ATOMIC_SEQ_CST ); proc->ready.pop.search.success = 0;
92 __atomic_fetch_add( &cltr->ready.pop.search.elock , proc->ready.pop.search.elock , __ATOMIC_SEQ_CST ); proc->ready.pop.search.elock = 0;
93 __atomic_fetch_add( &cltr->ready.pop.search.eempty , proc->ready.pop.search.eempty , __ATOMIC_SEQ_CST ); proc->ready.pop.search.eempty = 0;
94 __atomic_fetch_add( &cltr->ready.pop.search.espec , proc->ready.pop.search.espec , __ATOMIC_SEQ_CST ); proc->ready.pop.search.espec = 0;
95 __atomic_fetch_add( &cltr->ready.threads.migration , proc->ready.threads.migration , __ATOMIC_SEQ_CST ); proc->ready.threads.migration = 0;
96 __atomic_fetch_add( &cltr->ready.threads.threads , proc->ready.threads.threads , __ATOMIC_SEQ_CST ); proc->ready.threads.threads = 0;
97 __atomic_fetch_add( &cltr->ready.sleep.halts , proc->ready.sleep.halts , __ATOMIC_SEQ_CST ); proc->ready.sleep.halts = 0;
98 __atomic_fetch_add( &cltr->ready.sleep.cancels , proc->ready.sleep.cancels , __ATOMIC_SEQ_CST ); proc->ready.sleep.cancels = 0;
99 __atomic_fetch_add( &cltr->ready.sleep.wakes , proc->ready.sleep.wakes , __ATOMIC_SEQ_CST ); proc->ready.sleep.wakes = 0;
100 __atomic_fetch_add( &cltr->ready.sleep.exits , proc->ready.sleep.exits , __ATOMIC_SEQ_CST ); proc->ready.sleep.exits = 0;
101
102 #if defined(CFA_HAVE_LINUX_IO_URING_H)
103 __atomic_fetch_add( &cltr->io.alloc.fast , proc->io.alloc.fast , __ATOMIC_SEQ_CST ); proc->io.alloc.fast = 0;
104 __atomic_fetch_add( &cltr->io.alloc.slow , proc->io.alloc.slow , __ATOMIC_SEQ_CST ); proc->io.alloc.slow = 0;
105 __atomic_fetch_add( &cltr->io.alloc.fail , proc->io.alloc.fail , __ATOMIC_SEQ_CST ); proc->io.alloc.fail = 0;
106 __atomic_fetch_add( &cltr->io.alloc.revoke , proc->io.alloc.revoke , __ATOMIC_SEQ_CST ); proc->io.alloc.revoke = 0;
107 __atomic_fetch_add( &cltr->io.alloc.block , proc->io.alloc.block , __ATOMIC_SEQ_CST ); proc->io.alloc.block = 0;
108 __atomic_fetch_add( &cltr->io.submit.fast , proc->io.submit.fast , __ATOMIC_SEQ_CST ); proc->io.submit.fast = 0;
109 __atomic_fetch_add( &cltr->io.submit.slow , proc->io.submit.slow , __ATOMIC_SEQ_CST ); proc->io.submit.slow = 0;
110 __atomic_fetch_add( &cltr->io.flush.external , proc->io.flush.external , __ATOMIC_SEQ_CST ); proc->io.flush.external = 0;
111 __atomic_fetch_add( &cltr->io.calls.flush , proc->io.calls.flush , __ATOMIC_SEQ_CST ); proc->io.calls.flush = 0;
112 __atomic_fetch_add( &cltr->io.calls.submitted , proc->io.calls.submitted , __ATOMIC_SEQ_CST ); proc->io.calls.submitted = 0;
113 __atomic_fetch_add( &cltr->io.calls.drain , proc->io.calls.drain , __ATOMIC_SEQ_CST ); proc->io.calls.drain = 0;
114 __atomic_fetch_add( &cltr->io.calls.completed , proc->io.calls.completed , __ATOMIC_SEQ_CST ); proc->io.calls.completed = 0;
115 __atomic_fetch_add( &cltr->io.calls.errors.busy, proc->io.calls.errors.busy, __ATOMIC_SEQ_CST ); proc->io.calls.errors.busy = 0;
116 __atomic_fetch_add( &cltr->io.poller.sleeps , proc->io.poller.sleeps , __ATOMIC_SEQ_CST ); proc->io.poller.sleeps = 0;
117 #endif
118 }
119
120 void __print_stats( struct __stats_t * stats, int flags, const char * type, const char * name, void * id ) with( *stats ) {
121
122 if( flags & CFA_STATS_READY_Q ) {
123 double push_len = ((double)ready.push.local.attempt + ready.push.share.attempt + ready.push.extrn.attempt) / (ready.push.local.success + ready.push.share.success + ready.push.extrn.success);
124 double sLcl_len = ready.push.local.success ? ((double)ready.push.local.attempt) / ready.push.local.success : 0;
125 double sOth_len = ready.push.share.success ? ((double)ready.push.share.attempt) / ready.push.share.success : 0;
126 double sExt_len = ready.push.extrn.success ? ((double)ready.push.extrn.attempt) / ready.push.extrn.success : 0;
127
128 double rLcl_len = ready.pop.local .success ? ((double)ready.pop.local .attempt) / ready.pop.local .success : 0;
129 double rHlp_len = ready.pop.help .success ? ((double)ready.pop.help .attempt) / ready.pop.help .success : 0;
130 double rStl_len = ready.pop.steal .success ? ((double)ready.pop.steal .attempt) / ready.pop.steal .success : 0;
131 double rSch_len = ready.pop.search.success ? ((double)ready.pop.search.attempt) / ready.pop.search.success : 0;
132
133 __cfaabi_bits_print_safe( STDOUT_FILENO,
134 "----- %s \"%s\" (%p) - Ready Q Stats -----\n"
135 "- totals : %'3" PRIu64 " run, %'3" PRIu64 " schd (%'" PRIu64 "ext, %'" PRIu64 "mig, %'" PRId64 " )\n"
136 "- push avg : %'3.2lf (l: %'3.2lf/%'" PRIu64 ", s: %'3.2lf/%'" PRIu64 ", e: %'3.2lf : %'" PRIu64 "e)\n"
137 "- local : %'3.2lf (%'3" PRIu64 " try, %'3" PRIu64 " spc, %'3" PRIu64 " lck, %'3" PRIu64 " ept)\n"
138 "- help : %'3.2lf (%'3" PRIu64 " try, %'3" PRIu64 " spc, %'3" PRIu64 " lck, %'3" PRIu64 " ept)\n"
139 "- steal : %'3.2lf (%'3" PRIu64 " try, %'3" PRIu64 " spc, %'3" PRIu64 " lck, %'3" PRIu64 " ept)\n"
140 "- search : %'3.2lf (%'3" PRIu64 " try, %'3" PRIu64 " spc, %'3" PRIu64 " lck, %'3" PRIu64 " ept)\n"
141 "- Idle Slp : %'3" PRIu64 "h, %'3" PRIu64 "c, %'3" PRIu64 "w, %'3" PRIu64 "e\n"
142 "\n"
143 , type, name, id
144 , ready.pop.local.success + ready.pop.help.success + ready.pop.steal.success + ready.pop.search.success
145 , ready.push.local.success + ready.push.share.success + ready.push.extrn.success
146 , ready.push.extrn.success, ready.threads.migration, ready.threads.threads
147 , push_len, sLcl_len, ready.push.local.attempt, sOth_len, ready.push.share.attempt, sExt_len, ready.push.extrn.attempt
148 , rLcl_len, ready.pop.local .attempt, ready.pop.local .espec, ready.pop.local .elock, ready.pop.local .eempty
149 , rHlp_len, ready.pop.help .attempt, ready.pop.help .espec, ready.pop.help .elock, ready.pop.help .eempty
150 , rStl_len, ready.pop.steal .attempt, ready.pop.steal .espec, ready.pop.steal .elock, ready.pop.steal .eempty
151 , rSch_len, ready.pop.search.attempt, ready.pop.search.espec, ready.pop.search.elock, ready.pop.search.eempty
152 , ready.sleep.halts, ready.sleep.cancels, ready.sleep.wakes, ready.sleep.exits
153 );
154 }
155
156 #if defined(CFA_HAVE_LINUX_IO_URING_H)
157 if( flags & CFA_STATS_IO ) {
158 uint64_t total_allocs = io.alloc.fast + io.alloc.slow;
159 double avgfasta = ((double)io.alloc.fast) / total_allocs;
160
161 uint64_t total_submits = io.submit.fast + io.submit.slow;
162 double avgfasts = ((double)io.submit.fast) / total_submits;
163
164 double avgsubs = ((double)io.calls.submitted) / io.calls.flush;
165 double avgcomp = ((double)io.calls.completed) / io.calls.drain;
166
167 __cfaabi_bits_print_safe( STDOUT_FILENO,
168 "----- %s \"%s\" (%p) - I/O Stats -----\n"
169 "- total allocations : %'" PRIu64 "f, %'" PRIu64 "s (%'2.2lff) \n"
170 "- failures : %'" PRIu64 "oom, %'" PRIu64 "rvk, %'" PRIu64 "blk\n"
171 "- total submits : %'" PRIu64 "f, %'" PRIu64 "s (%'2.2lf) \n"
172 "- flush external : %'" PRIu64 "\n"
173 "- io_uring_enter : %'" PRIu64 " (%'" PRIu64 ", %'" PRIu64 " EBUSY)\n"
174 "- submits : %'" PRIu64 " (%'.2lf) \n"
175 "- completes : %'" PRIu64 " (%'.2lf) \n"
176 "- poller sleeping : %'" PRIu64 "\n"
177 "\n"
178 , type, name, id
179 , io.alloc.fast, io.alloc.slow, avgfasta
180 , io.alloc.fail, io.alloc.revoke, io.alloc.block
181 , io.submit.fast, io.submit.slow, avgfasts
182 , io.flush.external
183 , io.calls.flush, io.calls.drain, io.calls.errors.busy
184 , io.calls.submitted, avgsubs
185 , io.calls.completed, avgcomp
186 , io.poller.sleeps
187 );
188 }
189 #endif
190 }
191
192 #if defined(CFA_STATS_ARRAY)
193 extern "C" {
194 #include <stdio.h>
195 #include <errno.h>
196 #include <sys/stat.h>
197 #include <fcntl.h>
198 }
199
200 void __flush_stat( struct __stats_t * this, const char * name, void * handle) {
201 int ret = mkdir(".cfadata", 0755);
202 if(ret < 0 && errno != EEXIST) abort("Failed to create directory .cfadata: %d\n", errno);
203
204 char filename[100];
205 snprintf(filename, 100, ".cfadata/%s%p.data", name, handle);
206
207 int fd = open(filename, O_WRONLY | O_APPEND | O_CREAT, 0644);
208 if(fd < 0) abort("Failed to create file %s: %d\n", filename, errno);
209
210 for(i; this->array.cnt) {
211 char line[100];
212 size_t n = snprintf(line, 100, "%llu, %lld\n", this->array.values[i].ts, this->array.values[i].value);
213 write(fd, line, n);
214 }
215
216 this->array.cnt = 0;
217 close(fd);
218 }
219
220 static __spinlock_t stats_lock;
221
222 void __push_stat( struct __stats_t * this, int64_t value, bool external, const char * name, void * handle ) {
223 if(external) lock(stats_lock __cfaabi_dbg_ctx2);
224
225 if( this->array.cnt >= CFA_STATS_ARRAY ) __flush_stat( this, name, handle );
226
227 size_t idx = this->array.cnt;
228 this->array.cnt++;
229
230 if(external) unlock(stats_lock);
231
232 this->array.values[idx].ts = rdtscl();
233 this->array.values[idx].value = value;
234 }
235 #endif
236#endif
Note: See TracBrowser for help on using the repository browser.