feat(profiling): Add CPU and MEM profiling

This commit is contained in:
2026-04-06 13:15:09 +01:00
parent 0dc77c4583
commit a2432e7aa6
17 changed files with 472 additions and 2741 deletions
+95
View File
@@ -0,0 +1,95 @@
package stats
import (
"encoding/csv"
"fmt"
"os"
"runtime"
"time"
)
type RuntimeStats struct {
TotalAlloc uint64
Mallocs uint64
NumGC uint32
AllocDelta uint64
MallocsDelta uint64
GCDelta uint32
}
type RuntimeCollector struct {
startStats runtime.MemStats
memPath string
}
func NewRuntimeCollector(memPath string) *RuntimeCollector {
var stats runtime.MemStats
runtime.ReadMemStats(&stats)
return &RuntimeCollector{
startStats: stats,
memPath: memPath,
}
}
func (rc *RuntimeCollector) Collect() RuntimeStats {
var current runtime.MemStats
runtime.ReadMemStats(&current)
return RuntimeStats{
TotalAlloc: current.TotalAlloc,
Mallocs: current.Mallocs,
NumGC: current.NumGC,
AllocDelta: current.TotalAlloc - rc.startStats.TotalAlloc,
MallocsDelta: current.Mallocs - rc.startStats.Mallocs,
GCDelta: current.NumGC - rc.startStats.NumGC,
}
}
func (rc *RuntimeCollector) WriteStats() error {
stats := rc.Collect()
timestamp := time.Now().Format(time.RFC3339Nano)
// Check if file exists
fileExists := false
if _, err := os.Stat(rc.memPath); err == nil {
fileExists = true
}
// Open in append mode
file, err := os.OpenFile(rc.memPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return fmt.Errorf("failed to open mem.csv: %w", err)
}
defer file.Close()
writer := csv.NewWriter(file)
// Write header if new file
if !fileExists {
header := []string{
"timestamp", "total_alloc_bytes", "mallocs", "gc_cycles",
"alloc_delta", "mallocs_delta", "gc_delta",
}
if err := writer.Write(header); err != nil {
return fmt.Errorf("failed to write mem.csv header: %w", err)
}
}
// Write data row
row := []string{
timestamp,
fmt.Sprintf("%d", stats.TotalAlloc),
fmt.Sprintf("%d", stats.Mallocs),
fmt.Sprintf("%d", stats.NumGC),
fmt.Sprintf("%d", stats.AllocDelta),
fmt.Sprintf("%d", stats.MallocsDelta),
fmt.Sprintf("%d", stats.GCDelta),
}
if err := writer.Write(row); err != nil {
return fmt.Errorf("failed to write mem.csv row: %w", err)
}
writer.Flush()
return writer.Error()
}
+87
View File
@@ -0,0 +1,87 @@
#!/bin/bash
# Exit on error
set -e
# Default values
NETNS_NAME="myapp"
VETH_HOST="veth0"
VETH_NS="veth1"
HOST_IP="192.168.100.1"
NS_IP="192.168.100.2"
SUBNET="192.168.100.0/24"
PHYSICAL_IF="eth0"
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
-n|--namespace)
NETNS_NAME="$2"
shift 2
;;
-p|--physical-if)
PHYSICAL_IF="$2"
shift 2
;;
--help)
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " -n, --namespace NAME Namespace name (default: myapp)"
echo " -p, --physical-if NAME Physical interface (default: eth0)"
echo " --help Show this help"
exit 0
;;
*)
echo "Unknown option: $1"
echo "Use --help for usage information"
exit 1
;;
esac
done
echo "Configuration:"
echo " Namespace: $NETNS_NAME"
echo " Physical interface: $PHYSICAL_IF"
echo ""
echo "Creating network namespace: $NETNS_NAME"
sudo ip netns add $NETNS_NAME
echo "Creating veth pair: $VETH_HOST <-> $VETH_NS"
sudo ip link add $VETH_HOST type veth peer name $VETH_NS
echo "Moving $VETH_NS into namespace"
sudo ip link set $VETH_NS netns $NETNS_NAME
echo "Configuring host side ($VETH_HOST)"
sudo ip addr add $HOST_IP/24 dev $VETH_HOST
sudo ip link set $VETH_HOST up
echo "Configuring namespace side ($VETH_NS)"
sudo ip netns exec $NETNS_NAME ip addr add $NS_IP/24 dev $VETH_NS
sudo ip netns exec $NETNS_NAME ip link set $VETH_NS up
sudo ip netns exec $NETNS_NAME ip link set lo up
sudo ip netns exec $NETNS_NAME ip route add default via $HOST_IP
echo "Enabling IP forwarding"
sudo sysctl -w net.ipv4.ip_forward=1
echo "Disabling IPv6"
sudo ip netns exec $NETNS_NAME sysctl -w net.ipv6.conf.all.disable_ipv6=1
echo "Setting up NAT"
sudo iptables -t nat -A POSTROUTING -s $SUBNET -o $PHYSICAL_IF -j MASQUERADE
echo "Setting up forwarding rules"
sudo iptables -I FORWARD -i $VETH_HOST -o $PHYSICAL_IF -j ACCEPT
sudo iptables -I FORWARD -i $PHYSICAL_IF -o $VETH_HOST -j ACCEPT
echo ""
echo "Done! Network namespace '$NETNS_NAME' is ready."
echo ""
echo "To run your app in the namespace:"
echo " sudo ip netns exec $NETNS_NAME ./your_app"
echo ""
echo "To capture traffic:"
echo " sudo tshark -i $VETH_HOST -w app.pcap"