source: libcfa/src/concurrency/stats.cfa@ 424dfc4

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 424dfc4 was b39e6566, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Changed printing of stats to show percentage of pops rather than probe length.

  • 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 uint64_t total = ready.pop.local.success + ready.pop.help.success + ready.pop.steal.success + ready.pop.search.success;
129 double rLcl_pc = (100.0 * (double)ready.pop.local .success) / total;
130 double rHlp_pc = (100.0 * (double)ready.pop.help .success) / total;
131 double rStl_pc = (100.0 * (double)ready.pop.steal .success) / total;
132 double rSch_pc = (100.0 * (double)ready.pop.search.success) / total;
133
134 __cfaabi_bits_print_safe( STDOUT_FILENO,
135 "----- %s \"%s\" (%p) - Ready Q Stats -----\n"
136 "- totals : %'3" PRIu64 " run, %'3" PRIu64 " schd (%'" PRIu64 "ext, %'" PRIu64 "mig, %'" PRId64 " )\n"
137 "- push avg : %'3.0lf (l: %'3.2lf/%'" PRIu64 ", s: %'3.2lf/%'" PRIu64 ", e: %'3.2lf : %'" PRIu64 "e)\n"
138 "- local : %'3.0lf%%: %'3" PRIu64 " (%'3" PRIu64 " try, %'3" PRIu64 " spc, %'3" PRIu64 " lck, %'3" PRIu64 " ept)\n"
139 "- help : %'3.0lf%%: %'3" PRIu64 " (%'3" PRIu64 " try, %'3" PRIu64 " spc, %'3" PRIu64 " lck, %'3" PRIu64 " ept)\n"
140 "- steal : %'3.0lf%%: %'3" PRIu64 " (%'3" PRIu64 " try, %'3" PRIu64 " spc, %'3" PRIu64 " lck, %'3" PRIu64 " ept)\n"
141 "- search : %'3.0lf%%: %'3" PRIu64 " (%'3" PRIu64 " try, %'3" PRIu64 " spc, %'3" PRIu64 " lck, %'3" PRIu64 " ept)\n"
142 "- Idle Slp : %'3" PRIu64 "h, %'3" PRIu64 "c, %'3" PRIu64 "w, %'3" PRIu64 "e\n"
143 "\n"
144 , type, name, id
145 , total
146 , ready.push.local.success + ready.push.share.success + ready.push.extrn.success
147 , ready.push.extrn.success, ready.threads.migration, ready.threads.threads
148 , push_len, sLcl_len, ready.push.local.attempt, sOth_len, ready.push.share.attempt, sExt_len, ready.push.extrn.attempt
149 , rLcl_pc, ready.pop.local .success, ready.pop.local .attempt, ready.pop.local .espec, ready.pop.local .elock, ready.pop.local .eempty
150 , rHlp_pc, ready.pop.help .success, ready.pop.help .attempt, ready.pop.help .espec, ready.pop.help .elock, ready.pop.help .eempty
151 , rStl_pc, ready.pop.steal .success, ready.pop.steal .attempt, ready.pop.steal .espec, ready.pop.steal .elock, ready.pop.steal .eempty
152 , rSch_pc, ready.pop.search.success, ready.pop.search.attempt, ready.pop.search.espec, ready.pop.search.elock, ready.pop.search.eempty
153 , ready.sleep.halts, ready.sleep.cancels, ready.sleep.wakes, ready.sleep.exits
154 );
155 }
156
157 #if defined(CFA_HAVE_LINUX_IO_URING_H)
158 if( flags & CFA_STATS_IO ) {
159 uint64_t total_allocs = io.alloc.fast + io.alloc.slow;
160 double avgfasta = ((double)io.alloc.fast) / total_allocs;
161
162 uint64_t total_submits = io.submit.fast + io.submit.slow;
163 double avgfasts = ((double)io.submit.fast) / total_submits;
164
165 double avgsubs = ((double)io.calls.submitted) / io.calls.flush;
166 double avgcomp = ((double)io.calls.completed) / io.calls.drain;
167
168 __cfaabi_bits_print_safe( STDOUT_FILENO,
169 "----- %s \"%s\" (%p) - I/O Stats -----\n"
170 "- total allocations : %'" PRIu64 "f, %'" PRIu64 "s (%'2.2lff) \n"
171 "- failures : %'" PRIu64 "oom, %'" PRIu64 "rvk, %'" PRIu64 "blk\n"
172 "- total submits : %'" PRIu64 "f, %'" PRIu64 "s (%'2.2lf) \n"
173 "- flush external : %'" PRIu64 "\n"
174 "- io_uring_enter : %'" PRIu64 " (%'" PRIu64 ", %'" PRIu64 " EBUSY)\n"
175 "- submits : %'" PRIu64 " (%'.2lf) \n"
176 "- completes : %'" PRIu64 " (%'.2lf) \n"
177 "- poller sleeping : %'" PRIu64 "\n"
178 "\n"
179 , type, name, id
180 , io.alloc.fast, io.alloc.slow, avgfasta
181 , io.alloc.fail, io.alloc.revoke, io.alloc.block
182 , io.submit.fast, io.submit.slow, avgfasts
183 , io.flush.external
184 , io.calls.flush, io.calls.drain, io.calls.errors.busy
185 , io.calls.submitted, avgsubs
186 , io.calls.completed, avgcomp
187 , io.poller.sleeps
188 );
189 }
190 #endif
191 }
192
193 #if defined(CFA_STATS_ARRAY)
194 extern "C" {
195 #include <stdio.h>
196 #include <errno.h>
197 #include <sys/stat.h>
198 #include <fcntl.h>
199 }
200
201 void __flush_stat( struct __stats_t * this, const char * name, void * handle) {
202 int ret = mkdir(".cfadata", 0755);
203 if(ret < 0 && errno != EEXIST) abort("Failed to create directory .cfadata: %d\n", errno);
204
205 char filename[100];
206 snprintf(filename, 100, ".cfadata/%s%p.data", name, handle);
207
208 int fd = open(filename, O_WRONLY | O_APPEND | O_CREAT, 0644);
209 if(fd < 0) abort("Failed to create file %s: %d\n", filename, errno);
210
211 for(i; this->array.cnt) {
212 char line[100];
213 size_t n = snprintf(line, 100, "%llu, %lld\n", this->array.values[i].ts, this->array.values[i].value);
214 write(fd, line, n);
215 }
216
217 this->array.cnt = 0;
218 close(fd);
219 }
220
221 static __spinlock_t stats_lock;
222
223 void __push_stat( struct __stats_t * this, int64_t value, bool external, const char * name, void * handle ) {
224 if(external) lock(stats_lock __cfaabi_dbg_ctx2);
225
226 if( this->array.cnt >= CFA_STATS_ARRAY ) __flush_stat( this, name, handle );
227
228 size_t idx = this->array.cnt;
229 this->array.cnt++;
230
231 if(external) unlock(stats_lock);
232
233 this->array.values[idx].ts = rdtscl();
234 this->array.values[idx].value = value;
235 }
236 #endif
237#endif
Note: See TracBrowser for help on using the repository browser.