From cbe90cb3f6cfb5941bb96d454f1e0cf44e923592 Mon Sep 17 00:00:00 2001 From: spiritlhl <103393591+spiritLHLS@users.noreply.github.com> Date: Mon, 1 Jul 2024 11:28:16 +0000 Subject: [PATCH] =?UTF-8?q?v0.0.8=20-=20=E5=8A=A0=E5=85=A5=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E8=AE=B0=E5=BD=95=E5=8F=82=E6=95=B0=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=8F=82=E6=95=B0=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yaml | 2 +- cmd/main.go | 53 +++--- cpu/cputest.go | 382 ++++++++++++++++++++++---------------- cpu/version.go | 3 - model/model.go | 5 + 5 files changed, 262 insertions(+), 183 deletions(-) delete mode 100644 cpu/version.go create mode 100644 model/model.go diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 8271114..fd05332 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -24,7 +24,7 @@ jobs: run: | git config --global user.name 'github-actions' git config --global user.email 'github-actions@github.com' - TAG="v0.0.7-$(date +'%Y%m%d%H%M%S')" + TAG="v0.0.8-$(date +'%Y%m%d%H%M%S')" git tag $TAG git push origin $TAG env: diff --git a/cmd/main.go b/cmd/main.go index dbec5a0..c2c8727 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -4,10 +4,12 @@ import ( "flag" "fmt" "net/http" + "os" "runtime" "strings" "github.com/oneclickvirt/cputest/cpu" + "github.com/oneclickvirt/cputest/model" . "github.com/oneclickvirt/defaultset" ) @@ -16,50 +18,55 @@ func main() { http.Get("https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Foneclickvirt%2Fcputest&count_bg=%2323E01C&title_bg=%23555555&icon=sonarcloud.svg&icon_color=%23E7E7E7&title=hits&edge_flat=false") }() fmt.Println(Green("项目地址:"), Yellow("https://github.com/oneclickvirt/cputest")) - var showVersion bool - flag.BoolVar(&showVersion, "v", false, "show version") - languagePtr := flag.String("l", "", "Language parameter (en or zh)") - testMethodPtr := flag.String("m", "", "Specific Test Method (sysbench or geekbench)") - testThreadsPtr := flag.String("t", "", "Specific Test Threads (single or multi)") - flag.Parse() - if showVersion { - fmt.Println(cpu.CpuTestVersion) + var showVersion, help bool + var language, testMethod, testThreadMode string + cputestFlag := flag.NewFlagSet("cputest", flag.ContinueOnError) + cputestFlag.BoolVar(&help, "h", false, "Show help information") + cputestFlag.BoolVar(&showVersion, "v", false, "show version") + cputestFlag.StringVar(&language, "l", "", "Language parameter (en or zh)") + cputestFlag.StringVar(&testMethod, "m", "", "Specific Test Method (sysbench or geekbench)") + cputestFlag.StringVar(&testThreadMode, "t", "", "Specific Test Thread Mode (single or multi)") + cputestFlag.BoolVar(&model.EnableLoger, "log", false, "Enable logging") + cputestFlag.Parse(os.Args[1:]) + if help { + fmt.Printf("Usage: %s [options]\n", os.Args[0]) + cputestFlag.PrintDefaults() return } - var language, res, testMethod, testThread string - if *languagePtr == "" { - language = "zh" - } else { - language = strings.ToLower(*languagePtr) + if showVersion { + fmt.Println(model.CpuTestVersion) + return } - if *testMethodPtr == "" || *testMethodPtr == "sysbench" { + var res string + language = strings.ToLower(language) + if testMethod == "" || strings.ToLower(testMethod) == "sysbench" { testMethod = "sysbench" - } else if *testMethodPtr == "geekbench" { + } else if strings.ToLower(testMethod) == "geekbench" { testMethod = "geekbench" } - if *testThreadsPtr == "" || *testThreadsPtr == "single" { - testThread = "single" + if testThreadMode == "" || strings.ToLower(testThreadMode) == "single" { + testThreadMode = "single" } else { - testThread = strings.TrimSpace(strings.ToLower(*testThreadsPtr)) + testThreadMode = strings.TrimSpace(strings.ToLower(testThreadMode)) } if runtime.GOOS == "windows" { if testMethod != "winsat" && testMethod != "" { res = "Detected host is Windows, using Winsat for testing.\n" } - res += cpu.WinsatTest(language, testThread) + res += cpu.WinsatTest(language, testThreadMode) } else { switch testMethod { case "sysbench": - res = cpu.SysBenchTest(language, testThread) + res = cpu.SysBenchTest(language, testThreadMode) if res == "" { res = "Sysbench test failed, switching to Geekbench for testing.\n" - res += cpu.GeekBenchTest(language, testThread) + res += cpu.GeekBenchTest(language, testThreadMode) } case "geekbench": - res = cpu.GeekBenchTest(language, testThread) + res = cpu.GeekBenchTest(language, testThreadMode) if res == "" { res = "Geekbench test failed, switching to Sysbench for testing.\n" - res += cpu.SysBenchTest(language, testThread) + res += cpu.SysBenchTest(language, testThreadMode) } default: res = "Invalid test method specified.\n" diff --git a/cpu/cputest.go b/cpu/cputest.go index d24a660..ec6f0e1 100644 --- a/cpu/cputest.go +++ b/cpu/cputest.go @@ -14,6 +14,8 @@ import ( "github.com/PuerkitoBio/goquery" "github.com/imroc/req/v3" + "github.com/oneclickvirt/cputest/model" + . "github.com/oneclickvirt/defaultset" ) // runSysBenchCommand 执行 sysbench 命令进行测试 @@ -33,113 +35,150 @@ func runSysBenchCommand(numThreads, maxTime, version string) (string, error) { } func SysBenchTest(language, testThread string) string { + if model.EnableLoger { + InitLogger() + defer Logger.Sync() + } var result, singleScore, multiScore, totalTime, totalEvents string var temp []string comCheck := exec.Command("sysbench", "--version") output, err := comCheck.CombinedOutput() - if err == nil { - version := string(output) - if testThread == "single" { - singleResult, err := runSysBenchCommand("1", "5", version) - if err == nil { - tempList := strings.Split(singleResult, "\n") - for _, line := range tempList { - if strings.Contains(line, "events per second:") { - temp = strings.Split(line, ":") - if len(temp) == 2 { - singleScore = temp[1] - break - } - } else if singleScore == "" && totalTime == "" && strings.Contains(line, "total time:") { - temp = strings.Split(line, ":") - if len(temp) == 2 { - totalTime = strings.ReplaceAll(temp[1], "s", "") - } - } else if singleScore == "" && totalEvents == "" && strings.Contains(line, "total number of events:") { - temp = strings.Split(line, ":") - if len(temp) == 2 { - totalEvents = temp[1] - } - } + if err != nil { + if model.EnableLoger { + Logger.Info("cannot match sysbench command: " + err.Error()) + } + return "" + } + version := string(output) + if testThread == "single" { + singleResult, err := runSysBenchCommand("1", "5", version) + if err != nil { + if model.EnableLoger { + Logger.Info("sysbench test single score error: " + err.Error()) + } + return "" + } + tempList := strings.Split(singleResult, "\n") + for _, line := range tempList { + if strings.Contains(line, "events per second:") { + temp = strings.Split(line, ":") + if len(temp) == 2 { + singleScore = temp[1] + break } - if singleScore == "" && totalTime != "" && totalEvents != "" { - totalEventsFloat, err1 := strconv.ParseFloat(totalEvents, 64) - if err1 == nil { - totalTimeFloat, err2 := strconv.ParseFloat(totalTime, 64) - if err2 == nil { - singleScoreFloat := totalEventsFloat / totalTimeFloat - singleScore = strconv.FormatFloat(singleScoreFloat, 'f', 2, 64) - totalTime, totalEvents = "", "" - } - } + } else if singleScore == "" && totalTime == "" && strings.Contains(line, "total time:") { + temp = strings.Split(line, ":") + if len(temp) == 2 { + totalTime = strings.ReplaceAll(temp[1], "s", "") + } + } else if singleScore == "" && totalEvents == "" && strings.Contains(line, "total number of events:") { + temp = strings.Split(line, ":") + if len(temp) == 2 { + totalEvents = temp[1] } } - if language == "en" { - result += "1 Thread(s) Test: " - } else { - result += "1 线程测试(单核)得分: " + } + if singleScore == "" && totalTime != "" && totalEvents != "" { + totalEventsFloat, err1 := strconv.ParseFloat(totalEvents, 64) + if err1 != nil { + if model.EnableLoger { + Logger.Info("parse total events error: " + err1.Error()) + } + return "" } - result += singleScore + "\n" - } else if testThread == "multi" { - singleResult, err := runSysBenchCommand("1", "5", version) - if err == nil { - tempList := strings.Split(singleResult, "\n") - for _, line := range tempList { - if strings.Contains(line, "events per second:") { - temp = strings.Split(line, ":") - if len(temp) == 2 { - singleScore = temp[1] - } - } + totalTimeFloat, err2 := strconv.ParseFloat(totalTime, 64) + if err2 != nil { + if model.EnableLoger { + Logger.Info("parse total time error: " + err2.Error()) } + return "" } - if language == "en" { - result += "1 Thread(s) Test: " - } else { - result += "1 线程测试(单核)得分: " + singleScoreFloat := totalEventsFloat / totalTimeFloat + singleScore = strconv.FormatFloat(singleScoreFloat, 'f', 2, 64) + totalTime, totalEvents = "", "" + } + if language == "en" { + result += "1 Thread(s) Test: " + } else { + result += "1 线程测试(单核)得分: " + } + result += singleScore + "\n" + } else if testThread == "multi" { + singleResult, err := runSysBenchCommand("1", "5", version) + if err != nil { + if model.EnableLoger { + Logger.Info("sysbench test single score error: " + err.Error()) + } + return "" + } + + tempList := strings.Split(singleResult, "\n") + for _, line := range tempList { + if strings.Contains(line, "events per second:") { + temp = strings.Split(line, ":") + if len(temp) == 2 { + singleScore = temp[1] + } + } + } + if language == "en" { + result += "1 Thread(s) Test: " + } else { + result += "1 线程测试(单核)得分: " + } + result += singleScore + "\n" + if runtime.NumCPU() > 1 { + multiResult, err := runSysBenchCommand(fmt.Sprintf("%d", runtime.NumCPU()), "5", version) + if err != nil { + if model.EnableLoger { + Logger.Info("sysbench test multi score error: " + err.Error()) + } + return "" } - result += singleScore + "\n" - if runtime.NumCPU() > 1 { - multiResult, err := runSysBenchCommand(fmt.Sprintf("%d", runtime.NumCPU()), "5", version) - if err == nil { - tempList := strings.Split(multiResult, "\n") - for _, line := range tempList { - if strings.Contains(line, "events per second:") { - temp1 := strings.Split(line, ":") - if len(temp1) == 2 { - multiScore = temp1[1] - } - } else if multiScore == "" && totalTime == "" && strings.Contains(line, "total time:") { - temp = strings.Split(line, ":") - if len(temp) == 2 { - totalTime = strings.ReplaceAll(temp[1], "s", "") - } - } else if multiScore == "" && totalEvents == "" && strings.Contains(line, "total number of events:") { - temp = strings.Split(line, ":") - if len(temp) == 2 { - totalEvents = temp[1] - } - } + tempList := strings.Split(multiResult, "\n") + for _, line := range tempList { + if strings.Contains(line, "events per second:") { + temp1 := strings.Split(line, ":") + if len(temp1) == 2 { + multiScore = temp1[1] } - if multiScore == "" && totalTime != "" && totalEvents != "" { - totalEventsFloat, err1 := strconv.ParseFloat(totalEvents, 64) - if err1 == nil { - totalTimeFloat, err2 := strconv.ParseFloat(totalTime, 64) - if err2 == nil { - multiScoreFloat := totalEventsFloat / totalTimeFloat - multiScore = strconv.FormatFloat(multiScoreFloat, 'f', 2, 64) - totalTime, totalEvents = "", "" - } - } + } else if multiScore == "" && totalTime == "" && strings.Contains(line, "total time:") { + temp = strings.Split(line, ":") + if len(temp) == 2 { + totalTime = strings.ReplaceAll(temp[1], "s", "") + } + } else if multiScore == "" && totalEvents == "" && strings.Contains(line, "total number of events:") { + temp = strings.Split(line, ":") + if len(temp) == 2 { + totalEvents = temp[1] } } - if language == "en" { - result += fmt.Sprintf("%d", runtime.NumCPU()) + " Thread(s) Test: " - } else { - result += fmt.Sprintf("%d", runtime.NumCPU()) + " 线程测试(多核)得分: " + } + if multiScore == "" && totalTime != "" && totalEvents != "" { + totalEventsFloat, err1 := strconv.ParseFloat(totalEvents, 64) + if err1 != nil { + if model.EnableLoger { + Logger.Info("parse total events error: " + err1.Error()) + } + return "" + } + totalTimeFloat, err2 := strconv.ParseFloat(totalTime, 64) + if err2 != nil { + if model.EnableLoger { + Logger.Info("parse total time error: " + err2.Error()) + } + return "" } - result += multiScore + "\n" + multiScoreFloat := totalEventsFloat / totalTimeFloat + multiScore = strconv.FormatFloat(multiScoreFloat, 'f', 2, 64) + totalTime, totalEvents = "", "" } + if language == "en" { + result += fmt.Sprintf("%d", runtime.NumCPU()) + " Thread(s) Test: " + } else { + result += fmt.Sprintf("%d", runtime.NumCPU()) + " 线程测试(多核)得分: " + } + result += multiScore + "\n" } } return result @@ -157,85 +196,106 @@ func runGeekbenchCommand() (string, error) { // 调用 geekbench 命令执行 // https://github.com/masonr/yet-another-bench-script/blob/0ad4c4e85694dbcf0958d8045c2399dbd0f9298c/yabs.sh#L894 func GeekBenchTest(language, testThread string) string { + if model.EnableLoger { + InitLogger() + defer Logger.Sync() + } var result, singleScore, multiScore, link string comCheck := exec.Command("geekbench", "--version") // Geekbench 5.4.5 Tryout Build 503938 (corktown-master-build 6006e737ba) output, err := comCheck.CombinedOutput() version := string(output) - if err == nil { - if strings.Contains(version, "Geekbench 6") { - // 检测存在 /etc/os-release 文件且含 CentOS Linux 7 时,需要预先下载 GLIBC_2.27 才能使用 geekbench 6 - file, err := os.Open("/etc/os-release") - defer file.Close() - if err == nil { - scanner := bufio.NewScanner(file) - isCentOS7 := false - // 逐行读取文件内容 - for scanner.Scan() { - line := scanner.Text() - if strings.Contains(line, "CentOS Linux 7") { - isCentOS7 = true - break - } - } - if err := scanner.Err(); err == nil { - // 如果文件中包含 CentOS Linux 7,则打印提示信息 - if isCentOS7 && language == "zh" { - return "需要预先下载 GLIBC_2.27 才能使用 geekbench 6" - } else if isCentOS7 && language != "zh" { - return "You need to pre-download GLIBC_2.27 to use geekbench 6." - } + if err != nil { + if model.EnableLoger { + Logger.Info("cannot match geekbench command: " + err.Error()) + } + return "" + } + if strings.Contains(version, "Geekbench 6") { + // 检测存在 /etc/os-release 文件且含 CentOS Linux 7 时,需要预先下载 GLIBC_2.27 才能使用 geekbench 6 + file, err := os.Open("/etc/os-release") + defer file.Close() + if err == nil { + scanner := bufio.NewScanner(file) + isCentOS7 := false + for scanner.Scan() { + line := scanner.Text() + if strings.Contains(line, "CentOS Linux 7") { + isCentOS7 = true + break } } - } - // 解析 geekbench 执行结果 - if strings.Contains(version, "Geekbench") { - tp, err := runGeekbenchCommand() - if err == nil { - tempList := strings.Split(tp, "\n") - for _, line := range tempList { - if strings.Contains(line, "https://browser.geekbench.com") && strings.Contains(line, "cpu") { - link = strings.TrimSpace(line) - break - } + if err := scanner.Err(); err == nil { + // 如果文件中包含 CentOS Linux 7,则打印提示信息 + if isCentOS7 && language == "zh" { + return "需要预先下载 GLIBC_2.27 才能使用 geekbench 6" + } else if isCentOS7 && language != "zh" { + return "You need to pre-download GLIBC_2.27 to use geekbench 6." } } } - const ( - userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36" - accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" - referer = "browser.geekbench.com" - ) - client := req.DefaultClient() - client.SetTimeout(6 * time.Second) - client.SetCommonHeader("User-Agent", userAgent) - client.SetCommonHeader("Accept", accept) - client.SetCommonHeader("Referer", referer) - resp, err := client.R().Get(link) - if err != nil { - return "" + } + tp, err := runGeekbenchCommand() + if err != nil { + if model.EnableLoger { + Logger.Info("run geekbench command error: " + err.Error()) } - defer resp.Body.Close() - b, err := io.ReadAll(resp.Body) - if err != nil { - return "" + return "" + } + // 解析 geekbench 执行结果 + tempList := strings.Split(tp, "\n") + for _, line := range tempList { + if strings.Contains(line, "https://browser.geekbench.com") && strings.Contains(line, "cpu") { + link = strings.TrimSpace(line) + break } - body := string(b) - if resp.StatusCode != http.StatusOK { - return "" + } + const ( + userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36" + accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" + referer = "browser.geekbench.com" + ) + client := req.DefaultClient() + client.SetTimeout(6 * time.Second) + client.SetCommonHeader("User-Agent", userAgent) + client.SetCommonHeader("Accept", accept) + client.SetCommonHeader("Referer", referer) + resp, err := client.R().Get(link) + if err != nil { + if model.EnableLoger { + Logger.Info("geekbench test link error: " + err.Error()) } - doc, readErr := goquery.NewDocumentFromReader(strings.NewReader(body)) - if readErr != nil { - return "" + return "" + } + defer resp.Body.Close() + b, err := io.ReadAll(resp.Body) + if err != nil { + if model.EnableLoger { + Logger.Info("read response body error: " + err.Error()) } - textContent := doc.Find(".table-wrapper.cpu").Text() - resList := strings.Split(textContent, "\n") - for index, l := range resList { - if strings.Contains(l, "Single-Core") { - singleScore = resList[index-1] - } else if strings.Contains(l, "Multi-Core") { - multiScore = resList[index-1] - } + return "" + } + body := string(b) + if resp.StatusCode != http.StatusOK { + if model.EnableLoger { + Logger.Info("geekbench test status code not OK") + } + return "" + } + doc, readErr := goquery.NewDocumentFromReader(strings.NewReader(body)) + if readErr != nil { + if model.EnableLoger { + Logger.Info("parse response body error: " + readErr.Error()) + } + return "" + } + textContent := doc.Find(".table-wrapper.cpu").Text() + resList := strings.Split(textContent, "\n") + for index, l := range resList { + if strings.Contains(l, "Single-Core") { + singleScore = resList[index-1] + } else if strings.Contains(l, "Multi-Core") { + multiScore = resList[index-1] } } if link != "" && singleScore != "" { @@ -250,10 +310,17 @@ func GeekBenchTest(language, testThread string) string { } func WinsatTest(language, testThread string) string { + if model.EnableLoger { + InitLogger() + defer Logger.Sync() + } var result string cmd1 := exec.Command("winsat", "cpu", "-encryption") output1, err1 := cmd1.Output() if err1 != nil { + if model.EnableLoger { + Logger.Info("winsat cpu encryption error: " + err1.Error()) + } return "" } else { tempList := strings.Split(string(output1), "\n") @@ -273,6 +340,9 @@ func WinsatTest(language, testThread string) string { cmd2 := exec.Command("winsat", "cpu", "-compression") output2, err2 := cmd2.Output() if err2 != nil { + if model.EnableLoger { + Logger.Info("winsat cpu compression error: " + err2.Error()) + } return "" } else { tempList := strings.Split(string(output2), "\n") diff --git a/cpu/version.go b/cpu/version.go deleted file mode 100644 index c08087b..0000000 --- a/cpu/version.go +++ /dev/null @@ -1,3 +0,0 @@ -package cpu - -const CpuTestVersion = "v0.0.7" diff --git a/model/model.go b/model/model.go new file mode 100644 index 0000000..c3dd8a7 --- /dev/null +++ b/model/model.go @@ -0,0 +1,5 @@ +package model + +const CpuTestVersion = "v0.0.8" + +var EnableLoger = false