github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/benchmarks/fs/bazel_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 package bazel_test 15 16 import ( 17 "context" 18 "fmt" 19 "os" 20 "strings" 21 "testing" 22 23 "github.com/SagerNet/gvisor/pkg/cleanup" 24 "github.com/SagerNet/gvisor/pkg/test/dockerutil" 25 "github.com/SagerNet/gvisor/test/benchmarks/harness" 26 "github.com/SagerNet/gvisor/test/benchmarks/tools" 27 ) 28 29 // Dimensions here are clean/dirty cache (do or don't drop caches) 30 // and if the mount on which we are compiling is a tmpfs/bind mount. 31 type benchmark struct { 32 clearCache bool // clearCache drops caches before running. 33 fstype harness.FileSystemType // type of filesystem to use. 34 } 35 36 // Note: CleanCache versions of this test require running with root permissions. 37 func BenchmarkBuildABSL(b *testing.B) { 38 runBuildBenchmark(b, "benchmarks/absl", "/abseil-cpp", "absl/base/...") 39 } 40 41 // Note: CleanCache versions of this test require running with root permissions. 42 // Note: This test takes on the order of 10m per permutation for runsc on kvm. 43 func BenchmarkBuildRunsc(b *testing.B) { 44 runBuildBenchmark(b, "benchmarks/runsc", "/gvisor", "runsc:runsc") 45 } 46 47 func runBuildBenchmark(b *testing.B, image, workdir, target string) { 48 b.Helper() 49 // Get a machine from the Harness on which to run. 50 machine, err := harness.GetMachine() 51 if err != nil { 52 b.Fatalf("Failed to get machine: %v", err) 53 } 54 defer machine.CleanUp() 55 56 benchmarks := make([]benchmark, 0, 6) 57 for _, filesys := range []harness.FileSystemType{harness.BindFS, harness.TmpFS, harness.RootFS} { 58 benchmarks = append(benchmarks, benchmark{ 59 clearCache: true, 60 fstype: filesys, 61 }) 62 benchmarks = append(benchmarks, benchmark{ 63 clearCache: false, 64 fstype: filesys, 65 }) 66 } 67 68 for _, bm := range benchmarks { 69 pageCache := tools.Parameter{ 70 Name: "page_cache", 71 Value: "dirty", 72 } 73 if bm.clearCache { 74 pageCache.Value = "clean" 75 } 76 77 filesystem := tools.Parameter{ 78 Name: "filesystem", 79 Value: string(bm.fstype), 80 } 81 name, err := tools.ParametersToName(pageCache, filesystem) 82 if err != nil { 83 b.Fatalf("Failed to parse parameters: %v", err) 84 } 85 86 b.Run(name, func(b *testing.B) { 87 // Grab a container. 88 ctx := context.Background() 89 container := machine.GetContainer(ctx, b) 90 cu := cleanup.Make(func() { 91 container.CleanUp(ctx) 92 }) 93 defer cu.Clean() 94 mts, prefix, err := harness.MakeMount(machine, bm.fstype, &cu) 95 if err != nil { 96 b.Fatalf("Failed to make mount: %v", err) 97 } 98 99 runOpts := dockerutil.RunOpts{ 100 Image: image, 101 Mounts: mts, 102 } 103 104 // Start a container and sleep. 105 if err := container.Spawn(ctx, runOpts, "sleep", fmt.Sprintf("%d", 1000000)); err != nil { 106 b.Fatalf("run failed with: %v", err) 107 } 108 109 cpCmd := fmt.Sprintf("mkdir -p %s && cp -r %s %s/.", prefix, workdir, prefix) 110 if out, err := container.Exec(ctx, dockerutil.ExecOpts{}, 111 "/bin/sh", "-c", cpCmd); err != nil { 112 b.Fatalf("failed to copy directory: %v (%s)", err, out) 113 } 114 115 b.ResetTimer() 116 b.StopTimer() 117 118 // Drop Caches and bazel clean should happen inside the loop as we may use 119 // time options with b.N. (e.g. Run for an hour.) 120 for i := 0; i < b.N; i++ { 121 // Drop Caches for clear cache runs. 122 if bm.clearCache { 123 if err := harness.DropCaches(machine); err != nil { 124 b.Skipf("failed to drop caches: %v. You probably need root.", err) 125 } 126 } 127 128 b.StartTimer() 129 got, err := container.Exec(ctx, dockerutil.ExecOpts{ 130 WorkDir: prefix + workdir, 131 }, "bazel", "build", "-c", "opt", target) 132 if err != nil { 133 b.Fatalf("build failed with: %v logs: %s", err, got) 134 } 135 b.StopTimer() 136 137 want := "Build completed successfully" 138 if !strings.Contains(got, want) { 139 b.Fatalf("string %s not in: %s", want, got) 140 } 141 142 // Clean bazel in the case we are doing another run. 143 if i < b.N-1 { 144 if _, err = container.Exec(ctx, dockerutil.ExecOpts{ 145 WorkDir: prefix + workdir, 146 }, "bazel", "clean"); err != nil { 147 b.Fatalf("build failed with: %v", err) 148 } 149 } 150 } 151 }) 152 } 153 } 154 155 // TestMain is the main method for package fs. 156 func TestMain(m *testing.M) { 157 harness.Init() 158 harness.SetFixedBenchmarks() 159 os.Exit(m.Run()) 160 }