mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
cc0dc87fa2
Add the usage benchmark which queries memory usage from the container. This is meant to replace the size benchmark which has a ton of noise. Flakes are due to the complicated measurement technique of dropping caches -> parse /proc/meminfo -> start containers -> drops caches again -> parse /proc/meminfo -> take the diference. This was done because not all runtimes support docker/containerd stats. Buuuut...gVisor does, so we'll just take the stats figures to reduce noise for the memory usage benchmark. In addition, the returned types.StatsJSON object contains several useful stats like page faults and CPU usage, so adding these will be trivial and will not slow down benchmark performance. [types.StatsJSON linky link](https://github.com/moby/moby/blob/42c8b314993e5eb3cc2776da0bbe41d5eb4b707b/api/types/stats.go#LL153) PiperOrigin-RevId: 503342363
96 lines
3.0 KiB
Go
96 lines
3.0 KiB
Go
// Copyright 2020 The gVisor Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Package base holds utility methods common to the base tests.
|
|
package base
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"gvisor.dev/gvisor/pkg/test/dockerutil"
|
|
"gvisor.dev/gvisor/test/benchmarks/harness"
|
|
)
|
|
|
|
// ServerArgs wraps args for startServers and runServerWorkload.
|
|
type ServerArgs struct {
|
|
Machine harness.Machine
|
|
Port int
|
|
RunOpts dockerutil.RunOpts
|
|
Cmd []string
|
|
}
|
|
|
|
// StartServers starts b.N containers defined by 'runOpts' and 'cmd' and uses
|
|
// 'machine' to check that each is up.
|
|
func StartServers(ctx context.Context, b *testing.B, args ServerArgs) []*dockerutil.Container {
|
|
b.Helper()
|
|
servers := make([]*dockerutil.Container, 0, b.N)
|
|
|
|
// Create N servers and wait until each of them is serving.
|
|
for i := 0; i < b.N; i++ {
|
|
server, err := StartServer(ctx, b, args)
|
|
if err != nil {
|
|
CleanUpContainers(ctx, servers)
|
|
b.Fatalf("failed to start server: %v", err)
|
|
}
|
|
servers = append(servers, server)
|
|
}
|
|
return servers
|
|
}
|
|
|
|
// StartServer starts a single server and cleans it up if it fails.
|
|
func StartServer(ctx context.Context, b *testing.B, args ServerArgs) (*dockerutil.Container, error) {
|
|
server := args.Machine.GetContainer(ctx, b)
|
|
if err := server.Spawn(ctx, args.RunOpts, args.Cmd...); err != nil {
|
|
server.CleanUp(ctx)
|
|
return server, fmt.Errorf("failed to spawn server: %v", err)
|
|
}
|
|
// Wait until server is running.
|
|
if err := harness.WaitUntilContainerServing(ctx, args.Machine, server, args.Port); err != nil {
|
|
server.CleanUp(ctx)
|
|
return server, fmt.Errorf("failed to wait for serving server %q: %v", server.Name, err)
|
|
}
|
|
return server, nil
|
|
}
|
|
|
|
// CleanUpContainers cleans up a slice of containers.
|
|
func CleanUpContainers(ctx context.Context, containers []*dockerutil.Container) {
|
|
for _, c := range containers {
|
|
if c != nil {
|
|
c.CleanUp(ctx)
|
|
}
|
|
}
|
|
}
|
|
|
|
// RedisInstance returns a Redis container and its reachable IP.
|
|
func RedisInstance(ctx context.Context, b *testing.B, machine harness.Machine) *dockerutil.Container {
|
|
b.Helper()
|
|
// Spawn a redis instance for the app to use.
|
|
redis := machine.GetNativeContainer(ctx, b)
|
|
if err := redis.Spawn(ctx, dockerutil.RunOpts{
|
|
Image: "benchmarks/redis",
|
|
}); err != nil {
|
|
redis.CleanUp(ctx)
|
|
b.Fatalf("failed to spawn redis instance: %v", err)
|
|
}
|
|
|
|
if out, err := redis.WaitForOutput(ctx, "Ready to accept connections", 3*time.Second); err != nil {
|
|
redis.CleanUp(ctx)
|
|
b.Fatalf("failed to start redis server: %v %s", err, out)
|
|
}
|
|
return redis
|
|
}
|