1. Remove PID field as it is useless.
2. Rewrite parseStat() to make it faster and more correct:
- do not use fmt.Scanf as it is very slow;
- avoid splitting data into 20+ fields, of which we only need 2;
- make sure to not panic on short lines and other bad input;
- add some bad input tests (some fail with old code);
- use LastIndexByte instead of LastIndex.
Benchmarks:
before (from the previous commit message):
> BenchmarkParseStat-4 116415 10804 ns/op
> BenchmarkParseRealStat-4 240 4781769 ns/op
after:
> BenchmarkParseStat-4 1164948 1068 ns/op
> BenchmarkParseRealStat-4 331 3458315 ns/op
We are seeing 10x speedup in a synthetic benchmark, and about 1.4x
speedup in a real world benchmark.
While at it, do not ignore any possible errors, and properly wrap those.
[v2: use pkg/errors more, remove t.Logf from test]
[v3: rebased; drop pkg/errors; gofumpt'ed]
[v4: rebased; improved description]
[v5: rebased; mention bad input tests, added second benchmark results]
[v6: remove PID field, do not use strings.Split, further speedup]
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
1. Add a test case that tests parentheses in command.
2. Replace individual comparisons with reflect.DeepEqual.
This also fixes wrong %-style types in Fatalf statements.
3. Replace Fatalf with Errorf so we don't bail out on the first
failure, and do not check result on error.
4. Add two benchmarks. On my laptop, they show:
BenchmarkParseStat-4 116415 10804 ns/op
BenchmarkParseRealStat-4 240 4781769 ns/op
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
And Stat_t.PID and Stat_t.Name while we're at it. Then use the new
.State property in runType to distinguish between running and
zombie/dead processes, since kill(2) does not [1]. With this change
we no longer claim Running status for zombie/dead processes.
I've also removed the kill(2) call from runType. It was originally
added in 13841ef3 (new-api: return the Running state only if the init
process is alive, 2014-12-23), but we've been accessing
/proc/[pid]/stat since 14e95b2a (Make state detection precise,
2016-07-05, #930), and with the /stat access the kill(2) check is
redundant.
I also don't see much point to the previously-separate
doesInitProcessExist, so I've inlined that logic in runType.
It would be nice to distinguish between "/proc/[pid]/stat doesn't
exist" and errors parsing its contents, but I've skipped that for the
moment.
The Running -> Stopped change in checkpoint_test.go is because the
post-checkpoint process is a zombie, and with this commit zombie
processes are Stopped (and no longer Running).
[1]: https://github.com/opencontainers/runc/pull/1483#issuecomment-307527789
Signed-off-by: W. Trevor King <wking@tremily.us>