Ce document compare les performances d'eBPF par rapport aux méthodes traditionnelles de surveillance système, en s'appuyant sur des données empiriques pour démontrer les différences.
En général, eBPF offre des gains de performance significatifs dans la majorité des cas d'utilisation, bien qu'il ne soit pas universellement adapté à toutes les situations.
En juin 2024, une évaluation a été menée pour déterminer la viabilité d'eBPF en environnement de production. Les scénarios de test suivants ont été examinés :
- Suivi des appels système
- Surveillance des paquets réseau
- Surveillance des accès aux fichiers
- Suivi du cycle de vie des processus
Les approches comparées étaient :
- eBPF
- strace
- auditd
- inotify
- tcpdump
Configuraton du laboratoire de test
Matériel
- CPU : Intel Xeon E5-2680 v4 (28 cœurs)
- Mémoire vive : 64 Go
- Carte réseau : 10 Gbps
Logiciel
- Système d'exploitation : Ubuntu 22.04
- Noyau : 5.15.0-60-generic
- Compilateur Clang : 12.0.0
- Bibliothèque libbpf : 0.8.0
Méthodologie de test
Métriques de performance
- Utilisation du processeur
- Consommation de mémoire
- Latence
- Débit
- Précision
Outils d'analyse
perf: pour l'analyse CPU et mémoireab: pour les tests de chargewrk: pour les tests de charge réseautime: pour mesurer la latence
Trajet technique : Analyse par scénario
Scénario 1 : Suivi des appels système
Solution eBPF
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
struct syscall_event_data {
__u32 process_id;
char process_name[16];
__u64 syscall_number;
__u64 event_timestamp;
};
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 1 << 24);
} syscall_events SEC(".maps");
SEC("tracepoint/raw_syscalls/sys_enter")
int trace_syscall_entry(struct trace_event_raw_sys_enter *ctx)
{
struct syscall_event_data *event_data;
event_data = bpf_ringbuf_reserve(&syscall_events, sizeof(*event_data), 0);
if (!event_data) {
return 0;
}
event_data->process_id = bpf_get_current_pid_tgid() >> 32;
bpf_get_current_comm(event_data->process_name, sizeof(event_data->process_name));
event_data->syscall_number = ctx->id;
event_data->event_timestamp = bpf_ktime_get_ns();
bpf_ringbuf_submit(event_data, 0);
return 0;
}
char _license[] SEC("license") = "GPL";
Solution strace
strace -c -f -p $(pidof nginx)
Solution auditd
auditctl -a exit,always -F arch=b64 -S all
Résultats du test
| Indicateur | eBPF | strace | auditd |
|---|---|---|---|
| Utilisation CPU | 2% | 25% | 8% |
| Consommation mémoire | 50 Mo | 200 Mo | 100 Mo |
| Latence | 5 µs | 100 µs | 50 µs |
| Débit | 200 K/s | 20 K/s | 80 K/s |
| Précision | 100% | 100% | 100% |
Conclusion du scénario 1
eBPF se révèle la solution la plus performante pour le suivi des appels système :
- L'utilisatino CPU est 12 fois inférieure à celle de
strace. - La consommation mémoire est 4 fois moindre que celle de
strace. - La latence est 20 fois plus faible qu'avec
strace. - Le débit est 10 fois supérieur à celui de
strace.
Scénario 2 : Surveillance des paquets réseau
Solution eBPF (XDP)
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/udp.h>
struct network_packet_info {
__u32 source_ip;
__u32 destination_ip;
__u16 source_port;
__u16 destination_port;
__u64 capture_timestamp;
};
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF)