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