#!/usr/bin/env bcc-lua --[[ Copyright 2016 Marek Vavrusa 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)