Skip to content

Instantly share code, notes, and snippets.

@zhuizhuhaomeng
Created August 2, 2020 13:49
Show Gist options
  • Save zhuizhuhaomeng/feefbbff6c6f4cc69fd1d43fa399c38e to your computer and use it in GitHub Desktop.
Save zhuizhuhaomeng/feefbbff6c6f4cc69fd1d43fa399c38e to your computer and use it in GitHub Desktop.
#!/usr/bin/opsrun
use xray-cli;
use xray-agent-lib;
my Int $MAX-ITERS = 3;
my Str (@iterators, @results);
my Bool $finished;
my Int %mem{Str} = (
'http_luajit_allocator': 0,
'stream_luajit_allocator': 0,
'glibc_arena': 0,
'glibc_mmaped': 0,
'jemalloc_mmaped': 0,
'nginx_shm_loaded': 0,
'musl_libc_heap': 0,
);
my Int (%total-zones{Str}, %loaded-zones{Str});
my Str %addr-zones{Str};
my Int %loaded-unknow-map-files{Str};
my Int (%total-mmaps{Str}, %loaded-mmaps{Str});
my Int $sum-loaded-mmaps = 0;
my Str $tool = 'resty-memory';
my Str @base-opts;
my Int $len;
my Str $iter;
my Int $runs = 0;
my Str $data-file;
action check-shm-loaded (Int $pid) ret Int
{
my Int $sum-loaded = 0;
my Str (@map-files, @range-starts, %shm-start-to-end{Str});
my Str (%name-to-range{Str}, %range-to-zones{Str});
my Int $size;
my Str $zone;
my Str $range;
my Int ($loaded-page, $total-page);
my Int $pagesize = 4096;
$ getconf PAGE_SIZE,
{
failed =>
say("can't get page size by 'getconf PAGE_SIZE', use default value $pagesize"),
nop;
true =>
$pagesize = cout;
},
$ awk '$2 == "rw-s" && $6 == "/dev/zero" && $7 == "(deleted)"{print $1}' /proc/$.pid/maps,
stream {
out contains rx{^([a-f0-9]+)\-([a-f0-9]+)\n} =>
push(@range-starts, $1),
%shm-start-to-end{$1} = $2,
redo(tries: 1024);
found-prompt => break;
},
# range-starts is already sorted and with 12 chars.
lua {
local zones = %addr-zones
local starts = @range-starts
local map_files = @map-files
local start_to_end = %shm-start-to-end
local range_to_zones = %range-to-zones
local n = 0
for addr, zone in pairs(zones) do
local range
for i = 0, starts.len - 1 do
local start = starts[starts.base + i]
if addr >= start and addr < start_to_end[start] then
range = start .. "-" .. start_to_end[start]
break
end
end
if range then
range_to_zones[range] = zone
end
end
for i = 0, starts.len - 1 do
local start = starts[starts.base + i]
local range = start .. "-" .. start_to_end[start]
table.insert(map_files, "/proc/" .. $pid .. "/map_files/" .. range)
end
map_files.base = 1
map_files.len = starts.len
},
{
@map-files =>
$ mincore @.map-files,
stream {
out contains rx{^([a-f0-9]+\-[a-f0-9]+): (\d+)\/(\d+) pages present} =>
$range = $1,
$loaded-page = to-int($2),
$total-page = to-int($3),
$zone = %range-to-zones{$range},
{
defined($zone) =>
$size = %total-zones{$zone} / $total-page * $loaded-page,
%loaded-zones{$zone} = $size,
$sum-loaded += $size,
{
$loaded-page > 0 =>
# TODO: get pagesize in another way.
$pagesize = $size / $loaded-page;
},
done;
true =>
$size = $loaded-page * $pagesize,
%loaded-mmaps{$range} = $size,
%total-mmaps{$range} = $total-page * $pagesize,
$sum-loaded-mmaps += $size;
},
redo(tries: 1024);
found-prompt => break;
},
done;
},
return $sum-loaded;
}
action merge-result () {
my Str $data-file;
shift(@iterators),
$data-file = shift(@results),
{
!defined($data-file); $data-file eq "" =>
done;
true =>
$ cat "$.data-file",
stream {
out contains /^http luajit GC managed: (\d+)\n/ =>
%mem<http_luajit_GC_managed> = to-int($1);
out contains /^http luajit allocator: (\d+)\n/ =>
%mem<http_luajit_allocator> += to-int($1);
out contains /^stream luajit GC managed: (\d+)\n/ =>
%mem<stream_luajit_GC_managed> = to-int($1);
out contains /^stream luajit allocator: (\d+)\n/ =>
%mem<stream_luajit_allocator> += to-int($1);
out contains /^musl libc heap: (\d+)\n/ =>
%mem<musl_libc_heap> += to-int($1);
out contains /^glibc arena: (\d+)\n/ =>
%mem<glibc_arena> += to-int($1);
out contains /^glibc mmaped: (\d+)\n/ =>
%mem<glibc_mmaped> += to-int($1);
out contains /^jemalloc mmaped: (\d+)\n/ =>
%mem<jemalloc_mmaped> += to-int($1);
out contains /^shm zone (.*?): total=(\d+) addr=0x(\w+)\n/ =>
%total-zones{$1} = to-int($2),
%loaded-zones{$1} = 0,
%addr-zones{$3} = $1,
redo(tries: 1024);
found-prompt => break;
};
},
nop;
}
action finish-iterator (Int $pid) {
again:
{
elems(@iterators) == 0 =>
done;
true =>
merge-result,
goto(again, tries: $MAX-ITERS + 2);
},
%mem<nginx_shm_loaded> = check-shm-loaded($pid),
%mem<mmap_loaded> = $sum-loaded-mmaps,
$ cat /proc/$.pid/status | grep Vm,
stream {
out contains /VmExe:\s+(\d+)\s+kB/ =>
%mem<vm_exe> = to-int($1) * 1024;
out contains /VmLib:\s+(\d+)\s+kB/ =>
%mem<vm_lib> = to-int($1) * 1024;
out contains /VmStk:\s+(\d+)\s+kB/ =>
%mem<vm_stack> = to-int($1) * 1024;
found-prompt => break;
},
say("JS: json: resty-memory: ", '{"summary": ', encode-json(%mem),
',"total-shms":', encode-json(%total-zones),
',"loaded-shms":', encode-json(%loaded-zones),
',"total-mmaps":', encode-json(%total-mmaps),
',"loaded-mmaps":', encode-json(%loaded-mmaps),
'}'
),
exit(0);
}
goal all (Str $cwd, Str $ko-file, Int $pid) {
run {
$ cd $.cwd,
init-target-box,
@base-opts = gen-staprun-opts($pid),
say("info: running tool $tool ..."),
$runs++,
$data-file = "data.$runs",
run-staprun-simple($ko-file, @base-opts, nil, $data-file),
{
failed =>
check-readfault(cout),
die("failed to run tool: ", cout);
},
init-iterator(@iterators, @results, $MAX-ITERS - 1),
again:
$finished = push-iterator(@iterators, @results, cout, $data-file),
$len = elems(@iterators),
{
$finished =>
finish-iterator($pid),
done;
$len == 0 =>
# too much rollback
die("failed to continue from the previous run: ", cout);
$len > $MAX-ITERS =>
merge-result,
$len = elems(@iterators);
},
$iter = @iterators[$len - 1],
$runs++,
$data-file = "data.$runs",
run-staprun-simple($ko-file, @base-opts, $iter, $data-file),
{
failed =>
check-readfault(cout, true),
rollback-iterator(@iterators, @results);
true =>
goto(again, tries: 200);
},
nop;
}
}
goal all-odb (Str $cwd, Str $ko-file, Int $pid) {
run {
$ cd $.cwd,
init-target-box,
@base-opts = gen-odb-opts($pid),
say("info: running tool $tool by odb ..."),
$runs++,
$data-file = "data.$runs",
$ chmod +x $.ko-file,
run-odb-simple($ko-file, @base-opts, nil, $data-file),
{
failed =>
die("failed to run tool: ", cout);
},
init-iterator(@iterators, @results, $MAX-ITERS - 1),
again:
$finished = push-iterator(@iterators, @results, cout, $data-file),
$len = elems(@iterators),
{
$finished =>
finish-iterator($pid),
done;
$len == 0 =>
# too much rollback
die("failed to continue from the previous run: ", cout);
$len > $MAX-ITERS =>
merge-result,
$len = elems(@iterators);
},
$iter = @iterators[$len - 1],
$runs++,
$data-file = "data.$runs",
run-odb-simple($ko-file, @base-opts, $iter, $data-file),
{
failed =>
rollback-iterator(@iterators, @results);
true =>
goto(again, tries: 1000);
},
nop;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment