Orchestration

eBPF Tracing: Custom Kernel Metrics with bpftrace

September 2, 2026 Kubezilla Team 11 min read

eBPF Tracing: Custom Kernel Metrics with bpftrace in Kubernetes

The world of Kubernetes is dynamic, complex, and often a black box when it comes to understanding deep-seated performance issues. Traditional monitoring tools provide excellent insights into application-level metrics, CPU, memory, and network I/O, but they often fall short when you need to peer into the kernel’s inner workings. What if you could get granular, custom metrics directly from the Linux kernel, without modifying your applications or even restarting pods?

Enter eBPF (extended Berkeley Packet Filter) and its powerful frontend, bpftrace. eBPF allows you to run sandboxed programs in the Linux kernel without changing kernel source code or loading kernel modules. This capability unlocks unparalleled observability, security, and networking superpowers. When combined with bpftrace, a high-level tracing language, you can write concise scripts to extract virtually any kernel event, measure latency, count system calls, and even inspect data structures, providing a level of detail previously unattainable. In a Kubernetes environment, this translates to diagnosing elusive performance bottlenecks, understanding resource contention at a fundamental level, and building truly custom metrics that reflect your specific workload’s behavior.

This comprehensive guide will walk you through setting up and utilizing bpftrace in a Kubernetes cluster to extract custom kernel metrics. We’ll cover everything from the basics of eBPF and bpftrace to deploying a DaemonSet for cluster-wide tracing, collecting bespoke data, and integrating it into your observability stack. Prepare to unlock a new dimension of insight into your Kubernetes nodes and workloads.

TL;DR: Custom Kernel Metrics with bpftrace

Dive deep into Kubernetes node performance by using bpftrace for custom kernel-level metrics. Deploy bpftrace as a privileged DaemonSet to access kernel tracepoints and kprobes, then write simple scripts to gather specific data, like syscall counts or latency, directly from your nodes. Integrate these insights into your observability stack to diagnose elusive bottlenecks.

Key Commands:

# Deploy bpftrace as a privileged DaemonSet
kubectl apply -f https://raw.githubusercontent.com/kubezilla-io/tutorials/main/bpftrace-daemonset.yaml

# Access bpftrace on a node (replace  and )
kubectl debug node/ -it --image=quay.io/iovisor/bpftrace:v0.19.0 -- bash

# Run a simple bpftrace script (e.g., list syscalls)
bpftrace -e 'tracepoint:syscalls:sys_enter_* { @[comm] = count(); }'

# Get help on bpftrace probes
bpftrace -l 'tracepoint:syscalls:*'

# Clean up the DaemonSet
kubectl delete -f https://raw.githubusercontent.com/kubezilla-io/tutorials/main/bpftrace-daemonset.yaml

Prerequisites

Before embarking on your eBPF tracing journey with bpftrace, ensure you have the following:

* **A Kubernetes Cluster**: Any flavor (minikube, Kind, GKE, EKS, AKS, etc.) will work, but ensure you have `kubectl` configured and administrative access.
* **Linux Kernel Version**: eBPF capabilities, especially for bpftrace, require a modern Linux kernel. Version 4.9+ is generally sufficient, but 5.x+ offers more features and stability. You can check your node’s kernel version with `uname -r`.
* **`kubectl`**: The command-line tool for interacting with your Kubernetes cluster.
* **Basic Understanding of Kubernetes Concepts**: Pods, Deployments, DaemonSets, RBAC.
* **Basic Understanding of Linux System Calls and Kernel Concepts**: While not strictly necessary to *use* bpftrace, it will greatly aid in understanding *what* you are tracing and *why*.
* **bpftrace Familiarity (Optional but Recommended)**: If you’re new to bpftrace, a quick read of its official documentation can be beneficial.

Step-by-Step Guide: eBPF Tracing with bpftrace in Kubernetes

This guide will walk you through deploying bpftrace as a privileged DaemonSet, interacting with it, and writing custom scripts to gather kernel metrics.

Step 1: Understand eBPF and bpftrace

Before we deploy anything, let’s briefly recap what eBPF and bpftrace are and why they’re so revolutionary for observability.

eBPF is a powerful, in-kernel virtual machine that allows developers to run sandboxed programs in the Linux kernel. These programs can be attached to various points (e.g., system calls, network events, kernel functions) and execute custom logic without requiring kernel recompilation or loading insecure kernel modules. This provides unprecedented visibility and control over kernel operations. For instance, projects like Cilium heavily leverage eBPF for high-performance networking and security, and eBPF Observability with Hubble demonstrates its use for collecting network metrics.

bpftrace is a high-level tracing language and frontend for eBPF. It simplifies the process of writing eBPF programs, allowing you to quickly develop scripts to trace kernel events, measure latencies, count occurrences, and more, using a syntax inspired by awk and C. It compiles your scripts into eBPF bytecode, loads them into the kernel, and then processes the output. This makes it an ideal tool for ad-hoc troubleshooting and custom metric generation in dynamic environments like Kubernetes.

Step 2: Deploy bpftrace as a Privileged DaemonSet

To trace kernel events on your Kubernetes nodes, bpftrace needs privileged access to the host’s kernel. The most effective way to deploy it across all (or specific) nodes in your cluster is as a DaemonSet. This ensures that a bpftrace pod runs on every eligible node, allowing you to connect to it and run tracing scripts directly on the host.

We’ll use a `DaemonSet` that runs the `quay.io/iovisor/bpftrace` image. This image comes pre-packaged with `bpftrace` and all its dependencies. The key aspects of this DaemonSet are:
* `hostPID: true`: Allows the pod to see the PIDs from the host’s PID namespace.
* `privileged: true`: Grants the pod all capabilities, necessary for eBPF operations.
* `hostNetwork: true`: Allows the pod to use the host’s network namespace (optional for tracing, but good for general debugging).
* `volumeMounts` for `/sys` and `/proc`: Provides access to kernel interfaces required by bpftrace.

Create a file named `bpftrace-daemonset.yaml` with the following content:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: bpftrace
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: bpftrace
rules:
- apiGroups: [""]
  resources: ["nodes", "pods"]
  verbs: ["get", "list", "watch"] # Needed for kubectl debug to find nodes/pods
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: bpftrace
subjects:
- kind: ServiceAccount
  name: bpftrace
  namespace: kube-system
roleRef:
  kind: ClusterRole
  name: bpftrace
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: bpftrace
  namespace: kube-system
  labels:
    app: bpftrace
spec:
  selector:
    matchLabels:
      app: bpftrace
  template:
    metadata:
      labels:
        app: bpftrace
    spec:
      hostPID: true
      hostNetwork: true # Optional, but can be useful for network tracing
      privileged: true
      serviceAccountName: bpftrace # Use the created ServiceAccount
      containers:
      - name: bpftrace
        image: quay.io/iovisor/bpftrace:v0.19.0 # Use a specific, stable version
        imagePullPolicy: IfNotPresent
        command: ["sleep", "infinity"] # Keep the container running
        securityContext:
          privileged: true
        volumeMounts:
        - name: host-sys
          mountPath: /sys
          readOnly: true
        - name: host-proc
          mountPath: /proc
          readOnly: true
      volumes:
      - name: host-sys
        hostPath:
          path: /sys
      - name: host-proc
        hostPath:
          path: /proc

Now, apply this manifest to your cluster:

kubectl apply -f bpftrace-daemonset.yaml

This command creates a `ServiceAccount`, `ClusterRole`, `ClusterRoleBinding`, and a `DaemonSet` named `bpftrace` in the `kube-system` namespace. The `sleep infinity` command ensures the container stays alive, allowing you to `exec` into it later.

Verify

Check if the `bpftrace` pods are running on your nodes. You should see one pod per node (or fewer if your `nodeSelector` restricts deployment).

kubectl get pods -n kube-system -l app=bpftrace

Expected output (will vary based on your node count):

NAME             READY   STATUS    RESTARTS   AGE
bpftrace-abcde   1/1     Running   0          2m
bpftrace-fghij   1/1     Running   0          2m

Step 3: Connect to a bpftrace Pod and Run Basic Traces

With the `bpftrace` DaemonSet running, you can now connect to any of the pods and execute `bpftrace` commands directly on the host’s kernel. This is typically done using `kubectl exec` or `kubectl debug`. We’ll use `kubectl debug` as it’s often more convenient for host-level debugging.

First, identify a node you want to trace.

kubectl get nodes

Then, use `kubectl debug` to get a shell into the `bpftrace` container on that specific node. Replace `` with the actual name of your node.

kubectl debug node/ -it --image=quay.io/iovisor/bpftrace:v0.19.0 -- bash

This command starts a temporary `debug` pod on the target node, mounts the host’s root filesystem, and gives you a shell. You’ll be in a shell where `bpftrace` is available and has the necessary permissions.

Once inside the shell, you can start running bpftrace scripts. Let’s try a simple one: counting system calls globally.

bpftrace -e 'tracepoint:syscalls:sys_enter_* { @syscalls = count(); }'

This script attaches to every `sys_enter` tracepoint (i.e., every system call entry) and increments a counter named `@syscalls`. Press `Ctrl+C` to stop the trace and see the final count.

Verify

You’ll see output continuously updating with the count, then a final summary when you press `Ctrl+C`.

Attaching 320 probes...
^C

@syscalls: 23681

This shows the total number of system calls observed during the tracing period. This is a very basic example, but it demonstrates bpftrace’s ability to tap into kernel events.

Step 4: Explore Available Probes

bpftrace can attach to various types of probes, including:
* `kprobe`/`kretprobe`: Kernel function entry/return points.
* `uprobe`/`uretprobe`: Userspace function entry/return points.
* `tracepoint`: Stable, well-defined points in the kernel code.
* `perf_event`: Hardware performance counters.
* `profile`: Time-based or event-based sampling.
* `BEGIN`/`END`: Script startup/shutdown.

Knowing which probes are available on your system is crucial for writing targeted scripts. You can list them using `bpftrace -l`.

Inside your `kubectl debug` shell, try listing some common tracepoints:

bpftrace -l 'tracepoint:syscalls:*'

This command lists all tracepoints related to system calls.

Verify

You’ll see a long list of system call entry and exit points.

tracepoint:syscalls:sys_enter_accept
tracepoint:syscalls:sys_enter_accept4
tracepoint:syscalls:sys_enter_access
tracepoint:syscalls:sys_enter_acct
...
tracepoint:syscalls:sys_exit_write
tracepoint:syscalls:sys_exit_writev

You can also list kernel functions (kprobes) by using `kprobe:*`. Be aware that there are *many* kernel functions, so you might want to filter aggressively (e.g., `kprobe:do_sys_open*`).

bpftrace -l 'kprobe:do_sys_open*'

Expected output:

kprobe:do_sys_open
kprobe:do_sys_openat2

Understanding these probes is the first step to crafting powerful custom metrics. For more in-depth exploration of kernel events, tools like `perf` can also be useful, but `bpftrace` offers a more scriptable and high-level interface.

Step 5: Write Custom bpftrace Scripts for Kubernetes Metrics

Now, let’s write some practical bpftrace scripts to gather custom metrics relevant to a Kubernetes environment. We’ll focus on common pain points: file I/O, network connections, and CPU usage.

To run these, ensure you are still in the `kubectl debug` shell on your target node.

Example 1: Top File Opens by Process

This script will show which processes are opening the most files on the node, which can indicate excessive I/O or misconfigured applications.

bpftrace -e 'tracepoint:syscalls:sys_enter_openat { @[comm] = count(); }'

Let it run for a bit (e.g., 10-30 seconds), then press `Ctrl+C`.

Verify

You’ll see a breakdown of processes and their openat syscall counts.

Attaching 1 probe...
^C

@[kubelet]: 120
@[containerd]: 85
@[dockerd]: 60
@[systemd]: 30
@[kube-proxy]: 15
@[bash]: 5

This output immediately highlights which components are most active in file operations. For example, a high count for `kubelet` might indicate frequent configuration reloads or volume operations.

Example 2: Network Connection Latency (TCP `connect`)

Measuring the latency of TCP connection attempts can reveal network issues or slow external services. This script traces the `connect` syscall.

bpftrace -e 'tracepoint:syscalls:sys_enter_connect { @start[tid] = nsecs; } tracepoint:syscalls:sys_exit_connect /@start[tid]/ { @latency = hist((nsecs - @start[tid]) / 1000); delete(@start[tid]); }'

Let it run, then `Ctrl+C`. This script records the timestamp when `connect` is entered and calculates the duration when it exits, then stores the latency in a histogram.

Verify

You’ll see a histogram of connection latencies in microseconds.

Attaching 2 probes...
^C

@latency:
[0, 1)                0
[1, 2)                0
[2, 4)                0
[4, 8)                0
[8, 16)               0
[16, 32)              0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[32, 64)              0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[64, 128)             0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[128, 256)            0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[256, 512)            0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[512, 1K)             0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[1K, 2K)              0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[2K, 4K)              0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[4K, 8K)              0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[8K, 16K)             0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[16K, 32K)            0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[32K, 64K)            0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[64K, 128K)           0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[128K, 256K)          0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[256K, 512K)          0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[512K, 1M)            0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[1M, 2M)              0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[2M, 4M)              0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[4M, 8M)              0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[8M, 16M)             0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[16M, 32M)            0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[32M, 64M)            0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[64M, 128M)           0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[128M, 256M)          0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[256M, 512M)          0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[512M, 1G)            0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[1G, 2G)              0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[2G, 4G)              0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[4G, 8G)              0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[8G, 16G)             0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[16G, 32G)            0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[32G, 64G)            0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[64G, 128G)           0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[128G, 256G)          0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[256G, 512G)          0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[512G, 1T)            0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[1T, 2T)              0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[2T, 4T)              0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[4T, 8T)              0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[8T, 16T)             0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[16T, 32T)            0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[32T, 64T)            0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[64T, 128T)           0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[128T, 256T)          0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[256T, 512T)          0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[512T, 1P)            0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[1P, 2P)              0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[2P, 4P)              0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[4P, 8P)              0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[8P, 16P)             0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[16P, 32P)            0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[32P, 64P)            0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[64P, 128P)           0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[128P, 256P)          0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[256P, 512P)          0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[512P, 1E)            0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|

*Note: The histogram output will depend heavily on the network activity during the trace. The example above shows a blank histogram, which is common if no connections were made during the short trace. In a busy system, you’d see bars.*

This can be incredibly useful for diagnosing issues with services trying to establish connections, whether to other pods, external databases, or APIs. For more advanced network monitoring in Kubernetes, consider solutions like Kubernetes Network Policies or even service meshes like Istio Ambient Mesh.

Example 3: CPU Run Queue Latency

When processes are ready to run but have to wait for a CPU, it indicates CPU contention. This script measures how long processes wait in the run queue.

bpftrace -e 'kprobe:finish_task_switch { @latencies = hist(nsecs - @start[tid]); } kprobe:__schedule { @start[tid] = nsecs; }'

This script attaches to `finish_task_switch` (when a process finishes switching) and `__schedule` (when the scheduler is invoked). It calculates the time between a process being scheduled out and being scheduled back in. Let it run for a while, then `Ctrl+C`.

Verify

You’ll get a histogram of CPU run queue latencies (in nanoseconds).

Attaching 2 probes...
^C

@latencies:
[0, 1) 0
[1, 2) 0
[2, 4) 0
[4, 8) 0
[8, 16) 0
[16, 32) 0
[32, 64) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[64, 128) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[128, 256) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[256, 512) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[512, 1K) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[1K, 2K) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[2K, 4K) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[4K, 8K) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[8K, 16K) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[16K, 32K) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[32K, 64K) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[64K, 128K) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[128K, 256K) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[256K, 512K) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[512K, 1M) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[1M, 2M) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[2M, 4M) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[4M, 8M) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[8M, 16M) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[16M, 32M) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[32M, 64M) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[64M, 128M) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[128M, 256M) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[256M, 512M) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[512M, 1G) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[1G, 2G) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[2G, 4G) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[4G, 8G) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[8G, 16G) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[16G, 32G) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[32G, 64G) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[64G, 128G) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[128G, 256G) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[256G, 512G) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[512G, 1T) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[1T, 2T) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[2T, 4T) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[4T, 8T) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[8T, 16T) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[16T, 32T) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[32T, 64T) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[64T, 128T) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[128T, 256T) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[256T, 512T) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[512T, 1P) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[1P, 2P) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[2P, 4P) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[4P, 8P) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[8P, 16P) 0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Leave a comment