github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/benchmarks/base/startup_test.go (about)

     1  // Copyright 2020 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package startup_test
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"os"
    21  	"testing"
    22  
    23  	"github.com/SagerNet/gvisor/pkg/test/dockerutil"
    24  	"github.com/SagerNet/gvisor/test/benchmarks/base"
    25  	"github.com/SagerNet/gvisor/test/benchmarks/harness"
    26  )
    27  
    28  // BenchmarkStartEmpty times startup time for an empty container.
    29  func BenchmarkStartupEmpty(b *testing.B) {
    30  	machine, err := harness.GetMachine()
    31  	if err != nil {
    32  		b.Fatalf("failed to get machine: %v", err)
    33  	}
    34  	defer machine.CleanUp()
    35  
    36  	ctx := context.Background()
    37  	for i := 0; i < b.N; i++ {
    38  		harness.DebugLog(b, "Running container: %d", i)
    39  		container := machine.GetContainer(ctx, b)
    40  		defer container.CleanUp(ctx)
    41  		if _, err := container.Run(ctx, dockerutil.RunOpts{
    42  			Image: "benchmarks/alpine",
    43  		}, "true"); err != nil {
    44  			b.Fatalf("failed to run container: %v", err)
    45  		}
    46  		harness.DebugLog(b, "Ran container: %d", i)
    47  	}
    48  }
    49  
    50  // BenchmarkStartupNginx times startup for a Nginx instance.
    51  // Time is measured from start until the first request is served.
    52  func BenchmarkStartupNginx(b *testing.B) {
    53  	// The machine to hold Nginx and the Node Server.
    54  	machine, err := harness.GetMachine()
    55  	if err != nil {
    56  		b.Fatalf("failed to get machine with: %v", err)
    57  	}
    58  	defer machine.CleanUp()
    59  
    60  	ctx := context.Background()
    61  	runOpts := dockerutil.RunOpts{
    62  		Image: "benchmarks/nginx",
    63  	}
    64  	runServerWorkload(ctx, b,
    65  		base.ServerArgs{
    66  			Machine: machine,
    67  			RunOpts: runOpts,
    68  			Port:    80,
    69  			Cmd:     []string{"nginx", "-c", "/etc/nginx/nginx_gofer.conf"},
    70  		})
    71  }
    72  
    73  // BenchmarkStartupNode times startup for a Node application instance.
    74  // Time is measured from start until the first request is served.
    75  // Note that the Node app connects to a Redis instance before serving.
    76  func BenchmarkStartupNode(b *testing.B) {
    77  	machine, err := harness.GetMachine()
    78  	if err != nil {
    79  		b.Fatalf("failed to get machine with: %v", err)
    80  	}
    81  	defer machine.CleanUp()
    82  
    83  	ctx := context.Background()
    84  	redis, redisIP := base.RedisInstance(ctx, b, machine)
    85  	defer redis.CleanUp(ctx)
    86  	runOpts := dockerutil.RunOpts{
    87  		Image:   "benchmarks/node",
    88  		WorkDir: "/usr/src/app",
    89  		Links:   []string{redis.MakeLink("redis")},
    90  	}
    91  
    92  	cmd := []string{"node", "index.js", redisIP.String()}
    93  	runServerWorkload(ctx, b,
    94  		base.ServerArgs{
    95  			Machine: machine,
    96  			Port:    8080,
    97  			RunOpts: runOpts,
    98  			Cmd:     cmd,
    99  		})
   100  }
   101  
   102  // runServerWorkload runs a server workload defined by 'runOpts' and 'cmd'.
   103  // 'clientMachine' is used to connect to the server on 'serverMachine'.
   104  func runServerWorkload(ctx context.Context, b *testing.B, args base.ServerArgs) {
   105  	b.ResetTimer()
   106  	for i := 0; i < b.N; i++ {
   107  		harness.DebugLog(b, "Running iteration: %d", i)
   108  		if err := func() error {
   109  			server := args.Machine.GetContainer(ctx, b)
   110  			defer func() {
   111  				b.StopTimer()
   112  				// Cleanup servers as we run so that we can go indefinitely.
   113  				server.CleanUp(ctx)
   114  				b.StartTimer()
   115  			}()
   116  			harness.DebugLog(b, "Spawning container: %s", args.RunOpts.Image)
   117  			if err := server.Spawn(ctx, args.RunOpts, args.Cmd...); err != nil {
   118  				return fmt.Errorf("failed to spawn node instance: %v", err)
   119  			}
   120  
   121  			harness.DebugLog(b, "Finding Container IP")
   122  			servingIP, err := server.FindIP(ctx, false)
   123  			if err != nil {
   124  				return fmt.Errorf("failed to get ip from server: %v", err)
   125  			}
   126  
   127  			// Wait until the Client sees the server as up.
   128  			harness.DebugLog(b, "Waiting for container to start.")
   129  			if err := harness.WaitUntilServing(ctx, args.Machine, servingIP, args.Port); err != nil {
   130  				return fmt.Errorf("failed to wait for serving: %v", err)
   131  			}
   132  			return nil
   133  		}(); err != nil {
   134  			b.Fatal(err)
   135  		}
   136  		harness.DebugLog(b, "Ran iteration: %d", i)
   137  	}
   138  }
   139  
   140  // TestMain is the main method for package network.
   141  func TestMain(m *testing.M) {
   142  	harness.Init()
   143  	os.Exit(m.Run())
   144  }