1 Demonstrations of funccount, the Linux eBPF/bcc version. 2 3 4 This program traces functions, tracepoints, or USDT probes that match a 5 specified pattern, and when Ctrl-C is hit prints a summary of their count 6 while tracing. Eg, tracing all kernel functions that begin with "vfs_": 7 8 # ./funccount 'vfs_*' 9 Tracing... Ctrl-C to end. 10 ^C 11 FUNC COUNT 12 vfs_create 1 13 vfs_rename 1 14 vfs_fsync_range 2 15 vfs_lock_file 30 16 vfs_fstatat 152 17 vfs_fstat 154 18 vfs_write 166 19 vfs_getattr_nosec 262 20 vfs_getattr 262 21 vfs_open 264 22 vfs_read 470 23 Detaching... 24 25 The above output shows that while tracing the vfs_read() function was called 470 26 times, and vfs_open() 264 times, etc. 27 28 This is useful for exploring kernel code, to figure out which functions are in 29 use and which are not. This can narrow down an investigation to just a few 30 functions, whose counts are similar to the workload investigated. 31 32 33 Tracing all tcp functions: 34 35 # ./funccount 'tcp_*' 36 Tracing... Ctrl-C to end. 37 ^C 38 FUNC COUNT 39 tcp_try_undo_recovery 1 40 tcp_twsk_destructor 1 41 tcp_enter_recovery 1 42 tcp_xmit_retransmit_queue 1 43 tcp_update_scoreboard 1 44 tcp_verify_retransmit_hint 1 45 tcp_tsq_handler.part.31 1 46 tcp_sacktag_write_queue 1 47 tcp_match_skb_to_sack 1 48 tcp_time_wait 1 49 tcp_mark_head_lost 1 50 tcp_init_cwnd_reduction 1 51 tcp_sacktag_one 1 52 tcp_sacktag_walk 1 53 tcp_retransmit_skb 1 54 tcp_tasklet_func 1 55 tcp_resume_early_retransmit 1 56 tcp_dsack_set 1 57 tcp_v4_syn_recv_sock 2 58 tcp_ca_openreq_child 2 59 tcp_try_fastopen 2 60 tcp_openreq_init_rwin 2 61 tcp_v4_init_req 2 62 tcp_create_openreq_child 2 63 tcp_v4_send_synack 2 64 tcp_v4_init_sequence 2 65 tcp_fragment 2 66 tcp_v4_conn_request 2 67 tcp_conn_request 2 68 tcp_v4_route_req 2 69 tcp_fragment_tstamp 2 70 tcp_try_keep_open 2 71 tcp_v4_reqsk_destructor 2 72 tcp_may_send_now 2 73 tcp_make_synack 2 74 tcp_child_process 2 75 tcp_check_req 2 76 tcp_fastretrans_alert 2 77 tcp_set_keepalive 2 78 tcp_finish_connect 3 79 tcp_connect_queue_skb 3 80 tcp_v4_connect 3 81 tcp_init_sock 3 82 tcp_v4_init_sock 3 83 tcp_connect 3 84 tcp_any_retrans_done.part.35 3 85 tcp_clear_retrans 3 86 tcp_setsockopt 4 87 tcp_update_metrics 5 88 tcp_done 5 89 tcp_initialize_rcv_mss 5 90 tcp_sndbuf_expand 5 91 tcp_fin 5 92 tcp_init_xmit_timers 5 93 tcp_close 5 94 tcp_init_congestion_control 5 95 tcp_init_metrics 5 96 tcp_gro_complete 5 97 tcp_free_fastopen_req 5 98 tcp_v4_destroy_sock 5 99 tcp_cleanup_congestion_control 5 100 tcp_send_fin 5 101 tcp_init_buffer_space 5 102 tcp_init_cwnd 5 103 tcp_select_initial_window 5 104 tcp_check_oom 5 105 tcp_default_init_rwnd 5 106 tcp_assign_congestion_control 5 107 tcp_getsockopt 6 108 tcp_ioctl 6 109 tcp_mtup_init 8 110 tcp_parse_options 8 111 tcp_mss_to_mtu 8 112 tcp_try_rmem_schedule 8 113 tcp_get_metrics 10 114 tcp_try_coalesce 10 115 tcp_rcv_state_process 14 116 tcp_sync_mss 14 117 tcp_write_timer_handler 15 118 tcp_write_timer 16 119 tcp_grow_window.isra.27 22 120 tcp_set_state 23 121 tcp_send_ack 37 122 tcp_delack_timer 42 123 tcp_delack_timer_handler 42 124 tcp_validate_incoming 91 125 tcp_prequeue_process 112 126 tcp_v4_early_demux 117 127 tcp_gro_receive 146 128 tcp_queue_rcv 167 129 tcp_data_queue 215 130 tcp_urg 219 131 tcp_send_delayed_ack 257 132 tcp_send_mss 275 133 tcp_push 275 134 tcp_sendmsg 275 135 tcp_event_data_recv 275 136 tcp_nagle_check 279 137 tcp_write_xmit 282 138 tcp_event_new_data_sent 282 139 tcp_current_mss 284 140 tcp_init_tso_segs 284 141 tcp_wfree 286 142 tcp_schedule_loss_probe 305 143 tcp_v4_send_check 323 144 tcp_transmit_skb 323 145 tcp_recvmsg 323 146 tcp_options_write 325 147 tcp_rcv_space_adjust 328 148 tcp_check_space 332 149 tcp_rcv_established 337 150 tcp_ack 337 151 tcp_parse_aligned_timestamp.part.43 345 152 tcp_prequeue 346 153 tcp_v4_do_rcv 351 154 tcp_v4_rcv 351 155 tcp_parse_md5sig_option 351 156 tcp_cleanup_rbuf 436 157 tcp_poll 468 158 tcp_established_options 604 159 tcp_v4_md5_lookup 615 160 tcp_release_cb 736 161 tcp_rearm_rto 843 162 tcp_md5_do_lookup 968 163 Detaching... 164 165 The current implementation can take many seconds to detach from tracing, after 166 Ctrl-C has been hit. 167 168 169 User functions can be traced in executables or libraries, and per-process 170 filtering is allowed: 171 172 # ./funccount -p 1442 /home/ubuntu/contentions:* 173 Tracing 15 functions for "/home/ubuntu/contentions:*"... Hit Ctrl-C to end. 174 ^C 175 FUNC COUNT 176 main 1 177 _start 1 178 primes_thread 2 179 insert_result 87186 180 is_prime 1252772 181 Detaching... 182 183 If /home/ubuntu is in the $PATH, then the following command will also work: 184 185 # ./funccount -p 1442 contentions:* 186 187 188 Counting libc write and read calls using regular expression syntax (-r): 189 190 # ./funccount -r 'c:(write|read)$' 191 Tracing 2 functions for "c:(write|read)$"... Hit Ctrl-C to end. 192 ^C 193 FUNC COUNT 194 read 2 195 write 4 196 Detaching... 197 198 199 Kernel tracepoints are also available as targets. For example, trace common 200 block I/O tracepoints and see how often they are invoked: 201 202 # ./funccount t:block:* 203 Tracing 19 functions for "t:block:*"... Hit Ctrl-C to end. 204 ^C 205 FUNC COUNT 206 block:block_rq_complete 7 207 block:block_rq_issue 7 208 block:block_getrq 7 209 block:block_rq_insert 7 210 Detaching... 211 212 213 Likewise, user-mode statically defined traces (USDT) can also be probed. For 214 example, count mutex-related events in pthreads: 215 216 # ./funccount u:pthread:*mutex* -p 1442 217 Tracing 7 functions for "u:pthread:*mutex*"... Hit Ctrl-C to end. 218 ^C 219 FUNC COUNT 220 mutex_init 1 221 mutex_entry 547122 222 mutex_acquired 547175 223 mutex_release 547185 224 Detaching... 225 226 227 An interval can be provided. Eg, printing output every 1 second for vfs calls: 228 229 # ./funccount -i 1 'vfs_*' 230 Tracing... Ctrl-C to end. 231 232 FUNC COUNT 233 vfs_fstatat 1 234 vfs_fstat 16 235 vfs_getattr_nosec 17 236 vfs_getattr 17 237 vfs_write 52 238 vfs_read 79 239 vfs_open 98 240 241 FUNC COUNT 242 vfs_fstatat 10 243 vfs_fstat 10 244 vfs_open 13 245 vfs_getattr_nosec 20 246 vfs_getattr 20 247 vfs_write 28 248 vfs_read 39 249 250 FUNC COUNT 251 vfs_fsync_range 2 252 vfs_lock_file 30 253 vfs_write 107 254 vfs_fstatat 129 255 vfs_fstat 130 256 vfs_open 154 257 vfs_getattr_nosec 222 258 vfs_getattr 222 259 vfs_read 384 260 ^C 261 Detaching... 262 263 This can be useful for making some ad hoc tools, exposing new counts of 264 kernel activity that aren't visible in other metrics. 265 266 Include -T to print timestamps on output. 267 268 269 A maximum duration can be set. For example, to print 5 x 1 second summaries 270 of vfs_read() calls: 271 272 # ./funccount -i 1 -d 5 vfs_read 273 Tracing 1 functions for "vfs_read"... Hit Ctrl-C to end. 274 275 FUNC COUNT 276 vfs_read 30 277 278 FUNC COUNT 279 vfs_read 26 280 281 FUNC COUNT 282 vfs_read 54 283 284 FUNC COUNT 285 vfs_read 25 286 287 FUNC COUNT 288 vfs_read 31 289 Detaching... 290 291 By leaving off the "-i 1", this will print a single 5 second summary: 292 293 # funccount.py -d 5 vfs_read 294 Tracing 1 functions for "vfs_read"... Hit Ctrl-C to end. 295 296 FUNC COUNT 297 vfs_read 167 298 Detaching... 299 300 This can be useful for finding out rates: trace all functions for ten seconds 301 and then divide by ten for the per-second rate. 302 303 304 The "*" wildcard can be used multiple times. Eg, matching functions that contain 305 the word "readdir": 306 307 # ./funccount '*readdir*' 308 Tracing... Ctrl-C to end. 309 ^C 310 FUNC COUNT 311 ext4_readdir 4 312 Detaching... 313 314 Matching "tcp" then "send": 315 316 # ./funccount '*tcp*send*' 317 Tracing... Ctrl-C to end. 318 ^C 319 FUNC COUNT 320 tcp_send_ack 4 321 tcp_send_delayed_ack 19 322 tcp_send_mss 26 323 tcp_sendmsg 26 324 tcp_v4_send_check 30 325 __tcp_v4_send_check 30 326 Detaching... 327 328 329 Full USAGE: 330 331 # ./funccount -h 332 usage: funccount [-h] [-p PID] [-i INTERVAL] [-d DURATION] [-T] [-r] [-D] 333 pattern 334 335 Count functions, tracepoints, and USDT probes 336 337 positional arguments: 338 pattern search expression for events 339 340 optional arguments: 341 -h, --help show this help message and exit 342 -p PID, --pid PID trace this PID only 343 -i INTERVAL, --interval INTERVAL 344 summary interval, seconds 345 -d DURATION, --duration DURATION 346 total duration of trace, seconds 347 -T, --timestamp include timestamp on output 348 -r, --regexp use regular expressions. Default is "*" wildcards 349 only. 350 -D, --debug print BPF program before starting (for debugging 351 purposes) 352 353 examples: 354 ./funccount 'vfs_*' # count kernel fns starting with "vfs" 355 ./funccount -r '^vfs.*' # same as above, using regular expressions 356 ./funccount -Ti 5 'vfs_*' # output every 5 seconds, with timestamps 357 ./funccount -d 10 'vfs_*' # trace for 10 seconds only 358 ./funccount -p 185 'vfs_*' # count vfs calls for PID 181 only 359 ./funccount t:sched:sched_fork # count calls to the sched_fork tracepoint 360 ./funccount -p 185 u:node:gc* # count all GC USDT probes in node, PID 185 361 ./funccount c:malloc # count all malloc() calls in libc 362 ./funccount go:os.* # count all "os.*" calls in libgo 363 ./funccount -p 185 go:os.* # count all "os.*" calls in libgo, PID 185 364 ./funccount ./test:read* # count "read*" calls in the ./test binary 365