Skip to content

Instantly share code, notes, and snippets.

@BruceChen7
Created December 29, 2022 14:44
Show Gist options
  • Save BruceChen7/49e5b799188805f401dd502e3b423ad6 to your computer and use it in GitHub Desktop.
Save BruceChen7/49e5b799188805f401dd502e3b423ad6 to your computer and use it in GitHub Desktop.
#bpftrace#redis
#!/usr/bin/env bpftrace
BEGIN
{
printf("Tracing redis-server function \"getMaxmemoryState\" as inlined into \"performEvictions\".\n");
printf("NOTE: These instrumentation points are from disassembly of the redis-server build:\n");
printf(" SHA1: 25a228b839a93a1395907a03f83e1eee448b0f14\n");
printf(" Build-id: 2fc7c1a80ad026179178fff7045bc7fb4ad3f82d\n");
printf(" Version string: Redis server v=6.2.6 sha=4930d19e:1 malloc=jemalloc-5.1.0 bits=64 build=aa3ee5297f58e2\n");
printf("\n");
// Disable to only show the mem_tofree results and histograms.
// Enable to also show intermediate variables.
@debug_mode = 0;
print(@debug_mode);
printf("\n");
printf("%-6s %-6s %-20s %s\n", "PID", "TID", "COMM", "Event details");
}
interval:s:3
{
printf("Exiting after reaching duration limit.");
exit();
}
interval:s:1
{
printf("Per-second summary histograms:\n\n");
print(@maxmemory_mb_lhist);
print(@mem_reported_mb_lhist);
print(@mem_overhead_hist);
print(@mem_used_mb_lhist);
print(@mem_tofree_hist);
clear(@maxmemory_mb_lhist);
clear(@mem_reported_mb_lhist);
clear(@mem_overhead_hist);
clear(@mem_used_mb_lhist);
clear(@mem_tofree_hist);
}
uprobe:/opt/gitlab/embedded/bin/redis-server:0x11b0b9
{
// At address 0x11b0b9, register rax has the result of "zmalloc_used_memory" (line 379) as type size_t (uint64).
$val = reg("ax");
@mem_reported[tid] = $val;
@mem_reported_mb_lhist[tid] = lhist($val / 1048576, 59000, 62000, 10);
if (@debug_mode == 1) {
printf("%-6d %-6d %-20s line 379: %llu = zmalloc_used_memory\n", pid, tid, comm, $val);
}
}
uprobe:/opt/gitlab/embedded/bin/redis-server:0x11b0c3
{
// At address 0x11b0c3, register rax has "server.maxmemory" (line 383) as type size_t (uint64).
$val = reg("ax");
@maxmemory[tid] = $val;
@maxmemory_mb_lhist[tid] = lhist($val / 1048576, 59000, 62000, 10);
if (@debug_mode == 1) {
printf("%-6d %-6d %-20s line 383: %llu = server.maxmemory\n", pid, tid, comm, $val);
}
}
uprobe:/opt/gitlab/embedded/bin/redis-server:0x11b0eb
{
// At address 0x11b0eb, register rax has the result of "freeMemoryGetNotCountedMemory" (line 389) as type size_t (uint64).
$val = reg("ax");
@mem_overhead[tid] = $val;
@mem_overhead_hist[tid] = hist($val);
if (@debug_mode == 1) {
printf("%-6d %-6d %-20s line 389: %llu = mem_overhead\n", pid, tid, comm, $val);
}
// This instrumentation is very brittle. It only works with this exact build of the binary, since we specify exact virtual addresses and registers.
// Check that the arithmetic works as expected. If not, we may be capturing the wrong registers or instructions. Or there may be other call paths.
// Register r12 has the result of "zmalloc_used_memory" (leftover from line 379) as type size_t (uint64).
if (reg("r12") != @mem_reported[tid]) {
printf("Instrumentation bug? Saved value of mem_reported (%llu) != register r12 (%llu)\n", @mem_reported[tid], reg("r12"));
exit();
}
}
uprobe:/opt/gitlab/embedded/bin/redis-server:0x11b0f3
{
// At address 0x11b0f3, register r12 has the adjusted mem_used (mem_reported - overhead) (line 390).
$val = reg("r12");
@mem_used[tid] = $val;
@mem_used_mb_lhist[tid] = lhist($val / 1048576, 59000, 62000, 10);
if (@debug_mode == 1) {
printf("%-6d %-6d %-20s line 390: %llu = mem_used = mem_reported (%llu) - mem_overhead (%llu))\n", pid, tid, comm, $val, @mem_reported[tid], @mem_overhead[tid]);
}
// This instrumentation is very brittle. It only works with this exact build of the binary, since we specify exact virtual addresses and registers.
// Check that the arithmetic works as expected. If not, we may be capturing the wrong registers or instructions. Or there may be other call paths.
if (@mem_used[tid] != (@mem_reported[tid] - @mem_overhead[tid])) {
printf("Instrumentation bug? mem_used: actual (%llu) != expected (%llu)\n", @mem_used[tid], (@mem_reported[tid] - @mem_overhead[tid]));
exit();
}
}
uprobe:/opt/gitlab/embedded/bin/redis-server:0x11b10c
{
// At address 0x11b10c, register r12 has the mem_tofree (mem_used - maxmemory) (line 407).
$val = reg("r12");
@mem_tofree[tid] = $val;
@mem_tofree_hist[tid] = hist($val);
if (@debug_mode == 1) {
printf("%-6d %-6d %-20s line 407: %llu = mem_tofree\n", pid, tid, comm, $val);
}
printf("%-6d %-6d %-20s eviction goal summary: mem_tofree (%llu) = mem_used (%llu) - maxmemory (%llu) ; mem_used (%llu) = mem_reported (%llu) - mem_overhead (%llu)\n",
pid,
tid,
comm,
@mem_tofree[tid],
@mem_used[tid],
@maxmemory[tid],
@mem_used[tid],
@mem_reported[tid],
@mem_overhead[tid]
);
// This instrumentation is very brittle. It only works with this exact build of the binary, since we specify exact virtual addresses and registers.
// Check that the arithmetic works as expected. If not, we may be capturing the wrong registers or instructions. Or there may be other call paths.
if (@mem_used[tid] != (@mem_reported[tid] - @mem_overhead[tid])) {
printf("Instrumentation bug? mem_used: actual (%llu) != expected (%llu)\n", @mem_used[tid], (@mem_reported[tid] - @mem_overhead[tid]));
exit();
}
if (@mem_tofree[tid] != (@mem_used[tid] - @maxmemory[tid])) {
printf("Instrumentation bug? mem_tofree: actual (%llu) != expected (%llu)\n", @mem_tofree[tid], (@mem_used[tid] - @maxmemory[tid]));
exit();
}
}
@BruceChen7
Copy link
Author

image
image
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment