Go 1.18 and up now provides a strings.Cut() which is better suited for
splitting key/value pairs (and similar constructs), and performs better:
```go
func BenchmarkSplit(b *testing.B) {
b.ReportAllocs()
data := []string{"12hello=world", "12hello=", "12=hello", "12hello"}
for i := 0; i < b.N; i++ {
for _, s := range data {
_ = strings.SplitN(s, "=", 2)[0]
}
}
}
func BenchmarkCut(b *testing.B) {
b.ReportAllocs()
data := []string{"12hello=world", "12hello=", "12=hello", "12hello"}
for i := 0; i < b.N; i++ {
for _, s := range data {
_, _, _ = strings.Cut(s, "=")
}
}
}
```
BenchmarkSplit
BenchmarkSplit-10 8244206 128.0 ns/op 128 B/op 4 allocs/op
BenchmarkCut
BenchmarkCut-10 54411998 21.80 ns/op 0 B/op 0 allocs/op
While looking at occurrences of `strings.Split()`, I also updated some for alternatives,
or added some constraints; for cases where an specific number of items is expected, I used `strings.SplitN()`
with a suitable limit. This prevents (theoretical) unlimited splits.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
GOGC=75 golangci-lint run
services/server/server.go:320:27: G114: Use of net/http serve function that has no support for setting timeouts (gosec)
return trapClosedConnErr(http.Serve(l, m))
^
services/server/server.go:340:27: G114: Use of net/http serve function that has no support for setting timeouts (gosec)
return trapClosedConnErr(http.Serve(l, m))
^
cmd/containerd-stress/main.go:238:13: G114: Use of net/http serve function that has no support for setting timeouts (gosec)
if err := http.ListenAndServe(c.Metrics, metrics.Handler()); err != nil {
^
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Introduce a --cri flag, which will enable running container-stress using the CRI,
instead of containerd's task API.
In doing so, we introduce cri_worker, rename the existing worker to ctr_worker, and introduce
a worker interface that each of these implement.
Signed-off-by: Eric Ernst <eric_ernst@apple.com>
For some runtimes, the container is not ready for exec until the
initial container task has been started (as opposed to just having the task created).
More specifically, running containerd-stress with --exec would break
with Kata Container shim, since the sandbox is not created until a
start is issued. By starting the container's primary task before adding
exec's, we can avoid:
```
error="cannot enter container exec-container-1, with err Sandbox not running, impossible to enter the container: unknown"
```
Signed-off-by: Eric Ernst <eric_ernst@apple.com>
The io/ioutil package has been deprecated as of Go 1.16, see
https://golang.org/doc/go1.16#ioutil. This commit replaces the existing
io/ioutil functions with their new definitions in io and os packages.
Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
Remove build tags which are already implied by the name of the file.
Ensures build tags are used consistently
Signed-off-by: Derek McGowan <derek@mcg.dev>
containerd-stress utility needs to be able to run with snapshotter
passed by user in cli in order to be able to stress test snapshotters.
This adds a cli option --snapshotter="<snapshotter-name>"
Signed-off-by: Alakesh Haloi <alakeshh@amazon.com>
This fixes following warning message by changing the default runtime
to io.containerd.runc.v2 and does not require user to set the runtime
from command line anymore.
"WARN[2021-03-17T21:11:01.441207858Z] runtime v1 is deprecated since
containerd v1.4, consider using runtime v2"
Signed-off-by: Alakesh Haloi <alakeshh@amazon.com>
The climan package has a command that can be registered with any urfav
cli app to generate man pages.
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This brings freebsd in line with Darwin, ie it builds, but some parts may not yet
be fully functional. There is now a WIP `runc` port for FreeBSD at
https://github.com/clovertrail/runc/tree/1501-SupportOnFreeBSD so should be able
to test further.
Signed-off-by: Justin Cormack <justin@specialbusservice.com>
Running the density tool will report Pss and Rss total and per container
values for shim memory usage. Values are reported in KB.
```bash
containerd-stress density --count 500
INFO[0000] pulling docker.io/library/alpine:latest
INFO[0000] generating spec from image
{"pss":421188,"rss":2439688,"pssPerContainer":842,"rssPerContainer":4879}
```
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This improves the exec support so that they can run along with the
normal stress tests. You don't have to pick exec stres or container
stress. They both run at the same time and report the different values.
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
By default, the generated spec will place containers in cgroups by their
ids, we need to use the namespace as the cgroup root to avoid
containers with the same name being placed in the same cgroup.
```
11:perf_event:/to/redis
10:freezer:/to/redis
9:memory:/to/redis
8:devices:/to/redis
7:net_cls,net_prio:/to/redis
6:pids:/to/redis
5:hugetlb:/to/redis
4:cpuset:/to/redis
3:blkio:/to/redis
2:cpu,cpuacct:/to/redis
1:name=systemd:/to/redis
11:perf_event:/te/redis
10:freezer:/te/redis
9:memory:/te/redis
8:devices:/te/redis
7:net_cls,net_prio:/te/redis
6:pids:/te/redis
5:hugetlb:/te/redis
4:cpuset:/te/redis
3:blkio:/te/redis
2:cpu,cpuacct:/te/redis
1:name=systemd:/te/redis
```
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
In order to do more advanced spec generation with images, snapshots,
etc, we need to inject the context and client into the spec generation
code.
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
Instead of requiring callers to read the struct fields to check for an
error, provide the exit results via a function instead which is more
natural.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
In all of the examples, its recommended to call `Wait()` before starting
a process/task.
Since `Wait()` is a blocking call, this means it must be called from a
goroutine like so:
```go
statusC := make(chan uint32)
go func() {
status, err := task.Wait(ctx)
if err != nil {
// handle async err
}
statusC <- status
}()
task.Start(ctx)
<-statusC
```
This means there is a race here where there is no guarentee when the
goroutine is going to be scheduled, and even a bit more since this
requires an RPC call to be made.
In addition, this code is very messy and a common pattern for any caller
using Wait+Start.
Instead, this changes `Wait()` to use an async model having `Wait()`
return a channel instead of the code itself.
This ensures that when `Wait()` returns that the client has a handle on
the event stream (already made the RPC request) before returning and
reduces any sort of race to how the stream is handled by grpc since we
can't guarentee that we have a goroutine running and blocked on
`Recv()`.
Making `Wait()` async also cleans up the code in the caller drastically:
```go
statusC, err := task.Wait(ctx)
if err != nil {
return err
}
task.Start(ctx)
status := <-statusC
if status.Err != nil {
return err
}
```
No more spinning up goroutines and more natural error
handling for the caller.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>