1#!/usr/bin/python 2# 3# gethostlatency Show latency for getaddrinfo/gethostbyname[2] calls. 4# For Linux, uses BCC, eBPF. Embedded C. 5# 6# This can be useful for identifying DNS latency, by identifying which 7# remote host name lookups were slow, and by how much. 8# 9# This uses dynamic tracing of user-level functions and registers, and may 10# need modifications to match your software and processor architecture. 11# 12# Copyright 2016 Netflix, Inc. 13# Licensed under the Apache License, Version 2.0 (the "License") 14# 15# 28-Jan-2016 Brendan Gregg Created this. 16 17from __future__ import print_function 18from bcc import BPF 19from time import strftime 20 21# load BPF program 22bpf_text = """ 23#include <uapi/linux/ptrace.h> 24 25struct val_t { 26 char host[80]; 27 u64 ts; 28}; 29BPF_HASH(start, u32, struct val_t); 30 31int do_entry(struct pt_regs *ctx) { 32 if (!ctx->di) 33 return 0; 34 struct val_t val = {}; 35 u32 pid = bpf_get_current_pid_tgid(); 36 bpf_probe_read(&val.host, sizeof(val.host), (void *)ctx->di); 37 val.ts = bpf_ktime_get_ns(); 38 start.update(&pid, &val); 39 return 0; 40} 41 42int do_return(struct pt_regs *ctx) { 43 struct val_t *valp; 44 u64 delta; 45 u32 pid = bpf_get_current_pid_tgid(); 46 47 valp = start.lookup(&pid); 48 if (valp == 0) 49 return 0; // missed start 50 51 delta = (bpf_ktime_get_ns() - valp->ts) / 1000; 52 bpf_trace_printk("%d %s\\n", delta, valp->host); 53 start.delete(&pid); 54 return 0; 55} 56""" 57b = BPF(text=bpf_text) 58b.attach_uprobe(name="c", sym="getaddrinfo", fn_name="do_entry") 59b.attach_uprobe(name="c", sym="gethostbyname", fn_name="do_entry") 60b.attach_uprobe(name="c", sym="gethostbyname2", fn_name="do_entry") 61b.attach_uretprobe(name="c", sym="getaddrinfo", fn_name="do_return") 62b.attach_uretprobe(name="c", sym="gethostbyname", fn_name="do_return") 63b.attach_uretprobe(name="c", sym="gethostbyname2", fn_name="do_return") 64 65# header 66print("%-9s %-6s %-12s %6s %s" % ("TIME", "PID", "COMM", "LATms", "HOST")) 67 68# format output 69while 1: 70 try: 71 (task, pid, cpu, flags, ts, msg) = b.trace_fields() 72 except ValueError: 73 continue 74 (delta, host) = msg.split(" ") 75 deltams = int(delta) / 1000 76 print("%-9s %-6d %-12.12s %6.2f %s" % (strftime("%H:%M:%S"), pid, task, 77 deltams, host)) 78