From 2c1f98b1efdd9e7de346534a192f7b3790c9abdf Mon Sep 17 00:00:00 2001 From: debugtalk Date: Fri, 16 Dec 2022 16:08:50 +0800 Subject: [PATCH] feat: add performance monitor for iOS, including CLI hrp ios perf --- docs/CHANGELOG.md | 3 +- hrp/cmd/ios/pcap.go | 5 ++- hrp/cmd/ios/perf.go | 87 ++++++++++++++++++++++++++++++++++++++ hrp/pkg/uixt/ios_device.go | 3 +- 4 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 hrp/cmd/ios/perf.go diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 3e364689..c0dc5acb 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## v4.3.1 (2022-12-15) +## v4.3.1 (2022-12-16) **go version** @@ -9,6 +9,7 @@ - feat: run step with specified loop times - feat: add options for FindTexts - feat: capture pcap file for iOS, including CLI `hrp ios pcap` and option `uixt.WithIOSPcapOn(true)` +- feat: add performance monitor for iOS, including CLI `hrp ios perf` and options `uixt.WithIOSPerfOptions(...)` - refactor: move all UI APIs to uixt pkg - docs: add examples for UI APIs diff --git a/hrp/cmd/ios/pcap.go b/hrp/cmd/ios/pcap.go index b4138ea2..73b5042f 100644 --- a/hrp/cmd/ios/pcap.go +++ b/hrp/cmd/ios/pcap.go @@ -6,11 +6,12 @@ import ( "syscall" "time" + "github.com/rs/zerolog/log" + "github.com/spf13/cobra" + "github.com/httprunner/httprunner/v4/hrp/internal/builtin" "github.com/httprunner/httprunner/v4/hrp/internal/env" "github.com/httprunner/httprunner/v4/hrp/pkg/uixt" - "github.com/rs/zerolog/log" - "github.com/spf13/cobra" ) var pcapCmd = &cobra.Command{ diff --git a/hrp/cmd/ios/perf.go b/hrp/cmd/ios/perf.go new file mode 100644 index 00000000..3824552b --- /dev/null +++ b/hrp/cmd/ios/perf.go @@ -0,0 +1,87 @@ +package ios + +import ( + "os" + "os/signal" + "syscall" + "time" + + "github.com/rs/zerolog/log" + "github.com/spf13/cobra" + + "github.com/httprunner/httprunner/v4/hrp/internal/builtin" + "github.com/httprunner/httprunner/v4/hrp/internal/env" + "github.com/httprunner/httprunner/v4/hrp/pkg/uixt" +) + +var perfCmd = &cobra.Command{ + Use: "perf", + Short: "capture ios performance data (cpu,mem,disk,net,fps,etc.)", + RunE: func(cmd *cobra.Command, args []string) error { + perfOptions := []uixt.IOSPerfOption{} + for _, p := range indicators { + switch p { + case "sys_cpu": + perfOptions = append(perfOptions, uixt.WithIOSPerfSystemCPU(true)) + case "sys_mem": + perfOptions = append(perfOptions, uixt.WithIOSPerfSystemMem(true)) + case "sys_net": + perfOptions = append(perfOptions, uixt.WithIOSPerfSystemNetwork(true)) + case "sys_disk": + perfOptions = append(perfOptions, uixt.WithIOSPerfSystemDisk(true)) + case "network": + perfOptions = append(perfOptions, uixt.WithIOSPerfNetwork(true)) + case "fps": + perfOptions = append(perfOptions, uixt.WithIOSPerfFPS(true)) + case "gpu": + perfOptions = append(perfOptions, uixt.WithIOSPerfGPU(true)) + } + } + perfOptions = append(perfOptions, uixt.WithIOSPerfOutputInterval(interval*1000)) + + device, err := uixt.NewIOSDevice( + uixt.WithUDID(udid), + uixt.WithIOSPerfOptions(perfOptions...), + ) + if err != nil { + log.Fatal().Err(err).Msg("failed to init ios device") + } + + err = builtin.EnsureFolderExists(env.ResultsPath) + if err != nil { + return err + } + + if err = device.StartPerf(); err != nil { + return err + } + defer device.StopPerf() + + c := make(chan os.Signal, 1) + signal.Notify(c, syscall.SIGTERM, syscall.SIGINT) + timer := time.NewTimer(time.Duration(timeDuration) * time.Second) + for { + select { + case <-timer.C: + return nil + case <-c: + log.Warn().Msg("received signal, stop perf") + return nil + } + } + }, +} + +var ( + interval int + indicators []string +) + +func init() { + perfCmd.Flags().StringVarP(&udid, "udid", "u", "", "specify device by udid") + perfCmd.Flags().StringSliceVarP(&indicators, "indicators", "p", []string{"sys_cpu", "sys_mem"}, + "specify performance monitor, e.g. sys_cpu,sys_mem,sys_net,sys_disk,fps,network,gpu") + perfCmd.Flags().IntVarP(&timeDuration, "duration", "t", 10, "specify time duraion in seconds") + perfCmd.Flags().IntVarP(&interval, "interval", "i", 3, "set interval in seconds") + iosRootCmd.AddCommand(perfCmd) +} diff --git a/hrp/pkg/uixt/ios_device.go b/hrp/pkg/uixt/ios_device.go index a508a777..50260c47 100644 --- a/hrp/pkg/uixt/ios_device.go +++ b/hrp/pkg/uixt/ios_device.go @@ -344,13 +344,13 @@ func (dev *IOSDevice) NewDriver(capabilities Capabilities) (driverExt *DriverExt } func (dev *IOSDevice) StartPerf() error { + log.Info().Msg("start performance monitor") data, err := dev.d.PerfStart(dev.perfOpitons()...) if err != nil { return err } dev.perfFile = filepath.Join(env.ResultsPath, "perf.data") - log.Info().Str("perfFile", dev.perfFile).Msg("create perf file") file, err := os.OpenFile(dev.perfFile, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0o755) if err != nil { @@ -384,6 +384,7 @@ func (dev *IOSDevice) StopPerf() string { return "" } close(dev.perfStop) + log.Info().Str("perfFile", dev.perfFile).Msg("stop performance monitor") return dev.perfFile }