| #!/usr/bin/env bcc-lua |
| --[[ |
| Copyright 2016 Marek Vavrusa <mvavrusa@cloudflare.com> |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| ]] |
| -- This example program measures latency of block device operations and plots it |
| -- in a histogram. It is similar to BPF example: |
| -- https://github.com/torvalds/linux/blob/master/samples/bpf/tracex3_kern.c |
| local ffi = require('ffi') |
| local bpf = require('bpf') |
| local S = require('syscall') |
| |
| -- Shared part of the program |
| local bins = 100 |
| local map = bpf.map('hash', 512, ffi.typeof('uint64_t'), ffi.typeof('uint64_t')) |
| local lat_map = bpf.map('array', bins) |
| |
| -- Kernel-space part of the program |
| local trace_start = bpf.kprobe('myprobe:blk_start_request', function (ptregs) |
| map[ptregs.parm1] = time() |
| end, false, -1, 0) |
| local trace_end = bpf.kprobe('myprobe2:blk_account_io_completion', function (ptregs) |
| -- The lines below are computing index |
| -- using log10(x)*10 = log2(x)*10/log2(10) = log2(x)*3 |
| -- index = 29 ~ 1 usec |
| -- index = 59 ~ 1 msec |
| -- index = 89 ~ 1 sec |
| -- index = 99 ~ 10sec or more |
| local delta = time() - map[ptregs.parm1] |
| local index = 3 * math.log2(delta) |
| if index >= bins then |
| index = bins-1 |
| end |
| xadd(lat_map[index], 1) |
| return true |
| end, false, -1, 0) |
| -- User-space part of the program |
| pcall(function() |
| local counter = 0 |
| local sym = {' ',' ','.','.','*','*','o','o','O','O','#','#'} |
| while true do |
| -- Print header once in a while |
| if counter % 50 == 0 then |
| print('|1us |10us |100us |1ms |10ms |100ms |1s |10s') |
| counter = 0 |
| end |
| counter = counter + 1 |
| -- Collect all events |
| local hist, events = {}, 0 |
| for i=29,bins-1 do |
| local v = tonumber(lat_map[i] or 0) |
| if v > 0 then |
| hist[i] = hist[i] or 0 + v |
| events = events + v |
| end |
| end |
| -- Print histogram symbols based on relative frequency |
| local s = '' |
| for i=29,bins-1 do |
| if hist[i] then |
| local c = math.ceil((hist[i] / (events + 1)) * #sym) |
| s = s .. sym[c] |
| else s = s .. ' ' end |
| end |
| print(s .. string.format(' ; %d events', events)) |
| S.sleep(1) |
| end |
| end) |