mirror of
https://github.com/varun-r-mallya/Python-BPF.git
synced 2025-12-31 21:06:25 +00:00
253 lines
54 KiB
Plaintext
253 lines
54 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "9d1a31e8-35d7-4ee6-8c90-f3715eaa2501",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from pythonbpf import bpf, map, struct, section, bpfglobal, BPF\n",
|
|
"from pythonbpf.helper import ktime, pid\n",
|
|
"from pythonbpf.maps import HashMap, PerfEventArray\n",
|
|
"from ctypes import c_void_p, c_uint64\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"import numpy as np"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "b0198957-42a3-4e1b-89ba-f08d3b9d3736",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Loading BPF program...\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"{'do_entry': <pylibbpf.pylibbpf.BpfProgram at 0xffff7c9e2c70>,\n",
|
|
" 'do_return': <pylibbpf.pylibbpf.BpfProgram at 0xffff7c6bb330>}"
|
|
]
|
|
},
|
|
"execution_count": 2,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"@bpf\n",
|
|
"@struct\n",
|
|
"class latency_event:\n",
|
|
" pid: c_uint64\n",
|
|
" delta_us: c_uint64 # Latency in microseconds\n",
|
|
"\n",
|
|
"\n",
|
|
"@bpf\n",
|
|
"@map\n",
|
|
"def start() -> HashMap:\n",
|
|
" return HashMap(key=c_uint64, value=c_uint64, max_entries=10240)\n",
|
|
"\n",
|
|
"\n",
|
|
"@bpf\n",
|
|
"@map\n",
|
|
"def events() -> PerfEventArray:\n",
|
|
" return PerfEventArray(key_size=c_uint64, value_size=c_uint64)\n",
|
|
"\n",
|
|
"\n",
|
|
"@bpf\n",
|
|
"@section(\"kprobe/vfs_read\")\n",
|
|
"def do_entry(ctx: c_void_p) -> c_uint64:\n",
|
|
" p, ts = pid(), ktime()\n",
|
|
" start.update(p, ts)\n",
|
|
" return 0\n",
|
|
"\n",
|
|
"\n",
|
|
"@bpf\n",
|
|
"@section(\"kretprobe/vfs_read\")\n",
|
|
"def do_return(ctx: c_void_p) -> c_uint64:\n",
|
|
" p = pid()\n",
|
|
" tsp = start.lookup(p)\n",
|
|
"\n",
|
|
" if tsp:\n",
|
|
" delta_ns = ktime() - tsp\n",
|
|
"\n",
|
|
" # Only track if latency > 1 microsecond\n",
|
|
" if delta_ns > 1000:\n",
|
|
" evt = latency_event()\n",
|
|
" evt.pid, evt.delta_us = p, delta_ns // 1000\n",
|
|
" events.output(evt)\n",
|
|
"\n",
|
|
" start.delete(p)\n",
|
|
"\n",
|
|
" return 0 # type: ignore [return-value]\n",
|
|
"\n",
|
|
"\n",
|
|
"@bpf\n",
|
|
"@bpfglobal\n",
|
|
"def LICENSE() -> str:\n",
|
|
" return \"GPL\"\n",
|
|
"\n",
|
|
"\n",
|
|
"# Load BPF\n",
|
|
"print(\"Loading BPF program...\")\n",
|
|
"b = BPF()\n",
|
|
"b.load()\n",
|
|
"b.attach_all()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "d84bba81-2923-4244-ad86-98925b9cc7d9",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Tracing vfs_read latency... Hit Ctrl-C to end.\n",
|
|
"Collected 1000 samples...\n",
|
|
"Collected 2000 samples...\n",
|
|
"Collected 3000 samples...\n",
|
|
"Collected 4000 samples...\n",
|
|
"Collected 5000 samples...\n",
|
|
"Collected 6000 samples...\n",
|
|
"Collected 6050 samples. Generating histogram...\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Collect latencies\n",
|
|
"latencies = []\n",
|
|
"\n",
|
|
"\n",
|
|
"def callback(cpu, event):\n",
|
|
" latencies.append(event.delta_us)\n",
|
|
"\n",
|
|
"\n",
|
|
"b[\"events\"].open_perf_buffer(callback, struct_name=\"latency_event\")\n",
|
|
"\n",
|
|
"print(\"Tracing vfs_read latency... Hit Ctrl-C to end.\")\n",
|
|
"\n",
|
|
"try:\n",
|
|
" while True:\n",
|
|
" b[\"events\"].poll(1000)\n",
|
|
" if len(latencies) > 0 and len(latencies) % 1000 == 0:\n",
|
|
" print(f\"Collected {len(latencies)} samples...\")\n",
|
|
"\n",
|
|
"except KeyboardInterrupt:\n",
|
|
" print(f\"Collected {len(latencies)} samples. Generating histogram...\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "939ffdc8-1806-4e6c-84ce-be109681178c",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Statistics:\n",
|
|
" Count: 6050\n",
|
|
" Min: 1 µs\n",
|
|
" Max: 1086 µs\n",
|
|
" Mean: 9.80 µs\n",
|
|
" Median: 3.00 µs\n",
|
|
" P95: 47.00 µs\n",
|
|
" P99: 158.00 µs\n",
|
|
"Histogram saved to vfs_read_latency.png\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAABKUAAAJOCAYAAABm7rQwAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjcsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvTLEjVAAAAAlwSFlzAAAPYQAAD2EBqD+naQAAjO9JREFUeJzs3Xl4FFXe/v+7s0PIQiCrhBAQ2QRBUMioCIIJGHGBZ+ZBEVBRlAk4EEd5UETAURRHcEPQUcBRcGG+igoMEEBAJChEI5sygGwiWQCTToAspOv3B7/02KRDQuiuJJ3367r6uuiq01XnfBLg5M6pKothGIYAAAAAAAAAE3nVdgcAAAAAAADQ8BBKAQAAAAAAwHSEUgAAAAAAADAdoRQAAAAAAABMRygFAAAAAAAA0xFKAQAAAAAAwHSEUgAAAAAAADAdoRQAAAAAAABMRygFAAAAAAAA0xFKAR6mVatWuvfee2u7Gw3K+vXrZbFYtH79erefa+rUqbJYLA7bLBaLxo4d6/ZzS9LChQtlsVh08OBBU853vsLCQkVERGjRokUX9Tkzv0aXorS0VLGxsXrjjTdquysAgP8fcyvzMbcyT03nVrVp5cqVatKkiXJzc2u7K3ABQinUC7fddpsaN26sgoKCStsMGzZMfn5+OnHihKRz/5k4e0VFRdk/Y7PZ9M9//lM9e/ZUWFiYgoKCdMUVV2jEiBHasmVLlf06/9jBwcG68cYbtXz58ksftJu58j/bxYsX6+WXX3bJsWrbwYMHHb6mvr6+at68uf7whz/oiSee0OHDh112rueee05Lly512fFcqa727ZVXXlFQUJCGDh1q31Y+mTx+/Hgt9sw1fH19lZqaqmeffVZFRUW13R0AHoy5lesxt3KOudU5dbVvdWVudfr0ac2ZM0eJiYmKjo5WUFCQunXrprlz56qsrMyh7YABA3T55ZdrxowZpvUP7kMohXph2LBhOnPmjD799FOn+0+fPq3PPvtMAwYMULNmzezbb775Zr333nsOrzlz5tj3P/LIIxo5cqSio6M1depUvfDCCxo4cKC2bNmilStXVqtv5ef45z//qccff1z79u3ToEGDtGrVqksbdD3iSROncnfddZfee+89vfPOO3rqqafUunVrvfzyy+rQoYM+/PBDh7a9e/fWmTNn1Lt374s6R00mJ5MnT9aZM2cu6jM1UVnfhg8frjNnziguLs7tfThfaWmpXnnlFT3wwAPy9va+qM/W9GtUG+677z4dP35cixcvru2uAPBgzK3qNuZWzK3McClzK1f7+eefNW7cOBmGodTUVP39739XfHy8/vznP+v++++v0P6hhx7Sm2++ecFgHfWDT213AKiO2267TUFBQVq8eLFGjBhRYf9nn32mU6dOadiwYQ7br7jiCt1zzz1Oj5mdna033nhDDz74oN566y2HfS+//HK1l4Oef44hQ4aoY8eOeuWVV5SUlFStY6Duufrqqyt87xw6dEiJiYkaOXKkOnTooKuuukqS5OXlpYCAALf259SpUwoMDJSPj498fGrvn25vb+9am7QsW7ZMubm5+tOf/nTRnzXja3QpDMNQUVGRGjVqpNDQUCUmJmrhwoVOJ2EA4ArMrWA25lbO1de5latFRUVpx44d6tSpk33bQw89pPvvv18LFizQU089pcsvv9y+b8iQIRo3bpyWLFnCfKmeY6UU6oVGjRpp8ODBWrt2rXJycirsX7x4sYKCgnTbbbdV+5gHDhyQYRi67rrrKuyzWCyKiIioUV87dOig5s2ba//+/Q7bi4uL9fTTT+vyyy+Xv7+/YmNj9fjjj6u4uNih3YIFC3TTTTcpIiJC/v7+6tixo+bOnVvhPIZh6G9/+5tatGihxo0bq2/fvtq1a1eN+lyZzz77TMnJyYqJiZG/v7/atGmjZ555xmEJbZ8+fbR8+XIdOnTIviy7VatWFz3u8iXvS5cu1ZVXXil/f3916tTJ6W9Vjx49qlGjRtn7FR8frzFjxqikpEQ///yzLBaLZs+eXeFzmzdvlsVi0QcffFCjesTFxWnhwoUqKSnRzJkz7dud3fdg7969GjJkiKKiohQQEKAWLVpo6NChys/Pt4/31KlTevfdd+11K79fRfmS6d27d+vuu+9W06ZNdf311zvsc2bRokVq166dAgIC1L17d23cuNFh/7333uvwtSl3/jEv1LfK7nvwxhtvqFOnTvL391dMTIxSUlKUl5fn0KZPnz668sortXv3bvXt21eNGzfWZZdd5lDLC1m6dKlatWqlNm3aVKv97zn7Gl1Mf1z997dVq1a69dZbtWrVKvXo0UONGjXSm2++ad9/8803a9OmTTp58uRFjxUAqoO5FXOr32NuxdyqJtatW6cbbrhBgYGBCg0N1e23364ff/yxQrv169erR48eCggIUJs2bfTmm29WqFHz5s0dAqlyd955pyRVOG5ERIS6dOmizz77rEZ9R93BSinUG8OGDdO7776rjz/+2OF6/ZMnT2rVqlW666671KhRI4fPFBUVVbgWOigoSP7+/vYlskuWLNEf//hHNW7c2CX9zM/P12+//ebwj7vNZtNtt92mTZs2afTo0erQoYN27Nih2bNn6z//+Y/DUt65c+eqU6dOuu222+Tj46MvvvhCf/7zn2Wz2ZSSkmJvN2XKFP3tb3/TLbfcoltuuUXfffedEhMTVVJS4pJxSOf+k2zSpIlSU1PVpEkTrVu3TlOmTJHVatWLL74oSXryySeVn5+vX375xT5ZadKkyUWPW5I2bdqkTz75RH/+858VFBSkV199VUOGDNHhw4ftlw78+uuvuvbaa5WXl6fRo0erffv2Onr0qP71r3/p9OnTat26ta677jotWrRIEyZMcDj+okWLFBQUpNtvv73GNUlISFCbNm2UlpZWaZuSkhIlJSWpuLhY48aNU1RUlI4ePaply5YpLy9PISEheu+99/TAAw/o2muv1ejRoyWpwoTgj3/8o9q2bavnnntOhmFcsF8bNmzQRx99pEceeUT+/v564403NGDAAH377be68sorL2qM1enb702dOlXTpk1T//79NWbMGO3Zs0dz587V1q1b9fXXX8vX19fe9rffftOAAQM0ePBg/elPf9K//vUvTZw4UZ07d9bAgQMv2K/Nmzfr6quvvqixVKU6/XHH319J2rNnj+666y499NBDevDBB9WuXTv7vu7du8swDG3evFm33nqrS8cMAOWYWzG3kphbVYa51YWtWbNGAwcOVOvWrTV16lSdOXNGr732mq677jp999139rDu+++/14ABAxQdHa1p06aprKxM06dPV3h4eLXOk5WVJelcaHW+7t2718n7dOEiGUA9cfbsWSM6OtpISEhw2D5v3jxDkrFq1SqH7ZKcvhYsWGBvM2LECEOS0bRpU+POO+80/v73vxs//vhjtfskyRg1apSRm5tr5OTkGNu2bTMGDBhgSDJefPFFe7v33nvP8PLyMr766iunff/666/t206fPl3hPElJSUbr1q3t73Nycgw/Pz8jOTnZsNls9u1PPPGEIckYOXJktfqekpJywTbO+vLQQw8ZjRs3NoqKiuzbkpOTjbi4uApt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",
|
|
"text/plain": [
|
|
"<Figure size 1200x600 with 2 Axes>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"# Create histogram with matplotlib\n",
|
|
"if latencies:\n",
|
|
" # Use log scale for better visualization\n",
|
|
" log_latencies = np.log2(latencies)\n",
|
|
"\n",
|
|
" plt.figure(figsize=(12, 6))\n",
|
|
"\n",
|
|
" # Plot 1: Linear histogram\n",
|
|
" plt.subplot(1, 2, 1)\n",
|
|
" plt.hist(latencies, bins=50, edgecolor=\"black\", alpha=0.7)\n",
|
|
" plt.xlabel(\"Latency (microseconds)\")\n",
|
|
" plt.ylabel(\"Count\")\n",
|
|
" plt.title(\"VFS Read Latency Distribution (Linear)\")\n",
|
|
" plt.grid(True, alpha=0.3)\n",
|
|
"\n",
|
|
" # Plot 2: Log2 histogram (like BCC)\n",
|
|
" plt.subplot(1, 2, 2)\n",
|
|
" plt.hist(log_latencies, bins=50, edgecolor=\"black\", alpha=0.7, color=\"orange\")\n",
|
|
" plt.xlabel(\"log2(Latency in µs)\")\n",
|
|
" plt.ylabel(\"Count\")\n",
|
|
" plt.title(\"VFS Read Latency Distribution (Log2)\")\n",
|
|
" plt.grid(True, alpha=0.3)\n",
|
|
"\n",
|
|
" # Add statistics\n",
|
|
" print(\"Statistics:\")\n",
|
|
" print(f\" Count: {len(latencies)}\")\n",
|
|
" print(f\" Min: {min(latencies)} µs\")\n",
|
|
" print(f\" Max: {max(latencies)} µs\")\n",
|
|
" print(f\" Mean: {np.mean(latencies):.2f} µs\")\n",
|
|
" print(f\" Median: {np.median(latencies):.2f} µs\")\n",
|
|
" print(f\" P95: {np.percentile(latencies, 95):.2f} µs\")\n",
|
|
" print(f\" P99: {np.percentile(latencies, 99):.2f} µs\")\n",
|
|
"\n",
|
|
" plt.tight_layout()\n",
|
|
" plt.savefig(\"vfs_read_latency.png\", dpi=150)\n",
|
|
" print(\"Histogram saved to vfs_read_latency.png\")\n",
|
|
" plt.show()\n",
|
|
"else:\n",
|
|
" print(\"No samples collected!\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "348abd5a-0d94-4cbc-866c-45455c2eb953",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3 (ipykernel)",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.13.3"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|