1#!/usr/bin/env bcc-lua 2--[[ 3Copyright 2016 Marek Vavrusa <mvavrusa@cloudflare.com> 4 5Licensed under the Apache License, Version 2.0 (the "License"); 6you may not use this file except in compliance with the License. 7You may obtain a copy of the License at 8 9http://www.apache.org/licenses/LICENSE-2.0 10 11Unless required by applicable law or agreed to in writing, software 12distributed under the License is distributed on an "AS IS" BASIS, 13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14See the License for the specific language governing permissions and 15limitations under the License. 16]] 17-- This example program measures latency of block device operations and plots it 18-- in a histogram. It is similar to BPF example: 19-- https://github.com/torvalds/linux/blob/master/samples/bpf/tracex3_kern.c 20local ffi = require('ffi') 21local bpf = require('bpf') 22local S = require('syscall') 23 24-- Shared part of the program 25local bins = 100 26local map = bpf.map('hash', 512, ffi.typeof('uint64_t'), ffi.typeof('uint64_t')) 27local lat_map = bpf.map('array', bins) 28 29-- Kernel-space part of the program 30local trace_start = bpf.kprobe('myprobe:blk_start_request', function (ptregs) 31 map[ptregs.parm1] = time() 32end, false, -1, 0) 33local trace_end = bpf.kprobe('myprobe2:blk_account_io_completion', function (ptregs) 34 -- The lines below are computing index 35 -- using log10(x)*10 = log2(x)*10/log2(10) = log2(x)*3 36 -- index = 29 ~ 1 usec 37 -- index = 59 ~ 1 msec 38 -- index = 89 ~ 1 sec 39 -- index = 99 ~ 10sec or more 40 local delta = time() - map[ptregs.parm1] 41 local index = 3 * math.log2(delta) 42 if index >= bins then 43 index = bins-1 44 end 45 xadd(lat_map[index], 1) 46 return true 47end, false, -1, 0) 48-- User-space part of the program 49pcall(function() 50 local counter = 0 51 local sym = {' ',' ','.','.','*','*','o','o','O','O','#','#'} 52 while true do 53 -- Print header once in a while 54 if counter % 50 == 0 then 55 print('|1us |10us |100us |1ms |10ms |100ms |1s |10s') 56 counter = 0 57 end 58 counter = counter + 1 59 -- Collect all events 60 local hist, events = {}, 0 61 for i=29,bins-1 do 62 local v = tonumber(lat_map[i] or 0) 63 if v > 0 then 64 hist[i] = hist[i] or 0 + v 65 events = events + v 66 end 67 end 68 -- Print histogram symbols based on relative frequency 69 local s = '' 70 for i=29,bins-1 do 71 if hist[i] then 72 local c = math.ceil((hist[i] / (events + 1)) * #sym) 73 s = s .. sym[c] 74 else s = s .. ' ' end 75 end 76 print(s .. string.format(' ; %d events', events)) 77 S.sleep(1) 78 end 79end)