bobuhiro11 / gokvm

KVM based tiny x86 hypervisor written in pure golang, which can boot Linux
https://blog.bobuhiro11.net/tags/gokvm.html
MIT License
206 stars 21 forks source link

Empty cpu.pprof file Issue #143

Closed mozartfish closed 1 year ago

mozartfish commented 1 year ago

I'm attempting to create a cpu.prof file using the following strategies

  1. Austin Burnett's Go Memory Profiling Strategy https://austburn.me/blog/go-profile.html
  2. Go Benchmark Test Strategy using main_test.go go test -cpuprofile cpu.prof -memprofile mem.prof -bench .

I'm producing an empty cpu.prof file and I can't figure out why this is happening and wondering if anyone has any suggestions for what might be causing this issue because I have been able to get smaller programs such as fibonacci program working.

Thank you

bobuhiro11 commented 1 year ago

I am very happy that you are contributing to this project.

After applying the following patch to the main branch, the benchmark runs and outputs example-cpu.prof. This seems like a good starting point.

diff --git a/machine/machine_test.go b/machine/machine_test.go
index f1d7d600a835..6ae44dc70fe7 100644
--- a/machine/machine_test.go
+++ b/machine/machine_test.go
@@ -9,6 +9,7 @@ import (
        "syscall"
        "testing"
        "time"
+       "runtime/pprof"

        "github.com/bobuhiro11/gokvm/kvm"
        "github.com/bobuhiro11/gokvm/machine"
@@ -95,6 +96,48 @@ func testNewAndLoadLinux(t *testing.T, kernel, tap, guestIPv4, hostIPv4, prefixL
        }
 }

+func BenchmarkNewAndLoadLinuxWithBzImage(b *testing.B) { // nolint:paralleltest
+       cpuProfile, err := os.Create("../example-cpu.prof")
+       if err != nil {
+               b.Fatal(err)
+       }
+       pprof.StartCPUProfile(cpuProfile)
+       defer pprof.StopCPUProfile()
+
+       for i := 0; i < b.N; i++ {
+               m, err := machine.New("/dev/kvm", 1, 1<<29)
+               if err != nil {
+                       b.Fatal(err)
+               }
+
+               param := fmt.Sprintf(`console=ttyS0 earlyprintk=serial noapic noacpi notsc `+
+                       `lapic tsc_early_khz=2000 pci=realloc=off virtio_pci.force_legacy=1 `+
+                       `rdinit=/init init=/init`)
+
+               kern, err := os.Open("../bzImage")
+               if err != nil {
+                       b.Fatal(err)
+               }
+
+               initrd, err := os.Open("../initrd")
+               if err != nil {
+                       b.Fatal(err)
+               }
+
+               if err = m.LoadLinux(kern, initrd, param); err != nil {
+                       b.Fatal(err)
+               }
+
+               go func() {
+                       if err = m.RunInfiniteLoop(0); err != nil {
+                               panic(err)
+                       }
+               }()
+
+               time.Sleep(10 * time.Second)
+       }
+}
+
 func TestNewAndLoadLinuxWithBzImage(t *testing.T) { // nolint:paralleltest
        testNewAndLoadLinux(t, "../bzImage", "tap0", "192.168.20.1", "192.168.20.2", "24")
 }
$ go test -bench=. ./machine/... -run BenchmarkNewAndLoadLinuxWithBzImage

Here are some other points of interest.