diff --git a/host/ide/build.js b/host/ide/build.js index 6a5fbd5f22c8e3b5b2b9a13a8825742df7563583..f153f333d4055d508fd83648262996331f2d32a7 100644 --- a/host/ide/build.js +++ b/host/ide/build.js @@ -17,47 +17,115 @@ const path = require('path'); const fs = require("fs"); const child_process = require("child_process"); const os = require("os"); +const log4js = require("log4js"); const compileServer = true const outDir = "dist" +const sdkWams = [ + "trace_streamer_sdk_builtin.js", + "trace_streamer_sdk_builtin.wasm" +] + const staticPath = [ "/src/img", "/server/cert", + "/src/doc", + "/src/figures", ] const staticFiles = [ "/server/version.txt", "/src/index.html", - "/src/base-ui/icon.svg" + "/src/base-ui/icon.svg", + "/server/wasm.json" ] const thirdParty = [ - {srcFilePath: "/third-party/sql-wasm.wasm", distFilePath:"/trace/database/sql-wasm.wasm" }, - {srcFilePath: "/third-party/sql-wasm.js", distFilePath:"/trace/database/sql-wasm.js" }, - {srcFilePath: "/third-party/worker.sql-wasm.js", distFilePath:"/trace/database/worker.sql-wasm.js"} + {srcFilePath: "/third-party/sql-wasm.wasm", distFilePath: "/trace/database/sql-wasm.wasm"}, + {srcFilePath: "/third-party/sql-wasm.js", distFilePath: "/trace/database/sql-wasm.js"}, + {srcFilePath: "/third-party/worker.sql-wasm.js", distFilePath: "/trace/database/worker.sql-wasm.js"} ] +let log; + function cpFile(from, to) { - fs.writeFileSync(to, fs.readFileSync(from)) + if (fs.existsSync(from)) { + fs.writeFileSync(to, fs.readFileSync(from)) + log.info("cp file %s to %s", from, to) + } else { + log.warn("file %s is not exists", from, to) + } } +function checkEnvironment() { + let goVersion = child_process.execSync("go version", { + encoding: "utf-8" + }) + log.info("go is", goVersion) + let nodeVersion = child_process.execSync("node -v", { + encoding: "utf-8" + }) + log.info("node version is", nodeVersion) + let tscVersion = child_process.execSync("tsc -v", { + encoding: "utf-8" + }) + log.info("tsc version is", tscVersion) + if (goVersion == "" || nodeVersion == "" || tscVersion == "") { + return false; + } + let traceStreamer = path.normalize(path.join(__dirname, "/bin")); + if (!checkDirExist(traceStreamer + "/trace_streamer_builtin.js")) { + log.error(traceStreamer + "/trace_streamer_builtin.js" + " Must exist") + return false; + } + if (!checkDirExist(traceStreamer + "/trace_streamer_builtin.wasm")) { + log.error(traceStreamer + "/trace_streamer_builtin.wasm" + " Must exist") + return false; + } + return true; +} + + +function initLog() { + log4js.configure({ + appenders: { + out: {type: "stdout"}, + }, + categories: { + default: {appenders: ["out"], level: "debug"}, + }, + }); + return log4js.getLogger("smartPerf"); +} + + function main() { + log = initLog(); + if (!checkEnvironment()) { + return; + } // clean outDir let outPath = path.normalize(path.join(__dirname, "/", outDir)); if (checkDirExist(outPath)) { + log.info("delete the last compilation result") removeDir(outPath) + log.info("delete the last compilation success") } // run tsc compile - let rootPath = path.join(__dirname,"/"); - child_process.execSync("tsc -p "+ rootPath) + log.info("start compiling typeScript code") + let rootPath = path.join(__dirname, "/"); + child_process.execSync("tsc -p " + rootPath, { + encoding: "utf-8" + }) + log.info("compiling typeScript code success") // run cp to mv all staticFile staticFiles.forEach(value => { let filePath = path.join(__dirname, value) let distFile; - if(value.startsWith("/src")) { + if (value.startsWith("/src")) { distFile = path.join(__dirname, outDir, value.substring(4, value.length + 1)) - } else if (value.startsWith("/server")){ + } else if (value.startsWith("/server")) { distFile = path.join(__dirname, outDir, value.substring(7, value.length + 1)) } cpFile(filePath, distFile); @@ -65,16 +133,16 @@ function main() { staticPath.forEach(value => { let pa = path.join(__dirname, value) let distPath; - if(value.startsWith("/src")) { + if (value.startsWith("/src")) { distPath = path.join(__dirname, outDir, value.substring(4, value.length + 1)) - } else if (value.startsWith("/server")){ + } else if (value.startsWith("/server")) { distPath = path.join(__dirname, outDir, value.substring(7, value.length + 1)) } copyDirectory(pa, distPath); }) thirdParty.forEach(value => { let thirdFile = path.join(__dirname, value.srcFilePath) - let thirdDistFile = path.join(__dirname, outDir, value.distFilePath) + let thirdDistFile = path.join(__dirname, outDir, value.distFilePath) cpFile(thirdFile, thirdDistFile); }) let traceStreamer = path.normalize(path.join(__dirname, "/bin")); @@ -82,22 +150,44 @@ function main() { let dest = path.normalize(path.join(__dirname, outDir, "/bin")); copyDirectory(traceStreamer, dest) // to mv traceStream Wasm and js - cpFile(traceStreamer + "/trace_streamer_builtin.js", rootPath + outDir +"/trace/database/trace_streamer_builtin.js") + cpFile(traceStreamer + "/trace_streamer_builtin.js", rootPath + outDir + "/trace/database/trace_streamer_builtin.js") cpFile(traceStreamer + "/trace_streamer_builtin.wasm", rootPath + outDir + "/trace/database/trace_streamer_builtin.wasm") + if (sdkWams.length > 0) { + sdkWams.forEach(fileName => { + cpFile(traceStreamer + "/" + fileName, rootPath + outDir + "/trace/database/" + fileName) + }) + } } else { - throw new Error("traceStreamer dir is Not Exits") + log.error("traceStreamer dir is not Exits") + return; } // compile server if (compileServer) { + log.log("start compile server") let serverSrc = path.normalize(path.join(__dirname, "/server/main.go")); + let rs; if (os.type() === "Windows_NT") { - child_process.spawnSync("go", ["build", "-o", outPath, serverSrc]) - } else if (os.type() == "Darwin"){ - child_process.spawnSync("go", ["build", "-o", outPath + "/main", serverSrc]) + rs = child_process.spawnSync("go", ["build", "-o", outPath, serverSrc], { + encoding: "utf-8" + }) + } else if (os.type() == "Darwin") { + rs = child_process.spawnSync("go", ["build", "-o", outPath + "/main", serverSrc], { + encoding: "utf-8" + }) } else { - child_process.spawnSync("go", ["build", "-o", outPath + "/main", serverSrc]) + rs = child_process.spawnSync("go", ["build", "-o", outPath + "/main", serverSrc], { + encoding: "utf-8" + }) } + if (rs.status == 0) { + log.log("compile server success") + } else { + log.error("compile server failed", rs) + } + } else { + log.warn("skip compile server") } + log.log("smartPerf compile success") } @@ -109,12 +199,14 @@ function copyDirectory(src, dest) { return false; } let directories = fs.readdirSync(src); - directories.forEach((value) =>{ + directories.forEach((value) => { let filePath = path.join(src, value); let fileSys = fs.statSync(filePath); if (fileSys.isFile()) { - fs.copyFileSync(filePath, path.join(dest, value)); - } else if (fileSys.isDirectory()){ + let destPath = path.join(dest, value); + log.info("cp file %s to %s", filePath, destPath) + fs.copyFileSync(filePath, destPath); + } else if (fileSys.isDirectory()) { copyDirectory(filePath, path.join(dest, value)); } }); @@ -126,11 +218,11 @@ function checkDirExist(dirPath) { function removeDir(outPath) { let files = []; - if(fs.existsSync(outPath)){ + if (fs.existsSync(outPath)) { files = fs.readdirSync(outPath); files.forEach((file, index) => { let curPath = outPath + "/" + file; - if(fs.statSync(curPath).isDirectory()){ + if (fs.statSync(curPath).isDirectory()) { removeDir(curPath); } else { fs.unlinkSync(curPath); @@ -139,4 +231,5 @@ function removeDir(outPath) { fs.rmdirSync(outPath); } } + main(); \ No newline at end of file diff --git a/host/ide/package.json b/host/ide/package.json index bc4e0ea0d5faee107ccc936dd72fc662f27c4def..834363e4dd69b7873f424e1e6e1c21b5cc866aba 100644 --- a/host/ide/package.json +++ b/host/ide/package.json @@ -1,12 +1,12 @@ { "name": "SmartPerf", "version": "1.0.0", - "description": "SmartPerf", + "description": "Smart Perf", "main": "index.js", "scripts": { "compile": "node ./build.js", - "test": "jest", - "test-c": "jest --coverage" + "test": "jest -u", + "test-c": "jest --coverage -u" }, "jest": { "testEnvironment": "jsdom", @@ -18,7 +18,8 @@ "!/dist/trace/database/uuidv4.min.js", "!/dist/trace/database/worker.sql-wasm.js", "!/dist/trace/database/worker.sql-wasm-debug.js", - "!/node_modules/" + "!/dist/trace/database/trace_streamer_builtin.js", + "!/dist/trace/database/trace_streamer_sdk_builtin.js" ], "globals": { "useWb": true @@ -26,6 +27,9 @@ "setupFiles": [ "jsdom-worker", "jest-canvas-mock" + ], + "setupFilesAfterEnv": [ + "/jest.setup.js" ] }, "repository": { @@ -44,7 +48,11 @@ "jest": "*", "jest-canvas-mock": "^2.3.1", "typescript": "^4.2.3", - "jsdom-worker": "^0.2.1" + "jsdom-worker": "^0.2.1", + "jest-environment-jsdom": "^28.1.0", + "node-fetch": "^2.6.7", + "log4js": "^6.4.4", + "usb": "^2.4.2" }, "dependencies": {} } diff --git a/host/ide/server/main.go b/host/ide/server/main.go index 995cffe734c904b684c312f684c1fba216080618..030d70a3ca7055150cf9ff65c436117f5a329968 100644 --- a/host/ide/server/main.go +++ b/host/ide/server/main.go @@ -15,28 +15,31 @@ package main //遇到报错请在当前目录下执行这个命令: go mod download golang.org/x/text import ( - "bufio" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "math/big" - "net" - "bytes" - "fmt" - "io" - "io/ioutil" - "log" - "mime" - "net/http" - "os" - "os/exec" - "path" - "path/filepath" - "runtime" - "strings" - "time" + "bufio" + "bytes" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/json" + "encoding/pem" + "fmt" + "io" + "io/ioutil" + "log" + "math/big" + "mime" + "net" + "net/http" + "os" + "os/exec" + "path" + "path/filepath" + "regexp" + "runtime" + "strconv" + "strings" + "time" ) const HttpPort = 9000 @@ -46,305 +49,359 @@ var exPath string // CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go // CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go func cors(fs http.Handler, version string) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { // return if you do not want the FileServer handle a specific request - r.Header.Add("Cross-Origin-Opener-Policy", "same-origin") - r.Header.Add("Cross-Origin-Embedder-Policy", "require-corp") - w.Header().Add("Cross-Origin-Opener-Policy", "same-origin") - w.Header().Add("Cross-Origin-Embedder-Policy", "require-corp") - w.Header().Set("Access-Control-Allow-Origin", "*") - w.Header().Set("Access-Control-Allow-Credentials", "true") - w.Header().Set("Access-Control-Allow-Headers", "x-requested-with, authorization, blade-auth") //* - w.Header().Set("Access-Control-Allow-Methods", "*") //* - w.Header().Set("Access-Control-Max-Age", "3600") - w.Header().Set("data-version", version) - fs.ServeHTTP(w, r) - } + r.Header.Add("Cross-Origin-Opener-Policy", "same-origin") + r.Header.Add("Cross-Origin-Embedder-Policy", "require-corp") + w.Header().Add("Cross-Origin-Opener-Policy", "same-origin") + w.Header().Add("Cross-Origin-Embedder-Policy", "require-corp") + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Credentials", "true") + w.Header().Set("Access-Control-Allow-Headers", "x-requested-with, authorization, blade-auth") //* + w.Header().Set("Access-Control-Allow-Methods", "*") //* + w.Header().Set("Access-Control-Max-Age", "3600") + w.Header().Set("data-version", version) + fs.ServeHTTP(w, r) + } } func exist(path string) bool { - _, err := os.Stat(path) - if err != nil { - if os.IsExist(err) { - return true - } - return false - } - return true + _, err := os.Stat(path) + if err != nil { + if os.IsExist(err) { + return true + } + return false + } + return true } func genSSL() { - if exist("cert/keyFile.key") || exist("cert/certFile.pem") { - fmt.Println("keyFile.key exists") - return - } - max := new(big.Int).Lsh(big.NewInt(1), 128) - serialNumber, _ := rand.Int(rand.Reader, max) - subject := pkix.Name{ - Organization: []string{"www.smartperf.com"}, - OrganizationalUnit: []string{"ITs"}, - CommonName: "www.smartperf.com", + if exist("cert/keyFile.key") || exist("cert/certFile.pem") { + fmt.Println("keyFile.key exists") + return + } + max := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, _ := rand.Int(rand.Reader, max) + subject := pkix.Name{ + Organization: []string{"www.smartperf.com"}, + OrganizationalUnit: []string{"ITs"}, + CommonName: "www.smartperf.com", + } + certificate509 := x509.Certificate{ + SerialNumber: serialNumber, + Subject: subject, + NotBefore: time.Now(), + NotAfter: time.Now().AddDate(10, 0, 0), + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, } - certificate509 := x509.Certificate{ - SerialNumber: serialNumber, - Subject: subject, - NotBefore: time.Now(), - NotAfter: time.Now().AddDate(10, 0, 0), - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, - } - chekDir("cert") - pk, _ := rsa.GenerateKey(rand.Reader, 1024) - derBytes, _ := x509.CreateCertificate(rand.Reader, &certificate509, &certificate509, &pk.PublicKey, pk) - certOut, _ := os.Create("cert/certFile.pem") - pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) - certOut.Close() - keyOut, _ := os.Create("cert/keyFile.key") - pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(pk)}) - keyOut.Close() + chekDir("cert") + pk, _ := rsa.GenerateKey(rand.Reader, 1024) + derBytes, _ := x509.CreateCertificate(rand.Reader, &certificate509, &certificate509, &pk.PublicKey, pk) + certOut, _ := os.Create("cert/certFile.pem") + pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + certOut.Close() + keyOut, _ := os.Create("cert/keyFile.key") + pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(pk)}) + keyOut.Close() } func main() { - genSSL() - exPath = getCurrentAbPath() - fmt.Println(exPath) - go func() { - version := "" - readVersion, versionErr := ioutil.ReadFile(exPath + "/version.txt") - if versionErr != nil { - version = "" - } else { - version = string(readVersion) - } - mux := http.NewServeMux() - mime.TypeByExtension(".js") - mime.AddExtensionType(".js", "application/javascript") - log.Println(mime.TypeByExtension(".js")) - mux.HandleFunc("/upload", uploadHandler) - mux.Handle("/upload/", http.StripPrefix("/upload/", http.FileServer(http.Dir(exPath+"/upload")))) - fs := http.FileServer(http.Dir(exPath + "/")) - mux.Handle("/application/", http.StripPrefix("/application/", cors(fs, version))) - ser := &http.Server{ - Addr: fmt.Sprintf(":%d", HttpPort), - Handler: mux, - } - log.Println(fmt.Sprintf("HTTP[%d]服务启动", HttpPort)) - open(fmt.Sprintf("https://localhost:%d/application", HttpPort)) - err := ser.ListenAndServeTLS("cert/certFile.pem", "cert/keyFile.key") - CheckErr(err) - }() - select {} + checkPort(HttpPort) + genSSL() + exPath = getCurrentAbPath() + fmt.Println(exPath) + go func() { + version := "" + readVersion, versionErr := ioutil.ReadFile(exPath + "/version.txt") + if versionErr != nil { + version = "" + } else { + version = string(readVersion) + } + mux := http.NewServeMux() + mime.TypeByExtension(".js") + mime.AddExtensionType(".js", "application/javascript") + log.Println(mime.TypeByExtension(".js")) + mux.HandleFunc("/upload", uploadHandler) + mux.HandleFunc("/logger", consoleHandler) + mux.Handle("/upload/", http.StripPrefix("/upload/", http.FileServer(http.Dir(exPath+"/upload")))) + fs := http.FileServer(http.Dir(exPath + "/")) + mux.Handle("/application/", http.StripPrefix("/application/", cors(fs, version))) + ser := &http.Server{ + Addr: fmt.Sprintf(":%d", HttpPort), + Handler: mux, + } + log.Println(fmt.Sprintf("HTTP[%d]服务启动", HttpPort)) + open(fmt.Sprintf("https://localhost:%d/application", HttpPort)) + err := ser.ListenAndServeTLS("cert/certFile.pem", "cert/keyFile.key") + CheckErr(err) + }() + select {} +} + +func getPidByPort(portNumber int) int { + resPid := -1 + var out bytes.Buffer + cmdRes := exec.Command("cmd", "/c", fmt.Sprintf("netstat -ano -p tcp | findstr %d", portNumber)) + cmdRes.Stdout = &out + cmdRes.Run() + cmdResStr := out.String() + findStr := regexp.MustCompile(`\s\d+\s`).FindAllString(cmdResStr, -1) + if len(findStr) > 0 { + pid, err := strconv.Atoi(strings.TrimSpace(findStr[0])) + if err != nil { + resPid = -1 + } else { + resPid = pid + } + } + return resPid } +type LoggerReq struct { + FileName string `json:"fileName"` + FileSize string `json:"fileSize"` +} + +func consoleHandler(w http.ResponseWriter, r *http.Request) { + chekDir(exPath + "/logger") + var now = time.Now() + var fileName = fmt.Sprintf("%d-%d-%d", now.Year(), now.Month(), now.Day()) + dst, err := os.OpenFile(exPath+"/logger/"+fileName, os.O_WRONLY|os.O_CREATE|os.O_APPEND|os.O_SYNC, 0666) + CheckErr(err) + contentType := r.Header["Content-Type"] + if len(contentType) > 0 { + contentTypeName := contentType[0] + if strings.HasPrefix(contentTypeName, "application/json") { + decoder := json.NewDecoder(r.Body) + var req LoggerReq + decoder.Decode(&req) + dst.WriteString(fmt.Sprintf("%s %s (%s M)\n", now.Format("2006-01-02 15:04:05"), req.FileName, req.FileSize)) + fmt.Fprintf(w, fmt.Sprintf("日志写入成功%s", exPath)) + } + } +} func uploadHandler(w http.ResponseWriter, r *http.Request) { - defer func() { - var err = recover() - fmt.Println(err) - }() - chekDir(exPath + "/upload") - contentType := r.Header["Content-Type"] - if len(contentType) > 0 { - contentTypeName := contentType[0] - if strings.HasPrefix(contentTypeName, "multipart/form-data") { - err := r.ParseMultipartForm(32 << 20) - CheckErr(err) - file, header, err := r.FormFile("file") - CheckErr(err) - filename := header.Filename - index := strings.LastIndex(filename, ".") - distFileName := fmt.Sprintf("%d", time.Now().Unix()) - distFileSuffix := filename[index:] - path := fmt.Sprintf("/upload/%s%s", distFileName, distFileSuffix) - dst, err := os.OpenFile(exPath+path, os.O_WRONLY|os.O_CREATE, 0666) - CheckErr(err) - defer dst.Close() - if _, err := io.Copy(dst, file); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - databaseUrl := transformDatabase(distFileName, distFileSuffix) - if databaseUrl != "" { - ohosTsPath := fmt.Sprintf("./upload/%s.ohos.ts", databaseUrl) - result, _ := PathExists(ohosTsPath) - if result { - readFile, readErr := ioutil.ReadFile(ohosTsPath) - if readErr == nil { - fmt.Println(string(readFile)) - split := SplitLines(string(readFile)) - fmt.Println(split) - if len(split) > 1 { - if strings.HasSuffix(split[0], ":0") { - fmt.Fprintf(w, fmt.Sprintf("/upload/%s", databaseUrl)) - return - } - } - } - } - } - http.Error(w, "文件生成失败", http.StatusNotFound) - return - } - } + defer func() { + var err = recover() + fmt.Println(err) + }() + chekDir(exPath + "/upload") + contentType := r.Header["Content-Type"] + if len(contentType) > 0 { + contentTypeName := contentType[0] + if strings.HasPrefix(contentTypeName, "multipart/form-data") { + err := r.ParseMultipartForm(32 << 20) + CheckErr(err) + file, header, err := r.FormFile("file") + CheckErr(err) + filename := header.Filename + index := strings.LastIndex(filename, ".") + distFileName := fmt.Sprintf("%d", time.Now().Unix()) + distFileSuffix := filename[index:] + path := fmt.Sprintf("/upload/%s%s", distFileName, distFileSuffix) + dst, err := os.OpenFile(exPath+path, os.O_WRONLY|os.O_CREATE, 0666) + CheckErr(err) + defer dst.Close() + if _, err := io.Copy(dst, file); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + databaseUrl := transformDatabase(distFileName, distFileSuffix) + if databaseUrl != "" { + ohosTsPath := fmt.Sprintf("./upload/%s.ohos.ts", databaseUrl) + result, _ := PathExists(ohosTsPath) + if result { + readFile, readErr := ioutil.ReadFile(ohosTsPath) + if readErr == nil { + fmt.Println(string(readFile)) + split := SplitLines(string(readFile)) + fmt.Println(split) + if len(split) > 1 { + if strings.HasSuffix(split[0], ":0") { + fmt.Fprintf(w, fmt.Sprintf("/upload/%s", databaseUrl)) + return + } + } + } + } + } + http.Error(w, "文件生成失败", http.StatusNotFound) + return + } + } } func SplitLines(s string) []string { - var lines []string - sc := bufio.NewScanner(strings.NewReader(s)) - for sc.Scan() { - lines = append(lines, sc.Text()) - } - return lines + var lines []string + sc := bufio.NewScanner(strings.NewReader(s)) + for sc.Scan() { + lines = append(lines, sc.Text()) + } + return lines } func readFileFirstLine(path string) string { - file, err := os.Open(path) - if err != nil { - return "" - } - defer file.Close() + file, err := os.Open(path) + if err != nil { + return "" + } + defer file.Close() - readFile := bufio.NewReader(file) - line, readErr := readFile.ReadString('\n') - if readErr != nil || io.EOF == err { - return "" - } - return line + readFile := bufio.NewReader(file) + line, readErr := readFile.ReadString('\n') + if readErr != nil || io.EOF == err { + return "" + } + return line } func PathExists(path string) (bool, error) { - _, err := os.Stat(path) - if err == nil { - return true, nil - } - if os.IsNotExist(err) { - return false, nil - } - return false, err + _, err := os.Stat(path) + if err == nil { + return true, nil + } + if os.IsNotExist(err) { + return false, nil + } + return false, err } func chekDir(path string) { - _, err := os.Stat(path) - if err != nil { - err := os.Mkdir(path, os.ModePerm) - if err != nil { - fmt.Printf("mkdir failed![%v]\n", err) - } else { - fmt.Printf("mkdir success!\n") - } - } + _, err := os.Stat(path) + if err != nil { + err := os.Mkdir(path, os.ModePerm) + if err != nil { + fmt.Printf("mkdir failed![%v]\n", err) + } else { + fmt.Printf("mkdir success!\n") + } + } } func CheckErr(err error) { - if err != nil { - log.Panicln(err) - } + if err != nil { + log.Panicln(err) + } } func open(url string) error { - if isWindows() { - return openUrlWindows(url) - } else if isDarwin() { - return openUrlDarwin(url) - } else { - return openUrlOther(url) - } + if isWindows() { + return openUrlWindows(url) + } else if isDarwin() { + return openUrlDarwin(url) + } else { + return openUrlOther(url) + } } func openUrlWindows(url string) error { - cmd := "cmd" - args := []string{"/c", "start", url} - return exec.Command(cmd, args...).Start() + cmd := "cmd" + args := []string{"/c", "start", url} + return exec.Command(cmd, args...).Start() } func openUrlDarwin(url string) error { - var cmd = "open" - var args = []string{url} - return exec.Command(cmd, args...).Start() + var cmd = "open" + var args = []string{url} + return exec.Command(cmd, args...).Start() } func openUrlOther(url string) error { - var cmd = "xdg-open" - var args = []string{url} - return exec.Command(cmd, args...).Start() + var cmd = "xdg-open" + var args = []string{url} + return exec.Command(cmd, args...).Start() } func isWindows() bool { - return runtime.GOOS == "windows" + return runtime.GOOS == "windows" } func isDarwin() bool { - return runtime.GOOS == "darwin" + return runtime.GOOS == "darwin" } func transformDatabase(name string, suffix string) string { - if isWindows() { - cmd := exec.Command( - "cmd", - "/c", - `.\bin\trace_streamer_windows.exe`, - fmt.Sprintf(`.\upload\%s%s`, name, suffix), - "-e", - fmt.Sprintf(`.\upload\%s.db`, name), - ) - var stdout, stderr bytes.Buffer - cmd.Stdout = &stdout // 标准输出 - cmd.Stderr = &stderr // 标准错误 - err := cmd.Run() - if err != nil { - return "" - } - return fmt.Sprintf("%s.db", name) - } else if isDarwin() { - cmd := exec.Command( - "/bin/bash", - "-c", - fmt.Sprintf("%s/bin/trace_streamer_mac %s/upload/%s%s -e %s/upload/%s.db", exPath, exPath, name, suffix, exPath, name), - ) - var stdout, stderr bytes.Buffer - cmd.Stdout = &stdout // 标准输出 - cmd.Stderr = &stderr // 标准错误 - err := cmd.Run() - outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes()) - fmt.Printf("out:\n%s\n :\n%s\n", outStr, errStr) - if err != nil { - return "" - } - return fmt.Sprintf("%s.db", name) - } else { - cmd := exec.Command( - "/bin/bash", - "-c", - fmt.Sprintf("%s/bin/trace_streamer_linux %s/upload/%s%s -e %s/upload/%s.db", exPath, exPath, name, suffix, exPath, name), - ) - var stdout, stderr bytes.Buffer - cmd.Stdout = &stdout // 标准输出 - cmd.Stderr = &stderr // 标准错误 - err := cmd.Run() - outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes()) - fmt.Printf("out:\n%s\n :\n%s\n", outStr, errStr) - if err != nil { - return "" - } - return fmt.Sprintf("%s.db", name) - } - return "" + if isWindows() { + cmd := exec.Command( + "cmd", + "/c", + `.\bin\trace_streamer_windows.exe`, + fmt.Sprintf(`.\upload\%s%s`, name, suffix), + "-e", + fmt.Sprintf(`.\upload\%s.db`, name), + ) + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout // 标准输出 + cmd.Stderr = &stderr // 标准错误 + err := cmd.Run() + if err != nil { + return "" + } + return fmt.Sprintf("%s.db", name) + } else if isDarwin() { + cmd := exec.Command( + "/bin/bash", + "-c", + fmt.Sprintf("%s/bin/trace_streamer_mac %s/upload/%s%s -e %s/upload/%s.db", exPath, exPath, name, suffix, exPath, name), + ) + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout // 标准输出 + cmd.Stderr = &stderr // 标准错误 + err := cmd.Run() + outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes()) + fmt.Printf("out:\n%s\n :\n%s\n", outStr, errStr) + if err != nil { + return "" + } + return fmt.Sprintf("%s.db", name) + } else { + cmd := exec.Command( + "/bin/bash", + "-c", + fmt.Sprintf("%s/bin/trace_streamer_linux %s/upload/%s%s -e %s/upload/%s.db", exPath, exPath, name, suffix, exPath, name), + ) + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout // 标准输出 + cmd.Stderr = &stderr // 标准错误 + err := cmd.Run() + outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes()) + fmt.Printf("out:\n%s\n :\n%s\n", outStr, errStr) + if err != nil { + return "" + } + return fmt.Sprintf("%s.db", name) + } + return "" } func getCurrentAbPath() string { - dir := getCurrentAbPathByExecutable() - tmpDir, _ := filepath.EvalSymlinks(os.TempDir()) - if strings.Contains(dir, tmpDir) { - return getCurrentAbPathByCaller() - } - return dir + dir := getExecutePath() + tmpDir, _ := filepath.EvalSymlinks(os.TempDir()) + if strings.Contains(dir, tmpDir) { + return getCallerPath() + } + return dir } -func getCurrentAbPathByCaller() string { - var abPath string - _, filename, _, ok := runtime.Caller(0) - if ok { - abPath = path.Dir(filename) - } - return abPath +func getCallerPath() string { + var pth string + _, fName, _, ok := runtime.Caller(0) + if ok { + pth = path.Dir(fName) + } + return pth } -func getCurrentAbPathByExecutable() string { - exePath, err := os.Executable() - if err != nil { - log.Fatal(err) - } - res, _ := filepath.EvalSymlinks(filepath.Dir(exePath)) - return res +func getExecutePath() string { + pth, err := os.Executable() + if err != nil { + log.Fatal(err) + } + res, _ := filepath.EvalSymlinks(filepath.Dir(pth)) + return res } + +func checkPort(port int) { + if isWindows() { + pid := getPidByPort(port) + if pid != -1 { + res := exec.Command("cmd", "/c", fmt.Sprintf("taskkill /F /PID %d /T", pid)) + res.Run() + } + } +} \ No newline at end of file diff --git a/host/ide/server/wasm.json b/host/ide/server/wasm.json new file mode 100644 index 0000000000000000000000000000000000000000..dc715f822dfc3bf93313f8b27ed46e8a1943d1a6 --- /dev/null +++ b/host/ide/server/wasm.json @@ -0,0 +1,20 @@ +{ + "WasmFiles": [ + { + "disPlayName": "common_mock", + "componentId": 0, + "pluginName": "mock-plugin", + "sampleInterval": 5000, + "wasmJsName": "trace_streamer_sdk_builtin.js", + "wasmName": "trace_streamer_sdk_builtin_wasm" + }, + { + "disPlayName": "dubai-plugin", + "componentId": 1, + "pluginName": "dubai-plugin", + "sampleInterval": 5000, + "wasmJsName": "trace_streamer_sdk_builtin.js", + "wasmName": "trace_streamer_sdk_builtin_wasm" + } + ] +} \ No newline at end of file diff --git a/host/ide/src/base-ui/button/LitButton.ts b/host/ide/src/base-ui/button/LitButton.ts index 516e1b8034f2ecce311aeceb23a526c8b3ed9063..7beacb9351e5b296b082a69fcd193a1751e662d2 100644 --- a/host/ide/src/base-ui/button/LitButton.ts +++ b/host/ide/src/base-ui/button/LitButton.ts @@ -13,14 +13,206 @@ * limitations under the License. */ -import {BaseElement} from "../BaseElement.js"; +import {BaseElement, element} from "../BaseElement.js"; +@element('lit-button') export class LitButton extends BaseElement { + private slotHtml: HTMLElement | undefined; + private button: HTMLButtonElement | null | undefined; + private litIcon: LitButton | null | undefined; + + + static get observedAttributes() { + return ["text", "back", "icon", "height", "width", "color", "font_size", "border", "padding", "justify_content", + "border_radius", "margin_icon", "opacity"] + } + + get text() { + return this.getAttribute("text") || '' + } + + set text(text: string) { + this.setAttribute("text", text) + } + + get back() { + return this.getAttribute("back") || '' + } + + set back(backColor: string) { + this.button!.style.backgroundColor = backColor + this.setAttribute("back", backColor) + } + + get icon() { + return this.getAttribute("icon") || '' + } + + set icon(icon: string) { + this.litIcon?.setAttribute("name", icon); + this.setAttribute("icon", icon); + if (icon) { + this.litIcon!.style.display = "block" + } + } + + get height() { + return this.getAttribute("height") || '' + } + + set height(height: string) { + this.setAttribute("height", height) + } + + get width() { + return this.getAttribute("width") || '' + } + + set width(width: string) { + this.setAttribute("width", width) + } + + set color(color: string) { + this.setAttribute("color", color) + } + + set font_size(fontSize: string) { + this.setAttribute("font_size", fontSize) + } + + set border(border: string) { + this.setAttribute("border", border) + } + + set padding(padding: string) { + this.setAttribute("padding", padding) + } + + set justify_content(justifyContent: string) { + this.setAttribute("justify_content", justifyContent) + } + + set border_radius(borderRadius: string) { + this.setAttribute("border_radius", borderRadius) + } + + set margin_icon(value: string) { + this.litIcon?.setAttribute("margin_icon", value); + } + + set opacity(value: string) { + this.litIcon?.setAttribute("opacity", value); + } + + initHtml(): string { - return ""; + return ` + +
+ +
+ ` } initElements(): void { + this.slotHtml = this.shadowRoot?.querySelector("#sl") as HTMLElement; + this.button = this.shadowRoot?.querySelector('#custom-button'); + this.litIcon = this.shadowRoot?.querySelector("#button-icon") as LitButton + if (this.litIcon.getAttribute("name") == "") { + this.litIcon!.style.display = "none" + } + } + attributeChangedCallback(name: string, oldValue: string, value: string) { + switch (name) { + case "text": + this.slotHtml!.innerText = value + break; + case "back": + this.button!.style.backgroundColor = value + break; + case "icon": + this.litIcon?.setAttribute("name", value); + if (value) { + this.litIcon!.style.display = "block" + } + break; + case "height": + this.button!.style.height = value; + break; + case "color": + this.button!.style.color = value; + break; + case "font_size": + this.button!.style.fontSize = value; + break; + case "border": + this.button!.style.border = value; + break; + case "padding": + this.button!.style.padding = value; + break; + case "justify_content": + this.button!.style.justifyContent = value; + break; + case "border_radius": + this.button!.style.borderRadius = value; + break; + case "margin_icon": + this.litIcon!.style.margin = value; + break; + case "opacity": + this.button!.style.opacity = value; + break; + } } + } \ No newline at end of file diff --git a/host/ide/src/base-ui/checkbox/LitCheckBox.ts b/host/ide/src/base-ui/checkbox/LitCheckBox.ts index a6b5d913591c14e0eb6c81af6f883627c437833f..2939dd72a29afd5c26818881136a1b194b85a06b 100644 --- a/host/ide/src/base-ui/checkbox/LitCheckBox.ts +++ b/host/ide/src/base-ui/checkbox/LitCheckBox.ts @@ -60,11 +60,10 @@ export class LitCheckBox extends BaseElement { return ` `; diff --git a/host/ide/src/base-ui/checkbox/LitCheckBoxWithText.ts b/host/ide/src/base-ui/checkbox/LitCheckBoxWithText.ts index 2de00a3fe8b08a16bca6f42e2e9f9c2a6869466d..78ff088d4a0d59e1af844e09237958a9b61f8032 100644 --- a/host/ide/src/base-ui/checkbox/LitCheckBoxWithText.ts +++ b/host/ide/src/base-ui/checkbox/LitCheckBoxWithText.ts @@ -70,24 +70,25 @@ export class LitCheckBoxWithText extends BaseElement { initHtml(): string { return ` - - - + + + + `; } diff --git a/host/ide/src/base-ui/icon.svg b/host/ide/src/base-ui/icon.svg index 168c113b584dbbbfb6a69687e65adf634768dd8b..67661ccc55c1d3b2cce28715003e4d1f39432355 100644 --- a/host/ide/src/base-ui/icon.svg +++ b/host/ide/src/base-ui/icon.svg @@ -1 +1,2233 @@ - + \ No newline at end of file diff --git a/host/ide/src/base-ui/menu/LitMainMenu.ts b/host/ide/src/base-ui/menu/LitMainMenu.ts index 008f584689ad7b12aae69de085f20124a0cb50c4..f991e245a2b66cb8ac46459f147d1e77be37687a 100644 --- a/host/ide/src/base-ui/menu/LitMainMenu.ts +++ b/host/ide/src/base-ui/menu/LitMainMenu.ts @@ -54,14 +54,14 @@ export class LitMainMenu extends BaseElement { if (item.fileChoose) { th.setAttribute('file', ""); th.addEventListener('file-change', e => { - if (item.fileHandler) { + if (item.fileHandler && !th.disabled) { item.fileHandler(e) } }) } else { th.removeAttribute('file'); th.addEventListener('click', e => { - if (item.clickHandler) { + if (item.clickHandler && !th.disabled) { item.clickHandler(item) } }) @@ -89,73 +89,74 @@ export class LitMainMenu extends BaseElement { initHtml(): string { return ` - + } + .header{ + display: grid; + background-color: var(--dark-background1,#FFFFFF); + border-bottom: 1px solid var(--dark-background1,#EFEFEF); + color: #47A7E0; + font-size: 1.4rem; + padding-left: 20px; + /*padding-right: 10px;*/ + gap: 0 20px; + box-sizing: border-box; + width: 100%; + height: 56px; + grid-template-columns: min-content 1fr min-content; + grid-template-rows: auto; + } + .header *{ + align-self: center; + user-select: none; + } + .version{ + color: #94979d; + padding: 20px; + font-size: 0.6rem; + width: 100%; + text-align: right; + } + *{ + box-sizing: border-box; + } + .menu-button{ + height: 47px; + width: 48px; + display: flex; + align-content: center; + justify-content: right; + cursor: pointer; + } +
- + +
- -
`; } } diff --git a/host/ide/src/base-ui/menu/LitMainMenuItem.ts b/host/ide/src/base-ui/menu/LitMainMenuItem.ts index 4af57f10fed85138d48e26c44f29077500c01a80..c164256bf60e2d529d48420adb54fd9a76aeb195 100644 --- a/host/ide/src/base-ui/menu/LitMainMenuItem.ts +++ b/host/ide/src/base-ui/menu/LitMainMenuItem.ts @@ -49,6 +49,18 @@ export class LitMainMenuItem extends BaseElement { } } + get back(): boolean { + return this.hasAttribute("back") + } + + set back(isShowBack: boolean) { + if (isShowBack) { + this.setAttribute("back", ''); + } else { + this.removeAttribute("back"); + } + } + initElements(): void { this.rootEL = this.shadowRoot?.querySelector('.root'); this.titleEl = this.shadowRoot?.querySelector('.name'); @@ -85,72 +97,76 @@ export class LitMainMenuItem extends BaseElement { initHtml(): string { return ` - - - -`; + + + + `; } attributeChangedCallback(name: string, oldValue: string, newValue: string) { diff --git a/host/ide/src/base-ui/popover/LitPopoverV.ts b/host/ide/src/base-ui/popover/LitPopoverV.ts index 6fd0a0861715a7990ef0b08586dd0fc67a4dfb0a..eee4038eea28aad353beccdda43faeb064c3c50e 100644 --- a/host/ide/src/base-ui/popover/LitPopoverV.ts +++ b/host/ide/src/base-ui/popover/LitPopoverV.ts @@ -13,32 +13,32 @@ * limitations under the License. */ -import {element,BaseElement} from "../BaseElement.js"; +import {BaseElement, element} from "../BaseElement.js"; @element("lit-popover") export class LitPopover extends BaseElement { static get observedAttributes() { return [ - 'title',/*标题*/ - 'trigger',/*触发条件 hover | click | focus[未实现]*/ - 'width',/*自定义高度*/ - 'placement',/*设置方向 topLeft top topRight leftTop left leftBottom rightTop right rightBottom bottomLeft bottom bottomRight*/ - 'visible'/*控制popover是否显示*/ + 'title', + 'trigger', + 'width', + 'placement', + 'visible' ] } - initElements(): void { - } - get visible(){ + get visible() { return this.getAttribute('visible') || 'false'; } - set visible(value){ + + set visible(value) { if (value) { this.setAttribute('visible', 'true'); - }else{ + } else { this.setAttribute('visible', 'false'); } } + get trigger() { return this.getAttribute('trigger') || 'hover' } @@ -51,7 +51,7 @@ export class LitPopover extends BaseElement { return this.getAttribute('title'); } - set title(value:any) { + set title(value: any) { this.setAttribute('title', value); } @@ -63,13 +63,15 @@ export class LitPopover extends BaseElement { this.setAttribute('width', value); } - get haveRadio(){ + get haveRadio() { return this.getAttribute("haveRadio") } + initElements(): void { + + } + initHtml() { - // super(); - // const shadowRoot = this.attachShadow({mode: 'open'}); return ` -
-
-
-
+ +
+
+
+
`; } - } \ No newline at end of file diff --git a/host/ide/src/base-ui/radiobox/LitRadioBox.ts b/host/ide/src/base-ui/radiobox/LitRadioBox.ts index daef13552c3b351a2f4861bab54a3a97e8c6fc81..d5bf7bb313746bccabaaa7eb985ee7f9205aae01 100644 --- a/host/ide/src/base-ui/radiobox/LitRadioBox.ts +++ b/host/ide/src/base-ui/radiobox/LitRadioBox.ts @@ -185,7 +185,10 @@ export class LitRadioBox extends BaseElement { `; diff --git a/host/ide/src/base-ui/select/LitAllocationSelect.ts b/host/ide/src/base-ui/select/LitAllocationSelect.ts new file mode 100644 index 0000000000000000000000000000000000000000..6247e783432d1b3ae3f89e4c049d79fe87c36368 --- /dev/null +++ b/host/ide/src/base-ui/select/LitAllocationSelect.ts @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../BaseElement.js"; + +@element('lit-allocation-select') +export class LitAllocationSelect extends BaseElement { + private inputElement: HTMLInputElement | null | undefined; + private inputContent: HTMLDivElement | undefined; + private options: any; + + static get observedAttributes() { + return [ + 'value','disabled','placeholder' + ]; + } + + get defaultPlaceholder() { + return this.getAttribute('placeholder') || ''; + } + + get placeholder() { + return this.getAttribute('placeholder') || this.defaultPlaceholder; + } + + set placeholder(value) { + this.setAttribute('placeholder', value); + } + + get value() { + return this.getAttribute('value') || ""; + } + + set value(value: string) { + this.setAttribute('value', value); + } + + set processData(value: Array) { + this.options.innerHTML = ''; + value.forEach( + item => { + let option = document.createElement("div"); + option.className = 'option'; + option.innerHTML = item; + option.style.padding = '8px 10px'; + this.options.appendChild(option); + this.inputElement?.focus(); + } + ) + } + + get placement(): string { + return this.getAttribute("placement") || ""; + } + + set placement(placement: string) { + if (placement) { + this.setAttribute("placement", placement); + } else { + this.removeAttribute("placement"); + } + } + + get listHeight() { + return this.getAttribute('list-height') || '256px'; + } + + set listHeight(value) { + this.setAttribute('list-height', value); + } + + initElements(): void { + this.inputContent = this.shadowRoot!.querySelector('.multipleSelect') as HTMLDivElement; + this.addEventListener('click', () => { + if (this.options.style.visibility == 'visible') { + this.options.style.visibility = 'hidden'; + this.options.style.opacity = '0'; + } else { + this.options.style.visibility = 'visible'; + this.options.style.opacity = '1'; + } + this.inputContent!.dispatchEvent(new CustomEvent('inputClick', {})); + }) + this.addEventListener('focusout', (e) => { + setTimeout(()=>{ + this.options.style.visibility = 'hidden'; + this.options.style.opacity = '0'; + }, 200) + }) + this.initData(); + } + + initHtml() { + return ` + +
+
+ +
+ +
+
+ + +
+ ` + } + + connectedCallback() { + } + + initData() { + this.inputElement = this.shadowRoot!.querySelector('input'); + this.options = this.shadowRoot!.querySelector('.body') as HTMLDivElement; + this.inputElement?.addEventListener('keyup', () => { + let filter = [...this.shadowRoot!.querySelectorAll('.option')].filter((a: HTMLDivElement) => { + if (a.textContent!.indexOf(this.inputElement!.value) <= -1) { + a.style.display = "none"; + } else { + a.style.display = "block"; + } + }); + this.value = this.inputElement!.value + this.inputContent!.dispatchEvent(new CustomEvent('valuable', {})); + }) + this.shadowRoot?.querySelectorAll('.option').forEach(a => { + a.addEventListener('click', (e) => { + a.dispatchEvent(new CustomEvent('onSelected', { + detail: { + selected: true, + text: a.textContent + } + })) + }) + a.addEventListener('onSelected', (e: any) => { + this.inputElement!.value = e.detail.text; + this.value = e.detail.text; + this.inputContent!.dispatchEvent(new CustomEvent('valuable', {})); + }) + }) + } + +} diff --git a/host/ide/src/base-ui/select/LitSelect.ts b/host/ide/src/base-ui/select/LitSelect.ts index 460cac9db3c0d3e23a1ea94f2cb96908c9442123..f927d547a52677f35ca6e7fd7670fb88f3ab5919 100644 --- a/host/ide/src/base-ui/select/LitSelect.ts +++ b/host/ide/src/base-ui/select/LitSelect.ts @@ -17,586 +17,641 @@ import {BaseElement, element} from "../BaseElement.js"; @element('lit-select') export class LitSelect extends BaseElement { - private focused:any; - private inputElement:any; - private clearElement:any; - private iconElement:any; - private searchElement:any; - private multipleRootElement:any; - static get observedAttributes() { - return [ - 'value',//默认值 - 'default-value',//默认值 - 'placeholder',//placeholder - 'disabled', - 'loading',//是否处于加载状态 - 'allow-clear',//是否允许清除 - 'show-search',//是否允许搜索 - 'list-height',//设置弹窗滚动高度 默认256px - 'border',//是否显示边框 - 'mode',// mode='multiple'多选 - ]; - } - initElements(): void { - - } - - get value() { - return this.getAttribute('value') || this.defaultValue; - } - - set value(value) { - this.setAttribute('value', value); - } - - get border() { - return this.getAttribute('border') || 'true'; - } - - set border(value) { - if (value) { - this.setAttribute('border', 'true'); - } else { - this.setAttribute('border', 'false'); - } - } - - get listHeight() { - return this.getAttribute('list-height') || '256px'; - } - - set listHeight(value) { - this.setAttribute('list-height', value); - } - - get defaultPlaceholder() { - return this.getAttribute('placeholder') || '请选择'; - } - - get showSearch() { - return this.hasAttribute('show-search'); - } - - set defaultValue(value) { - this.setAttribute('default-value', value); - } - - get defaultValue() { - return this.getAttribute('default-value') || ''; - } - - set placeholder(value) { - this.setAttribute('placeholder', value); - } - - get placeholder() { - return this.getAttribute('placeholder') || this.defaultPlaceholder; - } - - get loading() { - return this.hasAttribute('loading'); - } - - set loading(value) { - if (value) { - this.setAttribute('loading', ''); - } else { - this.removeAttribute('loading') - } - } - - initHtml() { - // super(); - // const shadowRoot = this.attachShadow({mode: 'open'}); - return` + private focused: any; + private inputElement: any; + private clearElement: any; + private iconElement: any; + private searchElement: any; + private multipleRootElement: any; + + static get observedAttributes() { + return [ + 'value', + 'default-value', + 'placeholder', + 'disabled', + 'loading', + 'allow-clear', + 'show-search', + 'list-height', + 'border', + 'mode', + ]; + } + + get value() { + return this.getAttribute('value') || this.defaultValue; + } + + set value(value) { + this.setAttribute('value', value); + } + + get rounded() { + return this.hasAttribute("rounded"); + } + + set rounded(rounded: boolean) { + if (rounded) { + this.setAttribute("rounded", ''); + } else { + this.removeAttribute("rounded"); + } + } + + get placement(): string { + return this.getAttribute("placement") || ""; + } + + set placement(placement: string) { + if (placement) { + this.setAttribute("placement", placement); + } else { + this.removeAttribute("placement"); + } + } + + get border() { + return this.getAttribute('border') || 'true'; + } + + set border(value) { + if (value) { + this.setAttribute('border', 'true'); + } else { + this.setAttribute('border', 'false'); + } + } + + get listHeight() { + return this.getAttribute('list-height') || '256px'; + } + + set listHeight(value) { + this.setAttribute('list-height', value); + } + + get defaultPlaceholder() { + return this.getAttribute('placeholder') || '请选择'; + } + + set canInsert(can:boolean) { + if (can) { + this.setAttribute("canInsert",''); + } else { + this.removeAttribute("canInsert") + } + } + + get canInsert() { + return this.hasAttribute("canInsert") + } + get showSearch() { + return this.hasAttribute('show-search'); + } + + get defaultValue() { + return this.getAttribute('default-value') || ''; + } + + set defaultValue(value) { + this.setAttribute('default-value', value); + } + + get placeholder() { + return this.getAttribute('placeholder') || this.defaultPlaceholder; + } + + set placeholder(value) { + this.setAttribute('placeholder', value); + } + + get loading() { + return this.hasAttribute('loading'); + } + + set loading(value) { + if (value) { + this.setAttribute('loading', ''); + } else { + this.removeAttribute('loading') + } + } + + set dataSource(value: any) { + value.forEach((a: any) => { + let option = document.createElement('lit-select-option'); + option.setAttribute('value', a.key); + option.textContent = a.val; + this.append(option) + }) + this.initOptions(); + } + + initElements(): void { + } + + initHtml() { + return ` -
-
- - - - -
-
- - -
+ +
+
+
+ + + + +
+
+ + +
` - } - - isMultiple() { - return this.hasAttribute('mode') && this.getAttribute('mode') === 'multiple' - } - - newTag(value:any, text:any) { - let tag:any = document.createElement('div'); - let icon:any = document.createElement('lit-icon'); - icon.classList.add('tag-close') - icon.name = 'close' - let span = document.createElement('span'); - tag.classList.add('tag'); - span.dataset['value'] = value; - span.textContent = text; - tag.append(span); - tag.append(icon); - icon.onclick = (ev:any) => { - tag.parentElement.removeChild(tag); - this.querySelector(`lit-select-option[value=${value}]`)!.removeAttribute('selected') - if (this.shadowRoot!.querySelectorAll('.tag').length == 0) { - this.inputElement.style.width = 'auto'; - this.inputElement.placeholder = this.defaultPlaceholder; - } - ev.stopPropagation(); - } - tag.value = value; - tag.dataset['value'] = value; - tag.text = text; - tag.dataset['text'] = text; - return tag; - } - - //当 custom element首次被插入文档DOM时,被调用。 - connectedCallback() { - this.tabIndex = 0;//设置当前组件为可以获取焦点 - this.focused = false; - this.inputElement = this.shadowRoot!.querySelector('input'); - this.clearElement = this.shadowRoot!.querySelector('.clear'); - this.iconElement = this.shadowRoot!.querySelector('.icon'); - this.searchElement = this.shadowRoot!.querySelector('.search'); - this.multipleRootElement = this.shadowRoot!.querySelector('.multipleRoot'); - //点击清理 清空input值,展示placeholder, - this.clearElement.onclick = (ev:any) => { - if (this.isMultiple()) { - let delNodes:Array = [] - this.multipleRootElement.childNodes.forEach((a:any) => { - if (a.tagName === 'DIV') { - delNodes.push(a); - } - }) - for (let i = 0; i < delNodes.length; i++) { - delNodes[i].remove(); - } - if (this.shadowRoot!.querySelectorAll('.tag').length == 0) { - this.inputElement.style.width = 'auto'; - this.inputElement.placeholder = this.defaultPlaceholder; - } - } - this.querySelectorAll('lit-select-option').forEach(a => a.removeAttribute('selected')); - this.inputElement.value = '' - this.clearElement.style.display = 'none'; - this.iconElement.style.display = 'flex'; - this.blur(); - ev.stopPropagation();//这里不会因为点击清理而触发 选择栏目显示或者隐藏 - this.dispatchEvent(new CustomEvent('onClear', {detail: ev}))//向外派发清理事件 - } - //初始化时遍历所有的option节点 - this.initOptions(); - //当前控件点击时 如果时select本身 需要显示 或 隐藏选择栏目,通过this.focused变量控制(默认为false) - this.onclick = (ev:any) => { - if (ev.target.tagName === 'LIT-SELECT') { - if (this.focused === false) { - this.inputElement.focus(); - this.focused = true; - } else { - this.blur(); - this.focused = false; - } - } - } - this.onmouseover = this.onfocus = ev => { - if (this.hasAttribute('allow-clear')) { - if (this.inputElement.value.length > 0 || this.inputElement.placeholder !== this.defaultPlaceholder) { - this.clearElement.style.display = 'flex' - this.iconElement.style.display = 'none'; - } else { - this.clearElement.style.display = 'none' - this.iconElement.style.display = 'flex'; - } - } - } - this.onmouseout = this.onblur = ev => { - if (this.hasAttribute('allow-clear')) { - this.clearElement.style.display = 'none'; - this.iconElement.style.display = 'flex'; - } - this.focused = false; - } - //输入框获取焦点时,value值 暂存于 placeholder 然后value值清空,这样值会以placeholder形式灰色展示,鼠标位于第一个字符 - this.inputElement.onfocus = (ev:any) => { - if (this.hasAttribute('disabled')) return;//如果控件处于disabled状态 直接忽略 - if (this.inputElement.value.length > 0) { - this.inputElement.placeholder = this.inputElement.value; - this.inputElement.value = '' - } - if (this.hasAttribute('show-search')) {//如果有show-search属性 需要显示放大镜,隐藏向下的箭头 - this.searchElement.style.display = 'flex'; - this.iconElement.style.display = 'none'; - } - this.querySelectorAll('lit-select-option').forEach(a => {//input获取焦点时显示所有可选项,相当于清理了搜索结果 - // @ts-ignore - a.style.display = 'flex'; - }) - } - //当输入框失去焦点的时候 placeholder 的值 保存到value上,input显示值 - this.inputElement.onblur = (ev:any) => { - if (this.hasAttribute('disabled')) return;//如果控件处于disabled状态 直接忽略 - if (this.isMultiple()) { - if (this.hasAttribute('show-search')) {//如果有show-search属性 失去焦点需要 隐藏放大镜图标,显示默认的向下箭头图标 - this.searchElement.style.display = 'none'; - this.iconElement.style.display = 'flex'; - } - } else { - if (this.inputElement.placeholder !== this.defaultPlaceholder) {//如果placeholder为 请输入(默认值)不做处理 - this.inputElement.value = this.inputElement.placeholder; //placeholder 保存的值放入 value中 - this.inputElement.placeholder = this.defaultPlaceholder;//placeholder 值为 默认值(请输入) - } - if (this.hasAttribute('show-search')) {//如果有show-search属性 失去焦点需要 隐藏放大镜图标,显示默认的向下箭头图标 - this.searchElement.style.display = 'none'; - this.iconElement.style.display = 'flex'; - } - } - } - //输入框每次文本变化 会匹配搜索的option 显示或者隐藏,达到搜索的效果 - this.inputElement.oninput = (ev:any) => { - let els = [...this.querySelectorAll('lit-select-option')]; - if (!ev.target.value) { - els.forEach((a:any) => a.style.display = 'flex'); - } else { - els.forEach((a:any) => { - let value = a.getAttribute('value'); - if (value.toLowerCase().indexOf(ev.target.value.toLowerCase()) !== -1 || - a.textContent.toLowerCase().indexOf(ev.target.value.toLowerCase()) !== -1) { - a.style.display = 'flex'; - } else { - a.style.display = 'none'; - } - }) - } - } - //输入框按下回车键,自动输入当前搜索出来的第一行,及display!='none'的第一个,搜索会隐藏其他行 - this.inputElement.onkeydown = (ev:any) => { - if (ev.key === 'Backspace') { - if (this.isMultiple()) { - let tag = this.multipleRootElement.lastElementChild.previousElementSibling; - if (tag) { - this.querySelector(`lit-select-option[value=${tag.value}]`)?.removeAttribute('selected'); - tag.remove() - if (this.shadowRoot!.querySelectorAll('.tag').length == 0) { - this.inputElement.style.width = 'auto'; - this.inputElement.placeholder = this.defaultPlaceholder; - } - } - } else { - this.clear(); - this.dispatchEvent(new CustomEvent('onClear', {detail: ev}))//向外派发清理事件 - } - } else if (ev.key === 'Enter') { - let filter = [...this.querySelectorAll('lit-select-option')].filter((a:any) => a.style.display !== 'none'); - if (filter.length > 0) { - this.inputElement.value = filter[0].textContent; - this.inputElement.placeholder = filter[0].textContent; - this.blur(); - // @ts-ignore - this.value=filter[0].getAttribute('value') - this.dispatchEvent(new CustomEvent('change', { - detail: { - selected: true, - value: filter[0].getAttribute('value'), - text: filter[0].textContent - } - }));//向外层派发change事件,返回当前选中项 - } - } - } - } - - initOptions(){ - this.querySelectorAll('lit-select-option').forEach(a => { - //如果节点的值为 当前控件的默认值 defalut-value则 显示该值对应的option文本 - if (this.isMultiple()) { - a.setAttribute('check', ''); - if (a.getAttribute('value') === this.defaultValue) { - let tag = this.newTag(a.getAttribute('value'), a.textContent); - this.multipleRootElement.insertBefore(tag, this.inputElement); - this.inputElement.placeholder = ''; - this.inputElement.value = ''; - this.inputElement.style.width = '1px'; - a.setAttribute('selected', ''); - } - // this.inputElement.focus(); - } else { - if (a.getAttribute('value') === this.defaultValue) { - this.inputElement.value = a.textContent; - a.setAttribute('selected', ''); - } - } - //每个option设置onSelected事件 接受当前点击的option - a.addEventListener('onSelected', (e:any) => { - //所有option设置为未选中状态 - if (this.isMultiple()) {//多选 - if (a.hasAttribute('selected')) { - let tag = this.shadowRoot!.querySelector(`div[data-value=${e.detail.value}]`); - // @ts-ignore - tag.parentElement!.removeChild(tag); - e.detail.selected = false; - } else { - let tag = this.newTag(e.detail.value, e.detail.text); - this.multipleRootElement.insertBefore(tag, this.inputElement); - this.inputElement.placeholder = ''; - this.inputElement.value = ''; - this.inputElement.style.width = '1px'; - } - if (this.shadowRoot!.querySelectorAll('.tag').length == 0) { - this.inputElement.style.width = 'auto'; - this.inputElement.placeholder = this.defaultPlaceholder; - } - this.inputElement.focus(); - } else {//单选 - [...this.querySelectorAll('lit-select-option')].forEach(a => a.removeAttribute('selected')) - this.blur();//失去焦点,隐藏选择栏目列表 - // @ts-ignore - this.inputElement.value = e.detail.text; - } - //设置当前option为选择状态 - if (a.hasAttribute('selected')) { - a.removeAttribute('selected') - } else { - a.setAttribute('selected', '') - } - //设置input的值为当前选择的文本 - // @ts-ignore - this.value = e.detail.value; - this.dispatchEvent(new CustomEvent('change', {detail: e.detail}));//向外层派发change事件,返回当前选中项 - }) - }) - } - //js调用清理选项 - clear() { - this.inputElement.value = ''; - this.inputElement.placeholder = this.defaultPlaceholder; - } - - //重置为默认值 - reset() { - this.querySelectorAll('lit-select-option').forEach(a => { - //如果节点的值为 当前控件的默认值 defalut-value则 显示该值对应的option文本 - [...this.querySelectorAll('lit-select-option')].forEach(a => a.removeAttribute('selected')) - if (a.getAttribute('value') === this.defaultValue) { - this.inputElement.value = a.textContent; - a.setAttribute('selected', ''); - } - }) - } - - //当 custom element从文档DOM中删除时,被调用。 - disconnectedCallback() { - - } - - //当 custom element被移动到新的文档时,被调用。 - adoptedCallback() { - } - - //当 custom element增加、删除、修改自身属性时,被调用。 - attributeChangedCallback(name:any, oldValue:any, newValue:any) { - if (name === 'value' && this.inputElement) { - if(newValue){ - [...this.querySelectorAll('lit-select-option')].forEach(a => { - if (a.getAttribute('value') === newValue) { - a.setAttribute('selected', ''); - this.inputElement.value = a.textContent; - } else { - a.removeAttribute('selected') - } - }) - }else{ - this.clear(); - } - } - } - set dataSource(value:any){ - value.forEach((a:any)=>{ - let option = document.createElement('lit-select-option'); - option.setAttribute('value',a.key); - option.textContent = a.val; - this.append(option) - }) - this.initOptions(); - } + } + + isMultiple() { + return this.hasAttribute('mode') && this.getAttribute('mode') === 'multiple' + } + + newTag(value: any, text: any) { + let tag: any = document.createElement('div'); + let icon: any = document.createElement('lit-icon'); + icon.classList.add('tag-close') + icon.name = 'close' + let span = document.createElement('span'); + tag.classList.add('tag'); + span.dataset['value'] = value; + span.textContent = text; + tag.append(span); + tag.append(icon); + icon.onclick = (ev: any) => { + tag.parentElement.removeChild(tag); + this.querySelector(`lit-select-option[value=${value}]`)!.removeAttribute('selected') + if (this.shadowRoot!.querySelectorAll('.tag').length == 0) { + this.inputElement.style.width = 'auto'; + this.inputElement.placeholder = this.defaultPlaceholder; + } + ev.stopPropagation(); + } + tag.value = value; + tag.dataset['value'] = value; + tag.text = text; + tag.dataset['text'] = text; + return tag; + } + + connectedCallback() { + this.tabIndex = 0; + this.focused = false; + this.inputElement = this.shadowRoot!.querySelector('input'); + this.clearElement = this.shadowRoot!.querySelector('.clear'); + this.iconElement = this.shadowRoot!.querySelector('.icon'); + this.searchElement = this.shadowRoot!.querySelector('.search'); + this.multipleRootElement = this.shadowRoot!.querySelector('.multipleRoot'); + this.clearElement.onclick = (ev: any) => { + if (this.isMultiple()) { + let delNodes: Array = [] + this.multipleRootElement.childNodes.forEach((a: any) => { + if (a.tagName === 'DIV') { + delNodes.push(a); + } + }) + for (let i = 0; i < delNodes.length; i++) { + delNodes[i].remove(); + } + if (this.shadowRoot!.querySelectorAll('.tag').length == 0) { + this.inputElement.style.width = 'auto'; + this.inputElement.placeholder = this.defaultPlaceholder; + } + } + this.querySelectorAll('lit-select-option').forEach(a => a.removeAttribute('selected')); + this.inputElement.value = '' + this.clearElement.style.display = 'none'; + this.iconElement.style.display = 'flex'; + this.blur(); + ev.stopPropagation(); + this.dispatchEvent(new CustomEvent('onClear', {detail: ev})) + } + this.initOptions(); + this.onclick = (ev: any) => { + if (ev.target.tagName === 'LIT-SELECT') { + if (this.focused === false) { + this.inputElement.focus(); + this.focused = true; + } else { + this.blur(); + this.focused = false; + } + } + } + this.onmouseover = this.onfocus = ev => { + if (this.focused === false && this.hasAttribute("adaptive-expansion")) { + let body = this.shadowRoot!.querySelector(".body"); + if (this.parentElement!.offsetTop < body!.clientHeight) { + body!.classList.add('body-bottom'); + } else { + body!.classList.remove('body-bottom'); + } + } + if (this.hasAttribute('allow-clear')) { + if (this.inputElement.value.length > 0 || this.inputElement.placeholder !== this.defaultPlaceholder) { + this.clearElement.style.display = 'flex' + this.iconElement.style.display = 'none'; + } else { + this.clearElement.style.display = 'none' + this.iconElement.style.display = 'flex'; + } + } + } + this.onmouseout = this.onblur = ev => { + if (this.hasAttribute('allow-clear')) { + this.clearElement.style.display = 'none'; + this.iconElement.style.display = 'flex'; + } + this.focused = false; + } + this.inputElement.onfocus = (ev: any) => { + if (this.hasAttribute('disabled')) return; + if (this.inputElement.value.length > 0) { + this.inputElement.placeholder = this.inputElement.value; + this.inputElement.value = '' + } + if (this.hasAttribute('show-search')) { + this.searchElement.style.display = 'flex'; + this.iconElement.style.display = 'none'; + } + this.querySelectorAll('lit-select-option').forEach(a => { + // @ts-ignore + a.style.display = 'flex'; + }) + } + this.inputElement.onblur = (ev: any) => { + if (this.hasAttribute('disabled')) return; + if (this.isMultiple()) { + if (this.hasAttribute('show-search')) { + this.searchElement.style.display = 'none'; + this.iconElement.style.display = 'flex'; + } + } else { + if (this.inputElement.placeholder !== this.defaultPlaceholder) { + this.inputElement.value = this.inputElement.placeholder; + this.inputElement.placeholder = this.defaultPlaceholder; + } + if (this.hasAttribute('show-search')) { + this.searchElement.style.display = 'none'; + this.iconElement.style.display = 'flex'; + } + } + } + this.inputElement.oninput = (ev: any) => { + let els = [...this.querySelectorAll('lit-select-option')]; + if(this.hasAttribute("show-search")) { + if (!ev.target.value) { + els.forEach((a: any) => a.style.display = 'flex'); + } else { + els.forEach((a: any) => { + let value = a.getAttribute('value'); + if (value.toLowerCase().indexOf(ev.target.value.toLowerCase()) !== -1 || + a.textContent.toLowerCase().indexOf(ev.target.value.toLowerCase()) !== -1) { + a.style.display = 'flex'; + } else { + a.style.display = 'none'; + } + }) + } + } else { + this.value = ev.target.value + } + } + this.inputElement.onkeydown = (ev: any) => { + if (ev.key === 'Backspace') { + if (this.isMultiple()) { + let tag = this.multipleRootElement.lastElementChild.previousElementSibling; + if (tag) { + this.querySelector(`lit-select-option[value=${tag.value}]`)?.removeAttribute('selected'); + tag.remove() + if (this.shadowRoot!.querySelectorAll('.tag').length == 0) { + this.inputElement.style.width = 'auto'; + this.inputElement.placeholder = this.defaultPlaceholder; + } + } + } else { + this.clear(); + this.dispatchEvent(new CustomEvent('onClear', {detail: ev}))//向外派发清理事件 + } + } else if (ev.key === 'Enter') { + if (!this.canInsert) { + let filter = [...this.querySelectorAll('lit-select-option')].filter((a: any) => a.style.display !== 'none'); + if (filter.length > 0) { + this.inputElement.value = filter[0].textContent; + this.inputElement.placeholder = filter[0].textContent; + this.blur(); + // @ts-ignore + this.value = filter[0].getAttribute('value') + this.dispatchEvent(new CustomEvent('change', { + detail: { + selected: true, + value: filter[0].getAttribute('value'), + text: filter[0].textContent + } + })); + } + } + } + } + } + + initOptions() { + this.querySelectorAll('lit-select-option').forEach(a => { + if (this.isMultiple()) { + a.setAttribute('check', ''); + if (a.getAttribute('value') === this.defaultValue) { + let tag = this.newTag(a.getAttribute('value'), a.textContent); + this.multipleRootElement.insertBefore(tag, this.inputElement); + this.inputElement.placeholder = ''; + this.inputElement.value = ''; + this.inputElement.style.width = '1px'; + a.setAttribute('selected', ''); + } + } else { + if (a.getAttribute('value') === this.defaultValue) { + this.inputElement.value = a.textContent; + a.setAttribute('selected', ''); + } + } + a.addEventListener('mouseup',(e)=>{ + e.stopPropagation() + }); + a.addEventListener('mousedown',(e)=>{ + e.stopPropagation() + }); + a.addEventListener('onSelected', (e: any) => { + if (this.isMultiple()) { + if (a.hasAttribute('selected')) { + let tag = this.shadowRoot!.querySelector(`div[data-value=${e.detail.value}]`) as HTMLElement; + if (tag) { + tag.parentElement!.removeChild(tag); + } + e.detail.selected = false; + } else { + let tag = this.newTag(e.detail.value, e.detail.text); + this.multipleRootElement.insertBefore(tag, this.inputElement); + this.inputElement.placeholder = ''; + this.inputElement.value = ''; + this.inputElement.style.width = '1px'; + } + if (this.shadowRoot!.querySelectorAll('.tag').length == 0) { + this.inputElement.style.width = 'auto'; + this.inputElement.placeholder = this.defaultPlaceholder; + } + this.inputElement.focus(); + } else { + [...this.querySelectorAll('lit-select-option')].forEach(a => a.removeAttribute('selected')) + this.blur(); + // @ts-ignore + this.inputElement.value = e.detail.text; + } + if (a.hasAttribute('selected')) { + a.removeAttribute('selected') + } else { + a.setAttribute('selected', '') + } + // @ts-ignore + this.value = e.detail.value; + this.dispatchEvent(new CustomEvent('change', {detail: e.detail}));//向外层派发change事件,返回当前选中项 + }) + }) + } + + clear() { + this.inputElement.value = ''; + this.inputElement.placeholder = this.defaultPlaceholder; + } + + reset() { + this.querySelectorAll('lit-select-option').forEach(a => { + [...this.querySelectorAll('lit-select-option')].forEach(a => a.removeAttribute('selected')) + if (a.getAttribute('value') === this.defaultValue) { + this.inputElement.value = a.textContent; + a.setAttribute('selected', ''); + } + }) + } + + disconnectedCallback() { + + } + + adoptedCallback() { + } + + attributeChangedCallback(name: any, oldValue: any, newValue: any) { + if (name === 'value' && this.inputElement) { + if (newValue) { + [...this.querySelectorAll('lit-select-option')].forEach(a => { + if (a.getAttribute('value') === newValue) { + a.setAttribute('selected', ''); + this.inputElement.value = a.textContent; + } else { + a.removeAttribute('selected') + } + }) + } else { + this.clear(); + } + } + } } diff --git a/host/ide/src/base-ui/select/LitSelectOption.ts b/host/ide/src/base-ui/select/LitSelectOption.ts index 440097f0fbc379ebec633a082b9291028becca8d..601f5383ff695398207b297575b6a4fd7fc573ba 100644 --- a/host/ide/src/base-ui/select/LitSelectOption.ts +++ b/host/ide/src/base-ui/select/LitSelectOption.ts @@ -17,14 +17,14 @@ import {BaseElement} from "../BaseElement.js"; import "../icon/LitIcon.js" export class LitSelectOption extends BaseElement { - static get observedAttributes() { - return ['selected','disabled','check'] - } + static get observedAttributes() { + return ['selected', 'disabled', 'check'] + } - initHtml() { - // super(); - // const shadowRoot = this.attachShadow({mode: 'open'}); - return` + initHtml() { + // super(); + // const shadowRoot = this.attachShadow({mode: 'open'}); + return ` -
- +
+
- + ` - } + } - initElements(): void { + initElements(): void { - } + } - //当 custom element首次被插入文档DOM时,被调用。 - connectedCallback() { - if(!this.hasAttribute('disabled')){ - this.onclick=ev => { - this.dispatchEvent(new CustomEvent('onSelected',{detail:{ - selected:true, - value: this.getAttribute('value'), - text: this.textContent - }})) - } - } + //当 custom element首次被插入文档DOM时,被调用。 + connectedCallback() { + if (!this.hasAttribute('disabled')) { + this.onclick = ev => { + this.dispatchEvent(new CustomEvent('onSelected', { + detail: { + selected: true, + value: this.getAttribute('value'), + text: this.textContent + } + })) + } + } - } + } - //当 custom element从文档DOM中删除时,被调用。 - disconnectedCallback() { + //当 custom element从文档DOM中删除时,被调用。 + disconnectedCallback() { - } + } - //当 custom element被移动到新的文档时,被调用。 - adoptedCallback() { - } + //当 custom element被移动到新的文档时,被调用。 + adoptedCallback() { + } - //当 custom element增加、删除、修改自身属性时,被调用。 - attributeChangedCallback(name:any, oldValue:any, newValue:any) { + //当 custom element增加、删除、修改自身属性时,被调用。 + attributeChangedCallback(name: any, oldValue: any, newValue: any) { - } + } } if (!customElements.get('lit-select-option')) { - customElements.define('lit-select-option', LitSelectOption); + customElements.define('lit-select-option', LitSelectOption); } diff --git a/host/ide/src/base-ui/select/LitSelectV.ts b/host/ide/src/base-ui/select/LitSelectV.ts new file mode 100644 index 0000000000000000000000000000000000000000..9879d3e0a8d60106f2a142c5295ff5a21e41878c --- /dev/null +++ b/host/ide/src/base-ui/select/LitSelectV.ts @@ -0,0 +1,497 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../BaseElement.js"; +import {LitSelectOption} from "./LitSelectOption.js"; + +@element('lit-select-v') +export class LitSelectV extends BaseElement { + showItems: Array = []; + itemValue: Array = []; + customItem: Array = []; + private focused: any; + private inputElement: any; + private searchInputElement: any; + private iconElement: any; + private options: HTMLDivElement | undefined; + private body: HTMLDivElement | undefined; + + private valueStr: string = ''; + + static get observedAttributes() { + return [ + 'value', + 'default-value', + 'placeholder', + 'disabled', + 'show-search', + 'border', + 'mode', + ]; + } + + get value() { + return this.inputElement!.value || this.defaultValue; + } + + get rounded() { + return this.hasAttribute("rounded"); + } + + set rounded(rounded: boolean) { + if (rounded) { + this.setAttribute("rounded", ''); + } else { + this.removeAttribute("rounded"); + } + } + + get placement(): string { + return this.getAttribute("placement") || ""; + } + + set placement(placement: string) { + if (placement) { + this.setAttribute("placement", placement); + } else { + this.removeAttribute("placement"); + } + } + + get border() { + return this.getAttribute('border') || 'true'; + } + + set border(value) { + if (value) { + this.setAttribute('border', 'true'); + } else { + this.setAttribute('border', 'false'); + } + } + + get defaultPlaceholder() { + return this.getAttribute('placeholder') || ''; + } + + get defaultValue() { + return this.getAttribute('default-value') || ''; + } + + set defaultValue(value) { + this.setAttribute('default-value', value); + } + + get placeholder() { + return this.getAttribute('placeholder') || this.defaultPlaceholder; + } + + set placeholder(value) { + this.setAttribute('placeholder', value); + } + + set all(isAll: boolean) { + if (isAll) { + this.setAttribute('is-all', ''); + } else { + this.removeAttribute('is-all'); + } + } + + get all() { + return this.hasAttribute('is-all'); + } + + dataSource(value: Array, valueStr: string) { + this.options!.innerHTML = ''; + if (value.length > 0) { + this.body!.style.display = "block" + this.valueStr = valueStr; + this.itemValue = value; + if (valueStr != "") { + let option = document.createElement("lit-select-option"); + if (this.all) { + option.setAttribute("selected", ""); + this.showItems = value + } + option.setAttribute('value', valueStr); + option.textContent = valueStr; + this.options!.appendChild(option); + this.initDataItem(value); + this.initCustomOptions() + } else { + this.initDataItem(value); + this.initOptions() + } + } else { + this.body!.style.display = "none" + } + if (this.title == 'Event List') { + let inputElement = this.shadowRoot?.querySelector('input') as HTMLInputElement; + inputElement.readOnly = false + } + } + + initDataItem(value: Array) { + value.forEach( + item => { + let option = document.createElement("lit-select-option"); + if (this.showItems.indexOf(item) > -1 || this.all) { + option.setAttribute("selected", "") + } + option.className = 'option'; + option.setAttribute('value', item); + option.textContent = item; + this.options!.appendChild(option); + } + ) + } + + initElements(): void { + this.tabIndex = 0; + this.focused = false; + this.inputElement = this.shadowRoot!.querySelector('#select-input') as HTMLInputElement; + this.searchInputElement = this.shadowRoot!.querySelector('#search-input') as HTMLInputElement; + this.body = this.shadowRoot!.querySelector('.body') as HTMLDivElement; + this.options = this.shadowRoot!.querySelector('.body-opt') as HTMLDivElement; + this.iconElement = this.shadowRoot!.querySelector('.icon'); + this.onclick = (ev: any) => { + if (this.focused === false) { + this.focused = true; + } else { + this.focused = false; + } + } + this.searchInputElement?.addEventListener('keyup', () => { + let options = [...this.shadowRoot!.querySelectorAll('.option')] + options.filter((a: LitSelectOption) => { + if (a.textContent!.indexOf(this.searchInputElement!.value) <= -1) { + a.style.display = "none"; + } else { + a.style.display = "flex"; + } + }); + }) + + this.onmouseout = this.onblur = ev => { + this.focused = false; + } + this.inputElement.onfocus = (ev: any) => { + if (this.hasAttribute('disabled')) return; + } + this.inputElement.onblur = (ev: any) => { + if (this.hasAttribute('disabled')) return; + } + } + + initHtml() { + return ` + +
+ + +
+
+
+ +
+
+ + +
+
+ ` + } + + connectedCallback() { + } + + initCustomOptions() { + let querySelector = this.shadowRoot?.querySelector(`lit-select-option[value="${this.valueStr}"]`) as LitSelectOption; + this.shadowRoot?.querySelectorAll('lit-select-option').forEach(a => { + a.setAttribute('check', ''); + a.addEventListener('onSelected', (e: any) => { + if (a.hasAttribute("selected")) { + let number = this.showItems.indexOf(a.textContent!); + if (number > -1) { + this.showItems!.splice(number, 1); + this.inputElement!.value = this.showItems; + } + this.all = false + querySelector.removeAttribute("selected"); + a.removeAttribute("selected"); + return; + } else { + let index = this.itemValue.indexOf(a.textContent!); + let value = this.showItems.indexOf(a.textContent!); + if (index > -1 && value == -1) { + this.showItems.push(a.textContent!); + this.inputElement!.value = this.showItems; + } + if (this.showItems.length >= this.itemValue.length) { + querySelector.setAttribute('selected', '') + this.all = true; + } else { + querySelector.removeAttribute('selected') + this.all = false; + } + a.setAttribute('selected', '') + } + }) + }) + this.selectAll(querySelector); + } + + + initOptions() { + this.options!.addEventListener('click', ev => { + let items = this.inputElement!.value.split(","); + this.customItem = [] + items.forEach((item: string) => { + if (item.trim() != "") { + let indexItem = this.itemValue.indexOf(item.trim()); + if (indexItem == -1) { + this.customItem.push(item.trim()) + } + } + }); + if (this.customItem.length > 0) { + this.inputElement.value = this.customItem.concat(this.showItems); + } else { + this.inputElement.value = this.showItems + } + }) + this.shadowRoot?.querySelectorAll('lit-select-option').forEach(a => { + a.setAttribute('check', ''); + a.addEventListener('onSelected', (e: any) => { + if (a.hasAttribute("selected")) { + let number = this.showItems.indexOf(a.textContent!); + if (number > -1) { + this.showItems.splice(number, 1) + } + a.removeAttribute("selected"); + return; + } else { + let index = this.itemValue.indexOf(a.textContent!); + if (index > -1) { + this.showItems.push(a.textContent!); + } + a.setAttribute('selected', '') + } + }) + }) + } + + selectAll(querySelector: LitSelectOption) { + querySelector?.addEventListener("click", ev => { + if (querySelector.hasAttribute("selected")) { + this.shadowRoot?.querySelectorAll('lit-select-option').forEach(a => { + a.setAttribute('selected', ''); + this.all = true + }) + this.itemValue.forEach(i => { + this.showItems.push(i) + }) + this.inputElement.value = this.itemValue; + } else { + this.shadowRoot?.querySelectorAll('lit-select-option').forEach(i => { + i.removeAttribute('selected'); + this.all = false + }) + this.showItems = []; + this.inputElement.value = ""; + } + }) + } + + attributeChangedCallback(name: any, oldValue: any, newValue: any) { + } + +} diff --git a/host/ide/src/base-ui/slicer/lit-slicer.ts b/host/ide/src/base-ui/slicer/lit-slicer.ts new file mode 100644 index 0000000000000000000000000000000000000000..906080ba20f1da807cdc91ef0c5491f76c7cfbcc --- /dev/null +++ b/host/ide/src/base-ui/slicer/lit-slicer.ts @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class LitSlicer extends HTMLElement { + static get observedAttributes() { + return ["direction"] //direction = 'horizontal'或者'vertical' + } + + constructor() { + super(); + const shadowRoot = this.attachShadow({mode: 'open'}); + shadowRoot.innerHTML = ` + +
+ +
+ ` + } + + set direction(val: any) { + // this.setAttribute('direction',val); + if (val.startsWith('h')) { + this.shadowRoot!.querySelector('div')!.style.flexDirection = 'row' + } else if (val.startsWith('v')) { + this.shadowRoot!.querySelector('div')!.style.flexDirection = 'column' + } + } + + connectedCallback() { + + } + + disconnectedCallback() { + + } + + attributeChangedCallback(name: any, oldValue: any, newValue: any) { + (this as any)[name] = newValue; + } + + set style(v: any) { + // this.shadowRoot.querySelector('#root').setAttribute('style',v) + } +} + +if (!customElements.get('lit-slicer')) { + customElements.define('lit-slicer', LitSlicer); +} + + +export class LitSlicerTrack extends HTMLElement { + private line: HTMLElement | null | undefined; + private draging: boolean = false; + private normalWidth: number = 0; + + static get observedAttributes() { + return ["range-left", "range-right"] + } + + get rangeLeft() { + return parseInt(this.getAttribute('range-left') || '200'); + } + + set rangeLeft(val: number) { + this.setAttribute('range-left', `${val}`); + } + + get rangeRight() { + return parseInt(this.getAttribute('range-right') || '300'); + } + + set rangeRight(val: number) { + this.setAttribute('range-right', `${val}`); + } + + constructor() { + super(); + const shadowRoot = this.attachShadow({mode: 'open'}); + shadowRoot.innerHTML = ` + +
+
+ ` + } + + //当 custom element首次被插入文档DOM时,被调用。 + connectedCallback() { + this.line = this.shadowRoot?.querySelector('#root') + let parentDirection = this.parentElement!.getAttribute("direction") || 'horizontal' + if (parentDirection.startsWith("h")) { + this.line!.className = 'rootH' + let previousElementSibling = this.previousElementSibling as HTMLElement; + let preX: number, preY: number, preWidth: number; + this.line!.onmousedown = (e) => { + this.draging = true; + preX = e.pageX; + preWidth = previousElementSibling!.clientWidth; + if (this.normalWidth == 0) this.normalWidth = previousElementSibling!.clientWidth; + previousElementSibling!.style.width = preWidth + 'px' + document.body.style.userSelect = 'none'; + document.body.style.webkitUserSelect = 'none'; + // @ts-ignore + document.body.style.msUserSelect = 'none'; + document.onmousemove = (e1) => { + if (this.draging) { + if ((preWidth + e1.pageX - preX) >= (this.normalWidth - this.rangeLeft) && (preWidth + e1.pageX - preX) <= (this.normalWidth + this.rangeRight)) { + previousElementSibling!.style.width = (preWidth + e1.pageX - preX) + 'px' + } + } + } + document.onmouseleave = (e2) => { + this.draging = false; + document.body.style.userSelect = 'auto'; + document.body.style.webkitUserSelect = 'auto'; + // @ts-ignore + document.body.style.msUserSelect = 'auto'; + } + document.onmouseup = (e3) => { + this.draging = false; + document.body.style.userSelect = 'auto'; + document.body.style.webkitUserSelect = 'auto'; + // @ts-ignore + document.body.style.msUserSelect = 'auto'; + } + } + } else { + this.line!.className = 'rootV' + let previousElementSibling = this.previousElementSibling as HTMLElement; + let preY: number, preHeight: number; + this.line!.onmousedown = (e) => { + this.draging = true; + preY = e.pageY; + preHeight = previousElementSibling?.clientHeight; + previousElementSibling!.style!.height = preHeight + 'px' + document.onmousemove = (e1) => { + if (this.draging) { + previousElementSibling.style.height = (preHeight + e1.pageY - preY) + 'px' + } + } + document.onmouseleave = (e2) => { + this.draging = false; + } + document.onmouseup = (e3) => { + this.draging = false; + } + } + } + + } + + //当 custom element从文档DOM中删除时,被调用。 + disconnectedCallback() { + this.line!.onmousedown = null; + } + + //当 custom element被移动到新的文档时,被调用。 + adoptedCallback() { + } + + //当 custom element增加、删除、修改自身属性时,被调用。 + attributeChangedCallback(name: any, oldValue: any, newValue: any) { + } +} + +if (!customElements.get('lit-slicer-track')) { + customElements.define('lit-slicer-track', LitSlicerTrack); +} \ No newline at end of file diff --git a/host/ide/src/base-ui/slider/LitSlider.ts b/host/ide/src/base-ui/slider/LitSlider.ts index fa7042104174350c1e69c5345ca2aa7639b50c7e..e54e9ea8907c590db0ac43f7248c3dd6bde13f6a 100644 --- a/host/ide/src/base-ui/slider/LitSlider.ts +++ b/host/ide/src/base-ui/slider/LitSlider.ts @@ -21,54 +21,57 @@ export class LitSlider extends BaseElement { private litSlider: HTMLInputElement | undefined | null; private litSliderCon: HTMLDivElement | undefined | null; private litResult: HTMLInputElement | undefined | null; - private litSliderButton: HTMLDivElement | undefined | null; private slotEl: HTMLSlotElement | undefined | null; private currentValue: number = 0; - private sliderLineHeight: string | undefined; - private sliderButtonHeight: string | undefined; - private sliderButtonWidth: string | undefined; private defaultTimeText: string | undefined | null; static get observedAttributes() { return ['percent', 'disabled-X', 'custom-slider', 'custom-line', 'custom-button'] } - get sliderStyle() { - if (this.hasAttribute('custom-slider')) { - this.defaultTimeText = "64"; - return { - minRange: 4, - maxRange: 512, - defaultValue: this.defaultTimeText, - resultUnit: "MB", - stepSize: 2, - lineColor: "var(--dark-color3,#46B1E3)", - buttonColor: "#999999" - } + get sliderStyle(): LitSliderStyle { + if (this.litSliderStyle) { + return this.litSliderStyle } else { - let defaultTime = "00:00:50"; - this.defaultTimeText = defaultTime.split(':')[2]; return { - minRange: 10, - maxRange: 600, - defaultValue: defaultTime, - resultUnit: "h:m:s", + minRange: 0, + maxRange: 100, + defaultValue: "0", + resultUnit: "", stepSize: 1, - lineColor: "var(--dark-color4,#61CFBE)", + lineColor: "var(--dark-color3,#46B1E3)", buttonColor: "#999999" } } - } - set sliderStyle(value) { + set sliderStyle(value: LitSliderStyle) { this.litSliderStyle = value; - this.litSliderStyle = this.sliderStyle; + this.currentValue = Number(value.defaultValue) this.litSliderStyle.defaultValue = value.defaultValue - if (this.hasAttribute('custom-slider')) { - this.renderCustomSlider(); + if (this.litSliderStyle.resultUnit === 'h:m:s') { + let timeData = this.litSliderStyle.defaultValue.split(':'); + let timeSize = Number(timeData[0]) * 3600 + Number(timeData[1]) * 60 + Number(timeData[2]); + this.defaultTimeText = timeSize.toString() + let defaultSize = (timeSize - this.litSliderStyle.minRange) * 100 / (this.litSliderStyle + .maxRange - this.litSliderStyle.minRange); + this.litSlider!.style.backgroundSize = defaultSize + '%' } else { - this.renderDefaultSlider(); + this.defaultTimeText = this.litSliderStyle.defaultValue + this.litSlider!.style.backgroundSize = '0%' + if (Number(this.litSliderStyle.defaultValue)) { + let defaultSize = (Number(this.litSliderStyle.defaultValue) - this.litSliderStyle.minRange) + / (this.litSliderStyle.maxRange - this.litSliderStyle.minRange) * 100; + this.litSlider!.style.backgroundSize = defaultSize + '%' + } + } + let htmlInputElement = this.shadowRoot?.querySelector('#slider') as HTMLInputElement; + let attribute = htmlInputElement.getAttribute('type'); + if (attribute === 'range') { + htmlInputElement!.setAttribute('value', this.defaultTimeText!) + htmlInputElement!.setAttribute('min', this.litSliderStyle!.minRange.toString()) + htmlInputElement!.setAttribute('max', this.litSliderStyle!.maxRange.toString()) + htmlInputElement!.setAttribute('step', this.litSliderStyle!.stepSize.toString()) } } @@ -118,6 +121,8 @@ export class LitSlider extends BaseElement { set percent(value: string) { this.setAttribute('percent', value); + let resultNumber = (Number(value) - this.sliderStyle!.minRange) * 100 / (this.sliderStyle!.maxRange - this.sliderStyle!.minRange); + this.litSlider!.style.backgroundSize = resultNumber + '%'; } get resultUnit() { @@ -128,20 +133,11 @@ export class LitSlider extends BaseElement { this.setAttribute('resultUnit', value); } - get sliderSize() { - return this.currentValue; - } - initElements(): void { + this.litSlider = this.shadowRoot?.querySelector('#slider') as HTMLInputElement; } initHtml(): string { - this.litSliderStyle = this.sliderStyle; - this.currentValue = Number(this.sliderStyle.defaultValue); - let parentElement = this.parentNode as Element; - if (parentElement) { - parentElement.setAttribute('percent', this.defaultTimeText + ""); - } return `
- - ${this.litSliderStyle?.resultUnit} +
` } @@ -296,64 +247,35 @@ export class LitSlider extends BaseElement { // It is called when the custom element is first inserted into the document DOM. connectedCallback() { this.slotEl = this.shadowRoot?.querySelector('#slot'); - this.litSlider = this.shadowRoot?.querySelector('#slider'); this.litSliderCon = this.shadowRoot?.querySelector('#slider-con'); - this.litResult = this.shadowRoot?.querySelector('#result'); // Add a slider for input event listeners this.litSlider?.addEventListener('input', this.inputChangeEvent) this.litSlider?.addEventListener('change', this.inputChangeEvent) - // Add slot slot to change event listeners - this.slotEl?.addEventListener('slotchange', this.slotChangeEvent); - // Add a slider for line click event listeners - this.litSlider?.addEventListener('click', this.sliderClickEvent); - // Add a slider button to start touching the event listener - this.litSliderButton?.addEventListener('TouchEvent', this.sliderStartTouchEvent); this.litSliderStyle = this.sliderStyle; } - slotChangeEvent = (event: any) => { - } - - sliderClickEvent = (event: any) => { - } - inputChangeEvent = (event: any) => { if (this.litSlider) { this.currentValue = parseInt(this.litSlider?.value) - let resultNumber = (this.currentValue - this.litSliderStyle!.minRange) * 100 / (this.litSliderStyle!.maxRange - this.litSliderStyle!.minRange); - this.percent = Math.floor(resultNumber) + "%"; + let resultNumber = (this.currentValue - this.litSliderStyle!.minRange) * 100 / (this + .litSliderStyle!.maxRange - this.litSliderStyle!.minRange); + this.percent = Number(resultNumber) + "%"; this.litSliderCon?.style.setProperty('percent', this.currentValue + "%") let parentElement = this.parentNode as Element; parentElement.setAttribute('percent', this.currentValue + ""); - if (this.sliderStyle.resultUnit === 'MB') { + if (this.sliderStyle.resultUnit === 'h:m:s') { this.litSlider!.style.backgroundSize = this.percent; - this.litResult!.value = " " + this.currentValue; - } else if (this.sliderStyle.resultUnit === 'h:m:s') { + } else { this.litSlider!.style.backgroundSize = this.percent; - let time = this.formatSeconds(this.litSlider?.value); - this.litResult!.value = " " + time; } + this.parentElement!.setAttribute('percent', this.litSlider?.value) } } - sliderStartTouchEvent = (event: any) => { - - } - - sliderMoveTouchEvent = (event: any) => { - - } - - sliderEndTouchEvent = (event: any) => { - - } - disconnectedCallback() { this.litSlider?.removeEventListener('input', this.inputChangeEvent); this.litSlider?.removeEventListener('change', this.inputChangeEvent) - this.litSlider?.removeEventListener('click', this.sliderClickEvent); - this.litSliderButton?.removeEventListener('TouchEvent', this.sliderStartTouchEvent); } adoptedCallback() { @@ -374,17 +296,23 @@ export class LitSlider extends BaseElement { } } - renderCustomSlider() { - } - renderDefaultSlider() { - if (!this.litSliderStyle) return; + let htmlInputElement = this.shadowRoot?.querySelector('#slider') as HTMLInputElement; + let attribute = htmlInputElement.getAttribute('type'); + if (attribute === 'range') { + htmlInputElement!.setAttribute('value', this.defaultTimeText!) + htmlInputElement!.setAttribute('min', this.litSliderStyle!.minRange.toString()) + htmlInputElement!.setAttribute('max', this.litSliderStyle!.maxRange.toString()) + htmlInputElement!.setAttribute('step', this.litSliderStyle!.stepSize.toString()) + } } formatSeconds(value: string) { let result = parseInt(value) - let hours = Math.floor(result / 3600) < 10 ? '0' + Math.floor(result / 3600) : Math.floor(result / 3600); - let minute = Math.floor((result / 60 % 60)) < 10 ? '0' + Math.floor((result / 60 % 60)) : Math.floor((result / 60 % 60)); + let hours = Math.floor(result / 3600) < 10 ? '0' + Math.floor(result / 3600) : Math + .floor(result / 3600); + let minute = Math.floor((result / 60 % 60)) < 10 ? '0' + Math + .floor((result / 60 % 60)) : Math.floor((result / 60 % 60)); let second = Math.floor((result % 60)) < 10 ? '0' + Math.floor((result % 60)) : Math.floor((result % 60)); let resultTime = ''; if (hours === '00') { @@ -407,7 +335,7 @@ export interface LitSliderStyle { maxRange: number defaultValue: string resultUnit: string - stepSize?: number + stepSize: number lineColor?: string buttonColor?: string } diff --git a/host/ide/src/base-ui/switch/lit-switch.ts b/host/ide/src/base-ui/switch/lit-switch.ts index 2dc25eaef92b593d9f371b835930c43792c0cd6d..ca53eed104bf51efd2ca6d7e1b8cb749926d4302 100644 --- a/host/ide/src/base-ui/switch/lit-switch.ts +++ b/host/ide/src/base-ui/switch/lit-switch.ts @@ -65,15 +65,20 @@ export default class LitSwitch extends BaseElement { -webkit-tap-highlight-color: transparent; } #name{ - cursor:pointer; + transition:0.31s width,0.31s height,0.31s background-color; + width:2.41em; + height:1.21em; + background: #3391FF; display:flex; - width:2.4em; - height:1.2em; - padding:.125em; - border-radius:1.2em; - background:#eee; - transition:.3s width,.3s height,.3s background-color; + padding:0.124em; + border-radius:1.21em; + cursor:pointer; + } + + :host(:not([checked])) #name { + background: #999999; } + #name::before{ content:''; flex:0; diff --git a/host/ide/src/base-ui/table/lit-table-column.ts b/host/ide/src/base-ui/table/lit-table-column.ts index b66d3004018cbedfce1300070da3a6e1daad2fc3..9c9f1956b623494f8dd10e3c4cd70ac7120b4678 100644 --- a/host/ide/src/base-ui/table/lit-table-column.ts +++ b/host/ide/src/base-ui/table/lit-table-column.ts @@ -25,13 +25,13 @@ export class LitTableColumn extends HTMLElement { super(); const shadowRoot = this.attachShadow({mode: 'open'}); shadowRoot.innerHTML = ` - - + + ` } diff --git a/host/ide/src/base-ui/table/lit-table.ts b/host/ide/src/base-ui/table/lit-table.ts index 7a6dab11a1bd1461c481db69b432914305272191..4eaeebfed3abf66f01881f0ff21d2f88062c2da7 100644 --- a/host/ide/src/base-ui/table/lit-table.ts +++ b/host/ide/src/base-ui/table/lit-table.ts @@ -13,7 +13,6 @@ * limitations under the License. */ - import {LitTableColumn} from "./lit-table-column.js"; import {element} from "../BaseElement.js"; import "../utils/Template.js" @@ -24,8 +23,10 @@ export class LitTable extends HTMLElement { meauseRowElement: HTMLDivElement | undefined currentRecycleList: HTMLDivElement[] = [] currentTreeDivList: HTMLDivElement[] = [] + public rememberScrollTop = false private ds: Array = [] private recycleDs: Array = [] + private normalDs: Array = [] private gridTemplateColumns: any /*Grid css layout descriptions are obtained according to the clustern[] nested structure*/ private st: HTMLSlotElement | null | undefined @@ -36,161 +37,190 @@ export class LitTable extends HTMLElement { private treeElement: HTMLDivElement | undefined | null private tableColumns: NodeListOf | undefined private colCount: number = 0 - + private currentScrollTop: number = 0 + private isRecycleList: boolean = true + private isScrollXOutSide: boolean = false; constructor() { super(); const shadowRoot = this.attachShadow({mode: 'open'}); shadowRoot.innerHTML = ` - + } + :host([grid-line]) .td{ + border-left: 1px solid #f0f0f0; + } + :host([grid-line]) .td:last-of-type{ + border-right: 1px solid #f0f0f0; + } + .table{ + width: 100%; + color: var(--dark-color2,#262626); + } + .thead{ + display: grid; + position: sticky; + top: 0; + font-weight: bold; + font-size: .9rem; + color: var(--dark-color1,#000); + background-color: var(--dark-background,#FFFFFF); + z-index: 1; + } + .tbody{ + width: 100%; + top: 0; + left: 0; + right:0; + bottom:0; + display: flex; + flex-direction: row + row-gap: 1px; + column-gap: 1px; + } + .tree{ + overflow-x:hidden; + overflow-y:hidden; + display: grid; + grid-template-columns: 1fr; + row-gap: 1px; + column-gap: 1px; + position:relative; + } + .tree:hover{ + overflow-x: overlay; + } + .tree-first-body{ + min-width: 100%; + box-sizing: border-box; + display:flex; + align-items:center; + white-space: nowrap; + cursor: pointer; + } + .tree-first-body:hover{ + background-color: var(--dark-background6,#DEEDFF); /*antd #fafafa 42b983*/ + } + .body{ + display: grid; + grid-template-columns: 1fr; + row-gap: 1px; + column-gap: 1px; + flex:1; + position: relative; + } + :host([grid-line]) .tbody{ + border-bottom: 1px solid #f0f0f0; + background-color: #f0f0f0; + } + .th{ + grid-column-gap: 5px; + display: grid; + background-color: var(--dark-background,#FFFFFF); + } - -
-
-
-
-
-
-
- ` + .tree-icon{ + font-size: 1.2rem; + width: 20px; + height: 20px; + padding-right: 5px; + padding-left: 5px; + cursor: pointer; + } + .tree-icon:hover{ + color: #42b983; + } + .row-checkbox,row-checkbox-all{ + } + :host([no-head]) .thead{ + display: none; + } + .up-svg{ + position: absolute; + right: 5px; + top: 8px; + bottom: 8px; + width: 15px; + height: 15px; + } + .down-svg{ + position: absolute; + top: 8px; + right: 5px; + bottom: 8px; + width: 15px; + height: 15px; + } + .mouse-select{ + background-color: var(--dark-background6,#DEEDFF); + } + .mouse-in{ + background-color: var(--dark-background6,#DEEDFF); + } + .export{ + width:30px; + height:30px; + cursor:pointer; + color:var(--dark-background6,#262626); + box-sizing: border-box; + position:fixed; + right:30px; + bottom:15px; + } + + + + +
+
+
+
+
+
+
+ ` } static get observedAttributes() { @@ -217,12 +247,14 @@ export class LitTable extends HTMLElement { this.setAttribute('scroll-y', value); } + get dataSource() { return this.ds || []; } set dataSource(value) { this.ds = value; + this.isRecycleList = false if (this.hasAttribute('tree')) { this.renderTreeTable(); } else { @@ -231,11 +263,19 @@ export class LitTable extends HTMLElement { } get recycleDataSource() { - return this.recycleDs || []; + return this.ds || []; } set recycleDataSource(value) { - this.tableElement!.scrollTop = 0 + this.isScrollXOutSide = this.tableElement!.scrollWidth > this.tableElement!.clientWidth + this.isRecycleList = true + this.ds = value; + if (this.rememberScrollTop) { + this.currentScrollTop = this.tableElement!.scrollTop; + this.tableElement!.scrollTop = 0 + } else { + this.tableElement!.scrollTop = 0 + } if (this.hasAttribute('tree')) { this.recycleDs = this.meauseTreeRowElement(value) } else { @@ -243,7 +283,64 @@ export class LitTable extends HTMLElement { } } - // It is called when the custom element is first inserted into the document DOM. + move1px() { + this.tableElement!.scrollTop = this.tableElement!.scrollTop + 1 + } + + dataExportInit() { + let exportDiv = this.shadowRoot!.querySelector(".export") + exportDiv && (exportDiv.onclick = () => { + this.exportData() + }); + let tab = document?.querySelector("body > sp-application")?.shadowRoot?.querySelector("#sp-system-trace") + ?.shadowRoot?.querySelector("div > trace-sheet")?.shadowRoot?.querySelector("#tabs"); + if (tab != undefined) { + new ResizeObserver(() => { + if (tab && tab.clientHeight > (38 + 70)) { + exportDiv!.style.visibility = "visible"; + } else { + exportDiv!.style.visibility = "hidden"; + } + }).observe(tab) + } + } + + exportData() { + let formatData: any[] = this.formatExportData(this.ds) + let link = document.createElement('a') + link.download = new Date().getTime() + '.json' + link.href = 'data:text/plain,' + JSON.stringify(formatData, null, 4) + link.click() + } + + formatExportData(dataSource: any[]): any[] { + if (dataSource == undefined || dataSource.length == 0) { + return [] + } + if (this.columns == undefined) { + return [] + } + return dataSource.map((item) => { + let formatData: any = {} + this.columns!.forEach((column) => { + let dataIndex = column.getAttribute('data-index') + let columnName = column.getAttribute('title') + if (columnName == "") { + columnName = dataIndex + } + if (dataIndex && columnName && item[dataIndex] != undefined) { + formatData[columnName] = item[dataIndex] + } + }) + if (item.children != undefined) { + formatData.children = this.formatExportData(item.children) + } + return formatData + }) + } + + + //当 custom element首次被插入文档DOM时,被调用。 connectedCallback() { this.st = this.shadowRoot?.querySelector('#slot'); this.tableElement = this.shadowRoot?.querySelector('.table'); @@ -252,6 +349,29 @@ export class LitTable extends HTMLElement { this.tbodyElement = this.shadowRoot?.querySelector('.body'); this.tableColumns = this.querySelectorAll('lit-table-column'); this.colCount = this.tableColumns!.length; + this.tableElement?.addEventListener("copy",(e)=>{ + // @ts-ignore + let clipboardData = e.clipboardData || window.clipboardData; + if(!clipboardData) return ; + // @ts-ignore + let text = window.getSelection().toString(); + if(text){ + e.preventDefault(); + let length = this.tableColumns?.length||1; + let strings = text.split("\n"); + let formatStr = "" + for (let i = 0; i < strings.length; i++) { + if(i%length != 0){ + formatStr+=" " + } + formatStr+=strings[i] + if(i!=0&&i%length == length - 1){ + formatStr += "\n" + } + } + clipboardData.setData('text/plain', formatStr) + } + }) this.st?.addEventListener('slotchange', () => { this.theadElement!.innerHTML = ''; setTimeout(() => { @@ -276,7 +396,6 @@ export class LitTable extends HTMLElement { this.shadowRoot!.querySelectorAll('.tr').forEach(a => a.removeAttribute('checked')); } } - box.appendChild(checkbox); rowElement.appendChild(box); } @@ -317,24 +436,24 @@ export class LitTable extends HTMLElement { let NS = "http://www.w3.org/2000/svg"; let upSvg: any = document.createElementNS(NS, "svg"); let upPath: any = document.createElementNS(NS, "path"); - upSvg.setAttribute('fill', '#efefef'); + upSvg.setAttribute('fill', 'var(--dark-color1,#212121)'); upSvg.setAttribute('viewBox', '0 0 1024 1024'); - upSvg.setAttribute('stroke', '#000000'); + upSvg.setAttribute('stroke', 'var(--dark-color1,#212121)'); upSvg.classList.add('up-svg'); upPath.setAttribute("d", "M858.9 689L530.5 308.2c-9.4-10.9-27.5-10.9-37 0L165.1 689c-12.2 14.2-1.2 35 18.5 35h656.8c19.7 0 30.7-20.8 18.5-35z"); upSvg.appendChild(upPath); let downSvg: any = document.createElementNS(NS, "svg"); let downPath: any = document.createElementNS(NS, "path"); - downSvg.setAttribute('fill', '#efefef'); + downSvg.setAttribute('fill', 'var(--dark-color1,#212121)'); downSvg.setAttribute('viewBox', '0 0 1024 1024'); - downSvg.setAttribute('stroke', '#efefef'); + downSvg.setAttribute('stroke', 'var(--dark-color1,#212121)'); downSvg.classList.add('down-svg'); downPath.setAttribute("d", "M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z"); downSvg.appendChild(downPath) if (i == 0) { h.sortType = 0; // 默认以第一列 降序排序 作为默认排序 - upSvg.setAttribute('fill', '#fff'); - downSvg.setAttribute('fill', '#fff'); + upSvg.setAttribute('fill', 'var(--dark-color1,#212121)'); + downSvg.setAttribute('fill', 'var(--dark-color1,#212121)'); } upSvg.style.display = 'none'; downSvg.style.display = 'none'; @@ -342,9 +461,9 @@ export class LitTable extends HTMLElement { h.appendChild(downSvg); h.onclick = () => { this?.shadowRoot?.querySelectorAll('.td-order svg').forEach((it: any) => { - it.setAttribute('fill', '#fff'); - it.setAttribute('fill', '#fff'); + it.setAttribute('fill', 'var(--dark-color1,#212121)'); it.sortType = 0; + it.style.display = 'none'; }) if (h.sortType == undefined || h.sortType == null) { h.sortType = 0; @@ -355,20 +474,20 @@ export class LitTable extends HTMLElement { } switch (h.sortType) { case 1: - upSvg.setAttribute('fill', '#333'); - downSvg.setAttribute('fill', '#fff'); + upSvg.setAttribute('fill', 'var(--dark-color1,#212121)'); + downSvg.setAttribute('fill', 'var(--dark-color1,#212121)'); upSvg.style.display = 'block'; downSvg.style.display = 'none'; break; case 2: - upSvg.setAttribute('fill', '#fff'); - downSvg.setAttribute('fill', '#333'); + upSvg.setAttribute('fill', 'var(--dark-color1,#212121)'); + downSvg.setAttribute('fill', 'var(--dark-color1,#212121)'); upSvg.style.display = 'none'; downSvg.style.display = 'block'; break; default: - upSvg.setAttribute('fill', "#fff"); - downSvg.setAttribute('fill', "#fff"); + upSvg.setAttribute('fill', "var(--dark-color1,#212121)"); + downSvg.setAttribute('fill', "var(--dark-color1,#212121)"); upSvg.style.display = 'none'; downSvg.style.display = 'none'; break; @@ -402,15 +521,16 @@ export class LitTable extends HTMLElement { this.gridTemplateColumns = gridTemplateColumns.join(' '); if (this.selectable) { let s = area.map(a => '"_checkbox_ ' + (a.map((aa: any) => aa.t).join(' ')) + '"').join(' '); - rowElement.style.gridTemplateColumns = "60px " + gridTemplateColumns.join(' ');//`repeat(${this.colCount},1fr)` + rowElement.style.gridTemplateColumns = "60px " + gridTemplateColumns.join(' '); rowElement.style.gridTemplateRows = `repeat(${area.length},1fr)` rowElement.style.gridTemplateAreas = s } else { let s = area.map(a => '"' + (a.map((aa: any) => aa.t).join(' ')) + '"').join(' '); - rowElement.style.gridTemplateColumns = gridTemplateColumns.join(' ');//`repeat(${this.colCount},1fr)` + rowElement.style.gridTemplateColumns = gridTemplateColumns.join(' '); rowElement.style.gridTemplateRows = `repeat(${area.length},1fr)` rowElement.style.gridTemplateAreas = s } + this.theadElement!.innerHTML = '' this.theadElement!.append(rowElement); this.treeElement!.style.top = this.theadElement?.clientHeight + "px" }); @@ -449,6 +569,7 @@ export class LitTable extends HTMLElement { renderTable() { if (!this.columns) return; if (!this.ds) return; // If no data source is set, it is returned directly + this.normalDs = [] this.tbodyElement!.innerHTML = '';// Clear the table contents this.ds.forEach((rowData: any) => { let rowElement = document.createElement('div'); @@ -501,7 +622,7 @@ export class LitTable extends HTMLElement { if (cl.hasAttribute('fixed')) { this.fixed(td, cl.getAttribute('fixed') || '', "#ffffff") } - td.innerHTML = rowData[dataIndex]; + td.innerHTML = this.formatName(rowData[dataIndex]); rowElement.append(td); } @@ -509,11 +630,21 @@ export class LitTable extends HTMLElement { if (this.selectable) { // If the table with selection is preceded by a 60px column rowElement.style.gridTemplateColumns = '60px ' + gridTemplateColumns.join(' '); } else { - rowElement.style.gridTemplateColumns = gridTemplateColumns.join(' ');// + rowElement.style.gridTemplateColumns = gridTemplateColumns.join(' '); } rowElement.onclick = e => { - this.dispatchEvent(new CustomEvent('row-click', {detail: rowData, composed: true})); + this.dispatchEvent(new CustomEvent('row-click', { + detail: { + rowData, data: rowData, callBack: (isSelected: boolean) => {//是否爲单选 + if (isSelected) { + this.clearAllSelection(rowData) + } + this.setSelectedRow(rowData.isSelected, [rowElement]) + } + }, composed: true + })); } + this.normalDs.push(rowElement); this.tbodyElement!.append(rowElement); }) } @@ -533,7 +664,7 @@ export class LitTable extends HTMLElement { return !father[pid]; }); } - let treeData = toTreeData(this.ds, ids[0], ids[1]);// + let treeData = toTreeData(this.ds, ids[0], ids[1]); let offset = 30; let offsetVal = offset; const drawRow = (arr: any, parentNode: any) => { @@ -584,11 +715,9 @@ export class LitTable extends HTMLElement { if (cl.template) { // @ts-ignore let cloneNode = cl.template.render(rowData).content.cloneNode(true); - // cloneNode.classList.add('td'); td = document.createElement('div'); td.classList.add('td'); td.style.wordBreak = 'break-all' - // td.style.whiteSpace = 'pre-wrap' td.style.justifyContent = cl.getAttribute('align') || '' if (cl.hasAttribute('fixed')) { this.fixed(td, cl.getAttribute('fixed') || '', "#ffffff") @@ -598,14 +727,12 @@ export class LitTable extends HTMLElement { td = document.createElement('div'); td.classList.add('td'); td.style.wordBreak = 'break-all' - // td.style.whiteSpace = 'pre-wrap' td.style.justifyContent = cl.getAttribute('align') || '' if (cl.hasAttribute('fixed')) { this.fixed(td, cl.getAttribute('fixed') || '', "#ffffff") } - // td.style.position='sticky'; // @ts-ignore - td.innerHTML = rowData[dataIndex]; + td.innerHTML = this.formatName(rowData[dataIndex]); } rowElement.append(td) } else { @@ -615,11 +742,8 @@ export class LitTable extends HTMLElement { if (cl.template) { // @ts-ignore let cloneNode = cl.template.render(rowData).content.cloneNode(true); - // cloneNode.classList.add('td'); td = document.createElement('div'); td.classList.add('td'); - // td.style.wordBreak = 'break-all' - // td.style.whiteSpace = 'pre-wrap' td.style.justifyContent = cl.getAttribute('align') || '' if (cl.hasAttribute('fixed')) { this.fixed(td, cl.getAttribute('fixed') || '', "#ffffff") @@ -628,15 +752,12 @@ export class LitTable extends HTMLElement { } else { td = document.createElement('div'); td.classList.add('td'); - // td.style.wordBreak = 'break-all' - // td.style.whiteSpace = 'pre-wrap' td.style.justifyContent = cl.getAttribute('align') || '' if (cl.hasAttribute('fixed')) { this.fixed(td, cl.getAttribute('fixed') || '', "#ffffff") } - // td.style.position='sticky'; // @ts-ignore - td.innerHTML = rowData[dataIndex]; + td.innerHTML = this.formatName(rowData[dataIndex]); } if (rowData.children && rowData.children.length > 0) { let btn = document.createElement('lit-icon'); @@ -655,9 +776,9 @@ export class LitTable extends HTMLElement { }) if (this.selectable) { - rowElement.style.gridTemplateColumns = '60px ' + gridTemplateColumns.join(' ');//`repeat(${this.colCount},1fr)` + rowElement.style.gridTemplateColumns = '60px ' + gridTemplateColumns.join(' '); } else { - rowElement.style.gridTemplateColumns = gridTemplateColumns.join(' ');//`repeat(${this.colCount},1fr)` + rowElement.style.gridTemplateColumns = gridTemplateColumns.join(' '); } rowElement.onclick = e => { this.dispatchEvent(new CustomEvent('row-click', {detail: rowData, composed: true})); @@ -705,10 +826,11 @@ export class LitTable extends HTMLElement { meauseAllRowHeight(list: any[]): TableRowObject[] { this.tbodyElement!.innerHTML = ''; this.meauseRowElement = undefined - this.tbodyElement && (this.tbodyElement.style.width = this.tableElement?.clientWidth + "px") + let head = this.shadowRoot!.querySelector(".th"); + this.tbodyElement && (this.tbodyElement.style.width = head?.clientWidth + "px") this.currentRecycleList = [] let headHeight = 0 - let totalHeight = headHeight + let totalHeight = headHeight; let visibleObjects: TableRowObject[] = []; list.forEach((rowData, index) => { let height = this.meauseElementHeight(rowData); @@ -718,7 +840,7 @@ export class LitTable extends HTMLElement { tableRowObject.data = rowData tableRowObject.rowIndex = index if (Math.max(totalHeight, this.tableElement!.scrollTop + headHeight) <= Math.min(totalHeight + height, this.tableElement!.scrollTop + this.tableElement!.clientHeight + headHeight)) { - let newTableElement = this.createNewTableElement(rowData); + let newTableElement = this.createNewTableElement(tableRowObject); newTableElement.style.transform = `translateY(${totalHeight}px)` this.tbodyElement?.append(newTableElement) this.currentRecycleList.push(newTableElement) @@ -726,7 +848,7 @@ export class LitTable extends HTMLElement { totalHeight += height visibleObjects.push(tableRowObject) }) - this.tbodyElement && (this.tbodyElement.style.height = totalHeight + "px") + this.tbodyElement && (this.tbodyElement.style.height = totalHeight + (this.isScrollXOutSide?0:0) + "px") this.tableElement && (this.tableElement.onscroll = (event) => { let top = this.tableElement!.scrollTop; let skip = 0; @@ -736,12 +858,12 @@ export class LitTable extends HTMLElement { break; } } - let reduce = this.currentRecycleList.map((item) => item.clientHeight).reduce((a, b) => a + b,0); - if(reduce == 0){ + let reduce = this.currentRecycleList.map((item) => item.clientHeight).reduce((a, b) => a + b, 0); + if (reduce == 0) { return } while (reduce <= this.tableElement!.clientHeight) { - let newTableElement = this.createNewTableElement(visibleObjects[skip].data); + let newTableElement = this.createNewTableElement(visibleObjects[skip]); this.tbodyElement?.append(newTableElement) this.currentRecycleList.push(newTableElement) reduce += newTableElement.clientHeight @@ -804,8 +926,8 @@ export class LitTable extends HTMLElement { break; } } - let reduce = this.currentRecycleList.map((item) => item.clientHeight).reduce((a, b) => a + b,0); - if(reduce == 0){ + let reduce = this.currentRecycleList.map((item) => item.clientHeight).reduce((a, b) => a + b, 0); + if (reduce == 0) { return } while (reduce <= this.tableElement!.clientHeight) { @@ -843,7 +965,7 @@ export class LitTable extends HTMLElement { td.template = column.template } else { td = document.createElement('div') - td.innerHTML = rowData.data[dataIndex]; + td.innerHTML = this.formatName(rowData.data[dataIndex]); td.dataIndex = dataIndex } if (rowData.data.children && rowData.data.children.length > 0) { @@ -853,27 +975,29 @@ export class LitTable extends HTMLElement { } else { td.style.paddingLeft = rowData.depth * 15 + 20 + 'px'; } + (td as any).data = rowData.data td.classList.add('tree-first-body'); td.style.position = 'absolute'; td.style.top = '0px' td.style.left = '0px' - td.onmouseover = () => { + td.onmouseenter = () => { let indexOf = this.currentTreeDivList.indexOf(td); + this.currentRecycleList.forEach((row)=>{ + row.classList.remove('mouse-in') + }) if (indexOf >= 0 && indexOf < this.currentRecycleList.length && td.innerHTML != "") { - this.setSelectedRow(true,[(this.treeElement?.children[indexOf] as HTMLElement),newTableElement]); + this.setMouseIn(true, [newTableElement]); } } - td.onmouseout = () => { + td.onmouseleave = () => { let indexOf = this.currentTreeDivList.indexOf(td); if (indexOf >= 0 && indexOf < this.currentRecycleList.length) { - this.setSelectedRow(false,[(this.treeElement?.children[indexOf] as HTMLElement),newTableElement]); + this.setMouseIn(false, [newTableElement]); } } td.onclick = () => { - this.dispatchEvent(new CustomEvent('row-click', {detail: {...rowData.data,callBack:(isSelected:boolean)=>{ - let indexOf = this.currentTreeDivList.indexOf(td); - this.setSelectedRow(isSelected,[(this.currentRecycleList[indexOf] as HTMLElement),td]) - }}, composed: true,})); + let indexOf = this.currentTreeDivList.indexOf(td); + this.dispatchRowClickEvent(rowData, [(this.treeElement?.children[indexOf] as HTMLElement), newTableElement]) } this.treeElement!.style.width = column.getAttribute('width') this.treeElement?.append(td) @@ -882,43 +1006,48 @@ export class LitTable extends HTMLElement { gridTemplateColumns.push(column.getAttribute('width') || '1fr') td = document.createElement('div') td.classList.add('td'); - // td.style.wordBreak = 'break-all' td.style.overflow = 'hidden' td.style.textOverflow = 'ellipsis' td.style.whiteSpace = "nowrap" td.title = rowData.data[dataIndex] - // td.innerHTML = rowData.data[dataIndex]; td.dataIndex = dataIndex - td.style.justifyContent = column.getAttribute('align')||'flex-start' + td.style.justifyContent = column.getAttribute('align') || 'flex-start' if (column.template) { td.appendChild(column.template.render(rowData.data).content.cloneNode(true)); td.template = column.template } else { - td.innerHTML = rowData.data[dataIndex]; + td.innerHTML = this.formatName(rowData.data[dataIndex]); } newTableElement.append(td) } }); (this.treeElement?.lastChild as HTMLElement).style.transform = `translateY(${treeTop}px)`; + (newTableElement as any).data = rowData.data newTableElement.style.gridTemplateColumns = gridTemplateColumns.join(' '); newTableElement.style.position = 'absolute'; newTableElement.style.top = '0px' newTableElement.style.left = '0px' newTableElement.style.cursor = 'pointer' - newTableElement.onmouseover = () => { + newTableElement.onmouseenter = () => { + if ((newTableElement as any).data.isSelected) return; let indexOf = this.currentRecycleList.indexOf(newTableElement); + this.currentTreeDivList.forEach((row)=>{ + row.classList.remove('mouse-in') + }) if (indexOf >= 0 && indexOf < this.treeElement!.children.length) { - this.setSelectedRow(true,[(this.treeElement?.children[indexOf] as HTMLElement),newTableElement]); + this.setMouseIn(true, [(this.treeElement?.children[indexOf] as HTMLElement)]); } } - newTableElement.onmouseout = () => { + newTableElement.onmouseleave = () => { + if ((newTableElement as any).data.isSelected) return; let indexOf = this.currentRecycleList.indexOf(newTableElement); if (indexOf >= 0 && indexOf < this.treeElement!.children.length) { - this.setSelectedRow(false,[(this.treeElement?.children[indexOf] as HTMLElement),newTableElement]); + this.setMouseIn(false, [(this.treeElement?.children[indexOf] as HTMLElement)]); } } newTableElement.onclick = e => { - this.dispatchEvent(new CustomEvent('row-click', {detail: rowData.data, composed: true})); + let indexOf = this.currentRecycleList.indexOf(newTableElement); + this.dispatchRowClickEvent(rowData, [(this.treeElement?.children[indexOf] as HTMLElement), newTableElement]) } return newTableElement } @@ -980,7 +1109,7 @@ export class LitTable extends HTMLElement { totalHeight += it.height } }) - this.tbodyElement && (this.tbodyElement.style.height = totalHeight + "px") + this.tbodyElement && (this.tbodyElement.style.height = totalHeight + (this.isScrollXOutSide?0:0) + "px") this.treeElement!.style.height = (this.tableElement!.clientHeight - this.theadElement!.clientHeight) + "px" let visibleObjects = this.recycleDs.filter((item) => { return !item.rowHidden @@ -993,8 +1122,8 @@ export class LitTable extends HTMLElement { break; } } - let reduce = this.currentRecycleList.map((item) => item.clientHeight).reduce((a, b) => a + b,0); - if(reduce == 0){ + let reduce = this.currentRecycleList.map((item) => item.clientHeight).reduce((a, b) => a + b, 0); + if (reduce == 0) { return } while (reduce <= this.tableElement!.clientHeight) { @@ -1002,7 +1131,7 @@ export class LitTable extends HTMLElement { if (this.hasAttribute('tree')) { newTableElement = this.createNewTreeTableElement(visibleObjects[skip]); } else { - newTableElement = this.createNewTableElement(visibleObjects[skip].data) + newTableElement = this.createNewTableElement(visibleObjects[skip]) } this.tbodyElement?.append(newTableElement) if (this.hasAttribute('tree')) { @@ -1036,36 +1165,23 @@ export class LitTable extends HTMLElement { td.style.textOverflow = 'ellipsis' td.style.whiteSpace = "nowrap" td.dataIndex = dataIndex - td.style.justifyContent = column.getAttribute('align')||'flex-start' - td.title = rowData[dataIndex] + td.style.justifyContent = column.getAttribute('align') || 'flex-start' + td.title = rowData.data[dataIndex] if (column.template) { - td.appendChild(column.template.render(rowData).content.cloneNode(true)); + td.appendChild(column.template.render(rowData.data).content.cloneNode(true)); td.template = column.template } else { - td.innerHTML = rowData[dataIndex]; + td.innerHTML = this.formatName(rowData.data[dataIndex]); } newTableElement.append(td) }) - newTableElement.onclick = ()=>{ - let detail = {...rowData,selectedCallback:()=>{ - if (detail.isSelected != undefined) { - if(detail.isSelected){ - newTableElement.setAttribute("selected","") - }else { - newTableElement.removeAttribute("selected") - } - rowData.isSelected = !rowData.isSelected - } - }} - this.dispatchEvent(new CustomEvent('row-click', {detail: detail, composed: true})); - } - if (rowData.isSelected != undefined) { - if(rowData.isSelected){ - newTableElement.setAttribute("selected","") - }else { - newTableElement.removeAttribute("selected") - } + newTableElement.onclick = () => { + this.dispatchRowClickEvent(rowData, [newTableElement]) + } + if (rowData.data.isSelected != undefined) { + this.setSelectedRow(rowData.data.isSelected, [newTableElement]) } + (newTableElement as any).data = rowData.data newTableElement.style.cursor = "pointer" newTableElement.style.gridTemplateColumns = gridTemplateColumns.join(' '); newTableElement.style.position = 'absolute'; @@ -1084,15 +1200,16 @@ export class LitTable extends HTMLElement { } let childIndex = -1 element.childNodes.forEach((child) => { - if(child.nodeType!=1)return + if (child.nodeType != 1) return childIndex++; let idx = firstElement != undefined ? childIndex + 1 : childIndex; if (firstElement != undefined && childIndex == 0) { + (firstElement as any).data = rowObject.data if ((this.columns![0] as any).template) { firstElement.innerHTML = (this.columns![0] as any).template.render(rowObject.data).content.cloneNode(true).innerHTML } else { let dataIndex = this.columns![0].getAttribute('data-index') || '1'; - firstElement.innerHTML = rowObject.data[dataIndex] + firstElement.innerHTML = this.formatName(rowObject.data[dataIndex]) firstElement.title = rowObject.data[dataIndex] } if (rowObject.children && rowObject.children.length > 0) { @@ -1100,23 +1217,29 @@ export class LitTable extends HTMLElement { firstElement.insertBefore(btn, firstElement.firstChild); firstElement.style.paddingLeft = 15 * rowObject.depth + "px" } else { - firstElement.style.paddingLeft = 15 + 20 * rowObject.depth + "px" + firstElement.style.paddingLeft = 20 + 15 * rowObject.depth + "px" } firstElement.onclick = () => { - this.dispatchEvent(new CustomEvent('row-click', {detail: rowObject.data, composed: true})); + this.dispatchRowClickEvent(rowObject, [firstElement, element]) } firstElement.style.transform = `translateY(${rowObject.top - this.tableElement!.scrollTop}px)` + if (rowObject.data.isSelected != undefined) { + this.setSelectedRow(rowObject.data.isSelected, [firstElement]) + } else { + this.setSelectedRow(false, [firstElement]) + } } + let dataIndex = this.columns![idx].getAttribute('data-index') || '1'; if ((this.columns![idx] as any).template) { (child as HTMLElement).innerHTML = ""; - (child as HTMLElement).appendChild((this.columns![idx] as any).template.render(rowObject.data).content.cloneNode(true)) + (child as HTMLElement).appendChild((this.columns![idx] as any).template.render(rowObject.data).content.cloneNode(true)); + (child as HTMLElement).title = rowObject.data[dataIndex]; } else { - let dataIndex = this.columns![idx].getAttribute('data-index') || '1'; - (child as HTMLElement).innerHTML = rowObject.data[dataIndex]; + (child as HTMLElement).innerHTML = this.formatName(rowObject.data[dataIndex]); (child as HTMLElement).title = rowObject.data[dataIndex]; } }) - if(element.style.display == 'none'){ + if (element.style.display == 'none') { element.style.display = 'grid' } element.style.transform = `translateY(${rowObject.top}px)` @@ -1124,38 +1247,146 @@ export class LitTable extends HTMLElement { firstElement.style.display = 'flex' } element.onclick = e => { - let datail = {...rowObject.data,selectedCallback:()=>{ - if (datail.isSelected != undefined) { - if(datail.isSelected){ - element.setAttribute("selected","") - }else { - element.removeAttribute("selected") - } - rowObject.data.isSelected = !rowObject.data.isSelected - } - }} - this.dispatchEvent(new CustomEvent('row-click', {detail: datail, composed: true})); + if (firstElement != undefined) { + this.dispatchRowClickEvent(rowObject, [firstElement, element]) + } else { + this.dispatchRowClickEvent(rowObject, [element]) + } } + (element as any).data = rowObject.data if (rowObject.data.isSelected != undefined) { - if(rowObject.data.isSelected){ - element.setAttribute("selected","") - }else { - element.removeAttribute("selected") + this.setSelectedRow(rowObject.data.isSelected, [element]) + } else { + this.setSelectedRow(false, [element]) + } + } + + setSelectedRow(isSelected: boolean, rows: any[]) { + if (isSelected) { + rows.forEach((row) => { + if (row.classList.contains("mouse-in")) row.classList.remove('mouse-in'); + row.classList.add('mouse-select') + }) + } else { + rows.forEach((row) => { + row.classList.remove('mouse-select') + }) + } + } + + setMouseIn(isMouseIn: boolean, rows: any[]) { + if (isMouseIn) { + rows.forEach((row) => { + row.classList.add('mouse-in') + }) + } else { + rows.forEach((row) => { + row.classList.remove('mouse-in') + }) + } + } + + scrollToData(data: any) { + if (this.isRecycleList) { + if (this.recycleDs.length > 0) { + let filter = this.recycleDs.filter((item) => { + return item.data == data + }); + if (filter.length > 0) { + this.tableElement!.scrollTop = filter[0].top + } + this.setCurrentSelection(data) + } + } else { + if (this.normalDs.length > 0) { + let filter = this.normalDs.filter((item) => { + return item.data == data + }); + if (filter.length > 0) { + this.tableElement!.scrollTop = filter[0].top + } } - }else { - element.removeAttribute("selected") } + + + } + + expandList(datasource: any[]) { + let filter = this.recycleDs.filter((item) => { + return datasource.indexOf(item.data) != -1 + }); + if (filter.length > 0) { + filter.forEach((item) => { + item.expanded = true + item.rowHidden = false + }) + } + this.reMeauseHeight() } - setSelectedRow(isSelected:boolean,rows:any[]){ - if(isSelected){ - rows.forEach((row)=>{ - row.style.backgroundColor = "var(--dark-background6,#DEEDFF)" + clearAllSelection(rowObjectData: any) { + if (this.isRecycleList) { + this.recycleDs.forEach((item) => { + if (item.data != rowObjectData && item.data.isSelected) { + item.data.isSelected = false + } }) - }else { - rows.forEach((row)=>{ - row.style.backgroundColor = "var(--dark-background,#FFFFFF)" + this.setSelectedRow(false, this.currentTreeDivList) + this.setSelectedRow(false, this.currentRecycleList) + } else { + this.dataSource.forEach((item) => { + if (item != rowObjectData && item.isSelected) { + item.isSelected = false + } }) + this.setSelectedRow(false, this.normalDs) + } + + } + + setCurrentSelection(data: any) { + if (this.isRecycleList) { + if (data.isSelected != undefined) { + this.currentTreeDivList.forEach((item) => { + if ((item as any).data == data) { + this.setSelectedRow(data.isSelected, [item]) + } + }) + this.currentRecycleList.forEach((item) => { + if ((item as any).data == data) { + this.setSelectedRow(data.isSelected, [item]) + } + }) + } + } else { + if (data.isSelected != undefined) { + this.normalDs.forEach((item) => { + if ((item as any).data == data) { + this.setSelectedRow(data.isSelected, [item]) + } + }) + } + } + + } + + dispatchRowClickEvent(rowObject: any, elements: any[]) { + this.dispatchEvent(new CustomEvent('row-click', { + detail: { + ...rowObject.data, data: rowObject.data, callBack: (isSelected: boolean) => {//是否爲单选 + if (isSelected) { + this.clearAllSelection(rowObject.data) + } + this.setSelectedRow(rowObject.data.isSelected, elements) + } + }, composed: true, + })); + } + + formatName(name:any){ + if(name!=undefined&&name!==null){ + return name.toString().replace("<","<").replace(">",">") } + return "" } } diff --git a/host/ide/src/base-ui/tabs/lit-tabpane.ts b/host/ide/src/base-ui/tabs/lit-tabpane.ts index 1f8c681b7b443bac9f651fe04018fe9d42a8fa4c..ab2f8c9094c20421012084037961afaeaab606fd 100644 --- a/host/ide/src/base-ui/tabs/lit-tabpane.ts +++ b/host/ide/src/base-ui/tabs/lit-tabpane.ts @@ -80,16 +80,16 @@ export class LitTabpane extends BaseElement { initHtml(): string { return ` - - -`; + + + `; } connectedCallback() { diff --git a/host/ide/src/base-ui/tabs/lit-tabs.ts b/host/ide/src/base-ui/tabs/lit-tabs.ts index 25d23ce87135cb8799f76519a114911c16c2ce46..54b903a89d91dacd0221d0c9de8384d7bbfa425c 100644 --- a/host/ide/src/base-ui/tabs/lit-tabs.ts +++ b/host/ide/src/base-ui/tabs/lit-tabs.ts @@ -46,7 +46,8 @@ export class LitTabs extends HTMLElement { display: inline-flex; justify-content: center; align-items: center; - padding: 6px 0px 6px 12px; + /*padding: 6px 0px 6px 12px;*/ + padding-left: 12px; font-size: .9rem; font-weight: normal; cursor: pointer; @@ -83,8 +84,10 @@ export class LitTabs extends HTMLElement { :host([position^='top']) .nav-root{ display: flex; position: relative; - justify-content: center; - align-items: center; + height: 38px; + z-index: auto; + /*justify-content: center;*/ + /*align-items: center;*/ } :host(:not([mode]):not([position])) .tab-line,/*移动的线条*/ :host([mode='flat'][position^='top']) .tab-line{ @@ -94,14 +97,24 @@ export class LitTabs extends HTMLElement { :host(:not([position])) .tab-nav-container, :host([position^='top']) .tab-nav-container{ display: flex; - position: relative; - flex-direction: column; - overflow-y: hidden; - overflow-x: auto; - overflow: -moz-scrollbars-none; - -ms-overflow-style: none; - transition: all 0.3s; - flex: 1; + /*position: relative;*/ + /*flex-direction: column;*/ + /*overflow-y: hidden;*/ + /*overflow-x: auto;*/ + /*overflow: -moz-scrollbars-none; */ + /*-ms-overflow-style: none;*/ + /*transition: all 0.3s;*/ + + position: absolute; + overflow: auto; + height: 850px; + transform: rotateZ(-90deg) rotateY(180deg); + transform-origin: left top; + overflow-x: hidden; + width: 38px; + + cursor: row-resize; + user-select: none; } :host([position='top']) .tab-nav, :host([position='top-left']) .tab-nav{ @@ -112,6 +125,11 @@ export class LitTabs extends HTMLElement { user-select: none; margin-top: 6px; margin-left: 5px; + + transform: translateY(-38px) rotateZ(90deg) rotateX(180deg) translateY(38px); + transform-origin: left bottom; + flex-wrap: nowrap; + height: 38px; } :host([position='top-center']) .tab-nav{ display: flex; @@ -397,6 +415,7 @@ export class LitTabs extends HTMLElement {
+
@@ -595,6 +614,13 @@ export class LitTabs extends HTMLElement { let label = (e.target! as HTMLElement).closest('div')!.querySelector('span')!.textContent; this.dispatchEvent(new CustomEvent('onTabClick', {detail: {key: key, tab: label}})) }; + + new ResizeObserver((entries) => { + let filling = this.shadowRoot!.querySelector("#tab-filling") + + this.shadowRoot!.querySelector(".tab-nav-container")!.style.height = filling!.offsetWidth+"px" + + }).observe(this.shadowRoot!.querySelector("#tab-filling")!); } activeByKey(key: string) { diff --git a/host/ide/src/command/Cmd.ts b/host/ide/src/command/Cmd.ts new file mode 100644 index 0000000000000000000000000000000000000000..426988a90108720b2d32b2a7cb0473ce4e69d997 --- /dev/null +++ b/host/ide/src/command/Cmd.ts @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export class Cmd { + /** + * exec objdump to disassembling binary and find addr to show 100 line + * @param command obj dump command + * @param addr addr of select line + * @param callback result callback + */ + static execObjDump(command: string, addr: string, callback: Function) { + const data = {cmd: command, addr: addr}; + let uri = `http://${window.location.host.split(':')[0]}:${window.location.port}/exec`; + fetch(uri, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }).then(response => { + if (response.ok) { + let result = response.text(); + result.then(output => { + callback(output); + }); + } + }); + } + + static execHdcCmd(command: string, callback: Function) { + const data = { + cmd: command, + tag: "shell" + }; + let uri = `http://${window.location.host.split(':')[0]}:${window.location.port}/hdcCmd`; + fetch(uri, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }).then(response => { + if (response.ok) { + let result = response.text(); + result.then(output => { + callback(output); + }); + } + }); + } + + static async execFileRecv(command: string, filePath: string, callback: Function) { + let fileName = filePath.substring(filePath.lastIndexOf("/") + 1) + const data = { + cmd: command, + tag: "file", + fileName: fileName + }; + let uri = `http://${window.location.host.split(':')[0]}:${window.location.port}/hdcCmd`; + let buf = await fetch(uri, { + method: 'POST', headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }).then(res => res.arrayBuffer()); + callback(buf); + } + + static execHdcTraceCmd(command: string, serialNumber: string, callback: Function) { + const data = { + cmd: command, + tag: "hiprofiler_cmd", + serialNumber: serialNumber + }; + let uri = `http://${window.location.host.split(':')[0]}:${window.location.port}/hdcCmd`; + fetch(uri, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }).then(response => { + if (response.ok) { + let result = response.text(); + result.then(output => { + callback(output); + }); + } + }); + } + + static formatString(string: string, params: string[]) { + if (params.length == 0) { + return string; + } + for (let i = 0; i < params.length; i++) { + string = string.replace(new RegExp('\\{' + i + '\\}', 'g'), params[i]); + } + return string; + } + + static showSaveFile(callback: Function) { + let uri = `http://${window.location.host.split(':')[0]}:${window.location.port}/showSaveDialog`; + fetch(uri, { + method: 'GET' + }).then(response => { + if (response.ok) { + let result = response.text(); + result.then(output => { + callback(output); + }); + } + }); + } + + static uploadFile(fd: FormData, callback: Function) { + let uri = `http://${window.location.host.split(':')[0]}:${window.location.port}/upload`; + fetch(uri, { + method: 'POST', + body: fd, + }).then(response => { + callback(response); + }); + } + + static copyFile(fileName: string, distFile: string, callback: Function) { + const data = { + filename: fileName, + distfile: distFile, + }; + let uri = `http://${window.location.host.split(':')[0]}:${window.location.port}/copyfile`; + fetch(uri, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }).then(response => { + callback(response); + }); + } + + static async openFileDialog() { + let uri = `http://${window.location.host.split(':')[0]}:${window.location.port}/showOpenDialog`; + let res = await fetch(uri, {method: 'POST'}) + let result = res.ok ? await res.text() : ""; + return result; + } +} \ No newline at end of file diff --git a/host/ide/src/command/CmdConstant.ts b/host/ide/src/command/CmdConstant.ts new file mode 100644 index 0000000000000000000000000000000000000000..d4abebe50005b9837d5330f3a187124295954203 --- /dev/null +++ b/host/ide/src/command/CmdConstant.ts @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export class CmdConstant { + static CMD_TRACE_FILE_SIZE = "hdc_std shell stat --format=%s " + static CMD_SHELL = "hdc_std shell " + static CMD_MOUNT = "hdc_std shell mount -o remount,rw /" + static CMD_GET_PROCESS = "hdc_std shell ps -A -opid,cmd" + static CMD_GET_APP_NMAE= "hdc_std shell ps -A -ocmd" + static CMD_GET_CPU_COUNT = "hdc_std shell grep -c 'processor' /proc/cpuinfo" + static CMD_GET_HIPERF_EVENTS = "hdc_std shell hiperf list" + static CMD_HDC_DEVICES = "hdc_std list targets" + static CMD_MOUNT_DEVICES = "hdc_std -t {0} shell mount -o remount,rw /" + static CMD_GET_PROCESS_DEVICES = "hdc_std -t {0} shell ps -A -opid,cmd" + static CMD_GET_APP_NMAE_DEVICES= "hdc_std -t {0} shell ps -A -ocmd" + static CMD_GET_CPU_COUNT_DEVICES = "hdc_std -t {0} shell grep -c 'processor' /proc/cpuinfo" + static CMD_GET_HIPERF_EVENTS_DEVICES = "hdc_std -t {0} shell hiperf list" + static CMD_FIEL_RECV_DEVICES = "hdc_std -t {0} file recv {1} ./" + static CMS_HDC_STOP = "hdc_std -t {0} shell killall hiprofilerd hiprofiler_plugins native_daemon hiperf hiebpf" + + " hiprofiler_cmd" + static CMS_STOP = "hdc_std shell killall hiprofilerd hiprofiler_plugins native_daemon hiperf hiebpf hiprofiler_cmd" +} \ No newline at end of file diff --git a/host/ide/src/doc/ability_monitor.html b/host/ide/src/doc/ability_monitor.html new file mode 100644 index 0000000000000000000000000000000000000000..f52b007b4612afd1047f07f1d00f6ba29238eaa8 --- /dev/null +++ b/host/ide/src/doc/ability_monitor.html @@ -0,0 +1,1115 @@ + + + + Ability Monitor + + + + + +
+

Ability Monitor抓取和展示说明

+ +

1.Ability Monitor的抓取

+

1.1.Ability Monitor抓取界面配置说明

+

点击Probes config,如选择抓取AbilityMonitor
+ GitHub Logo

+

1.2.Ability Monitor文件的抓取

+

点击Record setting,在output file path输入文件名hiprofiler_data_abilitymonitor.htrace,拖动滚动条设置buffer size大小是64M,抓取时长是50s
+ GitHub Logo

+

点击Trace command,就会根据上面的配置生成抓取命令,点击复制按钮,会将命令行复制
+ GitHub Logo

+

输入hdc_shell,进入设备,执行命令
+ GitHub Logo

+

进入指定目录,cd /data/local/tmp 进入到目录,会看到生成的trace文件
+ GitHub Logo

+

2.Ability Monitor功能介绍

+

将抓取的文件导入到smartperf工具查看,能了解CPU,内存,磁盘IO和网络的使用情况

+

2.1.Ability Monitor泳道图展示

+

Ability Monitor展开就可以看到泳道图,包括CPU,内存,磁盘IO,网络的使用情况
+ GitHub Logo

+
    +
  • +
    CPU Total Load: 总的CPU使用率
    +
    +
  • +
  • +
    CPU User Load: CPU在用户态空间运行的使用率
    +
    +
  • +
  • +
    CPU System Load:CPU在内核空间运行的使用率
    +
    +
  • +
  • +
    MemoryTotal: 总计物理内存的大小
    +
    +
  • +
  • +
    Cached:缓存的大小
    +
    +
  • +
  • +
    SwapTotal: 虚拟内存
    +
    +
  • +
  • +
    Disk Bytes Read/Sec:每秒从磁盘读取到内存的字节数。
    +
    +
  • +
  • +
    Disk Bytes Written/Sec: 每秒从内存写入磁盘的字节数。
    +
    +
  • +
  • +
    Disk Read Ops/Sec:读入的字节数
    +
    +
  • +
  • +
    Disk Written Ops/Sec: 写入的字节数
    +
    +
  • +
  • +
    Network Bytes In/Sec:每秒接收的网络数据字节数
    +
    +
  • +
  • +
    Network Bytes Out/Sec: 每秒发送的网络数据字节数
    +
    +
  • +
  • +
    Network Packets In/Sec:每秒接收的网络数据包数
    +
    +
  • +
  • +
    Network Packets Out/Sec: 每秒发送的网络数据包数
    +
    +
  • +
+

2.2.Ability Monitor泳道图的框选功能

+ +

可以对CPU,内存,磁盘IO和网络的数据进行框选,框选后在最下方的弹出层中会展示框选数据的统计表格,总共有六个tab页
+ Live Processes的Tab页
+ GitHub Logo

+
    +
  • +
    Process ID:进程的ID
    +
    +
  • +
  • +
    Process Name:进程名称
  • +
  • +
    Responsible Process:父进程ID
    +
    +
  • +
  • +
    User ID:用户ID
  • +
  • +
    %CPU:进程的CPU占用率
  • +
  • +
    CPU Time:CPU运行时间
  • +
  • +
    #Threads:进程的线程数量
    +
    +
  • +
  • +
    Memory:内存值
    +
    +
  • +
  • +
    Disk Writes(B):磁盘读入的字节数
    +
    +
  • +
  • +
    Disk Reads(B):磁盘写入的字节数
    +
    +
  • +
+

Processes History的Tab页
+ GitHub Logo

+
    +
  • +
    Process ID:进程ID
    +
    +
  • +
  • +
    Alive:进程是否存活
    +
    +
  • +
  • +
    First Seen:开始时间
    +
    +
  • +
  • +
    Last Seen:所选区域的结束时间
    +
    +
  • +
  • +
    Process Name:进程名称
    +
    +
  • +
  • +
    Responsible Process:父进程ID
    +
    +
  • +
  • +
    User ID:用户ID
    +
    +
  • +
  • +
    CPU Time:CPU运行时间
    +
    +
  • +
+

框选CPU Total Load,CPU User Load,CPU System Load三个区域的泳道图,会展示System CPU Summary的Tab页
+ GitHub Logo

+
    +
  • +
    Start Time:采集时间的时间戳
    +
    +
  • +
  • +
    Duration:前一次采集到本次采集的时间差
  • +
  • +
    TotalLoad%:总的CPU使用率
    +
    +
  • +
  • +
    UserLoad%:CPU在用户态空间运行的使用率
    +
    +
  • +
  • +
    SystemLoad%:CPU在内核空间运行的使用率
    +
    +
  • +
  • +
    Process:进程号
    +
    +
  • +
+

框选MemoryTotal,Cached,SwapTota三个区域的泳道图,会展示System Memory Summary的Tab页
+ GitHub Logo

+
    +
  • +
    Start Time:采集时间的时间戳
    +
    +
  • +
  • +
    Duration:前一次采集到本次采集的时间差
    +
    +
  • +
  • +
    MemTotal:总内存大小
    +
    +
  • +
  • +
    MemFree:空闲内存大小
    +
    +
  • +
  • +
    Buffers:文件的缓冲大小
    +
    +
  • +
  • +
    Cached:缓存的大小
    +
    +
  • +
  • +
    Shmem:已被分配的共享内存大小
    +
    +
  • +
  • +
    Slab:内核数据缓存大小
    +
    +
  • +
  • +
    SUnreclaim:不可回收的Slab大小
    +
    +
  • +
  • +
    Swap Toal:交换空间的总大小
    +
    +
  • +
  • +
    SwapFree:未被使用交换空间的大小
    +
    +
  • +
  • +
    Mapped:设备和文件等映射的大小
    +
    +
  • +
  • +
    VmallocUsed:已被使用的虚拟内存大小
    +
    +
  • +
  • +
    PageTables:管理内存分页的索引表大小
    +
    +
  • +
  • +
    KernelStack:Kernel消耗的内存
    +
    +
  • +
  • +
    Active: 在活跃使用中的缓冲或高速缓冲存储器页面文件的大小
    +
    +
  • +
  • +
    Inactive:在不经常使用中的缓冲或高速缓冲存储器页面文件的大小
    +
    +
  • +
  • +
    Unevictable:不能被释放的内存页
    +
    +
  • +
  • +
    VmallocTotal:可以vmalloc虚拟内存大小
    +
    +
  • +
  • +
    CmaTotal:总的连续可用内存
    +
    +
  • +
  • +
    CmaFree:空闲的可用内存
    +
    +
  • +
+

框选Disk Bytes Read/Sec,Disk Bytes Written/Sec,Disk Read Ops/Sec, Disk Written + Ops/Sec四个区域的泳道图,会展示System Disk Summary的Tab页
+ GitHub Logo

+
    +
  • +
    Start Time:采集时间的时间戳
    +
    +
  • +
  • +
    Duration:前一次采集到本次采集的时间差
    +        
  • +
  • +
    Data Read:从磁盘读取到内存的总字节数
    +
    +
  • +
  • +
    Data Read/sec:每秒从磁盘读取到内存的字节数
    +
    +
  • +
  • +
    Data Write:从磁盘写入磁盘的总字节数。
    +
    +
  • +
  • +
    Data Write/sec:每秒从内存写入磁盘的字节数。
    +
    +
  • +
  • +
    Reads In:读入的字节数
    +
    +
  • +
  • +
    Reads In/sec:每秒读入的字节数;
    +
    +
  • +
  • +
    Write Out:写入的字节数
    +
    +
  • +
  • +
    Write Out/sec:每秒写入的字节数
    +
    +
  • +
+

框选Network Bytes In/Sec,Network Bytes Out/Sec,Network Packets In/Sec,Network Packets + Out/Sec四个区域的泳道图,会展示System Network Summary的Tab页
+ GitHub Logo

+
    +
  • +
    Start Time:采集时间的时间戳;
    +
    +
  • +
  • +
    Duration:前一次采集到本次采集的时间差;
    +
    +
  • +
  • +
    Data Received:接收的网络数据总字节数;
    +
    +
  • +
  • +
    Data Received/sec:每秒接收的网络数据字节数;
    +
    +
  • +
  • +
    Data Send:发送的网络数据总字节数;
    +
    +
  • +
  • +
    Data Send/sec:每秒发送的网络数据字节数;
    +
    +
  • +
  • +
    Packets In:接收的网络总数据包数;
    +
    +
  • +
  • +
    Packets In/sec:每秒接收的网络数据包数;
    +
    +
  • +
  • +
    Packets Out:发送的网络总数据包数;
    +
    +
  • +
  • +
    Packets Out/sec:每秒发送的网络数据包数;
    +
    +
  • +
+
+ + + \ No newline at end of file diff --git a/host/ide/src/doc/bio_record.html b/host/ide/src/doc/bio_record.html new file mode 100644 index 0000000000000000000000000000000000000000..2f5d46ad8962d5d791a78084575be8615823877c --- /dev/null +++ b/host/ide/src/doc/bio_record.html @@ -0,0 +1,972 @@ + + + Bio抓取和展示说明 + + + + + +
+

Bio的抓取和展示说明

+ +

1.Bio的抓取

+ +

1.1.Bio抓取配置参数

+ +

GitHub Logo
+配置项说明

+
    +
  • +
    Start BIO Latency Record:配置项的总开关
    +
    +
  • +
  • +
    Process:默认配置的是整个系统的,也可选择单进程抓取
    +
    +
  • +
  • +
    Max Unwind Level:配置抓取调用栈的最大深度
    +
    +
  • +
+

再点击Record setting,在output file path输入文件名hiprofiler_data_bio.htrace,拖动滚动条设置buffer size大小是64M,抓取时长是50s
+GitHub Logo
+点击Trace command,就会根据上面的配置生成抓取命令,点击Record抓取,抓取过程中会显示抓取时长
+GitHub Logo

+

2.Bio展示说明

+ +

抓取结束后Bio的trace会自动加载展示
+GitHub Logo

+

界面布局介绍:页内存整体界面布局分为3个部分,其中

+
    +
  • +
    红色区域:泳道图
    +
    +
  • +
  • +
    绿色区域:详细信息
    +
    +
  • +
  • +
    黄色区域:辅助信息(Callstack)
    +
    +
  • +
+

2.1.Bio泳道图展示

+ +

Bio泳道图鼠标悬浮以10ms为区间展示该周期内最大的读或者写延迟
+GitHub Logo

+

2.2.Bio泳道图的框选功能

+ +

可以对泳道图进行框选,框选后在最下方的弹出层中会展示框选数据的统计表格,总共有三个tab页
+Disk I/O Tier Statistics的Tab页
+GitHub Logo

+
    +
  • +
    Tier/Process/Path: 按照Tier,Process,Path的维度去展示
    +
    +
  • +
  • +
    Count: 事件数量
    +
    +
  • +
  • +
    Total Latency:每种进程,事件的总延迟
    +
    +
  • +
  • +
    Min Total Latency:最小延迟时间
    +
    +
  • +
  • +
    Avg Total Latency: 平均延迟时间
    +
    +
  • +
  • +
    Max Total Latency:最大延迟时间
    +
    +
  • +
+

Disk I/O Latency Calltree的Tab页
+GitHub Logo

+
    +
  • +
    Call Stack:为经过符号解析后的Callstack,并且给出动态链接库或者进程名的信息
    +
    +
  • +
  • +
    Local:为该调用方法自身占用的CPU时间
    +
    +
  • +
  • +
    Weight:调用方法的执行占比
    +
    +
  • +
+

Trace Completion Times的Tab页
+GitHub Logo

+
    +
  • +
    Start:事件的开始时间
    +
    +
  • +
  • +
    Total Latency:事件的延迟时间
    +
    +
  • +
  • +
    Process:进程名(pid)
    +
    +
  • +
  • +
    Thread:线程名(tid)
    +
    +
  • +
  • +
    Latency per 4KB: 原始数据里没有,每4k数据的延迟时间,需要根据延迟的size跟延迟的时间去计算
    +
    +
  • +
  • +
    Opration:事件类型
    +
    +
  • +
  • +
    Bytes:延迟的数据量
    +
    +
  • +
  • +
    Path: 操作的文件路径
    +
    +
  • +
  • +
    Block Number:块数量
    +
    +
  • +
  • +
    Tier: 层级
    +
    +
  • +
  • +
    BackTrace;调用栈顶部函数,并显示调用栈深度
    +
    +
  • +
+

2.3.Bio支持多种Options展示风格

+ +

点击Disk I/O Latency Calltree的Tab页底部的Options,会有两个CheckBox复选框
+GitHub Logo

+
    +
  • +
    Invert:反向输出调用树
    +
    +
  • +
  • +
    Hide System so:隐藏系统库文件   
    +
    +
  • +
+

2.4.Bio支持过滤调用栈调用次数的展示风格

+ +

点击Disk I/O Latency Calltree的Tab页底部的Sample Counter Filter,可以填上区间值。过滤出符合该区间值调用次数的调用栈信息
+GitHub Logo

+

2.5.Bio功能的调用栈Group展示-数据分析支持剪裁功能

+ +

GitHub Logo

+
    +
  • +

    裁剪Callstack,点击Callstack上一个节点符号,再点击底部Symbol Filter按钮,则该符号自动被裁剪掉,同时将该节点往下所有的Callstack内容裁剪掉

    +
  • +
  • +

    裁剪Library,点击Library Filter按钮,则该库文件符号下所有的子节点也被裁剪

    +
  • +
  • +

    点击Reset按钮,将恢复选中的裁剪内容

    +
  • +
+

2.6.Bio功能的调用栈Group展示支持按条件过滤

+ +

在Input Filter输入关键字,会显示出带有该关键字的展示信息
+GitHub Logo

+

2.7.Bio辅助信息区展示调用栈

+ +

当在详细信息区选择一个符号时,将展示与该符号相关的完整的调用栈。如下图的Heaviest Stack Trace:
+GitHub Logo

+

2.8.Bio的Tier的过滤

+

通过选择根据Tier去过滤
+GitHub Logo

+

2.9.Bio的火焰图功能

+

点击Disk I/O Latency Calltree左下角的柱状图的图标,会切换到火焰图页面
+GitHub Logo
+进入到火焰图页面,火焰图的展示跟Callinfo的tab页的调用栈显示一致,鼠标放到色块上,悬浮框可以显示调用栈名称和Duration时长
+GitHub Logo
+鼠标左键火焰图,会进入下一级界面,右键回到上一级
+GitHub Logo

+
+ + + \ No newline at end of file diff --git a/host/ide/src/doc/capture_online.html b/host/ide/src/doc/capture_online.html new file mode 100644 index 0000000000000000000000000000000000000000..a7145743469d7f4099aa88d5bbff0dfb7a0c1f93 --- /dev/null +++ b/host/ide/src/doc/capture_online.html @@ -0,0 +1,789 @@ + + + + 在线抓取trace说明 + + + + + +
+

在线抓取trace说明

+

1.界面配置说明

+

GitHub Logo

+

说明:

+
    +
  • Record:trace抓取按钮
  • +
  • Add HDC Device:连接设备
  • +
+

2.trace文件的在线抓取

+

点击Add HDC Device在弹出的框里选择HDC-配对,点击连接,连接设备

+

GitHub Logo

+

点击Probes config,如选择抓取Scheduling details

+

GitHub Logo

+

抓取项说明:

+
    +
  • Scheduling details:线程切换事件,暂停恢复方法,线程唤醒事件,进程退出和销毁处理,新建线程处理方法,线程重命名处理方法
  • +
  • CPU Frequency and idle states:CPU频率信息和CPU空闲状态
  • +
  • Advanced ftrace config:线程切换事件,暂停恢复方法,线程唤醒事件,进程退出和销毁处理,新建线程处理方法,线程重命名处理方法,IRQ事件,时钟频率处理方法,Binder事件,线程调用堆栈开始和结束的处理
  • +
  • AbilityMonitor:进程的CPU,内存,磁盘,网络使用情况
  • +
  • Kernel meminfo:内核内存
  • +
  • Virtual memory stats:系统虚拟内存
  • +
  • Hitrace categories:Bytrace的抓取项,各解释项说明如下图:
  • +
+

GitHub Logo

+

再点击Record setting,在output file path输入文件名hiprofiler_data_example.htrace,拖动滚动条设置buffer size大小是64M,抓取时长是50s

+

GitHub Logo

+

点击Trace command,就会根据上面的配置生成抓取命令,点击Record

+

GitHub Logo

+

抓取过程中,上方会给出提示正在抓取,并显示出抓取时长

+

GitHub Logo

+

抓取完成后,界面会自动加载展示trace文件

+

GitHub Logo

+
+ + + \ No newline at end of file diff --git a/host/ide/src/doc/compile_smartperf.html b/host/ide/src/doc/compile_smartperf.html new file mode 100644 index 0000000000000000000000000000000000000000..966b50495f65fca25b2698dee48a3b8d363f136a --- /dev/null +++ b/host/ide/src/doc/compile_smartperf.html @@ -0,0 +1,884 @@ + + + + compile_smartperf + + + + + + +
+

SmartPerf 编译指导

+ +

1. 编译环境搭建:

+ +
  注意:在linux编译环境安装时以root或者其他 sudo 用户身份运行下面的命令
+
+

1.1 node 环境安装:

+ +
+ 1.1.1 下载Node js安装包(windows推荐, linux跳过此步骤)
+ +
       从网站 下载node js安装包 https://nodejs.org/en/download/current/
+
+
1.1.2 安装nodejs.
+ +
    +
  • ubuntu 20.04 与Debian 11系统中, 直接用apt-get安装,命令如下:
  • +
+
  先切换到 root用户下 sudo su
+    apt-get update 
+    apt-get install nodejs npm
+
+
    +
  • centos 系统中 使用yum 安装,命令如下:
  • +
+
  先切换到 root用户下 sudo su
+    sudo yum -y install nodejs npm 
+
+
    +
  • +

    windows系统中, 用安装包一路next即可:

    +
  • +
  • +

    安装完成后运行检查是否安装成功:

    +
  • +
+
  node -v
+  npm -v
+
+

出现版本号就代表安装成功了.

+
1.1.3 安装tsc typeScript 编译器
+ +
    +
  • 直接使用npm 安装运行命令:
  • +
+
npm install -g typescript
+
+备注:如果安装失败可以更换npm源,再次尝试.
+    tsc -v
+
+

1.2 go 编译环境安装: +

+ +
    +
  • ubuntu 环境下直接使用apt安装:
  • +
+
   apt-get install golang-go
+
+
    +
  • centos 系统中 使用yum 安装,命令如下:
  • +
+
先切换到 root用户下 sudo su
+
+  sudo yum -y install go 
+
+
    +
  • +

    windows 系统请自行下载安装包并完成安装。

    +
  • +
  • +

    安装完成后 命令行运行验证是否安装成功:

    +
  • +
+
    go version
+
+

2. + 项目编译:

+ +

2.1 先下载sql.js的二进制包,: +

+ +
	从如下 https://github.com/sql-js/sql.js/releases/download/v1.6.2/sqljs-all.zip 获取到sql.js的二进制包.
+	将压缩包解压后, 将文件放置到项目third-party 目录下.
+
+

+ 2.2 先编译获取trace_streamer 的二进制包:

+ +
参照:smartperf/trace_streamer/compile_trace_streamer.md 编译出wasm 、linux、Windows版本的二进制文件
+   将获取到二进制文件放入到项目bin目录下,如果项目目录中无bin目录 先创建bin目录.
+   然后将trace_streamer的二进制文件放入bin目录中.
+
+

+ 2.3 代码编译(依赖于上面node环境 和 go环境)

+ +
        1) 在项目目录安装项目依赖:
+            npm install
+        2) 在项目目录下运行命令:
+            npm run compile 
+编译成功后会有main 可执行文件生成
+
+

3. + 项目部署: +

+ +
      1. linux 版本部署需要给trace_stream程序赋予执行权限:
+          cd dist/bin 目录下,执行 chmod +x trace_streamer_*
+
+       直接运行 ./main 可执行程序,完成项目的部署;
+
+

4. 访问项目:

+
     在浏览器上打开 https://[部署机器ip地址]:9000/application/
+   !!! 注意一定是https.
+
+   备注:如果未出现如图所示网页.而是显示 无法访问此网站
+        可以在window cmd 里执行telnet [部署机器ip地址] 9000
+        如果显示端口连接失败 可能是防火墙未对9000 端口放开即可
+
+ +
+ + + \ No newline at end of file diff --git a/host/ide/src/doc/compile_trace_streamer.html b/host/ide/src/doc/compile_trace_streamer.html new file mode 100644 index 0000000000000000000000000000000000000000..5993f2d7905204447f2120669e218099819cc98c --- /dev/null +++ b/host/ide/src/doc/compile_trace_streamer.html @@ -0,0 +1,817 @@ + + + + compile_trace_streamer + + + + + + +
+

1.如何独立编译Trace_streamer

+ +

尽管本工具(trace_streamer)是在ohos工具箱中的一员,但你依然可以独立编译此工具。

+

本工具可以编译linux, mac, windows, WebAssembly版本。

+

本工具默认编译方式是使用gn

+
    +
  • 编译方式
  • +
+
third_party部分安装方式
+third_party相关控件下载链接:https://gitee.com/organizations/openharmony/projects
+在src路径下创建同级目录third_party。
+一、sqlite:
+1.打开上方链接,搜索sqlite。
+2.点击搜索结果进入下载界面,下载sqlite组件。
+3.把下载的文件解压后,文件夹命名为sqlite,并用代码路径中\prebuilts\buildsqlite\sqlite3build.gn文件替换sqlite目录中的BUILD.gn文件。
+4.把sqlite文件夹放入third_party目录中。
+二、protobuf:
+1.按上述下载方法,下载protobuf组件。
+2.把下载的文件解压后,文件夹命名为protobuf,并用代码路径中\prebuilts\buildprotobuf\protobufbuild.gn文件替换protobuf目录中的BUILD.gn文件。
+3.把protobuf文件夹放入third_party目录中。
+三、googletest:
+1.按上述下载方法,下载googletest相关组件。
+2.把下载的文件解压后,文件夹命名为googletest,并用代码路径中\prebuilts\buildgoogletest\googletestbuild.gn文件替换googletest目录中的BUILD.gn文件。
+3.把googletest文件夹放入third_party目录中。
+4.找到文件\googletest\include\gtest\internal\ gtest-port.h 把286行 #include <sstream> // NOLINT修改为
+#undef private
+#define private private
+#include <sstream>  // NOLINT
+#undef private
+#define private public
+ +

编译不同版本:linux, WebAssembly, mac

+
./build.sh linux/wasm/macx
+
+ +

如果需要编译WebAssembly版本,您需要在prebuilts/目录下安装emsdk

+
git clone https://github.com/juj/emsdk.git --depth=1
+cd emsdk
+git pull
+./emsdk update # this may not work, ignore it
+./emsdk install latest
+./emsdk activate latest
+安装之后,您需要将upstream目录复制到prebuilts/emsdk/emsdk,node复制到prebuilts/emsdk/node
+
+

安装之后,目录结构当如:

+
prebuilts/emsdk
+├── prebuilts/emsdk/emsdk
+│   ├── prebuilts/emsdk/emsdk/bin
+│   ├── prebuilts/emsdk/emsdk/emscripten
+│   │   ├── prebuilts/emsdk/emsdk/emscripten/cache
+│   │   ├── prebuilts/emsdk/emsdk/emscripten/cmake
+│   │   ├── prebuilts/emsdk/emsdk/emscripten/docs
+│   │   ├── prebuilts/emsdk/emsdk/emscripten/media
+│   │   ├── prebuilts/emsdk/emsdk/emscripten/node_modules
+│   │   ├── prebuilts/emsdk/emsdk/emscripten/__pycache__
+│   │   ├── prebuilts/emsdk/emsdk/emscripten/src
+│   │   ├── prebuilts/emsdk/emsdk/emscripten/system
+│   │   ├── prebuilts/emsdk/emsdk/emscripten/tests
+│   │   ├── prebuilts/emsdk/emsdk/emscripten/third_party
+│   │   └── prebuilts/emsdk/emsdk/emscripten/tools
+│   ├── prebuilts/emsdk/emsdk/include
+│   │   └── prebuilts/emsdk/emsdk/include/c++
+│   └── prebuilts/emsdk/emsdk/lib
+│       └── prebuilts/emsdk/emsdk/lib/clang
+└── prebuilts/emsdk/node
+    └── prebuilts/emsdk/node/14.18.2_64bit
+        ├── prebuilts/emsdk/node/14.18.2_64bit/bin
+        ├── prebuilts/emsdk/node/14.18.2_64bit/include
+        ├── prebuilts/emsdk/node/14.18.2_64bit/lib
+        └── prebuilts/emsdk/node/14.18.2_64bit/share
+
+

之后调用

+
./build.sh wasm进行编译,您需要将sh脚本进行部分修改,因为这个脚本内置了一些库的下载和解析方式
+
+
+ + + \ No newline at end of file diff --git a/host/ide/src/doc/des_binder.html b/host/ide/src/doc/des_binder.html new file mode 100644 index 0000000000000000000000000000000000000000..661c8afaa9338161ec409abe407aac77e4f07fae --- /dev/null +++ b/host/ide/src/doc/des_binder.html @@ -0,0 +1,841 @@ + + + + des_binder + + + + + +
+

binder事件上下文如何关联

+ +

binder事件相对复杂,这里是从ftrace事件中抽离出来的binder相关消息,用来作为开发者或用户追踪binder事件的参考
+ a binder event is identified by the sender and receive device, and a reply message only end
+ the last binder msg which reply the calling one.
+ the alloc_buf msg can always flow the binder_transaction, so we no need to identify the alloc msg with + transactionID

+

TAG TT need reply!!! needReply = + !isReply && !(flags & 0x01);

+ +
 RenderThread-2267  ( 1592) [003] ...1 168766.128108: binder_transaction: transaction=25155526 dest_node=25155471 dest_proc=506 dest_thread=0 reply=0 flags=0x10 code=0x9
+RenderThread-2267  ( 1592) [003] ...1 168766.128110: binder_transaction_alloc_buf: transaction=25155526 data_size=120 offsets_size=8
+
+

received

+ +
 Binder:506_2-537   (  506) [003] ...1 168766.128154: binder_transaction_received: transaction=25155526
+
+

binder is in DB, TAG A needReply

+ +
 Binder:506_2-537   (  506) [003] ...1 168766.128221: binder_transaction: transaction=25155529 dest_node=25155527 dest_proc=1592 dest_thread=2267 reply=0 flags=0x10 code=0x5f474854
+Binder:506_2-537   (  506) [003] ...1 168766.128223: binder_transaction_alloc_buf: transaction=25155529 data_size=72 offsets_size=0
+
+

+ +
 RenderThread-2267  ( 1592) [003] ...1 168766.128243: binder_transaction_received: transaction=25155529
+
+

the flowing is for TAG A, this is + the reply for TAG A

+ +
 RenderThread-2267  ( 1592) [003] ...1 168766.128262: binder_transaction: transaction=25155530 dest_node=0 dest_proc=506 dest_thread=537 reply=1 flags=0x8 code=0x0
+
+RenderThread-2267  ( 1592) [003] ...1 168766.128264: binder_transaction_alloc_buf: transaction=25155530 data_size=4 offsets_size=0
+
+

calc the dur of TAG A

+ +
 Binder:506_2-537   (  506) [003] ...1 168766.128288: binder_transaction_received: transaction=25155530
+
+

binder last TAG A needReply, this + is TAG B needReply!!!

+ +
 Binder:506_2-537   (  506) [003] ...1 168766.128328: binder_transaction: transaction=25155532 dest_node=25155527 dest_proc=1592 dest_thread=2267 reply=0 flags=0x10 code=0x2
+Binder:506_2-537   (  506) [003] ...1 168766.128330: binder_transaction_alloc_buf: transaction=25155532 data_size=72 offsets_size=0
+
+

in db

+ +
 RenderThread-2267  ( 1592) [003] ...1 168766.128347: binder_transaction_received: transaction=25155532
+
+

the reply message + is not in db Session D, this is the reply for TAG B

+ +
 RenderThread-2267  ( 1592) [003] ...1 168766.128361: binder_transaction: transaction=25155533 dest_node=0 dest_proc=506 dest_thread=537 reply=1 flags=0x0 code=0x0
+RenderThread-2267  ( 1592) [003] ...1 168766.128363: binder_transaction_alloc_buf: transaction=25155533 data_size=4 offsets_size=0
+
+

no this message in db, calcate the dur + of TAG B

+ +
 Binder:506_2-537   (  506) [003] ...1 168766.128385: binder_transaction_received: transaction=25155533
+
+

no this message in db + Session E, this is the reply for TAG TT

+ +
 Binder:506_2-537   (  506) [003] ...1 168766.128412: binder_transaction: transaction=25155534 dest_node=0 dest_proc=1592 dest_thread=2267 reply=1 flags=0x0 code=0x0
+
+Binder:506_2-537   (  506) [003] ...1 168766.128413: binder_transaction_alloc_buf: transaction=25155534 data_size=68 offsets_size=0
+
+

the dur of TAG TT is calcated by the + flowing msg

+ +
 RenderThread-2267  ( 1592) [003] ...1 168766.128430: binder_transaction_received: transaction=25155534
+
+
+ + + \ No newline at end of file diff --git a/host/ide/src/doc/des_metris_support.html b/host/ide/src/doc/des_metris_support.html new file mode 100644 index 0000000000000000000000000000000000000000..fb64ab26e66964615439b51f05ba0e57dadfd0dc --- /dev/null +++ b/host/ide/src/doc/des_metris_support.html @@ -0,0 +1,772 @@ + + + + Sql分析和Metrics说明 + + + + + +
+

Sql分析和Metrics说明

+

1.Sql分析功能介绍

+

点击Query(SQL),输入需要查询的sql语句,如select * from process,可以看到进程表数据

+

GitHub Logo

+

2.Metrics功能介绍

+

Metrics是更高级别的查询接口,无需手动键入任何SQL语句,只需要选择定制好的查询接口,就能获得想要跟踪的结果

+

2.1Metrics查询接口展示

+

如下图,查询接口在下拉框中,如选择trace_task_names,点击run,就能展示线程和进程相关数据

+

GitHub Logo

+

3.Info和stats功能

+

点击Info and stats,能查看到meta表和stats表信息

+

GitHub Logo

+

4.Download功能

+

点击DownLoad按钮,会将在线抓取的文件下载到本地

+

GitHub Logo

+
+ + + \ No newline at end of file diff --git a/host/ide/src/doc/des_stat.html b/host/ide/src/doc/des_stat.html new file mode 100644 index 0000000000000000000000000000000000000000..bd137384244b9f95ba3685313772f7c39a17c0a0 --- /dev/null +++ b/host/ide/src/doc/des_stat.html @@ -0,0 +1,2845 @@ + + + + des_stat + + + + + + +
+

TraceStreamer 解析数据状态表

+ +

TraceStreamer使用stat表统计解析trace数据源过程遇到的重要事件状态。通过stat表可以对trace数据源中各个类型事件的数据的数量,数据质量有一个基本了解。
+ 我们对不同类型的数据,统计了收到多少条,数据逻辑是否匹配,是否有不合法数据,是否有数据丢失情况,所有这些,是基于对数据格式本身和数据前后关系的主观认识。欢迎开发者提供更多的思路来帮我们完善数据本身的校验工作。 +

+

stat表支持统计的事件列表如下:

+

ftrace事件统计

+

ftrace相关事件属于系统内核事件,具体请参考linux内核相关技术网站(www.kernel.org)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
事件名称
binder_transaction
binder_transaction_alloc_buf
binder_transaction_lock
binder_transaction_locked
binder_transaction_received
binder_transaction_unlock
clk_disable
clk_enable
clk_set_rate
clock_disable
clock_enable
clock_set_rate
cpu_frequency
cpu_idle
ipi_entry
ipi_exit
irq_handler_entry
irq_handler_exit
memory (进程内存)
oom_score_adj_update
print
regulator_disable
regulator_disable_complete
regulator_set_voltage
regulator_set_voltage_complete
sched_process_exit
sched_process_free
sched_switch
sched_wakeup
sched_wakeup_new
sched_waking
signal_deliver
signal_generate
softirq_entry
softirq_exit
softirq_raise
suspend_resume
sys_enter
sys_exit
task_newtask
task_rename
trace_bblock_bio_queue
trace_block_bio_backmerge
trace_block_bio_bounce
trace_block_bio_complete
trace_block_bio_frontmerge
trace_block_bio_remap
trace_block_dirty_buffer
trace_block_getrq
trace_block_plug
trace_block_rq_complete
trace_block_rq_insert
trace_block_rq_issue
trace_block_rq_remap
trace_event_clock_sync
tracing_mark_write
workqueue_execute_end
workqueue_execute_start
+

fps事件统计

+ + + + + + + + + + + + +
事件名称
hidump_fps
+

日志事件统计

+ + + + + + + + + + + + +
事件名称
hilog
+

系统内存和系统虚拟内存事件

+ + + + + + + + + + + + + + + +
事件名称
sys_memory
sys_virtual_memory
+

内存申请和释放事件

+ + + + + + + + + + + + + + + +
事件名称
native_hook_free
native_hook_malloc
+

磁盘读写事件统计

+ + + + + + + + + + + + +
事件名称
trace_diskio
+

进程事件统计

+ + + + + + + + + + + + +
事件名称
trace_process
+

CPU使用率事件解析

+ + + + + + + + + + + + +
事件名称
trace_cpu_usage
+

网络数据事件解析

+ + + + + + + + + + + + +
事件名称
trace_network
+

事件对应解析状态:

+ +

每种事件解析数据都有5种状态,描述如下表:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
stat_typedescription
received统计trace数据源中总共有多少该事件。
data_lost统计TraceStreamer解析过程中发现丢失数据条数。
not_match统计有多少数据与上下文其他数据不匹配。
not_supported统计有多少暂不支持解析该事件(一个事件可能包含多种类型的子事件, TraceStreamer可能支持该事件的一部分子事件)。
invalid_data统计收到多少条该事件的非法数据。
+

数据状态级别

+ +

数据状态级别总共有4种,分别是:info, warn, error,fatal。由于数据的重要性不同,不同事件的同一种状态可能对应不同的级别。 例如binder_transaction_received的 not_supported状态的数据为info级别,而binder_transaction_alloc_buf的not_supported状态数据为warn级别。

+

您可以在src/cfg/trace_streamer_config.cpp的InitSecurityMap方法中自行定义相关事件的优先级。

+

事件,状态与级别对应关系

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
event_namestat_typeserverity
binder_transactionreceivedinfo
binder_transactiondata_losterror
binder_transactionnot_matchinfo
binder_transactionnot_supportedinfo
binder_transactioninvalid_dataerror
binder_transaction_receivedreceivedinfo
binder_transaction_receiveddata_losterror
binder_transaction_receivednot_matchinfo
binder_transaction_receivednot_supportedinfo
binder_transaction_receivedinvalid_dataerror
binder_transaction_alloc_bufreceivedinfo
binder_transaction_alloc_bufdata_losterror
binder_transaction_alloc_bufnot_matchinfo
binder_transaction_alloc_bufnot_supportedwarn
binder_transaction_alloc_bufinvalid_dataerror
binder_transaction_lockreceivedinfo
binder_transaction_lockdata_losterror
binder_transaction_locknot_matchinfo
binder_transaction_locknot_supportedwarn
binder_transaction_lockinvalid_dataerror
binder_transaction_lockedreceivedinfo
binder_transaction_lockeddata_losterror
binder_transaction_lockednot_matchinfo
binder_transaction_lockednot_supportedwarn
binder_transaction_lockedinvalid_dataerror
binder_transaction_unlockreceivedinfo
binder_transaction_unlockdata_losterror
binder_transaction_unlocknot_matchinfo
binder_transaction_unlocknot_supportedwarn
binder_transaction_unlockinvalid_dataerror
sched_switchreceivedinfo
sched_switchdata_losterror
sched_switchnot_matchinfo
sched_switchnot_supportedinfo
sched_switchinvalid_dataerror
task_renamereceivedinfo
task_renamedata_losterror
task_renamenot_matchinfo
task_renamenot_supportedinfo
task_renameinvalid_dataerror
task_newtaskreceivedinfo
task_newtaskdata_losterror
task_newtasknot_matchinfo
task_newtasknot_supportedinfo
task_newtaskinvalid_dataerror
tracing_mark_writereceivedinfo
tracing_mark_writedata_losterror
tracing_mark_writenot_matchinfo
tracing_mark_writenot_supportedinfo
tracing_mark_writeinvalid_dataerror
printreceivedinfo
printdata_losterror
printnot_matchinfo
printnot_supportedinfo
printinvalid_dataerror
sched_wakeupreceivedinfo
sched_wakeupdata_losterror
sched_wakeupnot_matchinfo
sched_wakeupnot_supportedinfo
sched_wakeupinvalid_dataerror
sched_wakingreceivedinfo
sched_wakingdata_losterror
sched_wakingnot_matchinfo
sched_wakingnot_supportedinfo
sched_wakinginvalid_dataerror
cpu_idlereceivedinfo
cpu_idledata_losterror
cpu_idlenot_matchinfo
cpu_idlenot_supportedinfo
cpu_idleinvalid_dataerror
cpu_frequencyreceivedinfo
cpu_frequencydata_losterror
cpu_frequencynot_matchinfo
cpu_frequencynot_supportedinfo
cpu_frequencyinvalid_dataerror
suspend_resumereceivedinfo
suspend_resumedata_losterror
suspend_resumenot_matchinfo
suspend_resumenot_supportedinfo
suspend_resumeinvalid_dataerror
workqueue_execute_startreceivedinfo
workqueue_execute_startdata_losterror
workqueue_execute_startnot_matchinfo
workqueue_execute_startnot_supportedinfo
workqueue_execute_startinvalid_dataerror
workqueue_execute_endreceivedinfo
workqueue_execute_enddata_losterror
workqueue_execute_endnot_matchinfo
workqueue_execute_endnot_supportedwarn
workqueue_execute_endinvalid_dataerror
clock_set_ratereceivedinfo
clock_set_ratedata_losterror
clock_set_ratenot_matchinfo
clock_set_ratenot_supportedwarn
clock_set_rateinvalid_dataerror
clock_enablereceivedinfo
clock_enabledata_losterror
clock_enablenot_matchinfo
clock_enablenot_supportedwarn
clock_enableinvalid_dataerror
clock_disablereceivedinfo
clock_disabledata_losterror
clock_disablenot_matchinfo
clock_disablenot_supportedwarn
clock_disableinvalid_dataerror
clk_set_ratereceivedinfo
clk_set_ratedata_losterror
clk_set_ratenot_matchinfo
clk_set_ratenot_supportedwarn
clk_set_rateinvalid_dataerror
clk_enablereceivedinfo
clk_enabledata_losterror
clk_enablenot_matchinfo
clk_enablenot_supportedwarn
clk_enableinvalid_dataerror
clk_disablereceivedinfo
clk_disabledata_losterror
clk_disablenot_matchinfo
clk_disablenot_supportedwarn
clk_disableinvalid_dataerror
sys_enterreceivedinfo
sys_enterdata_losterror
sys_enternot_matchinfo
sys_enternot_supportedwarn
sys_enterinvalid_dataerror
sys_exitreceivedinfo
sys_exitdata_losterror
sys_exitnot_matchinfo
sys_exitnot_supportedwarn
sys_exitinvalid_dataerror
regulator_set_voltagereceivedinfo
regulator_set_voltagedata_losterror
regulator_set_voltagenot_matchinfo
regulator_set_voltagenot_supportedwarn
regulator_set_voltageinvalid_dataerror
regulator_set_voltage_completereceivedinfo
regulator_set_voltage_completedata_losterror
regulator_set_voltage_completenot_matchinfo
regulator_set_voltage_completenot_supportedwarn
regulator_set_voltage_completeinvalid_dataerror
regulator_disablereceivedinfo
regulator_disabledata_losterror
regulator_disablenot_matchinfo
regulator_disablenot_supportedwarn
regulator_disableinvalid_dataerror
regulator_disable_completereceivedinfo
regulator_disable_completedata_losterror
regulator_disable_completenot_matchinfo
regulator_disable_completenot_supportedwarn
regulator_disable_completeinvalid_dataerror
ipi_entryreceivedinfo
ipi_entrydata_losterror
ipi_entrynot_matchinfo
ipi_entrynot_supportedwarn
ipi_entryinvalid_dataerror
ipi_exitreceivedinfo
ipi_exitdata_losterror
ipi_exitnot_matchinfo
ipi_exitnot_supportedwarn
ipi_exitinvalid_dataerror
irq_handler_entryreceivedinfo
irq_handler_entrydata_losterror
irq_handler_entrynot_matchinfo
irq_handler_entrynot_supportedwarn
irq_handler_entryinvalid_dataerror
irq_handler_exitreceivedinfo
irq_handler_exitdata_losterror
irq_handler_exitnot_matchinfo
irq_handler_exitnot_supportedwarn
irq_handler_exitinvalid_dataerror
softirq_raisereceivedinfo
softirq_raisedata_losterror
softirq_raisenot_matchinfo
softirq_raisenot_supportedwarn
softirq_raiseinvalid_dataerror
softirq_entryreceivedinfo
softirq_entrydata_losterror
softirq_entrynot_matchinfo
softirq_entrynot_supportedwarn
softirq_entryinvalid_dataerror
softirq_exitreceivedinfo
softirq_exitdata_losterror
softirq_exitnot_matchinfo
softirq_exitnot_supportedwarn
softirq_exitinvalid_dataerror
oom_score_adj_updatereceivedinfo
oom_score_adj_updatedata_losterror
oom_score_adj_updatenot_matchinfo
oom_score_adj_updatenot_supportedwarn
oom_score_adj_updateinvalid_dataerror
sched_wakeup_newreceivedinfo
sched_wakeup_newdata_losterror
sched_wakeup_newnot_matchinfo
sched_wakeup_newnot_supportedwarn
sched_wakeup_newinvalid_dataerror
sched_process_exitreceivedinfo
sched_process_exitdata_losterror
sched_process_exitnot_matchinfo
sched_process_exitnot_supportedwarn
sched_process_exitinvalid_dataerror
sched_process_freereceivedinfo
sched_process_freedata_losterror
sched_process_freenot_matchinfo
sched_process_freenot_supportedwarn
sched_process_freeinvalid_dataerror
trace_event_clock_syncreceivedinfo
trace_event_clock_syncdata_losterror
trace_event_clock_syncnot_matchinfo
trace_event_clock_syncnot_supportedwarn
trace_event_clock_syncinvalid_dataerror
memoryreceivedinfo
memorydata_losterror
memorynot_matchinfo
memorynot_supportedwarn
memoryinvalid_dataerror
hilogreceivedinfo
hilogdata_losterror
hilognot_matchinfo
hilognot_supportedwarn
hiloginvalid_dataerror
hidump_fpsreceivedinfo
hidump_fpsdata_losterror
hidump_fpsnot_matchinfo
hidump_fpsnot_supportedwarn
hidump_fpsinvalid_dataerror
native_hook_mallocreceivedinfo
native_hook_mallocdata_losterror
native_hook_mallocnot_matchinfo
native_hook_mallocnot_supportedwarn
native_hook_mallocinvalid_dataerror
native_hook_freereceivedinfo
native_hook_freedata_losterror
native_hook_freenot_matchinfo
native_hook_freenot_supportedwarn
native_hook_freeinvalid_dataerror
trace_diskioreceivedinfo
trace_diskiodata_losterror
trace_diskionot_matchinfo
trace_diskionot_supportedwarn
trace_diskioinvalid_dataerror
trace_processreceivedinfo
trace_processdata_losterror
trace_processnot_matchinfo
trace_processnot_supportedwarn
trace_processinvalid_dataerror
trace_cpu_usagereceivedinfo
trace_cpu_usagedata_losterror
trace_cpu_usagenot_matchinfo
trace_cpu_usagenot_supportedwarn
trace_cpu_usageinvalid_dataerror
trace_networkreceivedinfo
trace_networkdata_losterror
trace_networknot_matchinfo
trace_networknot_supportedwarn
trace_networkinvalid_dataerror
sys_memoryreceivedinfo
sys_memorydata_losterror
sys_memorynot_matchinfo
sys_memorynot_supportedwarn
sys_memoryinvalid_dataerror
sys_virtual_memoryreceivedinfo
sys_virtual_memorydata_losterror
sys_virtual_memorynot_matchinfo
sys_virtual_memorynot_supportedwarn
sys_virtual_memoryinvalid_dataerror
signal_generatereceivedinfo
signal_generatedata_losterror
signal_generatenot_matchinfo
signal_generatenot_supportedwarn
signal_generateinvalid_dataerror
signal_deliverreceivedinfo
signal_deliverdata_losterror
signal_delivernot_matchinfo
signal_delivernot_supportedwarn
signal_deliverinvalid_dataerror
trace_block_bio_backmergereceivedinfo
trace_block_bio_backmergedata_losterror
trace_block_bio_backmergenot_matchinfo
trace_block_bio_backmergenot_supportedwarn
trace_block_bio_backmergeinvalid_dataerror
trace_block_bio_bouncereceivedinfo
trace_block_bio_bouncedata_losterror
trace_block_bio_bouncenot_matchinfo
trace_block_bio_bouncenot_supportedwarn
trace_block_bio_bounceinvalid_dataerror
trace_block_bio_completereceivedinfo
trace_block_bio_completedata_losterror
trace_block_bio_completenot_matchinfo
trace_block_bio_completenot_supportedwarn
trace_block_bio_completeinvalid_dataerror
trace_block_bio_frontmergereceivedinfo
trace_block_bio_frontmergedata_losterror
trace_block_bio_frontmergenot_matchinfo
trace_block_bio_frontmergenot_supportedwarn
trace_block_bio_frontmergeinvalid_dataerror
trace_bblock_bio_queuereceivedinfo
trace_bblock_bio_queuedata_losterror
trace_bblock_bio_queuenot_matchinfo
trace_bblock_bio_queuenot_supportedwarn
trace_bblock_bio_queueinvalid_dataerror
trace_block_bio_remapreceivedinfo
trace_block_bio_remapdata_losterror
trace_block_bio_remapnot_matchinfo
trace_block_bio_remapnot_supportedwarn
trace_block_bio_remapinvalid_dataerror
trace_block_dirty_bufferreceivedinfo
trace_block_dirty_bufferdata_losterror
trace_block_dirty_buffernot_matchinfo
trace_block_dirty_buffernot_supportedwarn
trace_block_dirty_bufferinvalid_dataerror
trace_block_getrqreceivedinfo
trace_block_getrqdata_losterror
trace_block_getrqnot_matchinfo
trace_block_getrqnot_supportedwarn
trace_block_getrqinvalid_dataerror
trace_block_plugreceivedinfo
trace_block_plugdata_losterror
trace_block_plugnot_matchinfo
trace_block_plugnot_supportedwarn
trace_block_pluginvalid_dataerror
trace_block_rq_completereceivedinfo
trace_block_rq_completedata_losterror
trace_block_rq_completenot_matchinfo
trace_block_rq_completenot_supportedwarn
trace_block_rq_completeinvalid_dataerror
trace_block_rq_insertreceivedinfo
trace_block_rq_insertdata_losterror
trace_block_rq_insertnot_matchinfo
trace_block_rq_insertnot_supportedwarn
trace_block_rq_insertinvalid_dataerror
trace_block_rq_remapreceivedinfo
trace_block_rq_remapdata_losterror
trace_block_rq_remapnot_matchinfo
trace_block_rq_remapnot_supportedwarn
trace_block_rq_remapinvalid_dataerror
trace_block_rq_issuereceivedinfo
trace_block_rq_issuedata_losterror
trace_block_rq_issuenot_matchinfo
trace_block_rq_issuenot_supportedwarn
trace_block_rq_issueinvalid_dataerror
otherreceivedinfo
otherdata_losterror
othernot_matchinfo
othernot_supportedwarn
otherinvalid_dataerror
+ +
+ + + \ No newline at end of file diff --git a/host/ide/src/doc/des_support_event.html b/host/ide/src/doc/des_support_event.html new file mode 100644 index 0000000000000000000000000000000000000000..d0ba0ef37b4dbb38a025808b20bf3347e27b306b --- /dev/null +++ b/host/ide/src/doc/des_support_event.html @@ -0,0 +1,990 @@ + + + + des_support_event + + + + + +
+

TraceStreamer支持解析事件列表 +

+ +

ftrace事件

+ +
binder_transaction
+binder_transaction_received
+binder_transaction_alloc_buf
+binder_transaction_lock
+binder_transaction_locked
+binder_transaction_unlock
+sched_switch
+task_rename
+task_newtask
+tracing_mark_write
+print
+sched_wakeup
+sched_waking
+cpu_idle
+cpu_frequency
+suspend_resume
+workqueue_execute_start
+workqueue_execute_end
+clock_set_rate
+clock_enable
+clock_disable
+clk_set_rate
+clk_enable
+clk_disable
+sys_enter
+sys_exit
+regulator_set_voltage
+regulator_set_voltage_complete
+regulator_disable
+regulator_disable_complete
+ipi_entry
+ipi_exit
+irq_handler_entry
+irq_handler_exit
+softirq_raise
+softirq_entry
+softirq_exit
+sched_wakeup_new
+sched_process_exit
+trace_event_clock_sync
+
+

内存事件 +

+ +
mem.vm.size
+mem.rss
+mem.rss.anon
+mem.rss.file
+mem.rss.schem
+mem.swap
+mem.locked
+mem.hwm
+mem.oom_score_adj
+
+

系统内存事件 +

+ +
sys.mem.unspecified
+sys.mem.total
+sys.mem.free
+sys.mem.avaiable
+sys.mem.buffers
+sys.mem.cached
+sys.mem.swap.chard
+sys.mem.active
+sys.mem.inactive
+sys.mem.active.anon
+sys.mem.inactive.anon
+sys.mem.active_file
+sys.mem.inactive_file
+sys.mem.unevictable
+sys.mem.mlocked
+sys.mem.swap.total
+sys.mem.swap.free
+sys.mem.dirty
+sys.mem.writeback
+sys.mem.anon.pages
+sys.mem.mapped
+sys.mem.shmem
+sys.mem.slab
+sys.mem.slab.reclaimable
+sys.mem.slab.unreclaimable
+sys.mem.kernel.stack
+sys.mem.page.tables
+sys.mem.commit.limit
+sys.mem.commited.as
+sys.mem.vmalloc.total
+sys.mem.vmalloc.used
+sys.mem.vmalloc.chunk
+sys.mem.cma.total
+sys.mem.cma.free
+
+

+ 系统虚拟内存事件

+ +
sys.virtual.mem.unspecified
+sys.virtual.mem.nr.free.pages
+sys.virtual.mem.nr.alloc.batch
+sys.virtual.mem.nr.inactive.anon
+sys.virtual.mem.nr.active_anon
+sys.virtual.mem.nr.inactive.file
+sys.virtual.mem.nr.active_file
+sys.virtual.mem.nr.unevictable
+sys.virtual.mem.nr.mlock
+sys.virtual.mem.anon.pages
+sys.virtual.mem.nr.mapped
+sys.virtual.mem.nr.file.pages
+sys.virtual.mem.nr.dirty
+sys.virtual.mem.nr.writeback
+sys.virtual.mem.nr.slab.reclaimable
+sys.virtual.mem.nr.slab.unreclaimable
+sys.virtual.mem.nr.page_table.pages
+sys.virtual.mem.nr_kernel.stack
+sys.virtual.mem.nr.overhead
+sys.virtual.mem.nr.unstable
+sys.virtual.mem.nr.bounce
+sys.virtual.mem.nr.vmscan.write
+sys.virtual.mem.nr.vmscan.immediate.reclaim
+sys.virtual.mem.nr.writeback_temp
+sys.virtual.mem.nr.isolated_anon
+sys.virtual.mem.nr.isolated_file
+sys.virtual.mem.nr.shmem
+sys.virtual.mem.nr.dirtied
+sys.virtual.mem.nr.written
+sys.virtual.mem.nr.pages.scanned
+sys.virtual.mem.workingset.refault
+sys.virtual.mem.workingset.activate
+sys.virtual.mem.workingset_nodereclaim
+sys.virtual.mem.nr_anon.transparent.hugepages
+sys.virtual.mem.nr.free_cma
+sys.virtual.mem.nr.swapcache
+sys.virtual.mem.nr.dirty.threshold
+sys.virtual.mem.nr.dirty.background.threshold
+sys.virtual.mem.vmeminfo.pgpgin
+sys.virtual.mem.pgpgout
+sys.virtual.mem.pgpgoutclean
+sys.virtual.mem.pswpin
+sys.virtual.mem.pswpout
+sys.virtual.mem.pgalloc.dma
+sys.virtual.mem.pgalloc.normal
+sys.virtual.mem.pgalloc.movable
+sys.virtual.mem.pgfree
+sys.virtual.mem.pgactivate
+sys.virtual.mem.pgdeactivate
+sys.virtual.mem.pgfault
+sys.virtual.mem.pgmajfault
+sys.virtual.mem.pgrefill.dma
+sys.virtual.mem.pgrefill.normal
+sys.virtual.mem.pgrefill.movable
+sys.virtual.mem.pgsteal.kswapd.dma
+sys.virtual.mem.pgsteal.kswapd.normal
+sys.virtual.mem.pgsteal.kswapd.movable
+sys.virtual.mem.pgsteal.direct.dma
+sys.virtual.mem.pgsteal.direct.normal
+sys.virtual.mem.pgsteal_direct.movable
+sys.virtual.mem.pgscan.kswapd.dma
+sys.virtual.mem.pgscan_kswapd.normal
+sys.virtual.mem.pgscan.kswapd.movable
+sys.virtual.mem.pgscan.direct.dma
+sys.virtual.mem.pgscan.direct.normal
+sys.virtual.mem.pgscan.direct.movable
+sys.virtual.mem.pgscan.direct.throttle
+sys.virtual.mem.pginodesteal
+sys.virtual.mem.slabs_scanned
+sys.virtual.mem.kswapd.inodesteal
+sys.virtual.mem.kswapd.low.wmark.hit.quickly
+sys.virtual.mem.high.wmark.hit.quickly
+sys.virtual.mem.pageoutrun
+sys.virtual.mem.allocstall
+sys.virtual.mem.pgrotated
+sys.virtual.mem.drop.pagecache
+sys.virtual.mem.drop.slab
+sys.virtual.mem.pgmigrate.success
+sys.virtual.mem.pgmigrate.fail
+sys.virtual.mem.compact.migrate.scanned
+sys.virtual.mem.compact.free.scanned
+sys.virtual.mem.compact.isolated
+sys.virtual.mem.compact.stall
+sys.virtual.mem.compact.fail
+sys.virtual.mem.compact.success
+sys.virtual.mem.compact.daemon.wake
+sys.virtual.mem.unevictable.pgs.culled
+sys.virtual.mem.unevictable.pgs.scanned
+sys.virtual.mem.unevictable.pgs.rescued
+sys.virtual.mem.unevictable.pgs.mlocked
+sys.virtual.mem.unevictable.pgs.munlocked
+sys.virtual.mem.unevictable.pgs.cleared
+sys.virtual.mem.unevictable.pgs.stranded
+sys.virtual.mem.nr.zspages
+sys.virtual.mem.nr.ion.heap
+sys.virtual.mem.nr.gpu.heap
+sys.virtual.mem.allocstall.dma
+sys.virtual.mem.allocstall.movable
+sys.virtual.mem.allocstall.normal
+sys.virtual.mem.compact_daemon.free.scanned
+sys.virtual.mem.compact.daemon.migrate.scanned
+sys.virtual.mem.nr.fastrpc
+sys.virtual.mem.nr.indirectly.reclaimable
+sys.virtual.mem.nr_ion_heap_pool
+sys.virtual.mem.nr.kernel_misc.reclaimable
+sys.virtual.mem.nr.shadow_call.stack_bytes
+sys.virtual.mem.nr.shmem.hugepages
+sys.virtual.mem.nr.shmem.pmdmapped
+sys.virtual.mem.nr.unreclaimable.pages
+sys.virtual.mem.nr.zone.active.anon
+sys.virtual.mem.nr.zone.active.file
+ys.virtual.mem.nr.zone.inactive_anon
+sys.virtual.mem.nr.zone.inactive_file
+sys.virtual.mem.nr.zone.unevictable
+sys.virtual.mem.nr.zone.write_pending
+sys.virtual.mem.oom.kill
+sys.virtual.mem.pglazyfree
+sys.virtual.mem.pglazyfreed
+sys.virtual.mem.pgrefill
+sys.virtual.mem.pgscan.direct
+sys.virtual.mem.pgscan.kswapd
+sys.virtual.mem.pgskip.dma
+sys.virtual.mem.pgskip.movable
+sys.virtual.mem.pgskip.normal
+sys.virtual.mem.pgsteal.direct
+sys.virtual.mem.pgsteal.kswapd
+sys.virtual.mem.swap.ra
+sys.virtual.mem.swap.ra.hit
+
+
+ + + \ No newline at end of file diff --git a/host/ide/src/doc/des_tables.html b/host/ide/src/doc/des_tables.html new file mode 100644 index 0000000000000000000000000000000000000000..88f3c3bbddda0c577dda44343dd5cdfec3e12b74 --- /dev/null +++ b/host/ide/src/doc/des_tables.html @@ -0,0 +1,3049 @@ + + + + des_tables + + + + + + +
+

TraceStreamer数据库说明 +

+ +
  TraceStreamer虽然对外提供了各种各样的使用方式,但核心的业务仍是将trace数据源转化为易于理解和使用的数据库。用户可以通过SmartPerf界面直观的研究系统跟踪数据,也可在理解TraceStreamer生成的数据库的基础上,在TraceStreamer的交互模式或者Smartperf的数据库查询模式下,使用SQL查询语句自由组装查看用户关心的数据。 下文将对TraceStreamer生成的数据库进行详细描述,给用户使用SQL查询系统跟踪数据提供帮助。
+
+ +

+ __TraceStreamer输出的表格有如下几类: +

+
    +
  • 常规泳道图数据表
    + GitHub Logo
  • +
  • native memory数据源相关表
    + GitHub Logo
  • +
  • perf相关数据表
    + GitHub Logo
  • +
  • hisysevent相关数据表
    + GitHub Logo
  • +
+ +

+ TraceStreamer输出数据库包含以下表格 +

+ +
    +
  • app_name :记录HiSysEvent事件的事件名与IDE部分事件的字段名为APPNAME中存放的相关信息的映射关系。
  • +
  • args : 记录方法参数集合。
  • +
  • callstack : 记录调用堆栈和异步调用信息,其中depth,stack_id和parent_stack_id仅在非异步调用中有效。当cookid不为空时,为异步调用,此时callid为进程唯一号,否则为线程唯一号。
  • +
  • clk_event_filter : 记录时钟相关的信息。
  • +
  • clock_event_filter : 此结构用来维护时钟事件,cpu与唯一的ID做关联。
  • +
  • cpu_measure_filter : cpu事件过滤器表。
  • +
  • cpu_usage : 记录CPU使用率事件。
  • +
  • data_dict : 记录常用的字符串,将字符串和索引关联,降低程序运行的内存占用,用作辅助数据。
  • +
  • data_type : 记录数据类型和typeId的关联关系。
  • +
  • diskio : 记录磁盘读写数据事件。
  • +
  • file_system_callstack : 记录了采样相关信息。
  • +
  • file_system_samp : 记录了调用栈的相关信息。
  • +
  • hidump : 记录FPS(Frame Per Second)数据。
  • +
  • instant : 记录Sched_waking, sched_wakeup事件, 用作ThreadState表的上下文使用。
  • +
  • irq : 记录中断相关事件。
  • +
  • live_process : 记录了一些实时的进程中执行的一些数据。
  • +
  • log : 记录hilog打印日志数据。
  • +
  • measure : 记录所有的计量值。
  • +
  • measure_filter : 记录一个递增的filterid队列,所有其他的filter类型在获取过程中,均从此数据列表中获取下一个可用的filter_id并做记录。
  • +
  • meta : 记录执行解析操作相关的基本信息。
  • +
  • native_hook : 记录堆内存申请与释放相关的数据。
  • +
  • native_hook_frame : 记录堆内存申请与释放相关的调用栈。
  • +
  • network : 抓取网络信息传输时产生的一些相关信息。
  • +
  • perf_callchain : 记录Hiperf采样数据的调用栈信息。
  • +
  • perf_files : 记录Hiperf工具采集到的函数符号表和文件名。
  • +
  • perf_report : 记录Hiperf工具采集数据时的配置信息。包括:抓取的事件类型,抓取数据的命令, 抓数据时指定的进程名称。
  • +
  • perf_sample : 记录Hiperf工具的采样信息。
  • +
  • perf_thread : 记录Hiperf工具采集到的进程和线程数据。
  • +
  • process : 记录所有的进程信息。
  • +
  • process_filter : 过滤进程。
  • +
  • process_measure : 保存进程的所有计量值。
  • +
  • process_measure_filter : 将进程ID作为key1,进程的内存,界面刷新,屏幕亮度等信息作为key2,唯一确定一个filter_id。
  • +
  • raw : 此数据结构主要作为ThreadState的上下文使用,这张表是sched_waking,sched_wakup, cpu_idle事件的原始记录。
  • +
  • sched_slice : 此数据结构主要作为ThreadState的上下文使用,这张表是sched_switch事件的原始记录。
  • +
  • stat : 此结果用来统计数据解析中各类数据的数据条数,数据和合法性,数据的匹配程度(begin-end),数据的损失等,查看此结构对应的表,可对数据源有基本的了解。
  • +
  • symbols : 记录系统调用名称和其函数指针的对应关系,trace中用addr来映射function_name来节省存储空间。
  • +
  • syscall : 记录用户空间函数与内核空间函数相互调用记录。
  • +
  • hisys_event_measure : 记录所有的system event事件的相关数据,及其相关表的映射信息。
  • +
  • sys_event_filter : 记录所有的filter。
  • +
  • sys_mem_measure : 记录了所有的系统内存相关的测量信息。
  • +
  • thread : 记录所有的线程信息。
  • +
  • thread_filter : 过滤线程。
  • +
  • thread_state : 记录线程状态信息。
  • +
  • trace_range : 记录ftrace数据与其他类型数据的时间交集,供前端展示数据时使用。
  • +
+

表格关系图 +

+ +

进程表与线程表关系图:

+ +

GitHub Logo

+

描述:

+ +

当一个进程或者线程结束后,系统可能再次将该进程号或者线程号分配给其他进程或者线程,造成一个进程号或线程号代表多个进程或线程的情况。
+ Process和Thread表中的id字段可以唯一标识进程和线程。process表中的id在其他表中用作ipid字段。thread表中的id在其他表中用作itid字段。
+ thread表通过ipid字段关联process表的id字段,可以查询线程归属进程。 +

+

举例:

+ +

已知pid = 123,查看当前进程下的所有线程信息,可以使用如下SQL语句:
+ select thread.* from thread, process where process.pid = 123 and thread.ipid = process.id +

+

线程表与线程运行状态表关系图

+ +

GitHub Logo

+

描述:

+ +

thread_state表记录所有线程的运行状态信息,包含ts(状态起始时间),dur(状态持续时间),cpu, itid, state(线程状态)。 thread表的id字段与thread_state表的itid字段相关联。

+

举例:

+ +

已知tid = 123, 查看当前线程的所有运行状态信息,可以使用如下SQL语句:
+ select thread_state.* from thread, thread_state where thread.tid = 123 and thread.id = thread_state.itid

+

堆内存数据变化表关系图

+ +

GitHub Logo

+

描述:

+ +

native_hook表记录堆内存申请(AllocEvent)和释放(FreeEvent)数据。native_hook表通过ipid和itid字段分别与process和thread表的id字段关联,通过eventId与native_hook_frame表的eventId字段相关联。
+ native_hook表字段解释如下:
+ eventId: 唯一标识一次堆内存申请或释放, 通过与native_hook_frame表关联可以拿到当前申请或释放的函数调用堆栈。
+ addr: 堆内存申请/释放的地址
+ native_hook_size: 堆内存申请/释放的大小
+ native_hook_frame表记录内存申请/释放的调用堆栈。通过eventId区分一组调用堆栈,depth为堆栈深度,depth为0时,表示当前行为栈顶数据。 +

+

举例:

+ +

已知tid = 123, 查看当前线程的所有堆内存变化信息,可以使用如下SQL语句:
+ select native_hook.* from thread, native_hook where thread.tid = 123 and thread.id = native_hook.itid
+ 已知eventid = 0, 查看当前内存变化调用堆栈
+ select * from native_hook_frame where eventId = 0

+

日志表与进程线程表关系图

+ +

GitHub Logo

+

描述:

+ +

log表记录日志信息。可以根据seq字段的连续性,来判断是否存在日志丢失的情况。

+

举例:

+ +

已知tid = 123, 查看当前线程的所有error级别的日志,可以使用如下SQL语句:
+ select * from log where tid = 123 and level = "error"

+

perf表间关系图

+ +

GitHub Logo

+

描述:

+

perf_report:此表记录Hiperf工具采集数据时的配置信息。
+ perf_thread:此表记录hiperf采集到的进程和线程数据。
+ perf_sample:此表中记录Hiperf工具的采样信息。sample_id唯一表识一次采样记录,与perf_callchain表中的sample_id字段相关联。
+ thread_id为线程号。与perf_thread表中的thread_id字段相关联。event_type_id为当前采样的事件类型id,与perf_report表中的id字段相关联。
+ perf_callchain:此表格记录的是调用栈信息。
+ Perf_files:此表格主要存放着获取到的函数符号表和文件信息。file_id唯一表识一个文件,与perf_callchain表中的file_id字段相关联。 +

+

举例:

+ +

已知同步后的时间戳为28463134340470,查询采样数据
+ select * from perf_sample where timestamp_trace = 28463134340470
+ 已知同步后的时间戳为28463134340470,查询采样数据对应的的调用栈信息
+ select A.* from perf_callchain as A, perf_sample as B where B.timestamp_trace = 28463134340470 and A.sample_id = B.sample_id
+ 已知同步后的时间戳为28463134277762,查询采样数据的函数名及文件路径
+ select A.*, B.name, C.path from perf_sample as A, perf_callchain as B, perf_files as C where A.timestamp_trace = 28463134277762 and B.sample_id = A.sample_id and B.callchain_id = 0 and B.file_id = C.file_id and C.serial_id = 0
+ 已知线程号为6700,查询所有的采样记录
+ select * from perf_sample where thread_id = 6700
+ 已知进程号为7863,查询所有的采样记录
+ select A.* from perf_sample as A, perf_thread as B where B.process_id = 7863 and A.thread_id = B.thread_id
+ 查询所有采样对应的事件类型
+ select A.*, B.report_value from perf_sample as A, perf_report as B where A.event_type_id = B.id +

+

TraceStreamer输出数据库表格详细介绍

+ +

app_name表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
flagINT
app_nameINT
app_keyINT
+

表描述:

+ +

记录HiSysevent上报事件中的IDE相关事件中APPNAME的表关联信息。

+

字段详细描述:

+ +

app_name:对应的事件的信息ID
+ app_key:对应的事件的APPNAME字段的信息ID

+ +

args表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
keyINT
datatypeNUM
valueINT
argsetINT
+

表描述:

+ +

记录方法的参数集合

+

字段详细描述:

+ +

Key:键
+ Datatype:数据类型
+ Value:取值
+ Argset:参数集合

+ +

callstack表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
tsINT
durINT
callidINT
catNUM
nameNUM
depthINT
cookieINT
parent_idINT
argsetidINT
chainIdNUM
spanIdNUM
parentSpanIdNUM
flagNUM
argsNUM
+

表描述:

+

记录调用堆栈和异步调用信息,其中depth,stack_id和parent_stack_id仅在非异步的调用中有效。当cookid不为空时,为异步调用,此时callid为进程唯一号,否则为线程唯一号。

+

字段详细描述:

+ +

dur: 调用时长
+ callid:调用者的ID,比如针对线程表里面的id
+ name:调用名称
+ depth:调用深度
+ parent_id:父调用的id
+ spanId:分布式调用关联关系
+ flag:C表示分布式调用发送方,S表示接受方
+ args:分布式调用函数参数
+

+ +

clk_event_filter表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
typeNUM
nameNUM
cpuINT
+

表描述:

+ +

记录时钟信息

+

字段详细描述:

+ +

Type:时钟事件类型
+ Name:时钟事件名称

+ +

clock_event_filter表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
typeNUM
nameNUM
cpuINT
+

表描述:

+ +

此结构用来维护时钟事件,cpu与唯一的ID做关联

+

主要字段描述:

+ +

Type:时钟事件类型
+ Name:时钟事件名称

+ +

cpu_measure_filter表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
typeNUM
nameNUM
cpuINT
+

表描述:

+ +

将cpu号作为key1,cpu的频率,空闲等状态作为key2,唯一确定一个filter_id

+

主要字段描述:

+ +

Id(filterid), cpu:事件名称,cpu号

+ +

cpu_usage表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
tsINT
durINT
total_loadREAL
user_loadREAL
system_loadREAL
process_numINT
+

表描述:

+ +

记录了与CPU使用率相关的数据

+

主要字段描述:

+ +

total_load:总负荷
+ user_load:用户负载
+ system_load:系统负载
+ process_num:线程数

+ +

data_dict表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
dataNUM
+

表描述:

+ +

此表记录了一个数据类型ID和字符串的映射。

+

主要字段描述:

+ +

id:索引值
+ data:字符串

+ +

data_type表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
typeIdINT
descNUM
+

表描述:

+ +

此表记录了一个数据类型ID和数据描述的映射。

+

主要字段描述:

+ +

typeId::数据类型id
+ Desc:数据类型描述

+ +

diskio表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
tsINT
durINT
rdINT
wrINT
rd_speedREAL
wr_speedREAL
rd_countINT
wr_countINT
rd_count_speedREAL
wr_count_speedREAL
+

表描述:

+ +

记录了与磁盘读写相关的数据

+

主要字段描述:

+ +

rd_sectors_kb:读数据的速度
+ wr_sectors_kb:写入数据的速度
+ ts:时间戳

+ +

file_system_callstack表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
callchain_idINT
depthINT
ipINT
symbols_idINT
file_path_idINT
+

表描述:

+ +

记录了采样相关信息。

+

主要字段描述:

+ +

callchain_id:调用栈信息
+ depth:采样深度
+ ip:表识着唯一的文件调用栈的地址
+ symbols_id:存放函数名ID与data_dict表关联可以取出函数名
+ file_path_id:文件路径ID

+ +

file_system_sample表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
callchainINT
typeINT
ipidINT
start_tsINT
end_tsINT
durINT
return_valueINT
error_codeINT
fdINT
sizeINT
first_argumentINT
second_argumentINT
third_argumentINT
fourth_argumentINT
+

表描述:

+ +

记录了调用栈的相关信息。

+

主要字段描述:

+ +

callchain:调用栈信息ID与file_system_callstack表中call_chain_id字段相关联
+ type:对应文件操作open,close,read,write
+ ipid:线程所属的进程ID
+ start_ts:开始时间
+ end_ts:结束时间
+ dur:耗时
+ return_value:文件操作的返回值
+ error_code:文件操作发生错误时的错误码
+ fd:文件描述符fd
+ size:在type为read,write时对应的文件的读或者写的大小
+ first_argument:参数一
+ second_argument:参数二

+ third_argument:参数三

+ fourth_argument:参数四

+ +

hidump表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
tsINT
fpsINT
+

表描述:

+ +

此表记录了设备的帧率信息,fps。

+

相关字段描述:

+ +

fps:帧率值

+ +

instant表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
tsINT
nameNUM
refINT
ref_typeNUM
+

表描述:

+ +

记录了系统中的waking和wakeup事件。

+

字段描述:

+ +

ts:唤醒时间
+ name:唤醒事件的名称
+ ref:索引号
+ ref_type:索引类型

+ + +

irq表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
tsINT
durINT
callidINT
catNUM
nameNUN
depthINT
cookieINT
parent_idINT
argsetidINT
chainIdNUM
spanIdNUM
parentSpanIdNUM
flagNUM
argsNUM
+

表描述:

+ +

记录中断相关事件。

+

字段描述:

+ +

dur:调用中断时长
+ callid:调用中断者的ID,比如针对线程表里面的id
+ name:调用中断的名称
+ depth:中断调用的深度
+ parent_id:父调用中断的id
+ spanId:分布式调用中断关联关系

+ +

live_process表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
tsINT
durINT
cpu_timeINT
process_idINT
process_nameNUM
parent_process_idINT
uidINT
user_nameNUM
cpu_usageREAL
pss_infoINT
thread_numINT
disk_writesINT
disk_readsINT
+

表描述:

+ +

记录了一些实时的进程中执行的一些数据。

+

主要字段描述:

+ +

process_id:进程id
+ process_name:进程名
+ parent_process_id:父进程的id
+ uid:用户id
+ user_name:用户名
+ cpu_usage:cpu使用率
+ pss_info:进程信息
+ thread_num:线程数量
+ disk_writes:磁盘写量
+ disk_reads:磁盘读量

+ +

log表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
seqINT
tsINT
pidINT
tidINT
levelNUM
tagNUM
contextNUM
origintsINT
+

表描述:

+ +

记录日志信息。

+

关键字段描述:

+ +

Seq:日志序号,保证日志解析的准确性
+ Ts:打印日志时间
+ Pid:日志的进程号
+ Tid:日志的线程号
+ Level:日志级别
+ Tag:日志标签
+ Context:日志内容

+ +

measure表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
typeNUM
tsINT
valueINT
filter_idINT
+

表描述:

+ +

记录所有的计量值。

+

关键字段描述:

+ +

ts:事件时间
+ value:数值
+ filter_id:对应filter表中的ID

+ +

measure_filter表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idNUM
typeNUM
nameINT
source_arg_set_idINT
+

表描述:

+

记录一个递增的filterid队列,所有其他的filter类型在获取过程中,均从此数据列表中获取下一个可用的filter_id并做记录。

+

字段详细描述:

+ +

过滤分类(type),过滤名称(key2),数据ID(key1)。
+ 数据ID在process_measure_filter, sys_event_filter中作为id。

+ +

meta表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
nameNUM
valueNUM
+

表描述:

+ +

此表记录了数据解析或导出时的一些现场数据,比如使用的trace_streamer版本, 工具的发布时间,数据解析的时间,数据的持续时长,以及原始数据的格式。

+

主要字段描述:

+ +

Name:指定元数据的key
+ Value:指定元数据的value

+ +

native_hook表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
eventIdINT
ipidINT
itidINT
event_typeNUM
sub_typeNUM
start_tsINT
end_tsINT
durINT
addrINT
heap_sizeINT
all_heap_sizeINT
current_size_durINT
+

表描述:

+ +

记录native_hook抓取的某个进程的堆内存,内存映射相关数据。

+

关键字段描述:

+ +

eventId:唯一标识一条native_hook数据
+ event_type:事件类型取值范围(AllocEvent,FreeEvent,MmapEvent, MunmapEvent)
+ sub_type:子事件类型(只有sub_type字段为MmapEvent时,该字段才会有值)
+ start_ts:申请内存开始时间
+ end_ts:释放内存时间
+ Dur:申请内存活跃时间
+ Addr:申请内存地址
+ mem_size:申请或释放内存大小
+ all_mem_size:从采集数据开始到当前时刻,申请并活跃的内存总量。 event_type为AllocEvent或者FreeEvent时,表示活跃的堆内存总量。当event_type为MmapEvent或者MunmapEvent时,表示活跃的映射内存总量
+ current_size_dur:表示当前活跃内存总量的持续时间

+

native_hook_frame表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
eventIdINT
depthINT
ipINT
spINT
symbol_nameNUM
file_pathNUM
offsetINT
symbol_offsetINT
+

表描述:

+ +

记录了内存的申请和释放的堆栈。

+

相关字段描述:

+ +

eventID:标识一组调用堆栈
+ depth:调用栈深度
+ symbol_name:函数名 file_payh:函数所属文件
+ file_payh:函数所属文件

+

network表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
tsINT
durINT
txINT
rxINT
tx_speedREAL
rx_speedREAL
packet_inINT
packet_in_secREAL
packet_outINT
packet_out_secREAL
net_typeNUM
+

表描述:

+ +

记录了网络数据传输相关的信息。

+

主要字段描述:

+ +

tv_sec:时间,秒为单位
+ tv_nsec:时间,纳秒为单位
+ tx_bytes:网络数据的写入量
+ rx_bytes:网络数据的读取量

+

perf_callchain表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
sample_idINT
callchain_idINT
vaddr_in_fileINT
file_idINT
symbol_idINT
+

表描述:

+ +

记录了Hiperf采样数据的调用栈信息。

+

主要字段描述:

+ +

Sample_id:与PerfSample中的Sample_id相关联。代表一次采样
+ callchain_id: 调用栈深度
+ vaddr_in_file:函数在文件中的虚拟地址
+ file_id:与PerfFiles中的file_id字段相关联
+ symbol_id:与PerfFiles中的symbol_id相关联

+

perf_files表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
file_idINT
symbolNUM
pathNUM
+

表描述:

+ +

记录Hiperf工具采集到的函数符号表和文件名。

+

主要字段描述:

+ +

file_id:文件编号
+ serial_id:一个文件中可能有多个函数,serial_id表示函数的编号
+ symbol:函数名
+ path:文件路径

+

perf_report表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
report_typeNUM
report_valueNUM
+

表描述:

+ +

记录Hiperf工具采集数据时的配置信息。包括:抓取的事件类型,抓取数据的命令, 抓数据时指定的进程名称。

+

主要字段描述:

+ +

report_type:数据类型。取值只有三种类型:config_name(事件类型), workload(抓取的进程名), cmdline(抓取命令)
+ report_value: 对应类型的取值

+

perf_sample表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
sample_idINT
timestampINT
thread_idINT
event_countINT
event_type_idINT
timestamp_traceINT
cpu_idINT
thread_stateNUM
+

表描述:

+ +

记录Hiperf工具的采样信息。

+

主要字段描述:

+ +

sample_id:采样编码
+ timestamp:未进行时钟源同步的时间戳
+ thread_id:线程号
+ event_count:采样统计
+ event_type_id:事件类型编号。与PerfReport表的id字段相关联
+ timestamp_trace:时钟源同步后的时间戳
+ cpu_id:cpu核编号
+ thread_state:线程状态。采样对应Sched_Waking事件时,为Runing;对应Sched_Switch事件时,为Suspend。其余事件类型,为“-”

+

perf_thread表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
thread_idINT
process_idINT
thread_nameNUM
+

表描述:

+ +

记录Hiperf工具采集到的进程和线程数据。

+

主要字段描述:

+ +

thread_id:线程号
+ process_id:进程号
+ thread_name:线程名

+

process表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idNUM
typeINT
pidNUM
nameINT
start_tsNUM
+

表描述:

+ +

记录了进程相关数据。

+

关键字段描述:

+ +

id:进程在数据库重新重新定义的id,从0开始序列增长
+ pid:进程的真实id
+ name:进程名字

+

process_filter表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
typeNUM
nameNUM
ipidINT
+

表描述:

+ +

将进程ID作为key1,进程的内存,界面刷新,屏幕亮度等信息作为key2,唯一确定一个filter_id, filter_id同时被记录在filter表中。

+

主要字段描述:

+ +

id:进程id
+ type:进程类型
+ name:进程名
+ ipid:该进程表中的id与process表中的id相关联

+

process_measure表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
typeTEXT
tsINT
valueNUM
filter_idINT
+

表描述:

+ +

保存进程的内存,堆栈值等所有计量值信息。

+

字段详细描述:

+ +

ts:事件时间
+ value:数值
+ filter_id:对应process_measure_filter表中的ID

+

process_measure_filter表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
typeNUM
nameNUM
ipidINT
+

表描述:

+ +

将进程ID作为key1,进程的内存,界面刷新,屏幕亮度等信息作为key2,唯一确定一个filter_id, filter_id同时被记录在measure_filter表中。

+

字段详细描述:

+ +

filterid:来自measure_filter表
+ name:cpu状态名
+ ipid:进程内部编号

+

raw表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
typeNUM
tsINT
nameNUM
cpuINT
itidINT
+

表描述:

+ +

记录了系统中的waking、wakup、cpu_idel、cpu_frequency数据。

+

相关字段描述:

+ +

name:调度名称
+ cpu:事件发生在哪个CPU
+ itid:时间对应哪个utid

+

sched_slice表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
typeNUM
tsINT
durINT
cpuINT
itidINT
end_stateNUM
priorityINT
+

表描述:

+ +

此数据结构主要作为ThreadState的上下文使用,这张表是sched_switch事件的原始记录。

+

主要字段描述:

+ +

Dur:状态持续时长
+ ts:事件发生事件
+ cpu:事件发生在哪个cpu
+ itid:事件对应哪个utid
+ end_state:线程的终结状态

+

stat表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
event_nameNUM
stat_typeNUM
countINT
serverityNUM
sourceNUM
+

表描述:

+ +

此结果用来统计数据解析中各类数据的数据条数,数据和合法性,数据的匹配程度(begin-end),数据的损失等,查看此结构对应的表,可对数据源有基本的了解。

+

主要字段描述:

+ +

event_name:数据类型
+ stat_type:数据状态
+ count:数据条数
+ severity:严重级别
+ source:数据来源

+

symbols表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
funcnameNUM
addrINT
+

表描述:

+ +

此表记录了数值和函数调用名称的映射关系。

+

相关字段描述:

+ +

funcname:系统调用名称
+ addr:系统调用地址

+

syscall表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
syscall_numINT
typeTEXT
ipidINT
tsINT
retINT
+

表描述:

+ +

记录用户空间函数与内核空间函数相互调用记录。

+

相关字段描述:

+ +

syscall_num:系统调用的序号
+ type:enter或者exit
+ ipid:线程所属的进程ID
+ ts:时间戳
+ ret:返回值,在type为exit时有效

+

hisys_event_measure表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
name_idINT
key_idINT
typeINT
int_valueINT
string_valueTEXT
+

表描述:

+ +

记录所有的system event事件的相关数据,及其相关表的映射信息。

+

相关字段描述:

+ +

name_id:存放事件对应的ID,与app_name表和data_dict表相关联可以取出对应的字段
+ key_id:存放事件包含的字段的ID,通过上述关联关系可以取出对应的字段
+ type:存放事件所包含的字段的值所属的类型为int型还是string(0为int,1为string)
+ int_value:存放本事件所包含的字段的int型的值
+ string_value:存放本事件所包含的字段的string型的值

+

sys_event_filter表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
typeNUM
nameNUM
+

表描述:

+ +

记录所有的filter。

+

相关字段描述:

+ +

type:文件类型
+ name:文件名

+

sys_mem_measure表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
typeTEXT
tsINT
valueNUM
filter_idNUM
+

表描述:

+ +

记录系统内存与系统虚拟内存。

+

相关字段描述:

+ +

ts:事件时间
+ value:数值
+ filter_id:对应filter表中的ID

+

thread表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
typeNUM
tidINT
nameNUM
start_tsINT
end_tsINT
ipidINT
is_main_threadINT
+

表描述

+ +

记录了线程相关数据。

+

字段详细描述:

+ +

id:线程在数据库重新重新定义的id,从0开始序列增长
+ ipid:线程所属的进程id, 关联process表中的ID
+ name:线程名字
+ is_main_thread:是否主线程,主线程即该线程实际就是进程本身

+

thread_filter表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
typeNUM
nameNUM
itidINT
+

表描述:

+ +

将线程ID作为key1,线程的内存,界面刷新,屏幕亮度等信息作为key2,唯一确定一个filter_id, filter_id同时被记录在filter表中。

+

主要字段描述:

+ +

id:线程id
+ type:线程类型
+ name:线程名称
+ itid:该表中的tid与thread表中的tid相关联

+

thread_state表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
idINT
typeNUM
tsINT
durINT
cpuINT
itidINT
stateNUM
+

表描述:

+ +

记录了线程状态相关的数据。

+

字段详细描述:

+ +

id:线程状态在数据库中的id,从0开始序列增长
+ ts:该线程状态的起始时间
+ dur:该线程状态的持续时间
+ cpu:该线程在哪个cpu上执行(针对running状态的线程)
+ itid:该状态所属的线程id, 关联线程表中的id
+ state:线程实际的的状态值

+
'R', Runnable状态
+'S', interruptible sleep
+'D', uninterruptible sleep
+'T', Stoped
+'t', Traced
+'X', ExitedDead
+'Z', ExitZombie
+'x', TaskDead
+'I', TaskDead
+'K', WakeKill
+'P', Parked
+'N', NoLoad
+
+

trace_range表

+ +

表结构:

+ + + + + + + + + + + + + + + + + + +
Columns NameSQL TYPE
start_tsNUM
end_tsINT
+

表描述:

+ +

记录解析解析开始时间以及结束时间。

+

关键字段描述:

+ +

start_ts:trace的开始时间,纳秒为单位
+ end_ts:trace的结束时间,纳秒为单位

+
+ + + + + \ No newline at end of file diff --git a/host/ide/src/doc/des_wakup.html b/host/ide/src/doc/des_wakup.html new file mode 100644 index 0000000000000000000000000000000000000000..6d3ddc88b3a5ca8651c7983d83f0a58bd6f6a2fe --- /dev/null +++ b/host/ide/src/doc/des_wakup.html @@ -0,0 +1,767 @@ + + des_wakup + + + + + +
+

各应用程序对于trace事件的waking和wakeup处理是略有区别的。
+ waking是开始唤醒线程,wakeup是线程正式被唤醒,进入runnable(可运行状态)
+ 我们的策略是:被唤醒才是真正进入runnable状态,在没有wakeup事件的情况下,以waking为准。

+
+ + \ No newline at end of file diff --git a/host/ide/src/doc/file_system.html b/host/ide/src/doc/file_system.html new file mode 100644 index 0000000000000000000000000000000000000000..de3ba3de2d926498cfe83a129697fa5a3e227546 --- /dev/null +++ b/host/ide/src/doc/file_system.html @@ -0,0 +1,1046 @@ + + + FileSystem抓取和展示说明 + + + + + + +
+

FileSystem的抓取和展示说明

+ +

FileSystem分析文件系统的信息和活动,比如读和写操作等

+

1.FileSystem的抓取

+ +

1.1.FileSystem抓取配置参数

+ +

GitHub Logo
+配置项说明

+
    +
  • +
    Start FileSystem Record:配置项的总开关
    +
    +
  • +
  • +
    Process:默认配置的是整个系统的,也可选择单进程抓取
    +
    +
  • +
  • +
    Max Unwind Level:配置抓取调用栈的最大深度
    +
    +
  • +
+

再点击Record setting,在output file path输入文件名hiprofiler_data_filesystem.htrace,拖动滚动条设置buffer size大小是64M,抓取时长是50s
+GitHub Logo
+点击Trace command,就会根据上面的配置生成抓取命令,点击复制按钮,会将命令行复制
+GitHub Logo
+输入hdc_std shell,进入设备,执行命令
+GitHub Logo
+执行完成后,进入指定目录查看,在/data/local/tmp下就会生成trace文件
+GitHub Logo

+

2.FileSystem展示说明

+ +

将抓取的trace文件导入smartperf界面查看
+GitHub Logo

+

界面布局介绍:FileSystem整体界面布局分为3个部分,其中

+
    +
  • +
    红色区域:泳道图
    +
    +
  • +
  • +
    绿色区域:详细信息
    +
    +
  • +
  • +
    黄色区域:辅助信息(Callstack)
    +
    +
  • +
+

2.1.FileSystem泳道图展示

+ +

FileSystem泳道图按照读操作和写操作展示,鼠标移动都泳道图上,悬浮框会以10ms为周期展示读,写类型系统调用的次数
+GitHub Logo
+按住w键放大界面,悬浮框会显示当前时刻的文件读写次数
+GitHub Logo

+

2.2.FileSystem泳道图的框选功能

+ +

可以对读写操作泳道图进行框选,框选后在最下方的弹出层中会展示框选数据的统计表格,总共有五个tab页
+FileSystem statistics的Tab页
+GitHub Logo

+
    +
  • +
    Syscall/Process: 按照数据类型,进程分类显示
    +
    +
  • +
  • +
    Count: 系统调用的数量
    +
    +
  • +
  • +
    Logical Writes:写数据统计
    +
    +
  • +
  • +
    Logical Reads:读数据统计
    +
    +
  • +
  • +
    Other Filesystem Bytes:其他数据量
    +
    +
  • +
  • +
    Duration:总时长
    +
    +
  • +
  • +
    Min Duration:最小时长
    +
    +
  • +
  • +
    Avg Duration: 平均时长
    +
    +
  • +
  • +
    Max Duration:最大时长
    +
    +
  • +
+

FileSystem Calltree的Tab页
+GitHub Logo

+
    +
  • +
    Call Stack:为经过符号解析后的Callstack,并且给出动态链接库或者进程名的信息
    +
    +
  • +
  • +
    Local:为该调用方法自身占用的CPU时间
    +
    +
  • +
  • +
    Weight:调用方法的执行占比
    +
    +
  • +
+

FileSystem Events的Tab页
+GitHub Logo

+
    +
  • +
    Start: 起始时间
    +
    +
  • +
  • +
    Duration:时长
    +
    +
  • +
  • +
    Process:进程名
    +
    +
  • +
  • +
    Thread:线程名
    +
    +
  • +
  • +
    Firsr Argument:系统调用的第一个参数
    +
    +
  • +
  • +
    Second Argument:系统调用的第二个参数
    +
    +
  • +
  • +
    Third Argument:系统调用的第三个参数
    +
    +
  • +
  • +
    Fourth Argument:系统调用的第四个参数
    +
    +
  • +
  • +
    Retrun:系统调用的返回值
    +
    +
  • +
  • +
    Error:错误码
    +
    +
  • +
  • +
    Backtrace:调用栈顶部函数,并显示调用栈深度
    +
    +
  • +
+

File Descriptor History的Tab页
+GitHub Logo

+
    +
  • +
    Start: 起始时间
    +
    +
  • +
  • +
    Duration:时长
    +
    +
  • +
  • +
    Process:进程名
    +
    +
  • +
  • +
    Type:操作类型
    +
    +
  • +
  • +
    File Descriptor:fd
    +
    +
  • +
  • +
    Backtrace:调用栈顶部函数,并显示调用栈深度
    +
    +
  • +
+

File Descriptor Time Slice的Tab页
+GitHub Logo

+
    +
  • +
    Open Time: 打开的起始时间
    +
    +
  • +
  • +
    Open Duration:打开的时长
    +
    +
  • +
  • +
    Process:进程名
    +
    +
  • +
  • +
    File Descriptor:fd
    +
    +
  • +
  • +
    Backtrace:调用栈顶部函数,并显示调用栈深度
    +
    +
  • +
+

2.3.FileSystem支持多种Options展示风格

+ +

点击FileSystem Calltree的Tab页底部的Options,会有两个CheckBox复选框
+GitHub Logo

+
    +
  • +
    Invert:反向输出调用树
    +
    +
  • +
  • +
    Hide System so:隐藏系统库文件   
    +
    +
  • +
+

2.4.FileSystem支持过滤调用栈调用次数的展示风格

+ +

点击FileSystem Calltree的Tab页底部的Sample Counter Filter,可以填上区间值。过滤出符合该区间值调用次数的调用栈信息
+GitHub Logo

+

2.5.FileSystem功能的调用栈Group展示-数据分析支持剪裁功能

+ +

GitHub Logo

+
    +
  • +

    裁剪Callstack,点击Callstack上一个节点符号,再点击底部Symbol Filter按钮,则该符号自动被裁剪掉,同时将该节点往下所有的Callstack内容裁剪掉

    +
  • +
  • +

    裁剪Library,点击Library Filter按钮,则该库文件符号下所有的子节点也被裁剪

    +
  • +
  • +

    点击Reset按钮,将恢复选中的裁剪内容

    +
  • +
+

2.6.FileSystem功能的调用栈Group展示支持按条件过滤

+ +

在Input Filter输入关键字,会显示出带有该关键字的展示信息
+GitHub Logo

+

2.7.FileSystem辅助信息区展示调用栈

+ +

当在详细信息区选择一个符号时,将展示与该符号相关的完整的调用栈。如下图的Heaviest Stack Trace:
+GitHub Logo

+

2.8.FileSystem的事件类型的过滤

+

通过选择可以过滤是Open类型,还是Close类型事件
+GitHub Logo

+

2.9.FileSystem的火焰图功能

+

点击FileSystem Calltre左下角的柱状图的图标,会切换到火焰图页面
+GitHub Logo
+进入到火焰图页面,火焰图的展示跟Callinfo的tab页的调用栈显示一致,鼠标放到色块上,悬浮框可以显示调用栈名称和Duration时长
+GitHub Logo
+鼠标左键火焰图,会进入下一级界面,右键回到上一级
+GitHub Logo

+ +
+ + + + \ No newline at end of file diff --git a/host/ide/src/doc/hiSystemEvent.html b/host/ide/src/doc/hiSystemEvent.html new file mode 100644 index 0000000000000000000000000000000000000000..13a94d9d913e991d7f0a056f898ce0ec9f0dc8e6 --- /dev/null +++ b/host/ide/src/doc/hiSystemEvent.html @@ -0,0 +1,1038 @@ + + + + + HiSystemEvent抓取和展示说明 + + + + + +
+

HiSystemEvent的抓取和展示说明

+ +

HiSystemEvent应用功耗模块主要是展示应用的各个子类别功耗占比信息、应用的资源申请使用记录信息、应用功耗异常事件信息、功耗关联系统状态信息。

+

1.HiSystemEvent的抓取

+ +

1.1.HiSystemEvent抓取配置参数

+ +

勾选HiSystemEvent选项抓取HiSystemEvent数据
+ GitHub Logo
+ 再点击Record setting,在output file path输入文件名hiprofiler_data_hisystemevent.htrace,拖动滚动条设置buffer + size大小是64M,抓取时长是50s
+ GitHub Logo
+ 点击Trace command,就会根据上面的配置生成抓取命令,点击复制按钮,会将命令行复制
+ GitHub Logo
+ 输入hdc_std shell,进入设备,执行上述生成的命令
+ GitHub Logo
+ 执行完成后,进入指定目录查看,在/data/local/tmp下就会生成trace文件
+ GitHub Logo

+

2.HiSystemEvent展示说明

+ +

2.1.HiSystemEvent泳道图展示

+ +

将抓取的trace文件导入smartperf界面查看
+ GitHub Logo
+ 泳道图说明:

+
    +
  • +
    Anomaly Event泳道: 显示系统异常和应用异常的ToolTip
    +
    +
  • +
  • +
    System Event泳道: 以条状图显示,红色代表后台任务(WORKSCHEDULER),黄色代表应用锁(POWER),蓝色代表GPS定位(LOCATION)
    +
    +
  • +
  • +
    Power泳道:应用各个子类的功耗柱状图、折现图以及应用各个子类绘制的图例,鼠标的悬浮可以显示出各个子类功耗的具体值
    +
    +
  • +
  • +
    Brightness Nit泳道:鼠标悬浮可以显示屏幕亮度值
    +
    +
  • +
  • +
    Wifi Event Received泳道:鼠标悬浮可以显示WiFi信号强度值
    +
    +
  • +
  • +
    Audio Stream Change泳道:鼠标悬浮可以显示Audio状态(AUDIO_STREAM_CHANGE事件)
    +
    +
  • +
  • +
    Audio Volume Change泳道:鼠标悬浮可以显示Audio状态(AUDIO_VOLUME_CHANGE事件)
    +
    +
  • +
  • +
    Wifi State泳道:鼠标悬浮可以显示wifi开关状态(enable:开,disable:关)
    +
    +
  • +
  • +
    Bluetooth Br Switch State泳道:鼠标悬浮可以显示蓝牙开关状态(enable:开, disable:关)
    +
    +
  • +
  • +
    Location Switch State泳道:鼠标悬浮可以显示GPS开关状态(enable:开,disable:关)
    +
    +
  • +
+

2.2.HiSystemEvent泳道图的框选功能

+ +

可以对Energy各泳道图进行框选,框选后在最下方的弹出层中会展示框选数据的统计表格
+ System Details的Tab页
+ GitHub Logo

+
    +
  • +
    Event Name: 事件名称,事件包括后台任务,应用锁,GPS定位
    +
    +
  • +
  • +
    Time: 时间戳信息
    +
    +
  • +
+

点击事件名会显示该事件的详细信息的Tab页
+ GitHub Logo

+
    +
  • +
    EVENT_NAME:事件名称
    +
    +
  • +
  • +
    PID:应用PID
    +
    +
  • +
  • +
    UID:应用UID
    +
    +
  • +
  • +
    TYPE:类型
    +
    +
  • +
  • +
    STATE:状态值
    +
    +
  • +
  • +
    LOG_LEVEL:日志级别
    +
    +
  • +
  • +
    NAME:NAME信息
    +
    +
  • +
  • +
    MESSAGE:MESSAGE信息
    +
    +
  • +
  • +
    TAG:锁名
    +
    +
  • +
+

Power Battery的Tab页
+ GitHub Logo

+
    +
  • +
    Gas Gauge: 电池电量
    +
    +
  • +
  • +
    Charge:充电状态
    +
    +
  • +
  • +
    Screen:屏幕状态
    +
    +
  • +
  • +
    Level:电池百分比
    +
    +
  • +
  • +
    Current:电池电流
    +
    +
  • +
  • +
    Capacity:电池容量
    +
    +
  • +
  • +
    APP Name:应用包名
    +
    +
  • +
+

Power Details的Tab页
+ GitHub Logo

+
    +
  • +
    UID: 应用UID
    +
    +
  • +
  • +
    Charge:充电状态
    +
    +
  • +
  • +
    Foreground Duration(ms):前台使用时长
    +
    +
  • +
  • +
    Foreground Energy(mAs):前台使用功耗值
    +
    +
  • +
  • +
    Background Duration(ms):后台使用时长
    +
    +
  • +
  • +
    Background Energy(mAs):后台使用功耗值
    +
    +
  • +
  • +
    Screen On Duration(ms):亮屏使用时长
    +
    +
  • +
  • +
    Screen On Energy(mAs):亮屏使用功耗值
    +
    +
  • +
  • +
    Screen Off Duration(ms):灭屏使用时长
    +
    +
  • +
  • +
    Screen Off Energy(mAs):灭屏使用功耗值
    +
    +
  • +
  • +
    Foreground Count:应用前台扫描次数
    +
    +
  • +
  • +
    Background Count:应用后台扫描次数
    +
    +
  • +
  • +
    Screen On Count:应用亮屏扫描次数
    +
    +
  • +
  • +
    Screen Off Count:应用灭屏扫描次数
    +
    +
  • +
  • +
    Background Time(ms):灭屏使用功耗值
    +
    +
  • +
  • +
    Screen On Time(ms):应用亮屏使用时长
    +
    +
  • +
  • +
    Screen Off Time(ms):应用灭屏使用时长
    +
    +
  • +
  • +
    Energy(mAs):功耗值
    +
    +
  • +
  • +
    Load(%):占用率
    +
    +
  • +
  • +
    Usage(ms):应用使用时长
    +
    +
  • +
  • +
    Duration(ms):持续时长
    +
    +
  • +
  • +
    Camera Id:Camera类型,0:后置,1:前置
    +
    +
  • +
  • +
    Count:应用个数
    +
    +
  • +
  • +
    Energy Percent(%):功耗占比
    +
    +
  • +
+
+ + + + \ No newline at end of file diff --git a/host/ide/src/doc/memory_fetching.html b/host/ide/src/doc/memory_fetching.html new file mode 100644 index 0000000000000000000000000000000000000000..364053983b29e0b54dcedbdb76107cc2d7ea29db --- /dev/null +++ b/host/ide/src/doc/memory_fetching.html @@ -0,0 +1,960 @@ + + + 页内存抓取和展示说明 + + + + + + +
+

页内存的抓取和展示说明

+ +

页内存从page层面更深层次剖析应用程序的虚拟内存操作

+

1.页内存的抓取

+ +

1.1.页内存抓取配置参数

+ +

GitHub Logo
+配置项说明

+
    +
  • +
    Start Virtual Memory Record:配置项的总开关
    +
    +
  • +
  • +
    Process:默认配置的是整个系统的,也可选择单进程抓取
    +
    +
  • +
  • +
    Max Unwind Level:配置抓取调用栈的最大深度
    +
    +
  • +
+

再点击Record setting,在output file path输入文件名hiprofiler_data_ebpf.htrace,拖动滚动条设置buffer size大小是64M,抓取时长是50s
+GitHub Logo
+点击Trace command,就会根据上面的配置生成抓取命令,点击Record抓取,抓取过程中会显示抓取时长
+GitHub Logo

+

2.页内存展示说明

+ +

抓取结束后页内存的trace会自动加载展示
+GitHub Logo

+

界面布局介绍:页内存整体界面布局分为3个部分,其中

+
    +
  • +
    红色区域:泳道图
    +
    +
  • +
  • +
    绿色区域:详细信息
    +
    +
  • +
  • +
    黄色区域:辅助信息(Callstack)
    +
    +
  • +
+

2.1.页内存泳道图展示

+ +

页内存泳道图展示事件(Operation)发生的次数,每个事件都有持续时间,鼠标悬浮以10ms为区间进行次数统计
+GitHub Logo
+按住w键放大界面,悬浮框会显示当前时刻的事件发生次数
+GitHub Logo

+

2.2.页内存泳道图的框选功能

+ +

可以对泳道图进行框选,框选后在最下方的弹出层中会展示框选数据的统计表格,总共有三个tab页
+Virtual Memory Statistics的Tab页
+GitHub Logo

+
    +
  • +
    Operation/Process/Thread: 按照Operation为基点显示
    +
    +
  • +
  • +
    Count: 事件数量
    +
    +
  • +
  • +
    Duration:总时长
    +
    +
  • +
  • +
    Min Duration:最小时长
    +
    +
  • +
  • +
    Avg Duration: 平均时长
    +
    +
  • +
  • +
    Max Duration:最大时长
    +
    +
  • +
+

点击下方的Statistics by Thread,可以切换到按照Thread为基点显示数据
+GitHub Logo
+Virtual Memory Calltree的Tab页
+GitHub Logo

+
    +
  • +
    Call Stack:为经过符号解析后的Callstack,并且给出动态链接库或者进程名的信息
    +
    +
  • +
  • +
    Local:为该调用方法自身占用的CPU时间
    +
    +
  • +
  • +
    Weight:调用方法的执行占比
    +
    +
  • +
+

Virtual Memory Events的Tab页
+GitHub Logo

+
    +
  • +
    Start Time:起始时间
    +
    +
  • +
  • +
    Duration:时长
    +
    +
  • +
  • +
    Thread:线程名
    +
    +
  • +
  • +
    Operation:事件类型
    +
    +
  • +
  • +
    Address:内存地址
    +
    +
  • +
  • +
    Size:内存大小
    +
    +
  • +
+

2.3.页内存支持多种Options展示风格

+ +

点击Virtual Memory Calltree的Tab页底部的Options,会有两个CheckBox复选框
+GitHub Logo

+
    +
  • +
    Invert:反向输出调用树
    +
    +
  • +
  • +
    Hide System so:隐藏系统库文件   
    +
    +
  • +
+

2.4.页内存支持过滤调用栈调用次数的展示风格

+ +

点击Virtual Memory Calltree的Tab页底部的Sample Counter Filter,可以填上区间值。过滤出符合该区间值调用次数的调用栈信息
+GitHub Logo

+

2.5.页内存功能的调用栈Group展示-数据分析支持剪裁功能

+ +

GitHub Logo

+
    +
  • +

    裁剪Callstack,点击Callstack上一个节点符号,再点击底部Symbol Filter按钮,则该符号自动被裁剪掉,同时将该节点往下所有的Callstack内容裁剪掉

    +
  • +
  • +

    裁剪Library,点击Library Filter按钮,则该库文件符号下所有的子节点也被裁剪

    +
  • +
  • +

    点击Reset按钮,将恢复选中的裁剪内容

    +
  • +
+

2.6.页内存功能的调用栈Group展示支持按条件过滤

+ +

在Input Filter输入关键字,会显示出带有该关键字的展示信息
+GitHub Logo

+

2.7.页内存辅助信息区展示调用栈

+ +

当在详细信息区选择一个符号时,将展示与该符号相关的完整的调用栈。如下图的Heaviest Stack Trace:
+GitHub Logo

+

2.8.页内存的事件类型的过滤

+

通过选择可以过滤是File Backed In类型,还是Copy On Write类型事件
+GitHub Logo

+

2.9.页内存的火焰图功能

+

点击Virtual Memory Calltree左下角的柱状图的图标,会切换到火焰图页面
+GitHub Logo
+进入到火焰图页面,火焰图的展示跟Callinfo的tab页的调用栈显示一致,鼠标放到色块上,悬浮框可以显示调用栈名称和Duration时长
+GitHub Logo
+鼠标左键火焰图,会进入下一级界面,右键回到上一级
+GitHub Logo

+ +
+ + + + \ No newline at end of file diff --git a/host/ide/src/doc/native_memory.html b/host/ide/src/doc/native_memory.html new file mode 100644 index 0000000000000000000000000000000000000000..80cb0f39f1e9a281e2634fa59d2817f89e3ecd7d --- /dev/null +++ b/host/ide/src/doc/native_memory.html @@ -0,0 +1,1006 @@ + + + Native Memory抓取和展示说明 + + + + + + +
+

Native Memory抓取和展示说明

+ +

Native Memory是查看内存的分配和释放等情况

+

1.Native Memory的抓取

+ +

1.1.Native Memory抓取配置参数

+ +

GitHub Logo
+配置参数说明:

+
    +
  • ProcessId or ProcessName:设置抓取的进程ID或者进程名,此处以输入com.ohos.mms进程名为例
  • +
  • Max unwind level:抓取的栈的最大深度
  • +
  • Shared Memory Size:native_daemon和native_hook进程之间存储数据的共享内存大小
  • +
  • Filter Memory Size:只抓取大于该size的malloc数据(free不受影响)
  • +
+

再点击Record setting,在output file path输入文件名hiprofiler_data_nativememory.htrace,拖动滚动条设置buffer size大小是64M,抓取时长是50s
+GitHub Logo

+

点击Trace command,就会根据上面的配置生成抓取命令,点击复制按钮,会将命令行复制
+GitHub Logo

+

命令行参数说明:

+
    +
  • save_file:是否将hook数据保存成文件,不上报protobuf形式数据给hiprofilerd
  • +
  • filter_size:过滤malloc的大小,最小值是0,默认值是4096Byte
  • +
  • smb_pages:nativedeamon与libnativehook间的共享内存大小
  • +
  • max_stack_depth:最多回栈的层数,也就是抓取的栈的最大深度
  • +
  • fp_unwind:是否进行fp回栈
  • +
  • malloc_free_matching_interval:native_daemon从nativehook so的共享内存里取数据的间隔时间
  • +
  • string_compressed:是否进行字符串压缩
  • +
+

输入hdc_std shell,进入设备,执行命令
+GitHub Logo
+执行完成后,进入指定目录查看,在/data/local/tmp下就会生成trace文件
+GitHub Logo

+

2.Native Memory展示说明

+ +

将抓取的nativememory文件导入到smartperf工具中查看,查看内存的分配和释放等情况

+

2.1.Native Memory泳道图展示类型

+ +

点击齿轮状的图标可以设置内存的展示单位
+GitHub Logo

+
    +
  • +
    Current Bytes:以申请内存的size绘制泳道图
    +
    +
  • +
  • +
    Native Memory Density:以申请内存的数量绘制泳道图
    +
    +
  • +
  • +
    All Heap&AnonuymousVM:malloc分配和mmap分配的总量
    +
    +
  • +
  • +
    All Heap:malloc分配的内存
    +
    +
  • +
  • +
    All Anonymous VM:mmap分配的内存
    +
    +
  • +
+

2.2.Native Memory泳道图的框选功能

+ +

可以对内存的数据进行框选,框选后在最下方的弹出层中会展示框选数据的统计表格,总共有四个tab页
+Statistics的Tab页,主要显示了统计明细类型
+GitHub Logo

+
    +
  • +
    Memory Type:内存的类型
    +
    +
  • +
  • +
    Exsiting :框选区域内申请没有释放的大小
    +
    +
  • +
  • +
    #Exsiting :框选区域内申请没有释放的次数
    +
    +
  • +
  • +
    Transient:框选区域内释放的大小
    +
    +
  • +
  • +
    #Transient:框选区域内释放的次数
    +
    +
  • +
  • +
    Total Bytes:框选区间内申请的大小
    +
    +
  • +
  • +
    #Total: 框选区间内申请的次数
    +
    +
  • +
  • +
    Peak Value: 框选区间内内存申请的峰值
    +
    +
  • +
  • +
    Exsiting/Total:框选区间内剩余的内存比上申请的内存,其中浅紫色是框选区间内申请的大小/整个时间轴(申请+释放的总大小),深紫色是框选区间内(申请+释放)的大小/整个时间轴(申请+释放的总大小)
    +
    +
  • +
+

Call Info的Tab页,主要显示了调用树详细类型
+GitHub Logo

+
    +
  • +
    Symble Name:每个内存分配的调用栈
    +
    +
  • +
  • +
    Size :分配的总大小
    +
    +
  • +
  • +
    Count :相同调用栈出现的次数
    +
    +
  • +
+

Native Memory的Tab页,主要显示了单次分配信息列表
+GitHub Logo

+
    +
  • +
    Address:内存块的地址
    +
    +
  • +
  • +
    Memory Type :内存分配的类型
    +
    +
  • +
  • +
    Timestamp :时间戳信息
    +
    +
  • +
  • +
    State :内存地址当前状态Existed 表示框选范围内未释放,Freed表示已释放
    +
    +
  • +
  • +
    Size :该次申请分配内存的大小
    +
    +
  • +
  • +
    Responsible Library :调用该函数的库
    +
    +
  • +
  • +
    Responsible Caller  :调用该函数的方法
    +
    +
  • +
+

Snapshot List的Tab页,主要显示了各时刻内存的增长的差值
+GitHub Logo

+
    +
  • +
    Snapshot:标记的打点说明
    +
    +
  • +
  • +
    Timestamp :时间戳信息
    +
    +
  • +
  • +
    Net Growth :自从上次Snapshot的增长量,是计算的分配和释放的
    +
    +
  • +
  • +
    Total Growth :自从上次Snapshot的增长量,是计算的每一次分配的
    +
    +
  • +
  • +
    #Exsiting  :仍然存在的内存数
    +
    +
  • +
+

2.3.Native Memory的辅助信息功能

+ +

在Call Info和Native Memory的Tab页,点击选中某一行,右边画红线处会显示出该行调用栈的树结构信息
+GitHub Logo

+

2.4.Native Memory详细显示的过滤功能

+ +

点击下方的All Allocations可以对Allocation的lifeSpan进行过滤,有三个选择:All Allocatios,Create & Exsiting,Create & Destroyed
+GitHub Logo

+
    +
  • +
     All Allocations:所有的内存
    +
    +
  • +
  • +
     Created & Exsiting:创建且被存活的内存
    +
    +
  • +
  • +
     Created & Destroyed: 创建且被销毁的内存
    +
    +
  • +
+

点击下方的All Heap&Anonymous可以对内存类型进行过滤
+GitHub Logo

+
    +
  • +
    All Heap&AnonuymousVM:Heap和AnonuymousVM的总量
    +
    +
  • +
  • +
    All Heap:malloc分配的内存
    +
    +
  • +
  • +
    All Anonymous VM:mmap的匿名页
    +
    +
  • +
+

点击下方的Mark Snapshot可以在时间轴上打标签。出现小旗的标志,通过标注多个时间点。点击到Snapshot List标签页可以看到各个时间点的内存的增长值
+GitHub Logo

+

2.5.Native Memory的火焰图功能

+ +

点击callinfo左下角的柱状图的图标,会切换到火焰图页面
+GitHub Logo
+进入到火焰图页面,火焰图的展示跟Callinfo的tab页的调用栈显示一致,鼠标放到色块上,悬浮框可以显示调用栈名称和size大小
+GitHub Logo
+鼠标左键火焰图,会进入下一级界面,右键回到上一级
+GitHub Logo

+ +
+ + + + \ No newline at end of file diff --git a/host/ide/src/doc/perf.html b/host/ide/src/doc/perf.html new file mode 100644 index 0000000000000000000000000000000000000000..ac3815fb8e3e7f1523cd84b0be82b5bac2e02ef2 --- /dev/null +++ b/host/ide/src/doc/perf.html @@ -0,0 +1,857 @@ + + + + Perf的抓取和展示说明 + + + + + +
+

Perf的抓取和展示说明

+

HiPerf工具是对系统性能数据进行采样记录,并将采样数据保存为文件,进行读取,展示分析

+

1.Perf的抓取

+

1.1.Perf抓取配置参数

+ GitHub Logo

+

配置参数说明:

+
    +
  • Start Hiperf Sampling:配置项的总开关
  • +
  • Process:离线模式下配置的是整个系统的
  • +
  • Frequency:配置抓取的频率
  • +
  • Call Stack:配置抓取的堆栈类型
  • +
  • Advance Options:更多的抓取配置项
  • +
+

再点击Record setting,在output file path输入文件名hiprofiler_data_perf.htrace,拖动滚动条设置buffer size大小是64M,抓取时长是50s
+ GitHub Logo

+

点击Trace command,就会根据上面的配置生成抓取命令,点击复制按钮,会将命令行复制
+ GitHub Logo

+

输入hdc_shell,进入设备,执行命令
+ GitHub Logo

+

执行完成后,进入指定目录查看,在/data/local/tmp下就会生成trace文件
+ GitHub Logo

+

2.Perf展示说明

+

将抓取的trace文件导入smartperf界面查看
+ GitHub Logo

+ +

界面布局介绍:Perf整体界面布局分为3个部分,其中

+
    +
  • +
    红色区域:泳道图
    +
    +
  • +
  • +
    绿色区域:详细信息(Perf Profile和Sample List)
    +
    +
  • +
  • +
    黄色区域:辅助信息(Callstack)
    +
    +
  • +
+

2.1.Perf泳道图展示

+

Perf泳道图展示按照CPU使用量和线程和进程展示,鼠标移动都泳道图上,悬浮框会显示CPU的使用量
+ GitHub Logo

+

按住w键放大界面,泳道图会出现P的标志,鼠标移动到P图标上,悬浮框会显示每个callstack和调用的深度如下图
+ GitHub Logo

+

2.2.Perf泳道图的框选功能

+

可以对CPU使用量区,线程和进程区数据进行框选,框选后在最下方的弹出层中会展示框选数据的统计表格,总共有两个tab页
+ Perf Profile的Tab页
+ GitHub Logo

+
    +
  • Call Stack:为经过符号解析后的Callstack,并且给出动态链接库或者进程名的信息
  • +
  • Local:为该调用方法自身占用的CPU时间
  • +
  • Weight:调用方法的执行次数和占比
  • +
+

Sample List的Tab页
+ GitHub Logo

+
    +
  • Sample Time:采样的时间戳信息
  • +
  • Core:当前的CPU核信息
  • +
  • Process:进程名
  • +
  • Thread:线程名
  • +
  • State:运行状态
  • +
  • Backtrace:栈顶的调用栈名称
  • +
+

2.3.Perf支持多种Options展示风格

+

点击Perf Profile的Tab页底部的Options,会有两个CheckBox复选框
+ GitHub Logo

+
    +
  • Invert:反向输出调用树
  • +
  • Hide System so:隐藏系统库文件
  • +
+

2.4.Perf支持过滤调用栈调用次数的展示风格

+

点击Perf Profile的Tab页底部的Sample Counter Filter,可以填上区间值。过滤出符合该区间值调用次数的调用栈信息
+ GitHub Logo

+

2.5.Perf功能的调用栈Group展示-数据分析支持剪裁功能

+ GitHub Logo +
    +
  • 裁剪Callstack,点击Callstack上一个节点符号,再点击底部Symbol Filter按钮,则该符号自动被裁剪掉,同时将该节点往下所有的Callstack内容裁剪掉
  • +
  • 裁剪Library,点击Library Filter按钮,则该库文件符号下所有的子节点也被裁剪
  • +
  • 点击Reset按钮,将恢复选中的裁剪内容
  • +
+

2.6.Perf功能的调用栈Group展示支持按条件过滤

+

在Input Filter输入关键字,会显示出带有该关键字的展示信息
+ GitHub Logo

+

2.7.Perf辅助信息区展示调用栈

+

当在详细信息区选择一个符号时,将展示与该符号相关的完整的调用栈。对上展示到根节点,对下则展示CPU占用率最大的调用栈。调用栈右侧有Sliding bar可以滚动
+ 如下图的Heaviest Stack Trace:
+ GitHub Logo

+

2.8.Perf的火焰图功能

+

点击Perf Profile左下角的柱状图的图标,会切换到火焰图页面
+ GitHub Logo

+

进入到火焰图页面,火焰图的展示跟Callinfo的tab页的调用栈显示一致,鼠标放到色块上,悬浮框可以显示调用栈名称和count大小
+ GitHub Logo

+

鼠标左键火焰图,会进入下一级界面,右键回到上一级
+ GitHub Logo

+ +
+ + + \ No newline at end of file diff --git a/host/ide/src/doc/quickstart_hiprofiler_cmd.html b/host/ide/src/doc/quickstart_hiprofiler_cmd.html new file mode 100644 index 0000000000000000000000000000000000000000..fa1d0a6a883f7885fb56b33142d08427c6b03de4 --- /dev/null +++ b/host/ide/src/doc/quickstart_hiprofiler_cmd.html @@ -0,0 +1,817 @@ + + + 快速抓取trace说明 + + + + + + +
+

快速抓取trace说明

+ +

1.界面配置说明

+ +

GitHub Logo
+说明:

+
    +
  • Record setting:设置trace的抓取模式,buffer size大小,抓取时长
  • +
  • Trace command:生成的抓取命令行
  • +
  • Probes config:trace的抓取参数配置
  • +
  • Native Memory:NativeMemory数据的抓取参数配置
  • +
  • Hiperf:Hiperf数据的抓取参数配置
  • +
+

2.命令行的生成和trace文件的抓取

+ +

点击Probes config,如选择抓取Scheduling details
+GitHub Logo
+再点击Record setting,在output file path输入文件名hiprofiler_data_example.htrace,拖动滚动条设置buffer size大小是64M,抓取时长是50s
+GitHub Logo
+点击Trace command,就会根据上面的配置生成抓取命令,点击复制按钮,会将命令行复制
+GitHub Logo
+命令参数说明:

+
    +
  • -o:文件的输入路径和名称
  • +
  • -t:抓取的时长
  • +
  • buffer pages:buffer size大小
  • +
  • sample_duration:数据采集的时间
  • +
  • sample_interval:主动获取插件数据的间隔时间(ms,只针对轮询插件,例如memory插件,cpu插件,dikio插件等,对流式插件和独立插件无效)
  • +
  • trace_period_ms:ftrace插件读取内核缓冲区数据的间隔时间(ms)
  • +
  • hitrace_time:hitrace命令行抓取时间,与hiprofiler_cmd下发的-t配置联动
  • +
+

输入hdc_std shell,进入设备,执行命令
+GitHub Logo

+

执行完成后,命令行会给出提示
+GitHub Logo
+进入指定目录,cd /data/local/tmp 进入到目录,会看到生成的trace文件
+GitHub Logo

+ +
+ + + \ No newline at end of file diff --git a/host/ide/src/doc/quickstart_smartperf.html b/host/ide/src/doc/quickstart_smartperf.html new file mode 100644 index 0000000000000000000000000000000000000000..483594174e330e3f9dd8131d7a056de925a68e66 --- /dev/null +++ b/host/ide/src/doc/quickstart_smartperf.html @@ -0,0 +1,874 @@ + + + + 网页加载trace说明 + + + + + + +
+

网页加载trace说明

+ +

1.Web页面加载文件入口

+

将抓取的trace导入查看

+

GitHub Logo

+

说明:

+
    +
  • Open trace file:导入离线trace文件入口
  • +
  • Record new trace:抓取新的trace文件入口
  • +
+

2.导入文件后显示页面

+ +

GitHub Logo
+ 说明:

+
    +
  • 操作说明:在当前页面可以通过键盘上的wasd四个键位操纵当前的时间轴进行缩放,w放大,s为缩小,a为左移,d为右移。
  • +
+

trace功能介绍

+ +

trace 模块从上往下主要展示时间轴和cpu使用率、cpu使用情况、进程间通讯数据的方法调用情况、进程、线程和方法调用情况

+

1. 时间轴和cpu使用率

+ +

GitHub Logo
+ 最上方带刻度的为时间轴,主要展示当前抓取数据的总时长和时间刻度的分布情况,如上图所示,左下角展示总时长,
+ 中间区域展示的是抓取数据时间段内的cpu使用率,颜色越深代表cpu使用率越高,颜色越浅代表cpu使用率越低。
+ GitHub Logo
+ 在白色背景时间轴区域内可以点击后拖拽鼠标,可以对从鼠标按下到拖拽完成鼠标松开的区域内的数据进行筛选,高亮显示的部分为当前所选区域,如上图所示 +

+

2.cpu使用情况

+ +

GitHub Logo

+

如上图所示,当前抓取数据有4个cpu工作,前四组数据对应的是当前调用cpu的线程和对应的进程情况,以颜色作为区分。后四组数据则为cpu的使用频率信息。鼠标移动到相应的线程上还会将当前选中的进程信息全部置为高亮,其他的进程会置灰,如下图所示
+ GitHub Logo

+

2.1.cpu使用情况的框选功能

+ +

可以对cpu的数据进行框选,框选后在最下方的弹出层中会展示框选数据的统计表格,总共有七个tab页
+ CPU by thread的Tab页,主要显示了在框选时间区间内的进程名,进程号,线程名,线程号,总运行时长,平均运行时长和调度次数信息
+ GitHub Logo
+ CPU by process的Tab页,主要显示了在框选时间区间内的进程名,进程号,总运行时长,平均运行时长和调度次数信息
+ GitHub Logo
+ CPUUsage的Tab页,主要显示了在框选时间区间内,该频率时间占比前三的信息
+ GitHub Logo

+ States List的Tab页,按状态>进程>线程的维度去统计,需要呈现该状态的下线程名,进入该状态次数、该状态下时长、最大最小时长,平均时长、最大时长
+ GitHub Logo

+ Switches List的Tab页,按照进程>线程>状态、统计对应状态下的次数
+ GitHub Logo

+ Thread States的Tab页,按进程>线程>状态的维度去统计,需要呈现该状态的下线程名,进入该状态次数、该状态下时长、最小时长,平均时长、最大时长
+ GitHub Logo

+ Thread Switches的Tab页,按照状态>进程>线程、统计对应状态下的次数
+ GitHub Logo

+ States List,Switches List,Thread States,Thread Switches的4个Tab页,点击移动到某一行,鼠标会变成一个小手的标志,点击一下,就会进入辅助信息界面,会将选中行的辅助信息展示出来,包括开始时间,进程,线程,线程状态,对应的CPU,优先级等信息如下图
+ GitHub Logo

+ +

2.2.cpu使用情况的单选功能

+ +

单选CPU使用情况数据,单击方法会在选中的方法外层加上深色边框,能够突出当前选中色块,弹出层中会展示当前CPU上的进程名,线程名,开始时间和运行时长,线程运行状态等信息
+ GitHub Logo

+

3.FPS数据

+ +

FPS是帧率的显示,每秒产生画面的个数
+ GitHub Logo

+

3.1FPS的框选功能

+ +

可以对fps的数据进行框选,框选后在最下方的弹出层中会展示框选时间区间内的统计表格,主要显示了time(时间),FPS(帧率)
+ GitHub Logo

+

3.2.FPS的鼠标悬浮功能

+

鼠标移动到帧率的柱状图上,悬浮框会显示当前时间的FPS的值
+ GitHub Logo

+

4.进程,线程和方法数据

+ +

下图是进程数据,左边部分展示进程名称和id
+ GitHub Logo
+ 点击进程名前面向下箭头可以展开对应的线程进行查看,展开后的线程如下图,如果存在堆内存占用情况,就会显示在第一行,如果出现两个名字和id一样的线程,则第一个为线程的使用情况,第二为线程内的方法栈调用情况
+ GitHub Logo

+

+ 4.1进程,线程和方法数据的框选功能

+ +

可以对线程的数据进行框选,框选后在最下方的弹出层中会展示框选数据的统计表格,包含线程运行状态,线程调用栈的统计情况。当框选的数据中同时存在线程运行状态和线程调用栈数据,下方的弹出层中就会出现多个tab选项,可以进行切换

+

下图是线程运行状态框选统计信息,包括进程名,进程号,线程名,线程号,线程状态,状态持续时间,平均持续时间,该线程状态发生的次数
+ GitHub Logo

+

下图是线程调用栈框选统计信息,包括方法名,持续时间,平均持续时间,调用的次数
+ GitHub Logo

+

+ 4.2进程,线程和方法数据的单选功能

+ +

单选线程的state数据时,会展示当前选中线程的状态数据,开始时间和持续时长,线程状态,所在进程名称、
+ GitHub Logo
+ 单选调用栈数据,单击方法会在选中的方法外层加上黑色边框,能够突出当前选中的方法,弹出层中会展示当前方法的名称、开始时间和运行时长信息。
+ GitHub Logo

+ +

+ 4.3.线程的跳转功能

+

点击画红框处的带箭头的标志,会从CPU的线程概览视图跳转到线程的详情视图,同时从线程的详情视图也能跳转到CPU的线程概览视图
+ GitHub Logo
+

5.trace的其他功能

+

+ 5.1.小旗标志的功能

+

将选中数据的时间点通过小旗的方式在时间轴上展示,直观的展示选中数据的时间
+ GitHub Logo
+ 在下方输入空输入文字:我是trace,可以给小旗打备注
+ GitHub Logo
+

+ 5.2.收藏置顶功能

+

鼠标移动到某个页签,会出现星形的标志,点击该星形,可以将该行收藏置顶
+ GitHub Logo
+

+ 5.3.勾选功能

+

框选某一区域,该区域左边会出现CheckBox的复选框。选中的区域的复选框会出现打勾的状态。可以取消勾选,也可以重新勾选
+ GitHub Logo
+

+ 5.4.搜索功能

+

在搜索框中,可以输入线程,线程号等搜索自己想要的信息,搜索完成会高亮显示
+ GitHub Logo
+

在搜索框中输入调用栈的方法名,会跳转到对应的调用栈
+ GitHub Logo
+

+ 5.5.M键测量功能

+

放大trace中的色块,选中色块,键盘按下M,会出现像尺子一样的形状
+ GitHub Logo
+

+ + + + \ No newline at end of file diff --git a/host/ide/src/doc/quickstart_trace_streamer.html b/host/ide/src/doc/quickstart_trace_streamer.html new file mode 100644 index 0000000000000000000000000000000000000000..6c83f7d9d77c3a8d8e1c6bda90a0097bb8013abc --- /dev/null +++ b/host/ide/src/doc/quickstart_trace_streamer.html @@ -0,0 +1,898 @@ + + + + quickstart_trace_streamer + + + + + + +
+

trace_streamer工具说明

+

trace_streamer是一个trace数据流转化器,可以将一个trace文本文件或者基于proto序列化的二进制文件转换成为sqlite数据库的形式。 trace_streamer使用C++实现,支持在ohos, linux, mac等系统上使用,具有良好的跨平台特性。

+ GitHub Logo

+

+ 关于trace解析工具的使用说明:

+

trace_streamer工具可以2种方式使用

+
    +
  1. 可以将系统离线trace文件解析并转为db,此工具支持基于文本的trace和基于proto的trace。
  2. +
  3. trace_streamer工具还可以WebAssembly的方式在浏览器中运行,需暴露相关接口给js文件。
  4. +
+ +

+ 导出db模式

+ +

在导出db模式下,trace_streamer.exe trace文件路径名 -e 导出db路径名.db
+ 此命令可以将trace文件转为db
+ 本应用支持在ohos, linux, windows, mac使用。
+ 关于db文件的说明:
+ 使用db查看工具查看stat表,可以浏览当前数据一共有多少类数据,各类数据都收到多少条,数据是否正常等情况。在meta表会记录数据库导出时的一些系统信息,比如导入和导出的文件全路径,解析时间等信息。
+ meta表可以选择不导出(有些情况下会暴露系统敏感信息),在导出时添加 -nm选项即可。
+ 在数据导出之后,会在本地目录下生成一个trace_streamer.log文件,在导出db的目录下生成一个数据库文件同名,.db.ohos.ts后缀的文件
+ 文件内容如下:
+ 时间戳:执行结果(数字)
+ 应用运行时间

+

执行结果解释如下:0 代表执行成功 1 表示输入文件不匹配, 2 表示解析错误, 3其他错误

+

内置浏览器方式

+ +

trace_streamer可以WebAssembly方式在浏览器中运行,暴露如下接口给js

+
extern "C" {
+/* 上传trace数据
+ *
+ * @data: 数据的缓冲区
+ * @dataLen: 数据长度
+ *
+ * return: 0:成功; -1:失败
+*/
+EMSCRIPTEN_KEEPALIVE int TraceStreamerParseData(const uint8_t* data, int dataLen);
+
+/* 通知TS上传trace数据结束
+ *
+ * return: 0:成功; -1:失败
+*/
+EMSCRIPTEN_KEEPALIVE int TraceStreamerParseDataOver();
+
+/* 通过sql语句操作数据库
+ *
+ * @sql: sql语句
+ * @sqlLen: sql语句长度
+ *
+ * return: 0:成功; -1:失败
+*/
+EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlOperate(const uint8_t* sql, int sqlLen);
+
+/* 通过sql语句查询数据库
+ *
+ * @sql: sql语句
+ * @sqlLen: sql语句长度
+ * @out: 查询结果的缓冲区,查询结果为json
+ * @outLen: 缓冲区长度
+ *
+ * return: >0:查询成功,返回查询结果数据长度; -1:失败
+*/
+EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlQuery(const uint8_t* sql, int sqlLen, uint8_t* out, int outLen);
+
+} // extern "C"
+
+

+ 你也可以执行如下命令查看应用帮助

+ +

./trace_streamer --help
+ -i 选项可查看应用支持的事件源和具体的事件名列表 +

+

trace_streamer支持解析的事件列表

+

支持的事件列表参见<<SupportEventList.md>>

+

TraceStreamer重要概念介绍

+ +

1. 进程和线程标识符

+ +
 在通用操作系统中,进程号(pid/tgid)和线程号(tid)可能会被重复用于标识不同的进程或者线程。所以在trace数据源中,进程号(pid)和线程号(tid)也可能被重用。
+TraceStreamer在解析数据过程中,使用ipid(internal pid)唯一标识进程, itid(internal tid)唯一标识线程。
+

2. 计量器

+ +

用来记录系统中各种随时间连续变化的数值。例如: CPU的频率, 内存的使用量, 界面刷新频率。

+

举例

+ +

CPU频率:
+ GitHub Logo
+ 内存占用:
+ GitHub Logo

+

3. 过滤器

+ +

TraceStreamer设计过程中使用了流式处理的思想,数据从入口进入以后,就像进入一条河流,从上游流向下游,在河道中央有很多过滤器,每种过滤器会将流过的数据中自己关注的内容吸附捕捉到。最终,每个过滤器都拥有了大量同类型的数据,而且这些数据都是按时间序列排列的。TraceStreamer使用filterid来标识同一种用途的数据,可以方便在UI中绘制。
+ ![image][filterimageid]

+

Stat表设计

+ +

具体内容参见 des_stat

+

trace_streamer开发环境搭建和编译运行指引

+ +

本应用使用gn作为构建工具。

+

1、开发环境

+ +

ubuntu和mac使用vscode

+

对外部的依赖

+ +

本应用依赖与sqlite,protobuf(htrace解析部分依赖)

+

本应用同时依赖于src/protos目录下文件来生成相关pb.h,pb.cc文件

+

2.1、 编译linux和Mac版应用

+ +

在根目录下执行相关命令进行编译

+

2.2、 编译wasm

+ +

在根目录下执行相关命令进行编译

+

2.3、开始编译

+ +

具体方法可参考compile_trace_streamer

+ + +
+ + + \ No newline at end of file diff --git a/host/ide/src/doc/smaps.html b/host/ide/src/doc/smaps.html new file mode 100644 index 0000000000000000000000000000000000000000..30220c740ee608057ad227b0735b1170b3dc48b5 --- /dev/null +++ b/host/ide/src/doc/smaps.html @@ -0,0 +1,914 @@ + + + 进程smaps抓取和展示说明 + + + + + + +
+

进程smaps的抓取和展示说明

+ +

smaps展示了一个进程的内存消耗

+

1.smaps的抓取

+ +

1.1.smaps抓取配置参数

+ +

GitHub Logo
+配置项说明

+
    +
  • +
    Start VM Tracker Record:配置项的总开关
    +
    +
  • +
  • +
    Process:smaps的抓取只能选择单进程抓取
    +
    +
  • +
+

再点击Record setting,在output file path输入文件名hiprofiler_data_smaps.htrace,拖动滚动条设置buffer size大小是64M,抓取时长是50s
+GitHub Logo
+点击Trace command,就会根据上面的配置生成抓取命令,点击Record抓取,抓取过程中会显示抓取时长
+GitHub Logo

+

2.smaps展示说明

+ +

抓取结束后smaps的trace会自动加载展示
+GitHub Logo

+

界面布局介绍:smaps整体界面布局分为3个部分,其中

+
    +
  • +
    红色区域:泳道图
    +
    +
  • +
  • +
    绿色区域:详细信息
    +
    +
  • +
+

2.1.smaps泳道图展示

+ +

smaps泳道图展示当前时刻该进程的内存消耗
+GitHub Logo

+

2.2.smaps泳道图的框选功能

+ +

可以对泳道图进行框选,框选后在最下方的弹出层中会展示框选数据的统计表格,总共有两个个tab页
+VM Tracker Statistics的Tab页
+GitHub Logo

+
    +
  • +
    Type: 将抓取到的信息根据Type归类,分四类,Data,Text,Const,Other
    +
    +
  • +
  • +
    % of Res: 每行的Resident Size 占总Ressident Size的比例
    +
    +
  • +
  • +
    #Reg:统计的类型个数
    +
    +
  • +
  • +
    Path:虚拟内存块路径,类型中有多个则显示multiple
    +
    +
  • +
  • +
    Resident Size: smaps节点中Rss(Shared_Clean+Shared_Dirty+Private_Clean+Private_Dirty)
    +
    +
  • +
  • +
    Dirty Size:smaps节点中Shared_Dirty + Private_Dirty
    +
    +
  • +
  • +
    Swapped: smaps节点中Swap + SwapPss
    +
    +
  • +
  • +
    Virtual Size:smaps节点中Size
    +
    +
  • +
  • +
    Pss: smaps节点中Pss
    +
    +
  • +
  • +
    Res. %:Resident Size / Virtual Size 比值
    +
    +
  • +
+

VM Tracker Record List的Tab页
+GitHub Logo

+
    +
  • +
    Type: 将抓取到的信息根据Type归类,Data,Text,Const,Other
    +
    +
  • +
  • +
    Address Range: 每段虚拟内存段的开始和结束位置
    +
    +
  • +
  • +
    Dirty Size:smaps节点中Shared_Dirty + Private_Dirty
    +
    +
  • +
  • +
    Swapper: smaps节点中Swap + SwapPss
    +
    +
  • +
  • +
    Resident Size:smaps节点中Rss(Shared_Clean+Shared_Dirty+Private_Clean+Private_Dirty)
    +
    +
  • +
  • +
    Virtual Size:smaps节点中Size
    +
    +
  • +
  • +
    Pss:smaps节点中Pss
    +
    +
  • +
  • +
    Reside: Rss / Size 比值
    +
    +
  • +
  • +
    Protection: 内存块的权限(读写执行执行)
    +
    +
  • +
  • +
    Path: 内存段路径
    +
    +
  • +
+ +
+ + + + \ No newline at end of file diff --git a/host/ide/src/figures/AllocationType.jpg b/host/ide/src/figures/AllocationType.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b4372e720d7f3e0786603dfb0c7a535483e232eb Binary files /dev/null and b/host/ide/src/figures/AllocationType.jpg differ diff --git a/host/ide/src/figures/CallInfo.jpg b/host/ide/src/figures/CallInfo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..347a3106c492f364c24bab24a8996928c84ad853 Binary files /dev/null and b/host/ide/src/figures/CallInfo.jpg differ diff --git a/host/ide/src/figures/Generation.jpg b/host/ide/src/figures/Generation.jpg new file mode 100644 index 0000000000000000000000000000000000000000..91424c0d513ac85e677d0c114d3b8959f2f18520 Binary files /dev/null and b/host/ide/src/figures/Generation.jpg differ diff --git a/host/ide/src/figures/M.jpg b/host/ide/src/figures/M.jpg new file mode 100644 index 0000000000000000000000000000000000000000..574188a550e2fd585d5f596ac7076c9adc31fcf9 Binary files /dev/null and b/host/ide/src/figures/M.jpg differ diff --git a/host/ide/src/figures/NativeChart.jpg b/host/ide/src/figures/NativeChart.jpg new file mode 100644 index 0000000000000000000000000000000000000000..adac97a1428ad42bd8a040a4f4656a2b69346f46 Binary files /dev/null and b/host/ide/src/figures/NativeChart.jpg differ diff --git a/host/ide/src/figures/NativeMemory.jpg b/host/ide/src/figures/NativeMemory.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4790f80f37bb4e3b146da8a65c344f56f9d7934a Binary files /dev/null and b/host/ide/src/figures/NativeMemory.jpg differ diff --git a/host/ide/src/figures/Options.jpg b/host/ide/src/figures/Options.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8654b6e7a2c6a2d10904736ddb1d0c5293bb333d Binary files /dev/null and b/host/ide/src/figures/Options.jpg differ diff --git a/host/ide/src/figures/PerfProfile.jpg b/host/ide/src/figures/PerfProfile.jpg new file mode 100644 index 0000000000000000000000000000000000000000..45bdd9f91175b214be8afc79cdf930ecfa770968 Binary files /dev/null and b/host/ide/src/figures/PerfProfile.jpg differ diff --git a/host/ide/src/figures/ProcessesHistory.jpg b/host/ide/src/figures/ProcessesHistory.jpg new file mode 100644 index 0000000000000000000000000000000000000000..59ddc205b3b4ca3fa6ee13342c2e251494677896 Binary files /dev/null and b/host/ide/src/figures/ProcessesHistory.jpg differ diff --git a/host/ide/src/figures/Samplelist.jpg b/host/ide/src/figures/Samplelist.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f161a6c5a40405149ae296df339b43c154c2f81d Binary files /dev/null and b/host/ide/src/figures/Samplelist.jpg differ diff --git a/host/ide/src/figures/Scheduling.jpg b/host/ide/src/figures/Scheduling.jpg new file mode 100644 index 0000000000000000000000000000000000000000..35363847fee7908722083d874252022e6bd5c5d0 Binary files /dev/null and b/host/ide/src/figures/Scheduling.jpg differ diff --git a/host/ide/src/figures/Snapshotlist.jpg b/host/ide/src/figures/Snapshotlist.jpg new file mode 100644 index 0000000000000000000000000000000000000000..126208381afb6229ed169c1fb00ed81490e954c9 Binary files /dev/null and b/host/ide/src/figures/Snapshotlist.jpg differ diff --git a/host/ide/src/figures/StatesList.jpg b/host/ide/src/figures/StatesList.jpg new file mode 100644 index 0000000000000000000000000000000000000000..511000076ca1034ef6f286182d6d1ee8b529070f Binary files /dev/null and b/host/ide/src/figures/StatesList.jpg differ diff --git a/host/ide/src/figures/Statistics.jpg b/host/ide/src/figures/Statistics.jpg new file mode 100644 index 0000000000000000000000000000000000000000..466a3822cb995cc704323c89571e9dc5adf9d1ae Binary files /dev/null and b/host/ide/src/figures/Statistics.jpg differ diff --git a/host/ide/src/figures/Switchlist.jpg b/host/ide/src/figures/Switchlist.jpg new file mode 100644 index 0000000000000000000000000000000000000000..75e572346234b744ecb48286b896558c1635111c Binary files /dev/null and b/host/ide/src/figures/Switchlist.jpg differ diff --git a/host/ide/src/figures/abilitycommand.jpg b/host/ide/src/figures/abilitycommand.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5912fd7f6f697948d72ae56ab9c8a05f6f8d04d2 Binary files /dev/null and b/host/ide/src/figures/abilitycommand.jpg differ diff --git a/host/ide/src/figures/abilityexcutecommand.jpg b/host/ide/src/figures/abilityexcutecommand.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d9a4fe8ad1cb51d711cb6e681863f8bf81d12878 Binary files /dev/null and b/host/ide/src/figures/abilityexcutecommand.jpg differ diff --git a/host/ide/src/figures/abilityhtrace.jpg b/host/ide/src/figures/abilityhtrace.jpg new file mode 100644 index 0000000000000000000000000000000000000000..51ca07880e200c51453d22fc52120f3e9c1b02cd Binary files /dev/null and b/host/ide/src/figures/abilityhtrace.jpg differ diff --git a/host/ide/src/figures/abilitymonitorflowchart.jpg b/host/ide/src/figures/abilitymonitorflowchart.jpg new file mode 100644 index 0000000000000000000000000000000000000000..15c86a5b816003dbb850e203794d3ee8c7a0c2f7 Binary files /dev/null and b/host/ide/src/figures/abilitymonitorflowchart.jpg differ diff --git a/host/ide/src/figures/abilityset.jpg b/host/ide/src/figures/abilityset.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ebf4af23d4fb2ba8e838b4fa5f4d8527f5dcb43f Binary files /dev/null and b/host/ide/src/figures/abilityset.jpg differ diff --git a/host/ide/src/figures/abilitysetting.jpg b/host/ide/src/figures/abilitysetting.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6ab9c129818804c5d215e93ca78adb185f824171 Binary files /dev/null and b/host/ide/src/figures/abilitysetting.jpg differ diff --git a/host/ide/src/figures/bio/BioCalltree.jpg b/host/ide/src/figures/bio/BioCalltree.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ee3f25ddb028fbda43662b7baf976fc990407de8 Binary files /dev/null and b/host/ide/src/figures/bio/BioCalltree.jpg differ diff --git a/host/ide/src/figures/bio/BioOptions.jpg b/host/ide/src/figures/bio/BioOptions.jpg new file mode 100644 index 0000000000000000000000000000000000000000..80dd5a57e9f373cccf373c6b7fda9c3fc513ff15 Binary files /dev/null and b/host/ide/src/figures/bio/BioOptions.jpg differ diff --git a/host/ide/src/figures/bio/Biochart.jpg b/host/ide/src/figures/bio/Biochart.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b5451727c787f29b45ac8a4aad974b9062b30925 Binary files /dev/null and b/host/ide/src/figures/bio/Biochart.jpg differ diff --git a/host/ide/src/figures/bio/Biocounter.jpg b/host/ide/src/figures/bio/Biocounter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c2eedd02185175fe09cd6c180fc3af8777aeb283 Binary files /dev/null and b/host/ide/src/figures/bio/Biocounter.jpg differ diff --git a/host/ide/src/figures/bio/Biodatamining.jpg b/host/ide/src/figures/bio/Biodatamining.jpg new file mode 100644 index 0000000000000000000000000000000000000000..abc7a5dd5bc29966d066e8dacca88f0c6a974948 Binary files /dev/null and b/host/ide/src/figures/bio/Biodatamining.jpg differ diff --git a/host/ide/src/figures/bio/Bioexcuting.jpg b/host/ide/src/figures/bio/Bioexcuting.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fc5bb3891d86b03744d14d10940d406f7fc06a0d Binary files /dev/null and b/host/ide/src/figures/bio/Bioexcuting.jpg differ diff --git a/host/ide/src/figures/bio/Biofilter.jpg b/host/ide/src/figures/bio/Biofilter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..851944c928003870a4693ecae15d08c30c17c50c Binary files /dev/null and b/host/ide/src/figures/bio/Biofilter.jpg differ diff --git a/host/ide/src/figures/bio/Bioflame.jpg b/host/ide/src/figures/bio/Bioflame.jpg new file mode 100644 index 0000000000000000000000000000000000000000..592e6b343243a00ecdefc4aef63b7c6e5d5bc51b Binary files /dev/null and b/host/ide/src/figures/bio/Bioflame.jpg differ diff --git a/host/ide/src/figures/bio/Bioflamelevel.jpg b/host/ide/src/figures/bio/Bioflamelevel.jpg new file mode 100644 index 0000000000000000000000000000000000000000..78d2f14c2ca40f20a231c7dc060a667f08356914 Binary files /dev/null and b/host/ide/src/figures/bio/Bioflamelevel.jpg differ diff --git a/host/ide/src/figures/bio/Bioflameshow.jpg b/host/ide/src/figures/bio/Bioflameshow.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f7e8f9974ee4a6131e87f2164dde82009e2cf0a9 Binary files /dev/null and b/host/ide/src/figures/bio/Bioflameshow.jpg differ diff --git a/host/ide/src/figures/bio/Bioheaviesttrace.jpg b/host/ide/src/figures/bio/Bioheaviesttrace.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e76b66303697967022de21c22e4b7bad1f2e1c93 Binary files /dev/null and b/host/ide/src/figures/bio/Bioheaviesttrace.jpg differ diff --git a/host/ide/src/figures/bio/Bioinputfilter.jpg b/host/ide/src/figures/bio/Bioinputfilter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6d6e6b1a8b250e0eb01b5ba7882d2a0da8f00cc5 Binary files /dev/null and b/host/ide/src/figures/bio/Bioinputfilter.jpg differ diff --git a/host/ide/src/figures/bio/Biorecord.jpg b/host/ide/src/figures/bio/Biorecord.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d4aed0679233db239eb1b34cb06759d88d500399 Binary files /dev/null and b/host/ide/src/figures/bio/Biorecord.jpg differ diff --git a/host/ide/src/figures/bio/Biosetting.jpg b/host/ide/src/figures/bio/Biosetting.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6181cf4ac871a67bb7aa06601e8e7aaaabc061fb Binary files /dev/null and b/host/ide/src/figures/bio/Biosetting.jpg differ diff --git a/host/ide/src/figures/bio/Biostatistics.jpg b/host/ide/src/figures/bio/Biostatistics.jpg new file mode 100644 index 0000000000000000000000000000000000000000..259a9bc8f77c6db6f5516b57b60ed27915406ff5 Binary files /dev/null and b/host/ide/src/figures/bio/Biostatistics.jpg differ diff --git a/host/ide/src/figures/bio/Biosummary.jpg b/host/ide/src/figures/bio/Biosummary.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9d102cd8d03af610d7fa905664401df8334cb539 Binary files /dev/null and b/host/ide/src/figures/bio/Biosummary.jpg differ diff --git a/host/ide/src/figures/bio/Biotimes.jpg b/host/ide/src/figures/bio/Biotimes.jpg new file mode 100644 index 0000000000000000000000000000000000000000..60cd75aca70a6d55a66a26f9bd766fbefe7c6f33 Binary files /dev/null and b/host/ide/src/figures/bio/Biotimes.jpg differ diff --git a/host/ide/src/figures/callstack.jpg b/host/ide/src/figures/callstack.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fbcc33cf142a373fc381be32a1636b80096f7878 Binary files /dev/null and b/host/ide/src/figures/callstack.jpg differ diff --git a/host/ide/src/figures/callstackclick.jpg b/host/ide/src/figures/callstackclick.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bd9ed65526a34d967a1ac45b15aa8ecf96a0d1a4 Binary files /dev/null and b/host/ide/src/figures/callstackclick.jpg differ diff --git a/host/ide/src/figures/callstackselect.jpg b/host/ide/src/figures/callstackselect.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ccdbde9c618790875c1d1646f49504eca1f39583 Binary files /dev/null and b/host/ide/src/figures/callstackselect.jpg differ diff --git a/host/ide/src/figures/chart.jpg b/host/ide/src/figures/chart.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c17758ab78a2fd465bed0c13eeb84ad9e95fe588 Binary files /dev/null and b/host/ide/src/figures/chart.jpg differ diff --git a/host/ide/src/figures/checkbox.jpg b/host/ide/src/figures/checkbox.jpg new file mode 100644 index 0000000000000000000000000000000000000000..acbc9a40be5c054184bcbff8dba257b9d277e51d Binary files /dev/null and b/host/ide/src/figures/checkbox.jpg differ diff --git a/host/ide/src/figures/command.jpg b/host/ide/src/figures/command.jpg new file mode 100644 index 0000000000000000000000000000000000000000..08e4785d2f3bf00df27f06df3c0b973aa3af2d02 Binary files /dev/null and b/host/ide/src/figures/command.jpg differ diff --git a/host/ide/src/figures/commandend.jpg b/host/ide/src/figures/commandend.jpg new file mode 100644 index 0000000000000000000000000000000000000000..54996a8d125d988cce045a5411f716aec23a986e Binary files /dev/null and b/host/ide/src/figures/commandend.jpg differ diff --git a/host/ide/src/figures/cpu.jpg b/host/ide/src/figures/cpu.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f21a80d736774623f24a8f6a1472d5d7b4a2ad30 Binary files /dev/null and b/host/ide/src/figures/cpu.jpg differ diff --git a/host/ide/src/figures/cpu_frequency.png b/host/ide/src/figures/cpu_frequency.png new file mode 100644 index 0000000000000000000000000000000000000000..a18715fc696b3231b94425e4acd6aaf319bf399f Binary files /dev/null and b/host/ide/src/figures/cpu_frequency.png differ diff --git a/host/ide/src/figures/cpubyprocess.jpg b/host/ide/src/figures/cpubyprocess.jpg new file mode 100644 index 0000000000000000000000000000000000000000..470d4f3fdf5119773bc7b180d880a962d495b19d Binary files /dev/null and b/host/ide/src/figures/cpubyprocess.jpg differ diff --git a/host/ide/src/figures/cpubythread.jpg b/host/ide/src/figures/cpubythread.jpg new file mode 100644 index 0000000000000000000000000000000000000000..99c06e9d6fc87e390f33297623f519dc8fc37189 Binary files /dev/null and b/host/ide/src/figures/cpubythread.jpg differ diff --git a/host/ide/src/figures/cpuclick.jpg b/host/ide/src/figures/cpuclick.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f1a3c6d358474a1c649993cd673b66fade9871d6 Binary files /dev/null and b/host/ide/src/figures/cpuclick.jpg differ diff --git a/host/ide/src/figures/cpusage.jpg b/host/ide/src/figures/cpusage.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ecb696bb7f4bc7212999941c208daef0ff5abab5 Binary files /dev/null and b/host/ide/src/figures/cpusage.jpg differ diff --git a/host/ide/src/figures/cpusummary.jpg b/host/ide/src/figures/cpusummary.jpg new file mode 100644 index 0000000000000000000000000000000000000000..83b2fcac39d8e119c502275efed6a40af9c7f2c4 Binary files /dev/null and b/host/ide/src/figures/cpusummary.jpg differ diff --git a/host/ide/src/figures/datamining.jpg b/host/ide/src/figures/datamining.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bcc45679dba8ad79e227314b853a54d76f8ab3e2 Binary files /dev/null and b/host/ide/src/figures/datamining.jpg differ diff --git a/host/ide/src/figures/db_common.png b/host/ide/src/figures/db_common.png new file mode 100644 index 0000000000000000000000000000000000000000..29dbb080e1d213672b74d553610f6a24445663ad Binary files /dev/null and b/host/ide/src/figures/db_common.png differ diff --git a/host/ide/src/figures/db_hiperf.png b/host/ide/src/figures/db_hiperf.png new file mode 100644 index 0000000000000000000000000000000000000000..85cacf15a7153a0853c7aeee2fe34fba1f8983a8 Binary files /dev/null and b/host/ide/src/figures/db_hiperf.png differ diff --git a/host/ide/src/figures/db_hisys_event.png b/host/ide/src/figures/db_hisys_event.png new file mode 100644 index 0000000000000000000000000000000000000000..215265182de684f1b4a31fd7158309f8c7532053 Binary files /dev/null and b/host/ide/src/figures/db_hisys_event.png differ diff --git a/host/ide/src/figures/db_native_memory.png b/host/ide/src/figures/db_native_memory.png new file mode 100644 index 0000000000000000000000000000000000000000..0e1403e958fbf76f3d2c31fc6304426de6579afb Binary files /dev/null and b/host/ide/src/figures/db_native_memory.png differ diff --git a/host/ide/src/figures/details.jpg b/host/ide/src/figures/details.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9d9faf9dac54e6ec29953be33def7250e0eaa44b Binary files /dev/null and b/host/ide/src/figures/details.jpg differ diff --git a/host/ide/src/figures/disktab.jpg b/host/ide/src/figures/disktab.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4eaa9d89a260542ae24354db834b695b7b47971c Binary files /dev/null and b/host/ide/src/figures/disktab.jpg differ diff --git a/host/ide/src/figures/dump_and_mem.png b/host/ide/src/figures/dump_and_mem.png new file mode 100644 index 0000000000000000000000000000000000000000..2c3f59eef7476de91cafb8f59832c93fe4117e51 Binary files /dev/null and b/host/ide/src/figures/dump_and_mem.png differ diff --git a/host/ide/src/figures/excutecommand.jpg b/host/ide/src/figures/excutecommand.jpg new file mode 100644 index 0000000000000000000000000000000000000000..800db358d13c7144419e4620ae1a3a5e60f8d7e3 Binary files /dev/null and b/host/ide/src/figures/excutecommand.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemCalltree.jpg b/host/ide/src/figures/fileSystem/FileSystemCalltree.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6e7e2de008c1e5d6b670e9d6109292fc1a21e10e Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemCalltree.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemOptions.jpg b/host/ide/src/figures/fileSystem/FileSystemOptions.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b5ce7a6a6816502550c40d7e5237a8bd088233d0 Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemOptions.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemchart.jpg b/host/ide/src/figures/fileSystem/FileSystemchart.jpg new file mode 100644 index 0000000000000000000000000000000000000000..77ee172cf174350a55027c91ccc8f76b06596ad5 Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemchart.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemcommand.jpg b/host/ide/src/figures/fileSystem/FileSystemcommand.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4f8a671ee41b3205c84ae4d932f3e10a72edd888 Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemcommand.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemcount.jpg b/host/ide/src/figures/fileSystem/FileSystemcount.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6c049c9b564b301f5b28820bf748dc9831a29bb7 Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemcount.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemdatamining.jpg b/host/ide/src/figures/fileSystem/FileSystemdatamining.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dbcd816b0ac0db534f97f05d263e8aca4db12019 Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemdatamining.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemevents.jpg b/host/ide/src/figures/fileSystem/FileSystemevents.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5914209c0352e4cb950f361af79fa2395fe9508f Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemevents.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemexcutecommand.jpg b/host/ide/src/figures/fileSystem/FileSystemexcutecommand.jpg new file mode 100644 index 0000000000000000000000000000000000000000..abd178fdab114642fcde657a497dc97a3f0804ec Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemexcutecommand.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemfile.jpg b/host/ide/src/figures/fileSystem/FileSystemfile.jpg new file mode 100644 index 0000000000000000000000000000000000000000..536595781f01a39a41079c141439e0989bd6ca3b Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemfile.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemflame.jpg b/host/ide/src/figures/fileSystem/FileSystemflame.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d644c143e7a782d2a7e03708a589c2bc701d92d5 Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemflame.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemflamelevel.jpg b/host/ide/src/figures/fileSystem/FileSystemflamelevel.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2cff0eeb107da9e4155944eca57590011ed8b34e Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemflamelevel.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemflameshow.jpg b/host/ide/src/figures/fileSystem/FileSystemflameshow.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b03f7b31ca17606e26768406a0effab4a3ec5cee Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemflameshow.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemheaviesttrace.jpg b/host/ide/src/figures/fileSystem/FileSystemheaviesttrace.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2644870c90be8fcaa7a8ecc370a35faacdee2534 Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemheaviesttrace.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemhistory.jpg b/host/ide/src/figures/fileSystem/FileSystemhistory.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2cf792ddc44796d32114a4be2c4463c192a74b3e Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemhistory.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSysteminputfilter.jpg b/host/ide/src/figures/fileSystem/FileSysteminputfilter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ec0965db18378980c4f63be7a812a19ded10aaa9 Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSysteminputfilter.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemsamplecounter.jpg b/host/ide/src/figures/fileSystem/FileSystemsamplecounter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..666200868fce4b88495e1f3a95741ee84cf11ade Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemsamplecounter.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemstatistics.jpg b/host/ide/src/figures/fileSystem/FileSystemstatistics.jpg new file mode 100644 index 0000000000000000000000000000000000000000..86e2838c35e8c44dd740ce0c3847ab8aea873bac Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemstatistics.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemsummary.jpg b/host/ide/src/figures/fileSystem/FileSystemsummary.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b2e201cc6dca939ff309c5aca740bca190c07dd0 Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemsummary.jpg differ diff --git a/host/ide/src/figures/fileSystem/FileSystemtimeslice.jpg b/host/ide/src/figures/fileSystem/FileSystemtimeslice.jpg new file mode 100644 index 0000000000000000000000000000000000000000..570ada550e41b1850a01c55cc51444f2be922b2c Binary files /dev/null and b/host/ide/src/figures/fileSystem/FileSystemtimeslice.jpg differ diff --git a/host/ide/src/figures/fileSystem/filesystemfilter.jpg b/host/ide/src/figures/fileSystem/filesystemfilter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..39bffd42a0f6c667ad1aad05ee27b31c2782fa9b Binary files /dev/null and b/host/ide/src/figures/fileSystem/filesystemfilter.jpg differ diff --git a/host/ide/src/figures/fileSystem/filesystemrecord.jpg b/host/ide/src/figures/fileSystem/filesystemrecord.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f6130bb8c8c222bbd58b40d8a562575c07e1270e Binary files /dev/null and b/host/ide/src/figures/fileSystem/filesystemrecord.jpg differ diff --git a/host/ide/src/figures/fileSystem/filesystemsetting.jpg b/host/ide/src/figures/fileSystem/filesystemsetting.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3c5e3cee77c95c51159905045c6a2dd9a290e2d9 Binary files /dev/null and b/host/ide/src/figures/fileSystem/filesystemsetting.jpg differ diff --git a/host/ide/src/figures/filters.png b/host/ide/src/figures/filters.png new file mode 100644 index 0000000000000000000000000000000000000000..a02d9416f08382ff7a03e176e37e6479f5922c08 Binary files /dev/null and b/host/ide/src/figures/filters.png differ diff --git a/host/ide/src/figures/flag.jpg b/host/ide/src/figures/flag.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8720740c3256c2b64be4411809d9fa87d1ba0100 Binary files /dev/null and b/host/ide/src/figures/flag.jpg differ diff --git a/host/ide/src/figures/flaginput.jpg b/host/ide/src/figures/flaginput.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bc0b554ebb7569a2c65424c1025c7115b3f1c77d Binary files /dev/null and b/host/ide/src/figures/flaginput.jpg differ diff --git a/host/ide/src/figures/flame.jpg b/host/ide/src/figures/flame.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a188dcef2e8d44d2819f25e7c3599298900d7080 Binary files /dev/null and b/host/ide/src/figures/flame.jpg differ diff --git a/host/ide/src/figures/flamelevel2.jpg b/host/ide/src/figures/flamelevel2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..93b379960a2f0f01da97eef1e2aeeb2f7e1cd60c Binary files /dev/null and b/host/ide/src/figures/flamelevel2.jpg differ diff --git a/host/ide/src/figures/flameshow.jpg b/host/ide/src/figures/flameshow.jpg new file mode 100644 index 0000000000000000000000000000000000000000..618a552a8a43811c92979d512c647ffc9915f331 Binary files /dev/null and b/host/ide/src/figures/flameshow.jpg differ diff --git a/host/ide/src/figures/fps.jpg b/host/ide/src/figures/fps.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bfc18dfe881b738f6e9b100e4e32d5ab04dcb383 Binary files /dev/null and b/host/ide/src/figures/fps.jpg differ diff --git a/host/ide/src/figures/fpsselect.jpg b/host/ide/src/figures/fpsselect.jpg new file mode 100644 index 0000000000000000000000000000000000000000..14300f78ce384f8ad0366657e3b0eed2177e7505 Binary files /dev/null and b/host/ide/src/figures/fpsselect.jpg differ diff --git a/host/ide/src/figures/fpstip.jpg b/host/ide/src/figures/fpstip.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7b5954226117c9ffd08fb2a974214006180a8160 Binary files /dev/null and b/host/ide/src/figures/fpstip.jpg differ diff --git a/host/ide/src/figures/gray.jpg b/host/ide/src/figures/gray.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9bdb38037a286ea531485e6445553ea61f6d2e04 Binary files /dev/null and b/host/ide/src/figures/gray.jpg differ diff --git a/host/ide/src/figures/hdc/Device.jpg b/host/ide/src/figures/hdc/Device.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fbb598d131fdedd5584ef9ab42194ffb50d57dfb Binary files /dev/null and b/host/ide/src/figures/hdc/Device.jpg differ diff --git a/host/ide/src/figures/hdc/Schedulingdetails.jpg b/host/ide/src/figures/hdc/Schedulingdetails.jpg new file mode 100644 index 0000000000000000000000000000000000000000..78d9982358133090369cf40e13d11be62622173f Binary files /dev/null and b/host/ide/src/figures/hdc/Schedulingdetails.jpg differ diff --git a/host/ide/src/figures/hdc/bytacedescription.jpg b/host/ide/src/figures/hdc/bytacedescription.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3fa24ba1a434f70254294685e6b600e6518e4773 Binary files /dev/null and b/host/ide/src/figures/hdc/bytacedescription.jpg differ diff --git a/host/ide/src/figures/hdc/examplerecord.jpg b/host/ide/src/figures/hdc/examplerecord.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a3c3ca0a2e4db30149365d7d89f1cf886a0c8d35 Binary files /dev/null and b/host/ide/src/figures/hdc/examplerecord.jpg differ diff --git a/host/ide/src/figures/hdc/hdc.jpg b/host/ide/src/figures/hdc/hdc.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bf8c0e8bfd2ac208214203dd972f3b3821b06d5d Binary files /dev/null and b/host/ide/src/figures/hdc/hdc.jpg differ diff --git a/host/ide/src/figures/hdc/hdcfile.jpg b/host/ide/src/figures/hdc/hdcfile.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d5d56f9abdab6f8ce697daaf82a8c0449f909c82 Binary files /dev/null and b/host/ide/src/figures/hdc/hdcfile.jpg differ diff --git a/host/ide/src/figures/hdc/hdctracing.jpg b/host/ide/src/figures/hdc/hdctracing.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b24d5676213df9dba062bb2be7998296fca28562 Binary files /dev/null and b/host/ide/src/figures/hdc/hdctracing.jpg differ diff --git a/host/ide/src/figures/hdc/record.jpg b/host/ide/src/figures/hdc/record.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bf472ca30f4f8cb33038316f35be692e05eee34d Binary files /dev/null and b/host/ide/src/figures/hdc/record.jpg differ diff --git a/host/ide/src/figures/hdc/timesetting.jpg b/host/ide/src/figures/hdc/timesetting.jpg new file mode 100644 index 0000000000000000000000000000000000000000..52a1c5afc900054901b8c69d3e1a939d887a21c4 Binary files /dev/null and b/host/ide/src/figures/hdc/timesetting.jpg differ diff --git a/host/ide/src/figures/heaviesttrace1.jpg b/host/ide/src/figures/heaviesttrace1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..32c214c66ccf6e385c4cf64da6f862aad05a3864 Binary files /dev/null and b/host/ide/src/figures/heaviesttrace1.jpg differ diff --git a/host/ide/src/figures/hiSystemEvent/hisyseventPowerBattery.jpg b/host/ide/src/figures/hiSystemEvent/hisyseventPowerBattery.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b38ed1956188e99d96eaa35c414ba04d66ebd843 Binary files /dev/null and b/host/ide/src/figures/hiSystemEvent/hisyseventPowerBattery.jpg differ diff --git a/host/ide/src/figures/hiSystemEvent/hisyseventPowerdetails.jpg b/host/ide/src/figures/hiSystemEvent/hisyseventPowerdetails.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ce1e9af717655d732a90fe086f04a9734e1e7cbf Binary files /dev/null and b/host/ide/src/figures/hiSystemEvent/hisyseventPowerdetails.jpg differ diff --git a/host/ide/src/figures/hiSystemEvent/hisyseventsetting.jpg b/host/ide/src/figures/hiSystemEvent/hisyseventsetting.jpg new file mode 100644 index 0000000000000000000000000000000000000000..20d75c8776e91be32f5013cbcb27085d2995b3b2 Binary files /dev/null and b/host/ide/src/figures/hiSystemEvent/hisyseventsetting.jpg differ diff --git a/host/ide/src/figures/hiSystemEvent/hisystemcommand.jpg b/host/ide/src/figures/hiSystemEvent/hisystemcommand.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a213fb514968fc44ec993d6af4c5a15712d59141 Binary files /dev/null and b/host/ide/src/figures/hiSystemEvent/hisystemcommand.jpg differ diff --git a/host/ide/src/figures/hiSystemEvent/hisystemdetails.jpg b/host/ide/src/figures/hiSystemEvent/hisystemdetails.jpg new file mode 100644 index 0000000000000000000000000000000000000000..92e88f53834cf64559ad1841ac7f797574e5b114 Binary files /dev/null and b/host/ide/src/figures/hiSystemEvent/hisystemdetails.jpg differ diff --git a/host/ide/src/figures/hiSystemEvent/hisystemeventemexcutecommand.jpg b/host/ide/src/figures/hiSystemEvent/hisystemeventemexcutecommand.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ecbb7e70783c4d22be242e45bfb881ac45b75dba Binary files /dev/null and b/host/ide/src/figures/hiSystemEvent/hisystemeventemexcutecommand.jpg differ diff --git a/host/ide/src/figures/hiSystemEvent/hisystemeventfile.jpg b/host/ide/src/figures/hiSystemEvent/hisystemeventfile.jpg new file mode 100644 index 0000000000000000000000000000000000000000..df88e858a69ecf2e4a9a9f3f85bd8c71c0f750a3 Binary files /dev/null and b/host/ide/src/figures/hiSystemEvent/hisystemeventfile.jpg differ diff --git a/host/ide/src/figures/hiSystemEvent/hisystemeventrecord.jpg b/host/ide/src/figures/hiSystemEvent/hisystemeventrecord.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8ef5587d40bf09e2325f5d696cd9761380ca21e5 Binary files /dev/null and b/host/ide/src/figures/hiSystemEvent/hisystemeventrecord.jpg differ diff --git a/host/ide/src/figures/hiSystemEvent/hisystemeventsummary.jpg b/host/ide/src/figures/hiSystemEvent/hisystemeventsummary.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ce9654a92bd2e8564023b4fdeea4c711ec3e976c Binary files /dev/null and b/host/ide/src/figures/hiSystemEvent/hisystemeventsummary.jpg differ diff --git a/host/ide/src/figures/hiSystemEvent/systemselectdetals.jpg b/host/ide/src/figures/hiSystemEvent/systemselectdetals.jpg new file mode 100644 index 0000000000000000000000000000000000000000..65fee85ce45ea6ebcfbd57bdd2e2b5001ad73365 Binary files /dev/null and b/host/ide/src/figures/hiSystemEvent/systemselectdetals.jpg differ diff --git a/host/ide/src/figures/highlit.jpg b/host/ide/src/figures/highlit.jpg new file mode 100644 index 0000000000000000000000000000000000000000..24278fdc9e13fa79efcac8b8355f5d94919a01a7 Binary files /dev/null and b/host/ide/src/figures/highlit.jpg differ diff --git a/host/ide/src/figures/hiprofiler_plggins.jpg b/host/ide/src/figures/hiprofiler_plggins.jpg new file mode 100644 index 0000000000000000000000000000000000000000..026e2e665ef7f385bb89997381f714fa5400a698 Binary files /dev/null and b/host/ide/src/figures/hiprofiler_plggins.jpg differ diff --git a/host/ide/src/figures/hiprofilerd.jpg b/host/ide/src/figures/hiprofilerd.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d67f1a118dc151533f1b7047f821aa270508f5dc Binary files /dev/null and b/host/ide/src/figures/hiprofilerd.jpg differ diff --git a/host/ide/src/figures/hook_file.jpg b/host/ide/src/figures/hook_file.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d25aff2adaf908102c5b97c6d3a70bb3515e74df Binary files /dev/null and b/host/ide/src/figures/hook_file.jpg differ diff --git a/host/ide/src/figures/htrace.jpg b/host/ide/src/figures/htrace.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ed4d99923ec33d120db0e96b27bc4b772097eafe Binary files /dev/null and b/host/ide/src/figures/htrace.jpg differ diff --git a/host/ide/src/figures/inputfilter.jpg b/host/ide/src/figures/inputfilter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0beea5695a229a7527812634aaefdd2316074331 Binary files /dev/null and b/host/ide/src/figures/inputfilter.jpg differ diff --git a/host/ide/src/figures/jumpthread.jpg b/host/ide/src/figures/jumpthread.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bdb494ed810dab30cfd998718c08d6b891dd09db Binary files /dev/null and b/host/ide/src/figures/jumpthread.jpg differ diff --git a/host/ide/src/figures/lifespan.jpg b/host/ide/src/figures/lifespan.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f1976a4d15ea68334eff34cf60c21ffb9211c691 Binary files /dev/null and b/host/ide/src/figures/lifespan.jpg differ diff --git a/host/ide/src/figures/liveprocess.jpg b/host/ide/src/figures/liveprocess.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2088ba7ab29c07f105ed62df4a6226244326f34d Binary files /dev/null and b/host/ide/src/figures/liveprocess.jpg differ diff --git a/host/ide/src/figures/log.png b/host/ide/src/figures/log.png new file mode 100644 index 0000000000000000000000000000000000000000..0c9ac304183f2276454caeb2fea593a5e88bdc13 Binary files /dev/null and b/host/ide/src/figures/log.png differ diff --git a/host/ide/src/figures/main.jpg b/host/ide/src/figures/main.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5209395cb5c65c857a192b7e0ec768cd2170181e Binary files /dev/null and b/host/ide/src/figures/main.jpg differ diff --git a/host/ide/src/figures/mem_usage.png b/host/ide/src/figures/mem_usage.png new file mode 100644 index 0000000000000000000000000000000000000000..f4ebd6e272c424d6861e2e8150c72c1f4de9802a Binary files /dev/null and b/host/ide/src/figures/mem_usage.png differ diff --git a/host/ide/src/figures/memoryFetching/EBPFchart.jpg b/host/ide/src/figures/memoryFetching/EBPFchart.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6f19739e32b7cc583fdc46694aabc062db90b86d Binary files /dev/null and b/host/ide/src/figures/memoryFetching/EBPFchart.jpg differ diff --git a/host/ide/src/figures/memoryFetching/EBPFcount.jpg b/host/ide/src/figures/memoryFetching/EBPFcount.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d6ae10d0329df5da0d8f6bef8fda3416b5843036 Binary files /dev/null and b/host/ide/src/figures/memoryFetching/EBPFcount.jpg differ diff --git a/host/ide/src/figures/memoryFetching/VMCalltree.jpg b/host/ide/src/figures/memoryFetching/VMCalltree.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e8cc24bb1dbe1344c2bebed940d59267cd7a1318 Binary files /dev/null and b/host/ide/src/figures/memoryFetching/VMCalltree.jpg differ diff --git a/host/ide/src/figures/memoryFetching/VMEvents.jpg b/host/ide/src/figures/memoryFetching/VMEvents.jpg new file mode 100644 index 0000000000000000000000000000000000000000..67e9995426c8e2983de24e21fd9785e9713e1125 Binary files /dev/null and b/host/ide/src/figures/memoryFetching/VMEvents.jpg differ diff --git a/host/ide/src/figures/memoryFetching/VMfilter.jpg b/host/ide/src/figures/memoryFetching/VMfilter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fb29b5d8c8ca9a6202d96f8f5febf5bf45cd7514 Binary files /dev/null and b/host/ide/src/figures/memoryFetching/VMfilter.jpg differ diff --git a/host/ide/src/figures/memoryFetching/ebpf_bythread.jpg b/host/ide/src/figures/memoryFetching/ebpf_bythread.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eb5bf673a8d9d5244b1f1f61fd04ad9db21e66fc Binary files /dev/null and b/host/ide/src/figures/memoryFetching/ebpf_bythread.jpg differ diff --git a/host/ide/src/figures/memoryFetching/ebpfcommand.jpg b/host/ide/src/figures/memoryFetching/ebpfcommand.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2af7869dba909de20ea57959bddce15a53f3d572 Binary files /dev/null and b/host/ide/src/figures/memoryFetching/ebpfcommand.jpg differ diff --git a/host/ide/src/figures/memoryFetching/ebpfexcuting.jpg b/host/ide/src/figures/memoryFetching/ebpfexcuting.jpg new file mode 100644 index 0000000000000000000000000000000000000000..54b3afd3e2410f60df2c2bd79490d7bc88a902f8 Binary files /dev/null and b/host/ide/src/figures/memoryFetching/ebpfexcuting.jpg differ diff --git a/host/ide/src/figures/memoryFetching/ebpfrecord.jpg b/host/ide/src/figures/memoryFetching/ebpfrecord.jpg new file mode 100644 index 0000000000000000000000000000000000000000..706f7b8271eb363eeb2c93cc2be677176a21b32e Binary files /dev/null and b/host/ide/src/figures/memoryFetching/ebpfrecord.jpg differ diff --git a/host/ide/src/figures/memoryFetching/ebpfsetting.jpg b/host/ide/src/figures/memoryFetching/ebpfsetting.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e3f294f4274a2f97580eee974791434d42ecc4c1 Binary files /dev/null and b/host/ide/src/figures/memoryFetching/ebpfsetting.jpg differ diff --git a/host/ide/src/figures/memoryFetching/ebpfsummary.jpg b/host/ide/src/figures/memoryFetching/ebpfsummary.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5f08df19a4ea33c2c872ec616e9b810f296aa908 Binary files /dev/null and b/host/ide/src/figures/memoryFetching/ebpfsummary.jpg differ diff --git a/host/ide/src/figures/memoryFetching/vmOptions.jpg b/host/ide/src/figures/memoryFetching/vmOptions.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d6a38ba30aae5988f2c6c88ed784148a18515e8d Binary files /dev/null and b/host/ide/src/figures/memoryFetching/vmOptions.jpg differ diff --git a/host/ide/src/figures/memoryFetching/vmcounter.jpg b/host/ide/src/figures/memoryFetching/vmcounter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cfe3852d8b39c2d432fed6cb90dffdb06c36d570 Binary files /dev/null and b/host/ide/src/figures/memoryFetching/vmcounter.jpg differ diff --git a/host/ide/src/figures/memoryFetching/vmdatamining.jpg b/host/ide/src/figures/memoryFetching/vmdatamining.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4f732ce0053611e92124194095a89865df55e1e1 Binary files /dev/null and b/host/ide/src/figures/memoryFetching/vmdatamining.jpg differ diff --git a/host/ide/src/figures/memoryFetching/vmflame.jpg b/host/ide/src/figures/memoryFetching/vmflame.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6cb5ddeb7f91adc8113281e5042df9ab4722c965 Binary files /dev/null and b/host/ide/src/figures/memoryFetching/vmflame.jpg differ diff --git a/host/ide/src/figures/memoryFetching/vmflamelevel.jpg b/host/ide/src/figures/memoryFetching/vmflamelevel.jpg new file mode 100644 index 0000000000000000000000000000000000000000..37b9b4f64420deeca9f587483e8ff4efffa5dd0f Binary files /dev/null and b/host/ide/src/figures/memoryFetching/vmflamelevel.jpg differ diff --git a/host/ide/src/figures/memoryFetching/vmflameshow.jpg b/host/ide/src/figures/memoryFetching/vmflameshow.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a9cef6d91b3affcc951cbe090c5476e7c364aa6a Binary files /dev/null and b/host/ide/src/figures/memoryFetching/vmflameshow.jpg differ diff --git a/host/ide/src/figures/memoryFetching/vmheaviesttrace.jpg b/host/ide/src/figures/memoryFetching/vmheaviesttrace.jpg new file mode 100644 index 0000000000000000000000000000000000000000..686e2cea8757ab625739bf0248634f8b443c8e90 Binary files /dev/null and b/host/ide/src/figures/memoryFetching/vmheaviesttrace.jpg differ diff --git a/host/ide/src/figures/memoryFetching/vminputfilter.jpg b/host/ide/src/figures/memoryFetching/vminputfilter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a72512b81d455b732e61e4f551b1c68c11bc1020 Binary files /dev/null and b/host/ide/src/figures/memoryFetching/vminputfilter.jpg differ diff --git a/host/ide/src/figures/memoryFetching/vmstatistics.jpg b/host/ide/src/figures/memoryFetching/vmstatistics.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e316dd2623fd8dccf61f956a9006ba8768ef8253 Binary files /dev/null and b/host/ide/src/figures/memoryFetching/vmstatistics.jpg differ diff --git a/host/ide/src/figures/memorytab.jpg b/host/ide/src/figures/memorytab.jpg new file mode 100644 index 0000000000000000000000000000000000000000..76849b0b19d38d67efb563ac7fb04c5fc6e8b487 Binary files /dev/null and b/host/ide/src/figures/memorytab.jpg differ diff --git a/host/ide/src/figures/metrics/Sql.jpg b/host/ide/src/figures/metrics/Sql.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ecbea173d79c563dcd104e77b08cc1b7863ca214 Binary files /dev/null and b/host/ide/src/figures/metrics/Sql.jpg differ diff --git a/host/ide/src/figures/metrics/download.jpg b/host/ide/src/figures/metrics/download.jpg new file mode 100644 index 0000000000000000000000000000000000000000..227a292968d3ddefe6ac0252a620ec36e179d2cd Binary files /dev/null and b/host/ide/src/figures/metrics/download.jpg differ diff --git a/host/ide/src/figures/metrics/infoandstats.jpg b/host/ide/src/figures/metrics/infoandstats.jpg new file mode 100644 index 0000000000000000000000000000000000000000..79d8be3e5c48ff7070d45a99b7875390ce6edbd5 Binary files /dev/null and b/host/ide/src/figures/metrics/infoandstats.jpg differ diff --git a/host/ide/src/figures/metrics/metrics.jpg b/host/ide/src/figures/metrics/metrics.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d00a8999fe7c9790bf9e3d4c55ee6d05bd3f7568 Binary files /dev/null and b/host/ide/src/figures/metrics/metrics.jpg differ diff --git a/host/ide/src/figures/naitve_daemon.jpg b/host/ide/src/figures/naitve_daemon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..faa71b5f213d4fd546cfc85932906a77842b014d Binary files /dev/null and b/host/ide/src/figures/naitve_daemon.jpg differ diff --git a/host/ide/src/figures/naitvememoryfile.jpg b/host/ide/src/figures/naitvememoryfile.jpg new file mode 100644 index 0000000000000000000000000000000000000000..009480032a1bf861fadefe7a84ab7d00a7fa133a Binary files /dev/null and b/host/ide/src/figures/naitvememoryfile.jpg differ diff --git a/host/ide/src/figures/nativecallstack.jpg b/host/ide/src/figures/nativecallstack.jpg new file mode 100644 index 0000000000000000000000000000000000000000..18714303c76bb94aabb7d5a94ab95e15999152cf Binary files /dev/null and b/host/ide/src/figures/nativecallstack.jpg differ diff --git a/host/ide/src/figures/nativedaemon.jpg b/host/ide/src/figures/nativedaemon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e0dee8ee304996fed849d3c30463d9feea8d680b Binary files /dev/null and b/host/ide/src/figures/nativedaemon.jpg differ diff --git a/host/ide/src/figures/nativedemoncommand.jpg b/host/ide/src/figures/nativedemoncommand.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ad08b3b25fb0beefc81bed711bd8a4371916177f Binary files /dev/null and b/host/ide/src/figures/nativedemoncommand.jpg differ diff --git a/host/ide/src/figures/nativeexcutecommand.jpg b/host/ide/src/figures/nativeexcutecommand.jpg new file mode 100644 index 0000000000000000000000000000000000000000..24347f52d666aca9a0c529dff413c0dea8e9dbda Binary files /dev/null and b/host/ide/src/figures/nativeexcutecommand.jpg differ diff --git a/host/ide/src/figures/nativeflame.jpg b/host/ide/src/figures/nativeflame.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fdf303d888566eb899e2705bee52f6024530c855 Binary files /dev/null and b/host/ide/src/figures/nativeflame.jpg differ diff --git a/host/ide/src/figures/nativeflamelevel2.jpg b/host/ide/src/figures/nativeflamelevel2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..91cfecc809aa9ef66c088c7df2b635686783f20f Binary files /dev/null and b/host/ide/src/figures/nativeflamelevel2.jpg differ diff --git a/host/ide/src/figures/nativeflameshow.jpg b/host/ide/src/figures/nativeflameshow.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8e4c88206c6213ac4934f9f38f4de381ef3dddb1 Binary files /dev/null and b/host/ide/src/figures/nativeflameshow.jpg differ diff --git a/host/ide/src/figures/nativememorycommand.jpg b/host/ide/src/figures/nativememorycommand.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2e3cf45f0eecbd1379347b5ae38992e51984717d Binary files /dev/null and b/host/ide/src/figures/nativememorycommand.jpg differ diff --git a/host/ide/src/figures/nativememoryset.jpg b/host/ide/src/figures/nativememoryset.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d83c09a162628e73df3fdeba1d1f57cbdbd30b15 Binary files /dev/null and b/host/ide/src/figures/nativememoryset.jpg differ diff --git a/host/ide/src/figures/nativememorysetting.jpg b/host/ide/src/figures/nativememorysetting.jpg new file mode 100644 index 0000000000000000000000000000000000000000..58e57914b335c0fa28d7847ca6832127b25f9e38 Binary files /dev/null and b/host/ide/src/figures/nativememorysetting.jpg differ diff --git a/host/ide/src/figures/network.jpg b/host/ide/src/figures/network.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a928cf3ad96b3d0701dbe79013d48792b360f172 Binary files /dev/null and b/host/ide/src/figures/network.jpg differ diff --git a/host/ide/src/figures/opentrace.jpg b/host/ide/src/figures/opentrace.jpg new file mode 100644 index 0000000000000000000000000000000000000000..61174c198941064d6a9c305ca1a11ab479a53731 Binary files /dev/null and b/host/ide/src/figures/opentrace.jpg differ diff --git a/host/ide/src/figures/perf.png b/host/ide/src/figures/perf.png new file mode 100644 index 0000000000000000000000000000000000000000..9fc88ad255cece0040093392329e639e261c8bd9 Binary files /dev/null and b/host/ide/src/figures/perf.png differ diff --git a/host/ide/src/figures/perfcommand.jpg b/host/ide/src/figures/perfcommand.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7799c9f859eb8dea9f08ec03e6e3aee0005f1799 Binary files /dev/null and b/host/ide/src/figures/perfcommand.jpg differ diff --git a/host/ide/src/figures/perfexcutecommand.jpg b/host/ide/src/figures/perfexcutecommand.jpg new file mode 100644 index 0000000000000000000000000000000000000000..43c0361a2e363c8e645671cf525e005cc32d9f18 Binary files /dev/null and b/host/ide/src/figures/perfexcutecommand.jpg differ diff --git a/host/ide/src/figures/perffile.jpg b/host/ide/src/figures/perffile.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1e4b200913b1d0cad24ec5aab6b9535099686f66 Binary files /dev/null and b/host/ide/src/figures/perffile.jpg differ diff --git a/host/ide/src/figures/perfset.jpg b/host/ide/src/figures/perfset.jpg new file mode 100644 index 0000000000000000000000000000000000000000..63b6fa35d7381690ac035c3ea80db6e103351a43 Binary files /dev/null and b/host/ide/src/figures/perfset.jpg differ diff --git a/host/ide/src/figures/perfsetting.jpg b/host/ide/src/figures/perfsetting.jpg new file mode 100644 index 0000000000000000000000000000000000000000..883aaa90e162c4a03ece07830eab612f41c06fa7 Binary files /dev/null and b/host/ide/src/figures/perfsetting.jpg differ diff --git a/host/ide/src/figures/process.jpg b/host/ide/src/figures/process.jpg new file mode 100644 index 0000000000000000000000000000000000000000..62cad6b1f899e3be5abc1e17764a7aba6fca4a39 Binary files /dev/null and b/host/ide/src/figures/process.jpg differ diff --git a/host/ide/src/figures/process_thread.png b/host/ide/src/figures/process_thread.png new file mode 100644 index 0000000000000000000000000000000000000000..305a9bdb02d7776f086f8f13d5f6f72e72443226 Binary files /dev/null and b/host/ide/src/figures/process_thread.png differ diff --git a/host/ide/src/figures/psef.jpg b/host/ide/src/figures/psef.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1b5430ee308d344f043c95e7b9afd00a7faf4e33 Binary files /dev/null and b/host/ide/src/figures/psef.jpg differ diff --git a/host/ide/src/figures/samplecounter.jpg b/host/ide/src/figures/samplecounter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..943082f24cf9bf0ad3e452ce46bef906b53bbae6 Binary files /dev/null and b/host/ide/src/figures/samplecounter.jpg differ diff --git a/host/ide/src/figures/search.jpg b/host/ide/src/figures/search.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9e5900ec03c7cc688c2f150775db3a0b11028e71 Binary files /dev/null and b/host/ide/src/figures/search.jpg differ diff --git a/host/ide/src/figures/searchcallstack.jpg b/host/ide/src/figures/searchcallstack.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2dbd4cf5a838980b641df9a4e9c2871fd73034d8 Binary files /dev/null and b/host/ide/src/figures/searchcallstack.jpg differ diff --git a/host/ide/src/figures/smaps/smapschart.jpg b/host/ide/src/figures/smaps/smapschart.jpg new file mode 100644 index 0000000000000000000000000000000000000000..032d543261f85121367fa3f7e260e688b018d815 Binary files /dev/null and b/host/ide/src/figures/smaps/smapschart.jpg differ diff --git a/host/ide/src/figures/smaps/smapsexcuting.jpg b/host/ide/src/figures/smaps/smapsexcuting.jpg new file mode 100644 index 0000000000000000000000000000000000000000..53f86e1472c53801d7d3637ffadae6d493233921 Binary files /dev/null and b/host/ide/src/figures/smaps/smapsexcuting.jpg differ diff --git a/host/ide/src/figures/smaps/smapslist.jpg b/host/ide/src/figures/smaps/smapslist.jpg new file mode 100644 index 0000000000000000000000000000000000000000..598f6a1289980ead2857757d8d7ff513d5a022d9 Binary files /dev/null and b/host/ide/src/figures/smaps/smapslist.jpg differ diff --git a/host/ide/src/figures/smaps/smapsrecord.jpg b/host/ide/src/figures/smaps/smapsrecord.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9380722264bf06e22a1b1231e97eca0f06a0db1f Binary files /dev/null and b/host/ide/src/figures/smaps/smapsrecord.jpg differ diff --git a/host/ide/src/figures/smaps/smapssetting.jpg b/host/ide/src/figures/smaps/smapssetting.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d6d23c4133e2a33662913c931485f0fe2d4fb143 Binary files /dev/null and b/host/ide/src/figures/smaps/smapssetting.jpg differ diff --git a/host/ide/src/figures/smaps/smapsstatistics.jpg b/host/ide/src/figures/smaps/smapsstatistics.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4af1ef5ad619eeb8a0ed024286c868421118c428 Binary files /dev/null and b/host/ide/src/figures/smaps/smapsstatistics.jpg differ diff --git a/host/ide/src/figures/smaps/smapssummary.jpg b/host/ide/src/figures/smaps/smapssummary.jpg new file mode 100644 index 0000000000000000000000000000000000000000..df74018bc3bdfd6bec26d540415e2125e929530a Binary files /dev/null and b/host/ide/src/figures/smaps/smapssummary.jpg differ diff --git a/host/ide/src/figures/smartperf_framework.png b/host/ide/src/figures/smartperf_framework.png new file mode 100644 index 0000000000000000000000000000000000000000..62c1bc6cd61e07ba3014141f70941e6134d75681 Binary files /dev/null and b/host/ide/src/figures/smartperf_framework.png differ diff --git a/host/ide/src/figures/stars.jpg b/host/ide/src/figures/stars.jpg new file mode 100644 index 0000000000000000000000000000000000000000..62a3492126d240e8080f4be976abe0eb2d99315d Binary files /dev/null and b/host/ide/src/figures/stars.jpg differ diff --git a/host/ide/src/figures/summary.jpg b/host/ide/src/figures/summary.jpg new file mode 100644 index 0000000000000000000000000000000000000000..05c940ee7a6f2e303b57cbd7ca9c91396fbaed9e Binary files /dev/null and b/host/ide/src/figures/summary.jpg differ diff --git a/host/ide/src/figures/systraceconfig.jpg b/host/ide/src/figures/systraceconfig.jpg new file mode 100644 index 0000000000000000000000000000000000000000..057ee13ba1bbd1174cf8ab8d58e04de19f4971c2 Binary files /dev/null and b/host/ide/src/figures/systraceconfig.jpg differ diff --git a/host/ide/src/figures/thread_state.png b/host/ide/src/figures/thread_state.png new file mode 100644 index 0000000000000000000000000000000000000000..aa9f846fcc4b88c1b8e9df75e3aff7ada69537dc Binary files /dev/null and b/host/ide/src/figures/thread_state.png differ diff --git a/host/ide/src/figures/threadclick.jpg b/host/ide/src/figures/threadclick.jpg new file mode 100644 index 0000000000000000000000000000000000000000..65811e9317fd845bb5b2d3df752ffb742ad743e8 Binary files /dev/null and b/host/ide/src/figures/threadclick.jpg differ diff --git a/host/ide/src/figures/threadinfo.jpg b/host/ide/src/figures/threadinfo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d2b6be2acf86bcc2612ff4ab1a6b820e6551b9b6 Binary files /dev/null and b/host/ide/src/figures/threadinfo.jpg differ diff --git a/host/ide/src/figures/threadselect.jpg b/host/ide/src/figures/threadselect.jpg new file mode 100644 index 0000000000000000000000000000000000000000..38fda253bd3bab6d3388b1e19cd39d488386d2ba Binary files /dev/null and b/host/ide/src/figures/threadselect.jpg differ diff --git a/host/ide/src/figures/threadstates.jpg b/host/ide/src/figures/threadstates.jpg new file mode 100644 index 0000000000000000000000000000000000000000..475dde7276e119266eb76d2ab0f3d4eaa45d9df1 Binary files /dev/null and b/host/ide/src/figures/threadstates.jpg differ diff --git a/host/ide/src/figures/threadswitches.jpg b/host/ide/src/figures/threadswitches.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cc5974681992956657428d63cb8fbf8b8e01bd1c Binary files /dev/null and b/host/ide/src/figures/threadswitches.jpg differ diff --git a/host/ide/src/figures/time.jpg b/host/ide/src/figures/time.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a0221cb47e5874a05280a7315831fd61ec13cdd0 Binary files /dev/null and b/host/ide/src/figures/time.jpg differ diff --git a/host/ide/src/figures/trace.jpg b/host/ide/src/figures/trace.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3975199b39ee1cc2187358fef66932eea4b1c1b2 Binary files /dev/null and b/host/ide/src/figures/trace.jpg differ diff --git a/host/ide/src/figures/trace2.jpg b/host/ide/src/figures/trace2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6e324c54473450441105300db941db200b3da778 Binary files /dev/null and b/host/ide/src/figures/trace2.jpg differ diff --git a/host/ide/src/figures/trace_streamer_stream.png b/host/ide/src/figures/trace_streamer_stream.png new file mode 100644 index 0000000000000000000000000000000000000000..d36687d164a32bcb07f8f8bd699f0fb0b37e63bd Binary files /dev/null and b/host/ide/src/figures/trace_streamer_stream.png differ diff --git a/host/ide/src/figures/tracesetting.jpg b/host/ide/src/figures/tracesetting.jpg new file mode 100644 index 0000000000000000000000000000000000000000..52a1c5afc900054901b8c69d3e1a939d887a21c4 Binary files /dev/null and b/host/ide/src/figures/tracesetting.jpg differ diff --git a/host/ide/src/hdc/HdcDeviceManager.ts b/host/ide/src/hdc/HdcDeviceManager.ts new file mode 100644 index 0000000000000000000000000000000000000000..75549a1d79c3ce49a2d59d332266b95a6aea8ee2 --- /dev/null +++ b/host/ide/src/hdc/HdcDeviceManager.ts @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {HdcClient} from "./hdcclient/HdcClient.js"; +import {UsbTransmissionChannel} from "./transmission/UsbTransmissionChannel.js"; +import {HDC_DEVICE_FILTERS} from "./common/ConstantType.js"; +import {FormatCommand} from "./hdcclient/FormatCommand.js"; +import {log} from "../log/Log.js"; +import {HdcStream} from "./hdcclient/HdcStream.js"; +import {HdcCommand} from "./hdcclient/HdcCommand.js"; +import {SpRecordTrace} from "../trace/component/SpRecordTrace.js"; + +export class HdcDeviceManager { + private static clientList: Map = new Map(); + private static currentHdcClient: HdcClient; + private static FILE_RECV_PREFIX_STRING = "hdc file recv -cwd C:\\ " + + /** + * getDevices + */ + public static async getDevices(): Promise { + return navigator.usb.getDevices(); + } + + /** + * findDevice + */ + public static findDevice() { + if (!('usb' in navigator)) { + throw new Error('WebUSB not supported by the browser (requires HTTPS)'); + } + return navigator.usb.requestDevice({filters: HDC_DEVICE_FILTERS}); + } + + /** + * connect by serialNumber + * + * @param serialNumber serialNumber + */ + public static async connect(serialNumber: string): Promise { + let client = this.clientList.get(serialNumber); + if (client) { + if (client.usbDevice!.opened) { + log("device Usb is Open") + return true; + } else { + if (SpRecordTrace.serialNumber == serialNumber) { + SpRecordTrace.serialNumber = '' + } + log("device Usb not Open") + return false; + } + } else { + let connectDevice = await this.getDeviceBySerialNumber(serialNumber); + let usbChannel = await UsbTransmissionChannel.openHdcDevice(connectDevice); + if (usbChannel) { + let hdcClient = new HdcClient(usbChannel, connectDevice); + let connected = await hdcClient.connectDevice(); + if (connected) { + this.currentHdcClient = hdcClient; + this.clientList.set(serialNumber, hdcClient); + } + log("device Usb connected : " + connected) + return connected + } else { + log("device Usb connected failed: ") + return false; + } + } + } + + public static async getDeviceBySerialNumber(serialNumber: string): Promise { + const devices = await navigator.usb.getDevices(); + // @ts-ignore + return devices.find(dev => dev.serialNumber === serialNumber); + } + + /** + * disConnect by serialNumber + * + * @param serialNumber + */ + public static async disConnect(serialNumber: string): Promise { + let hdcClient = this.clientList.get(serialNumber); + if (hdcClient) { + await hdcClient.disconnect(); + this.clientList.delete(serialNumber); + return true; + } else { + return true; + } + } + + /** + * Execute shell on the currently connected device and return the result as a string + * + * @param cmd cmd + */ + public static async shellResultAsString(cmd: string, isSkipResult: boolean): Promise { + if (this.currentHdcClient) { + let hdcStream = new HdcStream(this.currentHdcClient, false); + await hdcStream.DoCommand(cmd); + let result: string = ''; + while (true) { + let dataMessage = await hdcStream.getMessage(); + if (dataMessage.channelClose || isSkipResult) { + result += dataMessage.getDataToString(); + await hdcStream.DoCommandRemote(new FormatCommand(HdcCommand.CMD_KERNEL_CHANNEL_CLOSE, "0", false)); + log("result is end, close") + break; + } + if (dataMessage.usbHead.sessionId == -1) { + return Promise.resolve("The device is abnormal"); + } + result += dataMessage.getDataToString(); + } + await hdcStream.closeStream(); + await hdcStream.DoCommandRemote(new FormatCommand(HdcCommand.CMD_KERNEL_CHANNEL_CLOSE, "0", false)); + return Promise.resolve(result); + } + return Promise.reject("not select device"); + } + + + /** + * Execute shell on the currently connected device and return the result as a string + * + * @param cmd cmd + */ + public static async stopHiprofiler(cmd: string, isSkipResult: boolean): Promise { + if (this.currentHdcClient) { + let hdcStream = new HdcStream(this.currentHdcClient, true); + await hdcStream.DoCommand(cmd); + let result: string = ''; + while (true) { + let dataMessage = await hdcStream.getMessage(); + if (dataMessage.channelClose || isSkipResult) { + await hdcStream.DoCommandRemote(new FormatCommand(HdcCommand.CMD_KERNEL_CHANNEL_CLOSE, "0", false)); + log("result is end, close") + break; + } + result += dataMessage.getDataToString(); + } + await hdcStream.closeStopStream(); + await hdcStream.DoCommandRemote(new FormatCommand(HdcCommand.CMD_KERNEL_CHANNEL_CLOSE, "0", false)); + return Promise.resolve(result); + } + return Promise.reject("not select device"); + } + + /** + * Execute shell on the currently connected device, the result is returned as Blob + * + * @param cmd cmd + */ + public static async shellResultAsBlob(cmd: string, isSkipResult: boolean): Promise { + if (this.currentHdcClient) { + let hdcStream = new HdcStream(this.currentHdcClient, false); + log("cmd is " + cmd); + await hdcStream.DoCommand(cmd); + let finalBuffer; + while (true) { + let dataMessage = await hdcStream.getMessage(); + if (dataMessage.channelClose || isSkipResult) { + log("result is end, close") + break; + } + let res = dataMessage.getData(); + if (res) { + if (!finalBuffer) { + finalBuffer = new Uint8Array(res); + } else { + finalBuffer = HdcDeviceManager.appendBuffer(finalBuffer, new Uint8Array(res)); + } + } + } + await hdcStream.closeStream(); + if (finalBuffer) { + return Promise.resolve(new Blob([finalBuffer])); + } + return Promise.resolve(new Blob()); + } + return Promise.reject("not select device"); + } + + /** + * appendBuffer + * + * @param buffer1 firstBuffer + * @param buffer2 secondBuffer + * @private + */ + private static appendBuffer(buffer1: Uint8Array, buffer2: Uint8Array) { + let tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength); + tmp.set(buffer1, 0); + tmp.set(buffer2, buffer1.byteLength); + return tmp; + }; + + /** + * Pull the corresponding file from the device side + * + * @param filename filename + */ + public static async fileRecv(filename: string, callBack: Function): Promise { + let finalBuffer; + if (this.currentHdcClient) { + let hdcStream = new HdcStream(this.currentHdcClient, false); + await hdcStream.DoCommand(HdcDeviceManager.FILE_RECV_PREFIX_STRING + filename + " ./"); + if (!finalBuffer && hdcStream.fileSize > 0) { + finalBuffer = new Uint8Array(hdcStream.fileSize); + log("Uint8Array size is " + finalBuffer.byteLength); + } + let offset = 0; + while (true) { + let dataMessage = await hdcStream.getMessage(); + if (dataMessage.channelClose) { + log("result is end, close") + break; + } + if (dataMessage.commandFlag == HdcCommand.CMD_FILE_FINISH) { + await hdcStream.DoCommandRemote(new FormatCommand(HdcCommand.CMD_KERNEL_CHANNEL_CLOSE, "", false)); + log("CMD_FILE_FINISH is end, close") + break; + } + let res = dataMessage.getData(); + if (res) { + let resRS: ArrayBuffer = res.slice(64); + if (finalBuffer) { + finalBuffer.set(new Uint8Array(resRS), offset); + offset += resRS.byteLength; + callBack((offset / hdcStream.fileSize * 100).toFixed(3)) + } + } + if (hdcStream.fileSize != -1 && offset >= hdcStream.fileSize) { + callBack(100) + await hdcStream.DoCommandRemote(new FormatCommand(HdcCommand.CMD_FILE_FINISH, "", false)); + } + } + } + if (finalBuffer) { + return Promise.resolve(new Blob([finalBuffer])); + } else { + return Promise.resolve(new Blob([])); + } + } + +} diff --git a/host/ide/src/hdc/common/BaseConversion.ts b/host/ide/src/hdc/common/BaseConversion.ts new file mode 100644 index 0000000000000000000000000000000000000000..b92cce2b50239e93c4b4f5b561f610917c206446 --- /dev/null +++ b/host/ide/src/hdc/common/BaseConversion.ts @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export function toHex8(num: number): string { + const padLen = 1 - num.toString(16).length; + let padded = ''; + for (let i = 0; i < padLen; i++) { + padded += '0'; + } + return padded + num.toString(16); +} + +export function toHex16(num: number): string { + const padLen = 2 - num.toString(16).length; + let padded = ''; + for (let i = 0; i < padLen; i++) { + padded += '0'; + } + return padded + num.toString(16); +} + +export function toHex32(num: number): string { + const padLen = 4 - num.toString(16).length; + let padded = ''; + for (let i = 0; i < padLen; i++) { + padded += '0'; + } + return padded + num.toString(16); +} + +export function toHex64(num: number): string { + const padLen = 8 - num.toString(16).length; + let padded = ''; + for (let i = 0; i < padLen; i++) { + padded += '0'; + } + return padded + num.toString(16); +} + +export function uint8ArrayToString(array: Uint8Array, convertToHex16: boolean): string { + let result: string = ""; + for (let i = 0; i < array.length; i++) { + if (convertToHex16) { + result = result + toHex16(array[i]); + } else { + result = result + array[i]; + } + } + return result; + +} + +export const Sleep = (ms: number) => { + return new Promise(resolve => setTimeout(resolve, ms)); +} \ No newline at end of file diff --git a/host/ide/src/hdc/common/ConstantType.ts b/host/ide/src/hdc/common/ConstantType.ts new file mode 100644 index 0000000000000000000000000000000000000000..f3075e1a17666e912aa9c03500875fb6909c7ab3 --- /dev/null +++ b/host/ide/src/hdc/common/ConstantType.ts @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const HANDSHAKE_MESSAGE: string = "OHOS HDC"; // sep not char '-', not more than 11 bytes +export const PACKET_FLAG = "HW"; +export const USB_PACKET_FLAG: string = "UB"; +export const MAX_PACKET_SIZE_HISPEED: number = 512; // uint16_t +export const MAX_USBFFS_BULK : number = 16384; +export const ERR_IO_FAIL = -14000; + +export const CMDSTR_SHELL:string = "shell"; +export const CMDSTR_FILE_SEND:string = "file send"; +export const CMDSTR_FILE_RECV:string = "file recv"; +export const HDC_DEVICE_FILTER = { + classCode: 255, + subclassCode: 80, + protocolCode: 1 +} as USBDeviceFilter; + +export const HDC_DEVICE_FILTERS = [HDC_DEVICE_FILTER]; \ No newline at end of file diff --git a/host/ide/src/hdc/common/ObjectToMemorySize.ts b/host/ide/src/hdc/common/ObjectToMemorySize.ts new file mode 100644 index 0000000000000000000000000000000000000000..39dad31e7d2e7336f411c966c454d13000f6d3ac --- /dev/null +++ b/host/ide/src/hdc/common/ObjectToMemorySize.ts @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class objectToMemorySize{ + private seen = new WeakSet + + /** + * objectToSize + * + * number:8 bytes (64-bit storage) + * String:一characters 2 bytes + * Boolean:4 bytes + * + * @param object + */ + objectToSize(object: any): any{ + const objType = typeof object + switch (objType) { + case 'string': + return object.length * 2 + case 'boolean': + return 4 + case 'number': + return 8 + case 'object': + if (Array.isArray(object)) { + // Array processing [1,2] [{x:1},{y:2}] + return object.map(this.objectToSize).reduce((res, cur) => res + cur, 0) + } else { + return this.sizeOfObj(object) + } + default: + return 0 + } + } + + sizeOfObj(object: any): number{ + if (object === null) return 0 + + let bytes = 0 + // The key in the object also takes up memory space + const props = Object.keys(object) + for (let i = 0; i < props.length; i++) { + const key = props[i] + // Whether the value is repeated or not, the key needs to be calculated + bytes += this.objectToSize(key) + if (typeof object[key] === 'object' && object[key] !== null) { + // 这里需要注意value使用相同内存空间(只需计算一次内存) + if (this.seen.has(object[key])) continue + this.seen.add(object[key]) + } + bytes += this.objectToSize(object[key]) + } + return bytes + } +} + diff --git a/host/ide/src/hdc/common/Serialize.ts b/host/ide/src/hdc/common/Serialize.ts new file mode 100644 index 0000000000000000000000000000000000000000..814078c3e1d7482faf34bdea2b315d17952fceae --- /dev/null +++ b/host/ide/src/hdc/common/Serialize.ts @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {WireType} from "../message/WireType.js"; +import {SessionHandShake} from "../message/SessionHandShake.js"; +import {PayloadProtect} from "../message/PayloadProtect.js"; +import {TransferConfig} from "../message/TransferConfig.js"; +import {TransferPayload} from "../message/TransferPayload.js"; +import {log} from "../../log/Log.js"; + +export class Serialize { + static bannerByteLength: number = 8 + + static serializeSessionHandShake(handShake: SessionHandShake): Uint8Array { + let bannerValue = this.serializeToString(1, handShake.banner); + let authTypeValue = this.serializeU8(2, handShake.authType); + let sessionIdValue = this.serializeU32(3, handShake.sessionId); + let connectKey = this.serializeToString(4, handShake.connectKey); + let buf = this.serializeToString(5, handShake.buf); + let mergedArray = new Uint8Array(bannerValue.length + authTypeValue.length + sessionIdValue.length + connectKey.length + buf.length); + mergedArray.set(bannerValue) + mergedArray.set(authTypeValue, bannerValue.length) + mergedArray.set(sessionIdValue, bannerValue.length + authTypeValue.length) + mergedArray.set(connectKey, bannerValue.length + authTypeValue.length + sessionIdValue.length) + mergedArray.set(buf, bannerValue.length + authTypeValue.length + sessionIdValue.length + connectKey.length) + return mergedArray; + } + + static serializePayloadProtect(payloadProtect: PayloadProtect): Uint8Array { + let channelId = this.serializeU32(1, payloadProtect.channelId); + let commandFlag = this.serializeU32(2, payloadProtect.commandFlag); + let checkSum = this.serializeU8(3, payloadProtect.checkSum); + let vCode = this.serializeU8(4, payloadProtect.vCode); + let mergedArray = new Uint8Array(channelId.length + commandFlag.length + checkSum.length + vCode.length); + mergedArray.set(channelId) + mergedArray.set(commandFlag, channelId.length) + mergedArray.set(checkSum, channelId.length + commandFlag.length) + mergedArray.set(vCode, channelId.length + commandFlag.length + checkSum.length) + return mergedArray; + } + + static serializeTransferConfig(transferConfig: TransferConfig): Uint8Array { + let fileSizeValue = this.serializeU64(1, transferConfig.fileSize); + let atimeValue = this.serializeU64(2, transferConfig.atime); + let mtimeValue = this.serializeU64(3, transferConfig.mtime); + let optionsValue = this.serializeToString(4, transferConfig.options); + let pathValue = this.serializeToString(5, transferConfig.path); + let optionalNameValue = this.serializeToString(6, transferConfig.optionalName); + let updateIfNewValue = this.serializeU32(7, transferConfig.updateIfNew ? 1 : 0); + let compressTypeValue = this.serializeU8(8, transferConfig.compressType); + let holdTimestampValue = this.serializeU32(9, transferConfig.holdTimestamp ? 1 : 0); + let functionNameValue = this.serializeToString(10, transferConfig.functionName); + let clientCwdValue = this.serializeToString(11, transferConfig.clientCwd); + let reserve1Value = this.serializeToString(12, transferConfig.reserve1); + let reserve2Value = this.serializeToString(13, transferConfig.reserve2); + let mergedArray = new Uint8Array(fileSizeValue.length + atimeValue.length + mtimeValue.length + optionsValue.length + pathValue.length + + optionalNameValue.length + updateIfNewValue.length + compressTypeValue.length + holdTimestampValue.length + + functionNameValue.length + clientCwdValue.length + reserve1Value.length + reserve2Value.length); + let offset = 0; + mergedArray.set(fileSizeValue) + offset += fileSizeValue.length; + mergedArray.set(atimeValue, offset) + offset += atimeValue.length; + mergedArray.set(mtimeValue, offset) + offset += mtimeValue.length; + mergedArray.set(optionsValue, offset) + offset += optionsValue.length; + mergedArray.set(pathValue, offset) + offset += pathValue.length; + mergedArray.set(optionalNameValue, offset) + offset += optionalNameValue.length; + mergedArray.set(updateIfNewValue, offset) + offset += updateIfNewValue.length; + mergedArray.set(compressTypeValue, offset) + offset += compressTypeValue.length; + mergedArray.set(holdTimestampValue, offset) + offset += holdTimestampValue.length; + mergedArray.set(functionNameValue, offset) + offset += functionNameValue.length; + mergedArray.set(clientCwdValue, offset) + offset += clientCwdValue.length; + mergedArray.set(reserve1Value, offset) + offset += reserve1Value.length; + mergedArray.set(reserve2Value, offset) + return mergedArray; + } + + static serializeTransferPayload(transferPayload: TransferPayload): Uint8Array { + let indexValue = this.serializeU64(1, transferPayload.index); + let compressTypeValue = this.serializeU8(2, transferPayload.compressType); + let compressSizeValue = this.serializeU32(3, transferPayload.compressSize); + let uncompressSizeValue = this.serializeU32(4, transferPayload.uncompressSize); + let mergedArray = new Uint8Array(indexValue.length + compressTypeValue.length + compressSizeValue.length + uncompressSizeValue.length); + let offset = 0; + mergedArray.set(indexValue) + offset += indexValue.length; + mergedArray.set(compressTypeValue, offset) + offset += compressTypeValue.length; + mergedArray.set(compressSizeValue, offset) + offset += compressSizeValue.length; + mergedArray.set(uncompressSizeValue, offset) + return mergedArray; + } + + static serializeToString(tag: number, value: string): Uint8Array { + let number = this.makeTagWireType(tag, WireType.LENGTH_DELIMETED); + let data = this.writeVarIntU32(number) + let dataLength = this.writeVarIntU32(value.length); + const encoder = new TextEncoder(); + const buffer = encoder.encode(value); + let stringValue = new Uint8Array(data.length + dataLength.length + buffer.length); + stringValue.set(data); + stringValue.set(dataLength, data.length); + stringValue.set(buffer, data.length + dataLength.length); + return stringValue; + } + + static serializeU8(tag: number, value: number): Uint8Array { + return this.serializeU32(tag, value); + } + + static serializeU32(tag: number, value: number): Uint8Array { + let makeTagWireType = this.writeTagWriteType(tag, WireType.VARINT); + let writeVarInt = this.writeVarIntU32(value); + let mergedArray = new Uint8Array(makeTagWireType.length + writeVarInt.length); + mergedArray.set(makeTagWireType); + mergedArray.set(writeVarInt, makeTagWireType.length); + return mergedArray; + } + + static serializeU64(tag: number, value: number): Uint8Array { + let makeTagWireType = this.writeTagWriteType(tag, WireType.VARINT); + let writeVarInt = this.writeVarIntU64(value); + let mergedArray = new Uint8Array(makeTagWireType.length + writeVarInt.length); + mergedArray.set(makeTagWireType); + mergedArray.set(writeVarInt, makeTagWireType.length); + return mergedArray; + } + + static writeTagWriteType(tag: number, wireType: number): Uint8Array { + let number = this.makeTagWireType(tag, wireType); + return this.writeVarIntU32(number); + } + + static makeTagWireType(tag: number, wireType: number): number { + return (tag << 3) | wireType; + } + + static writeVarIntU64(value: number): Uint8Array { + let buffer: number[] = [] + for (let index = 0; index < 10; index++) { + buffer[index] = value & 0b01111111; + value = value >> 7 + if (value) { + buffer[index] = buffer[index] | 0b10000000; + } else { + break; + } + } + return new Uint8Array(buffer); + } + + static writeVarIntU32(value: number): Uint8Array { + let buffer: number[] = [] + for (let index = 0; index < 5; index++) { + buffer[index] = value & 0b01111111; + value = value >> 7 + if (value) { + buffer[index] = buffer[index] | 0b10000000; + } else { + break; + } + } + return new Uint8Array(buffer); + } + + static parseHandshake(data: Uint8Array): SessionHandShake { + // banner + let bannerBuffer = data.buffer; + let bannerTag = this.getTag(WireType.LENGTH_DELIMETED, new DataView(bannerBuffer)); + let bannerLengthBuf = bannerBuffer.slice(1); + let bannerSize = this.readVarIntU32(new DataView(bannerLengthBuf)); + let bannerDataBuffer = bannerLengthBuf.slice(1); + let banner = this.parseString(bannerDataBuffer, bannerSize); + + // authType + let authBuffer = bannerDataBuffer.slice(bannerSize); + let authTypeTag = this.getTag(WireType.VARINT, new DataView(authBuffer)); + let authDataBuffer = authBuffer.slice(1); + let authTypeDataView = new DataView(authDataBuffer); + let authType = this.parseU8(authTypeDataView, 1); + + // sessionId + let sessionIdBuffer = authDataBuffer.slice(1); + let sessionIdTag = this.getTag(WireType.VARINT, new DataView(sessionIdBuffer)); + let sessionDataBuffer = sessionIdBuffer.slice(1); + let sessionIdDataView = new DataView(sessionDataBuffer); + let sessionId = this.parseU32(sessionIdDataView, 3); + + // connectKey + let connectKeyBuffer = sessionDataBuffer.slice(3); + let connectKeyTag = this.getTag(WireType.LENGTH_DELIMETED, new DataView(connectKeyBuffer)); + let connectLengthBuffer = connectKeyBuffer.slice(1); + let connectKeyDataView = new DataView(connectLengthBuffer); + let connectKeySize = this.readVarIntU32(connectKeyDataView); + let connectDataBuffer = connectLengthBuffer.slice(1); + let connectKey = this.parseString(connectDataBuffer, connectKeySize); + + // buf + let bufBuffer = connectDataBuffer.slice(connectKeySize); + let bufTag = this.getTag(WireType.LENGTH_DELIMETED, new DataView(bufBuffer)); + let lengthBuffer = bufBuffer.slice(1); + let bufDataView = new DataView(lengthBuffer); + let bufSize = this.readVarIntU32(bufDataView); + let dataBuffer = lengthBuffer.slice(1); + let buf = this.parseString(dataBuffer, bufSize); + return new SessionHandShake(banner, authType, sessionId, connectKey, buf); + } + + static parseTransferConfig(data: ArrayBuffer): TransferConfig { + let uint8Array = new Uint8Array(data); + // channelId + let dataBuffer = uint8Array.buffer + let channelTag = this.getTag(WireType.VARINT, new DataView(dataBuffer)); + let channelDataBuffer = dataBuffer.slice(1); + let channelDataView = new DataView(channelDataBuffer); + let fileSize = this.parseU64(channelDataView, 1); + console.log("parseTransferConfig fileSize,", fileSize) + return new TransferConfig(fileSize, 0, 0, "", "", + "", false, 0, false, + "", "", "", ""); + } + + + static parsePayloadProtect(data: ArrayBuffer): PayloadProtect { + let uint8Array = new Uint8Array(data); + + // channelId + let dataBuffer = uint8Array.buffer + let channelTag = this.getTag(WireType.VARINT, new DataView(dataBuffer)); + let channelDataBuffer = dataBuffer.slice(1); + let channelDataView = new DataView(channelDataBuffer); + let channelId = this.parseU32(channelDataView, 1); + + // commandFlag + let commandTagBuffer = channelDataBuffer.slice(1); + let commandTag = this.getTag(WireType.VARINT, new DataView(commandTagBuffer)); + let commandDataBuffer = commandTagBuffer.slice(1); + let commandDataView = new DataView(commandDataBuffer); + let commandFlag = this.parseU32(commandDataView, 1); + + // checkSum + let checkSumTagBuffer = commandDataBuffer.slice(1); + let checkSumTag = this.getTag(WireType.VARINT, new DataView(checkSumTagBuffer)); + let checkSumDataBuffer = checkSumTagBuffer.slice(1); + let checkSumDataView = new DataView(checkSumDataBuffer); + let checkSum = this.parseU8(checkSumDataView, 1); + + // vCode + let vCodeTagBuffer = checkSumDataBuffer.slice(1); + let vCodeTag = this.getTag(WireType.VARINT, new DataView(vCodeTagBuffer)); + let vCodeDataBuffer = vCodeTagBuffer.slice(1); + let vCodeDataView = new DataView(vCodeDataBuffer); + let vCode = this.parseU8(vCodeDataView, 1); + + return new PayloadProtect(channelId, commandFlag, checkSum, vCode); + } + + static parseString(buffer: ArrayBuffer, size: number): string { + let arrayBuffer = buffer.slice(0, size); + let textDecoder = new TextDecoder(); + return textDecoder.decode(arrayBuffer); + } + + static parseU8(dataView: DataView, size: number): number { + return this.parseU32(dataView, size) + } + + static parseU32(dataView: DataView, size: number): number { + return this.readVarIntU32(dataView); + } + + static parseU64(dataView: DataView, size: number): number { + return this.readVarIntU64(dataView); + } + + static readVarIntU32(dataView: DataView): number { + let value: number = 0; + for (let index = 0; index < 5; index++) { + if (dataView.byteLength < index + 1) { + return -1; + } + let int8 = dataView.getUint8(index); + let readValue = int8 & 0b01111111 + value |= readValue << 7 * index; + if (!(int8 & 0b10000000)) { + return value; + } + } + return -1; + } + + static readVarIntU64(dataView: DataView): number { + let value: number = 0; + for (let index = 0; index < 10; index++) { + if (dataView.byteLength < index + 1) { + return -1; + } + let int8 = dataView.getUint8(index); + let readValue = int8 & 0b01111111 + value |= readValue << 7 * index; + if (!(int8 & 0b10000000)) { + return value; + } + } + return -1; + } + + static readTagWireType(tagKey: number) { + let wireNewType: WireType = (tagKey & 0b0111); + return tagKey >> 3 + } + + static getTag(wireType: WireType, dataView: DataView) { + let tagKey = this.readVarIntU32(dataView); + return this.readTagWireType(tagKey); + } +} \ No newline at end of file diff --git a/host/ide/src/hdc/common/Utils.ts b/host/ide/src/hdc/common/Utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..c62fba9fe7641ab817f5c01ad3eaae543f4642d8 --- /dev/null +++ b/host/ide/src/hdc/common/Utils.ts @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {FormatCommand} from "../hdcclient/FormatCommand.js"; +import {warn} from "../../log/Log.js"; + +export class Utils { + private static localId = 1; + + public static getSessionId(): number { + return Math.round(Math.random() * 100000000); + } + + public static getLocalId(): number { + if (this.localId == 4294967295) { + this.localId = 1; + } + return this.localId++; + } + + public static formatCommand(cmd: string): FormatCommand { + let command = cmd; + if (cmd.startsWith("hdc_std")) { + command = command.substring("hdc_std ".length); + } else if (cmd.startsWith("hdc")) { + command = command.substring("hdc ".length); + } + let formatCommand = FormatCommand.string2FormatCommand(command); + // formatCommand Success + if (formatCommand.cmdFlag <= -1) { + warn("command : " + command + " is not Support",) + } + return formatCommand; + } + + public static numToHexString(num: number): string { + if(num == undefined||num == null||isNaN(num)){ + return "0x0" + } + if(num < 0){ + return "0x"+(num >>> 0).toString(16) + }else { + return "0x"+num.toString(16) + } + } +} \ No newline at end of file diff --git a/host/ide/src/hdc/hdcclient/AsyncQueue.ts b/host/ide/src/hdc/hdcclient/AsyncQueue.ts new file mode 100644 index 0000000000000000000000000000000000000000..ceff206bf365323036900d4f8772a88c7af2b2d2 --- /dev/null +++ b/host/ide/src/hdc/hdcclient/AsyncQueue.ts @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {DataMessage} from "../message/DataMessage.js"; + +export class DataMessageQueue { + private eleArray: Array; + + constructor() { + this.eleArray = new Array(); + } + + public push(entry: T): boolean { + if (entry == null) { + return false; + } + this.eleArray.unshift(entry); + return true; + } + + public pop(): T | undefined { + return this.eleArray.pop(); + } + + public size(): number { + return this.eleArray.length; + } +} + +interface Resolver { + (data: DataMessage): void +} + +export class AsyncQueue { + private promiseQueue: DataMessageQueue> = new DataMessageQueue>(); + private resolverQueue: DataMessageQueue = new DataMessageQueue(); + + add() { + this.promiseQueue.push(new Promise(resolve => { + this.resolverQueue.push(resolve); + })); + } + + enqueue(item: DataMessage) { + if (this.resolverQueue.size() == 0) { + this.add(); + } + const resolve = this.resolverQueue.pop(); + resolve ? resolve(item) : null; + } + + async dequeue(): Promise { + if (this.promiseQueue.size() == 0) { + this.add(); + } + return this.promiseQueue.pop() || new Promise(() => {}); + } +} \ No newline at end of file diff --git a/host/ide/src/hdc/hdcclient/DataListener.ts b/host/ide/src/hdc/hdcclient/DataListener.ts new file mode 100644 index 0000000000000000000000000000000000000000..8fb73862fcbc4d532981f8a5d3dc22d4fe40d0be --- /dev/null +++ b/host/ide/src/hdc/hdcclient/DataListener.ts @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {DataMessage} from "../message/DataMessage.js"; + +export interface DataListener { + createDataMessage(data: DataMessage):void; +} \ No newline at end of file diff --git a/host/ide/src/hdc/hdcclient/FormatCommand.ts b/host/ide/src/hdc/hdcclient/FormatCommand.ts new file mode 100644 index 0000000000000000000000000000000000000000..3ddfc3c2f492b964178278b9199b549fc2f5b62c --- /dev/null +++ b/host/ide/src/hdc/hdcclient/FormatCommand.ts @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {HdcCommand} from "./HdcCommand.js"; +import {CMDSTR_FILE_RECV, CMDSTR_FILE_SEND, CMDSTR_SHELL} from "../common/ConstantType.js"; +import {log} from "../../log/Log.js"; + +export class FormatCommand { + cmdFlag: number; // uint16_t + parameters: string; //string + bJumpDo: boolean; // boolean + + constructor(cmdFlag: number, parameters: string, bJumpDo: boolean) { + this.cmdFlag = cmdFlag; + this.parameters = parameters; + this.bJumpDo = bJumpDo; + } + + static string2FormatCommand(cmd: string): FormatCommand { + log("Command : " + cmd); + let formatCommand = new FormatCommand(-1, "", false); + if (cmd.startsWith(CMDSTR_SHELL + " ")) { + formatCommand.cmdFlag = HdcCommand.CMD_UNITY_EXECUTE; + formatCommand.parameters = cmd.substring((CMDSTR_SHELL + " ").length) + } else if (cmd.startsWith(CMDSTR_SHELL)) { + formatCommand.cmdFlag = HdcCommand.CMD_SHELL_INIT; + } else if (cmd.startsWith(CMDSTR_FILE_RECV)) { + formatCommand.cmdFlag = HdcCommand.CMD_FILE_INIT; + formatCommand.parameters = cmd.substring((CMDSTR_FILE_RECV + " ").length) + } else if (cmd.startsWith(CMDSTR_FILE_SEND)) { + formatCommand.cmdFlag = HdcCommand.CMD_FILE_INIT; + formatCommand.parameters = cmd.substring((CMDSTR_FILE_SEND + " ").length) + } else { + formatCommand.bJumpDo = true; + } + log("formatCommand cmdFlag is : " + formatCommand.cmdFlag); + log("formatCommand parameters is : " + formatCommand.parameters); + log("formatCommand bJumpDo is : " + formatCommand.bJumpDo); + return formatCommand; + } + +} \ No newline at end of file diff --git a/host/ide/src/hdc/hdcclient/HdcClient.ts b/host/ide/src/hdc/hdcclient/HdcClient.ts new file mode 100644 index 0000000000000000000000000000000000000000..45040283ab8a2fc3dd16efcf145748a20ab626b2 --- /dev/null +++ b/host/ide/src/hdc/hdcclient/HdcClient.ts @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {Serialize} from "../common/Serialize.js"; +import {HdcCommand} from "./HdcCommand.js"; +import {Utils} from "../common/Utils.js"; +import {HANDSHAKE_MESSAGE} from "../common/ConstantType.js"; +import {PayloadHead} from "../message/PayloadHead.js"; +import {TransmissionInterface} from "../transmission/TransmissionInterface.js"; +import {DataProcessing} from "../transmission/DataProcessing.js"; +import {DataListener} from "./DataListener.js"; +import {DataMessage} from "../message/DataMessage.js"; +import {SessionHandShake} from "../message/SessionHandShake.js"; +import {AuthType} from "../message/AuthType.js"; +import {debug, log} from "../../log/Log.js"; +import {HdcStream} from "./HdcStream.js"; +import {toHex16} from "../common/BaseConversion.js"; + +export class HdcClient implements DataListener { + usbDevice: USBDevice | undefined; + sessionId: number = 0; + private transmissionChannel: TransmissionInterface; + public readDataProcessing: DataProcessing; + private stream: HdcStream | undefined | null; + private hdcStopStream: HdcStream | undefined | null; + private cmdStream: number = -1; + private stopStream: number = -1; + + constructor(transmissionChannel: TransmissionInterface, usbDevice: USBDevice | undefined) { + this.transmissionChannel = transmissionChannel; + this.usbDevice = usbDevice; + this.readDataProcessing = new DataProcessing(this, transmissionChannel); + } + + async connectDevice(): Promise { + debug("start Connect Device") + this.sessionId = Utils.getSessionId(); + log("sessionId is " + this.sessionId) + // @ts-ignore + let handShake: SessionHandShake = new SessionHandShake(HANDSHAKE_MESSAGE, AuthType.AUTH_NONE, this.sessionId, this.usbDevice.serialNumber, ""); + let hs = Serialize.serializeSessionHandShake(handShake); + debug("start Connect hs ", hs) + let sendResult = await this.readDataProcessing.send(handShake.sessionId, 0, HdcCommand.CMD_KERNEL_HANDSHAKE, hs, hs.length); + if (sendResult) { + let handShake = await this.readDataProcessing.readUsbHead(); + let handBody = await this.readDataProcessing.readBody(handShake!.dataSize); + if (this.sessionId == handShake!.sessionId) { + debug("handShake: ", handShake); + let playHeadArray = handBody.buffer.slice(0, PayloadHead.getPayloadHeadLength()) + let resultPayloadHead: PayloadHead = PayloadHead.parsePlayHead(new DataView(playHeadArray)); + debug("resultPayloadHead is ", resultPayloadHead); + let headSize = resultPayloadHead.headSize; + let dataSize = resultPayloadHead.dataSize; + let resPlayProtectBuffer = handBody.buffer.slice(PayloadHead.getPayloadHeadLength(), PayloadHead.getPayloadHeadLength() + headSize); + debug("PlayProtect is ", resPlayProtectBuffer); + let resData = handBody.buffer.slice(PayloadHead.getPayloadHeadLength() + headSize, PayloadHead.getPayloadHeadLength() + headSize + dataSize); + debug("resData is ", resData); + this.readDataProcessing.startReadData().then(() => { + }); + return true; + } else { + log("session is not eq handShake?.sessionId is : " + handShake?.sessionId + " now session is " + this.sessionId) + return false; + } + } else { + return false; + } + } + + public async disconnect(): Promise { + try { + await this.transmissionChannel.close(); + this.readDataProcessing.stopReadData(); + } catch (e) { + } + } + + public bindStream(channel: number, hdcStream: HdcStream) { + this.cmdStream = channel; + this.stream = hdcStream; + } + + public bindStopStream(channel: number, hdcStopStream: HdcStream) { + this.stopStream = channel; + this.hdcStopStream = hdcStopStream; + } + + public unbindStream(channel: number): boolean { + this.stream = null; + return this.stream == null; + } + + public unbindStopStream(channel: number): boolean { + this.hdcStopStream = null; + return this.hdcStopStream == null; + } + + createDataMessage(data: DataMessage): void { + if (this.hdcStopStream && data.getChannelId() == this.stopStream) { + this.hdcStopStream.putMessageInQueue(data); + } + if (this.stream && data.getChannelId() == this.cmdStream) { + this.stream.putMessageInQueue(data); + } + if (data.getChannelId() == -1) { + this.stream?.putMessageInQueue(data); + this.hdcStopStream?.putMessageInQueue(data); + } + } +} + diff --git a/host/ide/src/hdc/hdcclient/HdcCommand.ts b/host/ide/src/hdc/hdcclient/HdcCommand.ts new file mode 100644 index 0000000000000000000000000000000000000000..eadc55e6aeba341813e0977a2678f6b3c3da7586 --- /dev/null +++ b/host/ide/src/hdc/hdcclient/HdcCommand.ts @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export enum HdcCommand { + // core commands types + CMD_KERNEL_HELP = 0, + CMD_KERNEL_HANDSHAKE = 1, + CMD_KERNEL_CHANNEL_CLOSE = 2, + CMD_KERNEL_SERVER_KILL = 3, + CMD_KERNEL_TARGET_DISCOVER = 4, + CMD_KERNEL_TARGET_LIST = 5, + CMD_KERNEL_TARGET_ANY = 6, + CMD_KERNEL_TARGET_CONNECT = 7, + CMD_KERNEL_TARGET_DISCONNECT = 8, + CMD_KERNEL_ECHO = 9, + CMD_KERNEL_ECHO_RAW = 10, + CMD_KERNEL_ENABLE_KEEPALIVE = 11, + CMD_KERNEL_WAKEUP_SLAVETASK = 12, + // One-pass simple commands + CMD_UNITY_COMMAND_HEAD = 1000, // not use + CMD_UNITY_EXECUTE = 1001, + CMD_UNITY_REMOUNT = 1002, + CMD_UNITY_REBOOT = 1003, + CMD_UNITY_RUNMODE = 1004, + CMD_UNITY_HILOG = 1005, + CMD_UNITY_TERMINATE = 1006, + CMD_UNITY_ROOTRUN = 1007, + CMD_JDWP_LIST = 1008, + CMD_JDWP_TRACK = 1009, + CMD_UNITY_COMMAND_TAIL = 1010, // not use + // It will be separated from unity in the near future + CMD_UNITY_BUGREPORT_INIT = 1011, + CMD_UNITY_BUGREPORT_DATA = 1012, + // Shell commands types + CMD_SHELL_INIT = 2000, + CMD_SHELL_DATA = 2001, + // File commands + CMD_FILE_INIT = 3000, + CMD_FILE_CHECK = 3001, + CMD_FILE_BEGIN = 3002, + CMD_FILE_DATA = 3003, + CMD_FILE_FINISH = 3004, + // App commands + CMD_APP_SIDELOAD = 3005, + CMD_APP_INIT = 3500, + CMD_APP_CHECK = 3501, + CMD_APP_BEGIN = 3502, + CMD_APP_DATA = 3503, + CMD_APP_FINISH = 3504, + CMD_APP_UNINSTALL = 3505, +} diff --git a/host/ide/src/hdc/hdcclient/HdcStream.ts b/host/ide/src/hdc/hdcclient/HdcStream.ts new file mode 100644 index 0000000000000000000000000000000000000000..df61bd9e7a3bfecad0b4e2130446750a4512547e --- /dev/null +++ b/host/ide/src/hdc/hdcclient/HdcStream.ts @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {DataMessage} from "../message/DataMessage.js"; +import {HdcClient} from "./HdcClient.js"; +import {FormatCommand} from "./FormatCommand.js"; +import {HdcCommand} from "./HdcCommand.js"; +import {Utils} from "../common/Utils.js"; +import {AsyncQueue} from "./AsyncQueue.js"; +import {toHex16} from "../common/BaseConversion.js"; +import {PayloadHead} from "../message/PayloadHead.js"; +import {Serialize} from "../common/Serialize.js"; + +export class HdcStream { + private dataMessages: AsyncQueue = new AsyncQueue(); + private readonly channelId: number + private interactiveShellMode: boolean = false; + private hdcClient: HdcClient; + public fileSize: number = -1; + + constructor(hdcClient: HdcClient, isStopCmd:boolean) { + this.hdcClient = hdcClient; + this.channelId = Utils.getLocalId(); + if (isStopCmd) { + this.hdcClient.bindStopStream(this.channelId, this); + } else { + this.hdcClient.bindStream(this.channelId, this); + } + } + + public async DoCommand(cmd: string): Promise { + let formatCommand; + if (this.interactiveShellMode) { + formatCommand = new FormatCommand(HdcCommand.CMD_SHELL_DATA, cmd, false); + } else { + formatCommand = Utils.formatCommand(cmd); + } + return this.DoCommandRemote(formatCommand); + } + + public async DoCommandRemote(command: FormatCommand): Promise { + switch (command.cmdFlag) { + case HdcCommand.CMD_SHELL_INIT: + case HdcCommand.CMD_SHELL_DATA: + case HdcCommand.CMD_UNITY_EXECUTE: + case HdcCommand.CMD_UNITY_TERMINATE: + case HdcCommand.CMD_UNITY_REMOUNT: + case HdcCommand.CMD_UNITY_REBOOT: + case HdcCommand.CMD_UNITY_RUNMODE: + case HdcCommand.CMD_UNITY_HILOG: { + let textEncoder = new TextEncoder(); + let data = textEncoder.encode(command.parameters); + let sendResult = await this.sendToDaemon(command, data, data.length); + if (sendResult) { + if (HdcCommand.CMD_SHELL_INIT == command.cmdFlag) { + this.interactiveShellMode = true; + } + } + break; + } + case HdcCommand.CMD_FILE_INIT: { + await this.FileRecvCommand(command); + break; + } + case HdcCommand.CMD_FILE_FINISH: + case HdcCommand.CMD_KERNEL_CHANNEL_CLOSE: { + let dataView = new DataView(new ArrayBuffer(1)); + if (command.parameters == "0") { + dataView.setUint8(0, 0); + } else { + dataView.setUint8(0, 1); + } + await this.sendToDaemon(command, new Uint8Array(dataView.buffer), 1); + break; + } + } + return false; + } + + async FileRecvCommand(command: FormatCommand) { + let sizeSend = command.parameters.length; + let cmdFlag: string = ''; + let sizeCmdFlag: number = 0; + if (HdcCommand.CMD_FILE_INIT == command.cmdFlag) { + cmdFlag = "send "; + sizeCmdFlag = 5; // 5: cmdFlag send size + } + if (!(command.parameters.length > cmdFlag.length)) { + } else { + let textEncoder = new TextEncoder(); + let data = textEncoder.encode(command.parameters); + let aa = data.slice(5); + await this.sendToDaemon(command, aa, aa.length); + let dataMessage = await this.getMessage(); + let playHeadArray = dataMessage.body!.buffer.slice(0, PayloadHead.getPayloadHeadLength()) + let resultPayloadHead: PayloadHead = PayloadHead.parsePlayHead(new DataView(playHeadArray)); + let headSize = resultPayloadHead.headSize; + let dataSize = resultPayloadHead.dataSize; + let resPlayProtectBuffer = dataMessage.body!.buffer.slice(11, 11 + headSize); + let payloadProtect = Serialize.parsePayloadProtect(resPlayProtectBuffer); + await this.handleCommandFileCheck() + } + } + + private async handleCommandFileCheck() { + let dataMessage = await this.getMessage(); + let playHeadArray = dataMessage.body!.buffer.slice(0, PayloadHead.getPayloadHeadLength()) + let resultPayloadHead: PayloadHead = PayloadHead.parsePlayHead(new DataView(playHeadArray)); + let headSize = resultPayloadHead.headSize; + let dataSize = resultPayloadHead.dataSize; + let resPlayProtectBuffer = dataMessage.body!.buffer.slice(PayloadHead.getPayloadHeadLength(), PayloadHead.getPayloadHeadLength() + headSize); + let payloadProtect = Serialize.parsePayloadProtect(resPlayProtectBuffer); + if (payloadProtect.commandFlag == HdcCommand.CMD_FILE_CHECK) { + if (dataSize > 0) { + let transferConfigBuffer = dataMessage.body!.buffer.slice(PayloadHead.getPayloadHeadLength() + headSize, PayloadHead.getPayloadHeadLength() + headSize + dataSize); + let transferConfig = Serialize.parseTransferConfig(transferConfigBuffer); + this.fileSize = transferConfig.fileSize; + } + let fileBegin = new FormatCommand(HdcCommand.CMD_FILE_BEGIN, "", false); + await this.sendToDaemon(fileBegin, new Uint8Array(0), 0); + } + } + + async sendToDaemon(command: FormatCommand, payload: Uint8Array, dataLength: number): Promise { + return await this.hdcClient.readDataProcessing.send(this.hdcClient.sessionId, this.channelId, command.cmdFlag, payload, dataLength); + } + + putMessageInQueue(dataMessage: DataMessage) { + this.dataMessages.enqueue(dataMessage); + } + + getMessage(): Promise { + return this.dataMessages.dequeue(); + } + + closeStream() { + this.hdcClient.unbindStream(this.channelId); + } + + closeStopStream() { + this.hdcClient.unbindStopStream(this.channelId); + } +} + + + diff --git a/host/ide/src/hdc/hdcclient/UsbProtocolOption.ts b/host/ide/src/hdc/hdcclient/UsbProtocolOption.ts new file mode 100644 index 0000000000000000000000000000000000000000..41d5d439d5a9d6cc875e64c982a5dd2a0d6f2ba9 --- /dev/null +++ b/host/ide/src/hdc/hdcclient/UsbProtocolOption.ts @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export enum UsbProtocolOption { + USB_OPTION_HEADER = 1, + USB_OPTION_RESET = 2, + USB_OPTION_RESERVE4 = 4, + USB_OPTION_RESERVE8 = 8, + USB_OPTION_RESERVE16 = 16, +} \ No newline at end of file diff --git a/host/ide/src/hdc/message/AuthType.ts b/host/ide/src/hdc/message/AuthType.ts new file mode 100644 index 0000000000000000000000000000000000000000..ad77fcb32a6cea6723ba1191b17d8d388accb8db --- /dev/null +++ b/host/ide/src/hdc/message/AuthType.ts @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class AuthType { + static AUTH_NONE: number = 0 // uint8 + static AUTH_TOKEN: number = 1 // uint8 + static AUTH_SIGNATURE: number = 2 //uint8 + static AUTH_PUBLICKEY: number = 3 //uint8 + static AUTH_OK: number = 4 //uint8 + + static getAuthTypeLength() { + return 1 + } +} \ No newline at end of file diff --git a/host/ide/src/hdc/message/BaseBean.ts b/host/ide/src/hdc/message/BaseBean.ts new file mode 100644 index 0000000000000000000000000000000000000000..280129fe6193418cfb2af43fdde99c385d44c689 --- /dev/null +++ b/host/ide/src/hdc/message/BaseBean.ts @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface BaseBean { + getDataView():DataView; +} \ No newline at end of file diff --git a/host/ide/src/hdc/message/DataMessage.ts b/host/ide/src/hdc/message/DataMessage.ts new file mode 100644 index 0000000000000000000000000000000000000000..adfed2d47d3a0535b45b2bd18b3dfa3976b476c3 --- /dev/null +++ b/host/ide/src/hdc/message/DataMessage.ts @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {USBHead} from "./USBHead.js"; +import {debug, log} from "../../log/Log.js"; +import {PayloadHead} from "./PayloadHead.js"; +import {Serialize} from "../common/Serialize.js"; +import {Utils} from "../common/Utils.js"; +import {HdcCommand} from "../hdcclient/HdcCommand.js"; + +export class DataMessage extends Object{ + body?: DataView; + + private _usbHead: USBHead; + private _channelId: number = -1; + private _result: string = ''; + private _channelClose: boolean = false; + private _resArrayBuffer: ArrayBuffer | undefined; + private _commandFlag:number = -1; + + constructor(usbHead: USBHead, body?: DataView) { + super(); + this._usbHead = usbHead; + this.body = body; + if (this.body) { + this.splitData(); + } + } + + splitData() { + let playHeadArray = this.body!.buffer.slice(0, 11) + let resultPayloadHead: PayloadHead = PayloadHead.parsePlayHead(new DataView(playHeadArray)); + let headSize = resultPayloadHead.headSize; + let dataSize = resultPayloadHead.dataSize; + let resultPlayProtectBuffer = this.body!.buffer.slice(11, 11 + headSize); + let payloadProtect = Serialize.parsePayloadProtect(resultPlayProtectBuffer); + this._channelId = payloadProtect.channelId; + this._commandFlag = payloadProtect.commandFlag; + if (payloadProtect.commandFlag == HdcCommand.CMD_KERNEL_CHANNEL_CLOSE) { + log("commandFlag: " + payloadProtect.commandFlag) + this._channelClose = true; + } else { + if (dataSize > 0) { + this._resArrayBuffer = this.body!.buffer.slice(11 + headSize, 11 + headSize + dataSize); + } + } + } + + public getChannelId(): number { + return this._channelId; + } + + public getData(): ArrayBuffer | undefined { + return this._resArrayBuffer; + } + + public getDataToString(): string { + let textDecoder = new TextDecoder(); + this._result = textDecoder.decode(this._resArrayBuffer); + return this._result; + } + + get usbHead(): USBHead { + return this._usbHead; + } + + set usbHead(value: USBHead) { + this._usbHead = value; + } + + get channelId(): number { + return this._channelId; + } + + set channelId(value: number) { + this._channelId = value; + } + + get result(): string { + return this._result; + } + + set result(value: string) { + this._result = value; + } + + get channelClose(): boolean { + return this._channelClose; + } + + set channelClose(value: boolean) { + this._channelClose = value; + } + + get resArrayBuffer(): ArrayBuffer | undefined { + return this._resArrayBuffer; + } + + set resArrayBuffer(value: ArrayBuffer | undefined) { + this._resArrayBuffer = value; + } + + get commandFlag(): number { + return this._commandFlag; + } + + set commandFlag(value: number) { + this._commandFlag = value; + } + + toString(): string { + return "usbHead: " + this._usbHead + + " channelId: " + this._channelId + + " result: " + this._result + + " channelClose: " + this._channelClose + + " commandFlag: " + this._commandFlag; + } +} \ No newline at end of file diff --git a/host/ide/src/hdc/message/PayloadHead.ts b/host/ide/src/hdc/message/PayloadHead.ts new file mode 100644 index 0000000000000000000000000000000000000000..345dea934d65b117d87da90161551fa21a2c94e7 --- /dev/null +++ b/host/ide/src/hdc/message/PayloadHead.ts @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseBean} from "./BaseBean.js"; + +export class PayloadHead extends Object implements BaseBean { + private _flag: Array = [0, 0]; //uint8_t ct.c_uint8 * 2 + private _reserve: Array; //uint8_t // encrypt'flag or others options ct.c_uint8 * 2 + private _protocolVer: number;// uint8_t 1 + private _headSize: number = 0; // uint16_t 2 + private _dataSize: number = 0; // uint32_t 4 + + constructor(flag: Array, reserve: Array, protocolVer: number, headSize: number, dataSize: number) { + super(); + this._flag = flag; + this._reserve = reserve; + this._protocolVer = protocolVer; + this._headSize = headSize; + this._dataSize = dataSize; + } + + static getPayloadHeadLength() { + return 11; + } + getDataView(): DataView { + const view = new DataView(new ArrayBuffer(11)); + view.setUint8(0, this._flag[0]); + view.setUint8(1, this._flag[1]); + view.setUint8(2, this._reserve[0]); + view.setUint8(3, this._reserve[1]); + view.setUint8(4, this._protocolVer); + view.setUint16(5, this._headSize, false); + view.setUint32(7, this._dataSize); + return view; + } + + static parsePlayHead(data: DataView): PayloadHead { + let flagZero = data.getUint8(0); + let flagOne = data.getUint8(1); + let reserveZero = data.getUint8(2); + let reserveOne = data.getUint8(3,); + let protocolVer = data.getUint8(4); + let headSize = data.getUint16(5); + let dataSize; + if (data.byteLength < 11) { + dataSize = 0; + } else { + dataSize = data.getUint32(7); + } + return new PayloadHead([flagZero, flagOne], [reserveZero, reserveOne], protocolVer, headSize, dataSize) + } + + get flag(): Array { + return this._flag; + } + + set flag(value: Array) { + this._flag = value; + } + + get headSize(): number { + return this._headSize; + } + + set headSize(value: number) { + this._headSize = value; + } + + get dataSize(): number { + return this._dataSize; + } + + set dataSize(value: number) { + this._dataSize = value; + } + + toString(): string { + return "PayloadHead: " + this.getDataView.toString() + + ", parsePlayHead: " + PayloadHead.parsePlayHead.toString() + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneCpu.ts b/host/ide/src/hdc/message/PayloadProtect.ts similarity index 31% rename from host/ide/src/trace/component/trace/sheet/TabPaneCpu.ts rename to host/ide/src/hdc/message/PayloadProtect.ts index cb5a3a769f90dbb9e4eb9bc55edb379707067ed8..38ce7a0a33f2d3a57f9c1ea42a2186d5e6a82810 100644 --- a/host/ide/src/trace/component/trace/sheet/TabPaneCpu.ts +++ b/host/ide/src/hdc/message/PayloadProtect.ts @@ -13,46 +13,62 @@ * limitations under the License. */ -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import {CpuStruct} from "../../../bean/CpuStruct.js"; - -@element('tabpane-cpu') -export class TabPaneCpu extends BaseElement { - private tbl: LitTable | null | undefined; - - set data(val: CpuStruct) { - this.tbl!.dataSource = [ - {name: 'Process', value: `${val.processName || 'Process'} [${val.processId}]`}, - {name: 'Thread', value: `${val.name || 'Thread'} [${val.tid}]`}, - {name: 'Cmdline', value: val.processCmdLine}, - {name: 'Start time', value: val.startTime}, - {name: 'Duration', value: val.dur}, - {name: 'Prio', value: val.priority}, - {name: 'End State', value: val.end_state}, - {name: 'Slice ID', value: val.id} - ] - } - - initElements(): void { - this.tbl = this.shadowRoot?.querySelector('#tbl3'); - } - - initHtml(): string { - return ` - - - - - - - `; +import {BaseBean} from "./BaseBean.js"; + +export class PayloadProtect extends Object implements BaseBean{ // reserve for encrypt and decrypt + private _channelId: number; //uint32_t + private _commandFlag: number; //uint32_t + private _checkSum: number;// uint8_t enable it will be lose about 20% speed + private _vCode: number; //uint8_t + + constructor(channelId: number, commandFlag: number, checkSum: number, vCode: number) { + super(); + this._channelId = channelId; + this._commandFlag = commandFlag; + this._checkSum = checkSum; + this._vCode = vCode; + } + + getDataView(): DataView { + return new DataView(new ArrayBuffer(24)); + } + + get channelId(): number { + return this._channelId; } + set channelId(value: number) { + this._channelId = value; + } + + get commandFlag(): number { + return this._commandFlag; + } + + set commandFlag(value: number) { + this._commandFlag = value; + } + + get checkSum(): number { + return this._checkSum; + } + + set checkSum(value: number) { + this._checkSum = value; + } + + get vCode(): number { + return this._vCode; + } + + set vCode(value: number) { + this._vCode = value; + } + + toString(): string { + return "channelId: " + this._channelId + + " commandFlag: " + this._commandFlag + + " checkSum: " + this._checkSum + + " vCode: " + this._vCode; + } } \ No newline at end of file diff --git a/host/ide/src/hdc/message/SessionHandShake.ts b/host/ide/src/hdc/message/SessionHandShake.ts new file mode 100644 index 0000000000000000000000000000000000000000..d79c086f444a5ebd5491e68f85415907d7b33ecc --- /dev/null +++ b/host/ide/src/hdc/message/SessionHandShake.ts @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {AuthType} from "./AuthType.js"; +import {HANDSHAKE_MESSAGE} from "../common/ConstantType.js"; +import {BaseBean} from "./BaseBean.js"; + +export class SessionHandShake extends Object implements BaseBean{ + private _banner: string = HANDSHAKE_MESSAGE; // string must first index + private _authType: number = AuthType.AUTH_NONE; // uint8_t auth none + private _sessionId: number = 0; // uint32_t + private _connectKey: string = ""; // string + private _buf: string = ""; // string + private _version:string = ""; + + constructor(banner: string, authType: number, sessionId: number, connectKey: string, buf: string) { + super(); + this._banner = banner; + this._authType = authType; + this._sessionId = sessionId; + this._connectKey = connectKey; + this._buf = buf; + } + + getDataView(): DataView { + const view = new DataView(new ArrayBuffer(24)); + return view; + } + + get banner(): string { + return this._banner; + } + + set banner(value: string) { + this._banner = value; + } + + get authType(): number { + return this._authType; + } + + set authType(value: number) { + this._authType = value; + } + + get sessionId(): number { + return this._sessionId; + } + + set sessionId(value: number) { + this._sessionId = value; + } + + get connectKey(): string { + return this._connectKey; + } + + set connectKey(value: string) { + this._connectKey = value; + } + + get buf(): string { + return this._buf; + } + + set buf(value: string) { + this._buf = value; + } + + get version(): string { + return this._version; + } + + set version(value: string) { + this._version = value; + } + + toString(): string { + return "banner: " + this._banner + + " authType: " + this._authType + + " sessionId: " + this._sessionId + + " connectKey: " + this._connectKey + + " buf: " + this._buf + + " version: " + this._version; + } +} diff --git a/host/ide/src/hdc/message/TransferConfig.ts b/host/ide/src/hdc/message/TransferConfig.ts new file mode 100644 index 0000000000000000000000000000000000000000..7ab751d1b6168bb1e917016b534e3e70894660a1 --- /dev/null +++ b/host/ide/src/hdc/message/TransferConfig.ts @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class TransferConfig extends Object{ + private _fileSize: number = -1; // uint64_t + private _atime: number = -1; // uint64_t ns + private _mtime: number = -1; // uint64_t ns + private _options: string = ''; // string + private _path: string = ''; + private _optionalName: string = ''; + private _updateIfNew: boolean = false; //bool + private _compressType: number = CompressType.COMPRESS_NONE; // uint8_t + private _holdTimestamp: boolean = false; //bool + private _functionName: string = ''; + private _clientCwd: string = ''; + private _reserve1: string = ''; + private _reserve2: string = ''; + + constructor(fileSize: number, atime: number, mtime: number, options: string, path: string, + optionalName: string, updateIfNew: boolean, compressType: number, holdTimestamp: boolean, + functionName: string, clientCwd: string, reserve1: string, reserve2: string) { + super(); + this._fileSize = fileSize; + this._atime = atime; + this._mtime = mtime; + this._options = options; + this._path = path; + this._optionalName = optionalName; + this._updateIfNew = updateIfNew; + this._compressType = compressType; + this._holdTimestamp = holdTimestamp; + this._functionName = functionName; + this._clientCwd = clientCwd; + this._reserve1 = reserve1; + this._reserve2 = reserve2; + } + + + get fileSize(): number { + return this._fileSize; + } + + set fileSize(value: number) { + this._fileSize = value; + } + + get atime(): number { + return this._atime; + } + + set atime(value: number) { + this._atime = value; + } + + get mtime(): number { + return this._mtime; + } + + set mtime(value: number) { + this._mtime = value; + } + + get options(): string { + return this._options; + } + + set options(value: string) { + this._options = value; + } + + get path(): string { + return this._path; + } + + set path(value: string) { + this._path = value; + } + + get optionalName(): string { + return this._optionalName; + } + + set optionalName(value: string) { + this._optionalName = value; + } + + get updateIfNew(): boolean { + return this._updateIfNew; + } + + set updateIfNew(value: boolean) { + this._updateIfNew = value; + } + + get compressType(): number { + return this._compressType; + } + + set compressType(value: number) { + this._compressType = value; + } + + get holdTimestamp(): boolean { + return this._holdTimestamp; + } + + set holdTimestamp(value: boolean) { + this._holdTimestamp = value; + } + + get functionName(): string { + return this._functionName; + } + + set functionName(value: string) { + this._functionName = value; + } + + get clientCwd(): string { + return this._clientCwd; + } + + set clientCwd(value: string) { + this._clientCwd = value; + } + + get reserve1(): string { + return this._reserve1; + } + + set reserve1(value: string) { + this._reserve1 = value; + } + + get reserve2(): string { + return this._reserve2; + } + + set reserve2(value: string) { + this._reserve2 = value; + } + + toString(): string { + return "fileSize: " + this._fileSize + + " atime: " + this._atime + + " mtime: " + this._mtime + + " options: " + this._options + + " path: " + this._path + + " optionalName: " + this._optionalName + + " updateIfNew: " + this._updateIfNew + + " compressType: " + this._compressType + + " holdTimestamp: " + this._holdTimestamp + + " functionName: " + this._functionName + + " clientCwd: " + this._clientCwd + + " reserve1: " + this._reserve1 + + " reserve2: " + this._reserve2; + } +} + +enum CompressType { COMPRESS_NONE, COMPRESS_LZ4, COMPRESS_LZ77, COMPRESS_LZMA, COMPRESS_BROTLI }; diff --git a/host/ide/src/hdc/message/TransferPayload.ts b/host/ide/src/hdc/message/TransferPayload.ts new file mode 100644 index 0000000000000000000000000000000000000000..811a239998d119ff1c6910b4e03bfe2cc1d62b0f --- /dev/null +++ b/host/ide/src/hdc/message/TransferPayload.ts @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class TransferPayload extends Object{ + private _index: number; // uint64_t + private _compressType: number; // uint8_t; + private _compressSize: number; // uint32_t + private _uncompressSize: number; //uint32_t + + constructor(index: number, compressType: number, compressSize: number, uncompressSize: number) { + super(); + this._index = index; + this._compressType = compressType; + this._compressSize = compressSize; + this._uncompressSize = uncompressSize; + } + + + getDataView(): DataView { + const view = new DataView(new ArrayBuffer(24)); + return view; + } + + get index(): number { + return this._index; + } + + set index(value: number) { + this._index = value; + } + + get compressType(): number { + return this._compressType; + } + + set compressType(value: number) { + this._compressType = value; + } + + get compressSize(): number { + return this._compressSize; + } + + set compressSize(value: number) { + this._compressSize = value; + } + + get uncompressSize(): number { + return this._uncompressSize; + } + + set uncompressSize(value: number) { + this._uncompressSize = value; + } + + toString(): string { + return "index: " + this._index + + " compressType: " + this._compressType + + " compressSize: " + this._compressSize + + " uncompressSize: " + this._uncompressSize; + } +} diff --git a/host/ide/src/hdc/message/USBHead.ts b/host/ide/src/hdc/message/USBHead.ts new file mode 100644 index 0000000000000000000000000000000000000000..63b102d5fc140a65a34e2864c9efccf92580c315 --- /dev/null +++ b/host/ide/src/hdc/message/USBHead.ts @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseBean} from "./BaseBean.js"; + +export class USBHead extends Object implements BaseBean { + private _flag: number[];// uint8_t 'flag', ct.c_uint8 * 2 flag[2] 2 + private _option: number; // uint8_t 1 + private _sessionId: number; // uint32_t 4 + private _dataSize: number; // uint32_t 4 + + constructor(flag: number[], option: number, sessionId: number, dataSize: number) { + super(); + this._flag = flag; + this._option = option; + this._sessionId = sessionId; + this._dataSize = dataSize; + } + static getFlag0Length() { + return 1; + } + + static getFlag1Length() { + return 1; + } + + static getOptionLength() { + return 1; + } + + static getSessionIdLength() { + return 4; + } + + static getDataSizeLength() { + return 4; + } + + static getUSBHeadLength() { + return 11; + } + + getDataView(): DataView { + let dataView = new DataView(new ArrayBuffer(11)); + dataView.setUint8(0, this._flag[0]); + dataView.setUint8(1, this._flag[1]); + dataView.setUint8(2, this._option); + dataView.setUint32(3, this._sessionId); + dataView.setUint32(7, this._dataSize); + return dataView; + } + + static parseHeadData(data: DataView): USBHead { + let flagZero = data.getUint8(0); + let flagOne = data.getUint8(1); + let option = data.getUint8(2); + let sessionId = data.getUint32(3); + let dataSize = data.getUint32(7); + return new USBHead([flagZero, flagOne], option, sessionId, dataSize); + } + + + get flag(): number[] { + return this._flag; + } + + set flag(value: number[]) { + this._flag = value; + } + + get option(): number { + return this._option; + } + + set option(value: number) { + this._option = value; + } + + get sessionId(): number { + return this._sessionId; + } + + set sessionId(value: number) { + this._sessionId = value; + } + + get dataSize(): number { + return this._dataSize; + } + + set dataSize(value: number) { + this._dataSize = value; + } + + toString(): string { + return "flag: " + this._flag + + " option: " + this._option + + " sessionId: " + this._sessionId + + " dataSize: " + this._dataSize; + } +} diff --git a/host/ide/src/hdc/message/WireType.ts b/host/ide/src/hdc/message/WireType.ts new file mode 100644 index 0000000000000000000000000000000000000000..67060a048fa2e62a9bad9cac003a9689d272f843 --- /dev/null +++ b/host/ide/src/hdc/message/WireType.ts @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class WireType { + static VARINT: number = 0 //uint32 + static FIXED64: number = 1 //uint32 + static LENGTH_DELIMETED: number = 2 //uint32 + static START_GROUP: number = 3 //uint32 + static END_GROUP: number = 4 //uint32 + static FIXED32: number = 5 //uint32 +} \ No newline at end of file diff --git a/host/ide/src/hdc/transmission/DataProcessing.ts b/host/ide/src/hdc/transmission/DataProcessing.ts new file mode 100644 index 0000000000000000000000000000000000000000..3bec3bbfefb67570bc6c1e1e08907456fbef67fc --- /dev/null +++ b/host/ide/src/hdc/transmission/DataProcessing.ts @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {TransmissionInterface} from "./TransmissionInterface.js"; +import {PACKET_FLAG, USB_PACKET_FLAG} from "../common/ConstantType.js"; +import {USBHead} from "../message/USBHead.js"; +import {DataMessage} from "../message/DataMessage.js"; +import {DataListener} from "../hdcclient/DataListener.js"; +import {PayloadProtect} from "../message/PayloadProtect.js"; +import {Serialize} from "../common/Serialize.js"; +import {PayloadHead} from "../message/PayloadHead.js"; +import {UsbProtocolOption} from "../hdcclient/UsbProtocolOption.js"; +import {toHex16} from "../common/BaseConversion.js"; +import {error, log} from "../../log/Log.js"; + +export class DataProcessing { + private readonly transmissionChannel: TransmissionInterface; + private dataListener: DataListener; + public readData = true; + private static usbHeadSize: number = 11; + private static vCode: number = 0x09; + private static checkSum: number = 0; + + constructor(dataListener: DataListener, transmissionChannel: TransmissionInterface) { + this.dataListener = dataListener; + this.transmissionChannel = transmissionChannel; + } + + public async startReadData(): Promise { + try { + while (this.readData) { + let usbHead = await this.readUsbHead(); + if (usbHead != null) { + let dataSize = usbHead!.dataSize; + if (dataSize > 0) { + let body = await this.readBody(dataSize); + let message = new DataMessage(usbHead, body); + this.dataListener.createDataMessage(message); + } else { + let message = new DataMessage(usbHead); + this.dataListener.createDataMessage(message); + } + } else { + log("head is null") + } + } + } catch (e) { + let ubsHead = new USBHead([-1, -1], -1, -1, -1); + let message = new DataMessage(ubsHead); + this.dataListener.createDataMessage(message); + error("error", e) + } + } + + public async readUsbHead(): Promise { + let res = await this.transmissionChannel.readData(USBHead.getUSBHeadLength()); + if (res) { + let useHead: USBHead = USBHead.parseHeadData(res); + return useHead; + } + return null; + } + + public async readBody(dataSize: number): Promise { + let data = await this.transmissionChannel.readData(dataSize); + return data; + } + + public async send(sessionId: number, channelId: number, commandFlag: number, data: Uint8Array, dataSize: number): Promise { + let protectBuf: PayloadProtect = new PayloadProtect(channelId, commandFlag, DataProcessing.checkSum, DataProcessing.vCode); + let pbs = Serialize.serializePayloadProtect(protectBuf); + let payloadHead: PayloadHead = new PayloadHead([PACKET_FLAG.charCodeAt(0), PACKET_FLAG.charCodeAt(1)], [0, 0], 1, pbs.byteLength, dataSize) + let dataView = payloadHead.getDataView(); + let playHeadArray = new Uint8Array(dataView.buffer); + let finalBufSize = dataView.byteLength + pbs.byteLength + dataSize; + let finalBuf = new Uint8Array(finalBufSize); + finalBuf.set(playHeadArray); + finalBuf.set(pbs, dataView.byteLength) + finalBuf.set(data, dataView.byteLength + pbs.byteLength); + if (this.transmissionChannel) { + let header = this.buildPacketHeader(sessionId, UsbProtocolOption.USB_OPTION_HEADER, finalBufSize); + await this.transmissionChannel.writeData(header); + await this.transmissionChannel.writeData(finalBuf); + return true; + } else { + this.stopReadData(); + return false; + } + } + + private buildPacketHeader(sessionId: number, option: number, dataSize: number): Uint8Array { + let head: USBHead = new USBHead([USB_PACKET_FLAG.charCodeAt(0), USB_PACKET_FLAG.charCodeAt(1)], option, sessionId, dataSize); + let dataView = head.getDataView(); + return new Uint8Array(dataView.buffer); + } + + public stopReadData() { + this.readData = false; + } + +} \ No newline at end of file diff --git a/host/ide/src/hdc/transmission/TransmissionInterface.ts b/host/ide/src/hdc/transmission/TransmissionInterface.ts new file mode 100644 index 0000000000000000000000000000000000000000..98a2dbb8a704e591d31c57e46e220829b653c572 --- /dev/null +++ b/host/ide/src/hdc/transmission/TransmissionInterface.ts @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface TransmissionInterface { + writeData(writeData:ArrayBuffer): Promise; + readData(length :number): Promise; + close(): Promise; +} \ No newline at end of file diff --git a/host/ide/src/hdc/transmission/UsbTransmissionChannel.ts b/host/ide/src/hdc/transmission/UsbTransmissionChannel.ts new file mode 100644 index 0000000000000000000000000000000000000000..760fafbc99315a66e4e6bed120a1bd41f6f3b7a6 --- /dev/null +++ b/host/ide/src/hdc/transmission/UsbTransmissionChannel.ts @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {TransmissionInterface} from "./TransmissionInterface.js"; +import {error, info, log} from "../../log/Log.js"; +import {HDC_DEVICE_FILTER} from "../common/ConstantType.js"; +import {HdcDeviceManager} from "../HdcDeviceManager.js"; + +export interface matchingUsbDevice { + configurationValue: number; + interfaceNumber: number; + endPoints: USBEndpoint[]; +} + +export class UsbTransmissionChannel implements TransmissionInterface { + private _device: USBDevice | null; + private readonly endpointIn: number; + private readonly endpointOut: number; + private readonly interfaceNumber: number; + + private constructor(device: USBDevice, endpointIn: number, endpointOut: number, interfaceNumber: number) { + this._device = device; + this.endpointIn = endpointIn; + this.endpointOut = endpointOut; + this.interfaceNumber = interfaceNumber; + } + + /** + * Send data to the device side + * + * @param writeData writeData + */ + async writeData(writeData: ArrayBuffer) { + await this._device?.transferOut(this.endpointOut, writeData); + } + + /** + * read data from device via usb + * + * @param length + */ + async readData(length: number): Promise { + const result = await this._device?.transferIn(this.endpointOut, length); + if (result?.data) { + return result.data; + } else { + return Promise.resolve(new DataView(new ArrayBuffer(0))); + } + } + + /** + * Close the device connection + */ + async close(): Promise { + await this._device?.releaseInterface(this.interfaceNumber) + await this._device?.close(); + this._device = null; + } + + /** + * 打开设备 + * + * @param usbDevice + */ + static async openHdcDevice(usbDevice: USBDevice): Promise { + try { + await usbDevice.open(); + const matchDevice = this.filterAndFindDevice(usbDevice, HDC_DEVICE_FILTER); + info("matchDevice is", matchDevice) + if (!matchDevice) { + throw new Error('Could not find hdc device'); + } + await usbDevice.selectConfiguration(matchDevice.configurationValue); + await usbDevice.claimInterface(matchDevice.interfaceNumber); + const endpointIn = UsbTransmissionChannel.filterEndpointNumber(matchDevice.endPoints, 'in'); + const endpointOut = UsbTransmissionChannel.filterEndpointNumber(matchDevice.endPoints, 'out'); + return new UsbTransmissionChannel(usbDevice, endpointIn, endpointOut, matchDevice.interfaceNumber); + } catch (e) { + return Promise.resolve(null); + } + } + + /** + * Filter out matching devices + * + * @param device device + * @param filter filter + */ + private static filterAndFindDevice(device: USBDevice, filter: USBDeviceFilter): matchingUsbDevice | null { + for (const config of device.configurations) { + for (const intf of config.interfaces) for (const al of intf.alternates) { + if (filter.classCode === al.interfaceClass && + filter.subclassCode === al.interfaceSubclass && + filter.protocolCode === al.interfaceProtocol) { + return { + configurationValue: config.configurationValue, + interfaceNumber: intf.interfaceNumber, + endPoints: al.endpoints + }; + } + } + } + return null; + } + + private static filterEndpointNumber(usbEndpoints: USBEndpoint[], dir: 'in' | 'out', type = 'bulk'): number { + let endpoint = usbEndpoints.filter(element => { + return (element.direction === dir && element.type === type); + }) + return endpoint[0].endpointNumber; + } +} \ No newline at end of file diff --git a/host/ide/src/icon.svg b/host/ide/src/icon.svg index 168c113b584dbbbfb6a69687e65adf634768dd8b..1cce633830ef2e9caf112ee0fe44e07f6bed4e53 100644 --- a/host/ide/src/icon.svg +++ b/host/ide/src/icon.svg @@ -1 +1,2173 @@ - + diff --git a/host/ide/src/img/down.png b/host/ide/src/img/down.png new file mode 100644 index 0000000000000000000000000000000000000000..1dcde0fbd8e8d15b7b2ce76fd0ac419bf29e107a Binary files /dev/null and b/host/ide/src/img/down.png differ diff --git a/host/ide/src/img/help.png b/host/ide/src/img/help.png new file mode 100644 index 0000000000000000000000000000000000000000..05cc5d13cb1d94025ac8c6381c0d1ef1cc7c7443 Binary files /dev/null and b/host/ide/src/img/help.png differ diff --git a/host/ide/src/img/normal_off.png b/host/ide/src/img/normal_off.png new file mode 100644 index 0000000000000000000000000000000000000000..5f6aa75d2bed70f851cf7269f86fa8d6432dbd08 Binary files /dev/null and b/host/ide/src/img/normal_off.png differ diff --git a/host/ide/src/img/normal_on.png b/host/ide/src/img/normal_on.png new file mode 100644 index 0000000000000000000000000000000000000000..90e57e33025b81e539f0f289a4d3866db0e21d71 Binary files /dev/null and b/host/ide/src/img/normal_on.png differ diff --git a/host/ide/src/img/screening.png b/host/ide/src/img/screening.png new file mode 100644 index 0000000000000000000000000000000000000000..ee7259c851aa4656d6896eac17ac2894ed300ac3 Binary files /dev/null and b/host/ide/src/img/screening.png differ diff --git a/host/ide/src/index.html b/host/ide/src/index.html index dc1753f754d8fbc46869cf0a633dc885ebf78b4f..fe0dcdc9cbcc2948feefefb78655a49d677a5591 100644 --- a/host/ide/src/index.html +++ b/host/ide/src/index.html @@ -39,9 +39,9 @@ let req = new XMLHttpRequest(); req.open('GET', document.location, false); req.send(null); - window.version = req.getResponseHeader('data-version')||"" + window.version = req.getResponseHeader('data-version') || "" - - + + diff --git a/host/ide/src/log/Log.ts b/host/ide/src/log/Log.ts index d74cbc3c54c78cbd2232564ad2e43cb4857afe47..1a1f44fe23f0e5417e79dd50e6eedb494e531500 100644 --- a/host/ide/src/log/Log.ts +++ b/host/ide/src/log/Log.ts @@ -43,7 +43,7 @@ export const log = (message?: any) => { } class SpLog { - private static nowLogLevel: LogLevel = LogLevel.ALL; + private static nowLogLevel: LogLevel = LogLevel.OFF; public static getNowLogLevel(): LogLevel { return this.nowLogLevel; diff --git a/host/ide/src/trace/SpApplication.ts b/host/ide/src/trace/SpApplication.ts index b5e8eff0a96fc1f0ff8594b3c807c19199257654..e3fdb034a85ee59f148ffb11f81562149c7a5388 100644 --- a/host/ide/src/trace/SpApplication.ts +++ b/host/ide/src/trace/SpApplication.ts @@ -17,6 +17,8 @@ import {BaseElement, element} from "../base-ui/BaseElement.js"; import "../base-ui/menu/LitMainMenu.js"; import "../base-ui/icon/LitIcon.js"; import {SpMetrics} from "./component/SpMetrics.js"; +import {SpHelp} from "./component/SpHelp.js"; +import "./component/SpHelp.js"; import {SpQuerySQL} from "./component/SpQuerySQL.js"; import "./component/SpQuerySQL.js"; import {SpSystemTrace} from "./component/SpSystemTrace.js"; @@ -27,23 +29,42 @@ import {LitProgressBar} from "../base-ui/progress-bar/LitProgressBar.js"; import {SpRecordTrace} from "./component/SpRecordTrace.js"; import {SpWelcomePage} from "./component/SpWelcomePage.js"; import {LitSearch} from "./component/trace/search/Search.js"; -import {threadPool} from "./database/SqlLite.js"; +import {DbPool, threadPool} from "./database/SqlLite.js"; import "./component/trace/search/Search.js"; import "./component/SpWelcomePage.js"; import "./component/SpSystemTrace.js"; import "./component/SpRecordTrace.js"; +import "./component/SpMetrics.js"; +import "./component/SpInfoAndStas.js"; +import "./component/trace/base/TraceRow.js"; +import {info, log} from "../log/Log.js"; +import {LitMainMenuGroup} from "../base-ui/menu/LitMainMenuGroup.js"; +import {LitMainMenuItem} from "../base-ui/menu/LitMainMenuItem.js"; +import {LitIcon} from "../base-ui/icon/LitIcon.js"; +import {Cmd} from "../command/Cmd.js"; import {TraceRow} from "./component/trace/base/TraceRow.js"; @element('sp-application') export class SpApplication extends BaseElement { + private static loadingProgress:number = 0; + private static progressStep:number = 2; static skinChange: Function | null | undefined = null; static skinChange2: Function | null | undefined = null; skinChangeArray: Array = []; private icon: HTMLDivElement | undefined | null private rootEL: HTMLDivElement | undefined | null + private spHelp: SpHelp | undefined | null + private keyCodeMap = { + 61: true, + 107: true, + 109: true, + 173: true, + 187: true, + 189: true, + }; static get observedAttributes() { - return ["server", "sqlite", "wasm", "dark", "vs", "query-sql"] + return ["server", "sqlite", "wasm", "dark", "vs", "query-sql","subsection"] } get dark() { @@ -67,6 +88,10 @@ export class SpApplication extends BaseElement { if (SpApplication.skinChange2) { SpApplication.skinChange2(value); } + + if (this.spHelp) { + this.spHelp.dark = value + } } get vs(): boolean { @@ -91,10 +116,6 @@ export class SpApplication extends BaseElement { return this.hasAttribute("server") } - get querySql(): boolean { - return this.hasAttribute("query-sql") - } - set server(s: boolean) { if (s) { this.setAttribute('server', '') @@ -103,6 +124,18 @@ export class SpApplication extends BaseElement { } } + get querySql(): boolean { + return this.hasAttribute("query-sql") + } + + set querySql(isShowMetric) { + if (isShowMetric) { + this.setAttribute('query-sql','') + } else { + this.removeAttribute('query-sql') + } + } + set search(search: boolean) { if (search) { this.setAttribute('search', '') @@ -111,6 +144,10 @@ export class SpApplication extends BaseElement { } } + get search(): boolean { + return this.hasAttribute("search") + } + addSkinListener(handler: Function) { this.skinChangeArray.push(handler) }; @@ -121,208 +158,223 @@ export class SpApplication extends BaseElement { initHtml(): string { return ` - -
- -
- `; } initElements() { let that = this; + this.querySql = true this.rootEL = this.shadowRoot!.querySelector(".root") let spWelcomePage = this.shadowRoot!.querySelector("#sp-welcome") as SpWelcomePage - let spMetrics = new SpMetrics(); + let spMetrics = this.shadowRoot!.querySelector("#sp-metrics") as SpMetrics // new SpMetrics(); + let spQuerySQL = this.shadowRoot!.querySelector("#sp-query-sql") as SpQuerySQL // new SpQuerySQL(); + let spInfoAndStats = this.shadowRoot!.querySelector("#sp-info-and-stats") as SpInfoAndStats // new SpInfoAndStats(); + let spSystemTrace = this.shadowRoot!.querySelector("#sp-system-trace") - let spInfoAndStats = new SpInfoAndStats(); + this.spHelp = this.shadowRoot!.querySelector("#sp-help") let spRecordTrace = this.shadowRoot!.querySelector("#sp-record-trace") - let spQuerySQL = this.shadowRoot!.querySelector("#sp-query-sql") let appContent = this.shadowRoot?.querySelector('#app-content') as HTMLDivElement; let mainMenu = this.shadowRoot?.querySelector('#main-menu') as LitMainMenu + let menu = mainMenu.shadowRoot?.querySelector('.menu-button') as HTMLDivElement let progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar let litSearch = this.shadowRoot?.querySelector('#lit-search') as LitSearch + let search = this.shadowRoot?.querySelector('.search-container') as HTMLElement let sidebarButton: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('.sidebar-button') - let childNodes = [spSystemTrace, spRecordTrace, spWelcomePage, spQuerySQL] + let childNodes = [spSystemTrace, spRecordTrace, spWelcomePage, spMetrics, spQuerySQL, spInfoAndStats, this.spHelp] litSearch.addEventListener("focus", () => { spSystemTrace!.keyboardEnable = false }) @@ -330,17 +382,21 @@ export class SpApplication extends BaseElement { spSystemTrace!.keyboardEnable = true }) litSearch.addEventListener("previous-data", (ev: any) => { - litSearch.index = spSystemTrace!.showPreCpuStruct(litSearch.index,litSearch.list); + litSearch.index = spSystemTrace!.showStruct(true, litSearch.index, litSearch.list); litSearch.blur(); }) litSearch.addEventListener("next-data", (ev: any) => { - litSearch.index = spSystemTrace!.showNextCpuStruct(litSearch.index,litSearch.list); + litSearch.index = spSystemTrace!.showStruct(false, litSearch.index, litSearch.list); litSearch.blur(); - // spSystemTrace!.search(e.detail.value) }) litSearch.valueChangeHandler = (value: string) => { if (value.length > 0) { - litSearch.list = spSystemTrace!.searchCPU(value); + let list = spSystemTrace!.searchCPU(value); + spSystemTrace!.searchFunction(list, value).then((mixedResults) => { + if(litSearch.searchValue != ""){ + litSearch.list = spSystemTrace!.searchSdk(mixedResults,value) + } + }) } else { litSearch.list = []; spSystemTrace?.visibleRows.forEach(it => { @@ -351,10 +407,10 @@ export class SpApplication extends BaseElement { } } spSystemTrace?.addEventListener("previous-data", (ev: any) => { - litSearch.index = spSystemTrace!.showPreCpuStruct(litSearch.index, litSearch.list); + litSearch.index = spSystemTrace!.showStruct(true, litSearch.index, litSearch.list); }) spSystemTrace?.addEventListener("next-data", (ev: any) => { - litSearch.index = spSystemTrace!.showNextCpuStruct(litSearch.index, litSearch.list); + litSearch.index = spSystemTrace!.showStruct(false, litSearch.index, litSearch.list); }) //打开侧边栏 sidebarButton!.onclick = (e) => { @@ -371,6 +427,7 @@ export class SpApplication extends BaseElement { } } let icon: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector("#main-menu")?.shadowRoot?.querySelector("div.header > div") + icon!.style.pointerEvents = 'none' icon!.onclick = (e) => { let menu: HTMLElement | undefined | null = this.shadowRoot?.querySelector("#main-menu") let menuButton: HTMLElement | undefined | null = this.shadowRoot?.querySelector('.sidebar-button') @@ -386,6 +443,16 @@ export class SpApplication extends BaseElement { } function showContent(showNode: HTMLElement) { + if (showNode === spSystemTrace) { + menu!.style.pointerEvents = 'auto' + sidebarButton!.style.pointerEvents = 'auto' + that.search = true + } else { + menu!.style.pointerEvents = 'none' + sidebarButton!.style.pointerEvents = 'none' + that.search = litSearch.isLoading + } + log("show pages" + showNode.id) childNodes.forEach((node) => { if (node === showNode) { showNode.style.visibility = 'visible' @@ -395,154 +462,355 @@ export class SpApplication extends BaseElement { }) } - function openTraceFile(ev: any) { - litSearch.clear(); - showContent(spSystemTrace!) - that.search = true - progressEL.loading = true - let fileName = (ev as any).name - let fileSize = ((ev as any).size / 1000000).toFixed(1) - document.title = `${fileName.substring(0, fileName.lastIndexOf('.'))} (${fileSize}M)` - if (that.server) { - threadPool.init("server").then(() => { - litSearch.setPercent("parse trace", 1); - // Load the trace file and send it to the background parse to return the db file path - const fd = new FormData() - that.freshMenuDisable(true) + function postLog(filename: string, fileSize: string) { + log("postLog filename is: " + filename + " fileSize: " + fileSize) + fetch(`https://${window.location.host.split(':')[0]}:9000/logger`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + fileName: filename, + fileSize: fileSize + }), + }).then(response => response.json()).then(data => { + }).catch((error) => { + }); + } + + function handleServerMode(ev: any, showFileName: string, fileSize: string, fileName: string, isClickHandle?: boolean) { + threadPool.init("server").then(() => { + info("init server ok"); + litSearch.setPercent("parse trace", 1); + // Load the trace file and send it to the background parse to return the db file path + const fd = new FormData() + that.freshMenuDisable(true) + if (that.vs && isClickHandle) { + fd.append("convertType", "vsUpload"); + fd.append('filePath', ev as any) + } else { fd.append('file', ev as any) - let uploadPath = `https://${window.location.host.split(':')[0]}:9001/upload` - if (that.vs) { - uploadPath = `http://${window.location.host.split(':')[0]}:${window.location.port}/upload` - } - fetch(uploadPath, { - method: 'POST', - body: fd, - }).then(res => { - litSearch.setPercent("load database", 5); - if (res.ok) { - let menus = [ - { - title: `${fileName.substring(0, fileName.lastIndexOf('.'))} (${fileSize}M)`, - icon: "file-fill", - clickHandler: function () { - that.search = true - showContent(spSystemTrace!) + } + let uploadPath = `https://${window.location.host.split(':')[0]}:9000/upload` + if (that.vs) { + uploadPath = `http://${window.location.host.split(':')[0]}:${window.location.port}/upload` + } + info("upload trace") + let dbName = ""; + fetch(uploadPath, { + method: 'POST', + body: fd, + }).then(res => { + litSearch.setPercent("load database", 5); + if (res.ok) { + info(" server Parse trace file success"); + let menus = [ + { + title: `${showFileName} (${fileSize}M)`, + icon: "file-fill", + clickHandler: function () { + that.search = true + showContent(spSystemTrace!) + } + }, + { + title: "DownLoad", + icon: "download", + clickHandler: function () { + if (that.vs) { + that.vsDownload(mainMenu, fileName, true, dbName); + } else { + that.download(mainMenu, fileName, true, dbName); } } - ]; - if (that.querySql) { + } + ]; + + if (that.querySql) { + if (spQuerySQL) { + spQuerySQL.reset() menus.push({ - title: "Query (SQL)", icon: "file", clickHandler: () => { - showContent(spQuerySQL!) + title: "Query (SQL)", icon: "filesearch", clickHandler: () => { + showContent(spQuerySQL) } }); } - mainMenu.menus!.splice(1, 1, { - collapsed: false, - title: "Current Trace", - describe: "Actions on the current trace", - children: menus - }) - that.freshMenuDisable(true) - return res.text(); - } else { - if (res.status == 404) { - litSearch.setPercent("This File is not supported!", -1) - progressEL.loading = false; - that.freshMenuDisable(false) - return Promise.reject(); + if (spMetrics) { + spMetrics.reset() + menus.push({ + title: "Metrics", icon: "metric", clickHandler: () => { + showContent(spMetrics) + } + }); } - } - }).then(res => { - if (res != undefined) { - let loadPath = `https://${window.location.host.split(':')[0]}:9001` - if (that.vs) { - loadPath = `http://${window.location.host.split(':')[0]}:${window.location.port}` + + if (spInfoAndStats) { + menus.push({ + title: "Info and stats", icon: "info", clickHandler: () => { + showContent(spInfoAndStats) + } + }); } - spSystemTrace!.loadDatabaseUrl(loadPath + res, (command: string, percent: number) => { - litSearch.setPercent(command + ' ', percent); - }, (res) => { - litSearch.setPercent("", 101); - progressEL.loading = false; - that.freshMenuDisable(false) - }) - } else { - litSearch.setPercent("", 101) + } + + mainMenu.menus!.splice(1, 1, { + collapsed: false, + title: "Current Trace", + describe: "Actions on the current trace", + children: menus + }) + + that.freshMenuDisable(true) + return res.text(); + } else { + if (res.status == 404) { + info(" server Parse trace file failed"); + litSearch.setPercent("This File is not supported!", -1) progressEL.loading = false; that.freshMenuDisable(false) + return Promise.reject(); } - - }) - }) - return; - } - if (that.sqlite) { - litSearch.setPercent("", 0); - threadPool.init("sqlite").then(res => { - let reader = new FileReader(); - reader.readAsArrayBuffer(ev as any) - reader.onloadend = function (ev) { - spSystemTrace!.loadDatabaseArrayBuffer(this.result as ArrayBuffer, (command: string, percent: number) => { - litSearch.setPercent(command + ' ', percent); - }, () => { + } + }).then(res => { + if (res != undefined) { + dbName = res; + info("get trace db"); + let loadPath = `https://${window.location.host.split(':')[0]}:9000` + if (that.vs) { + loadPath = `http://${window.location.host.split(':')[0]}:${window.location.port}` + } + SpApplication.loadingProgress = 0; + SpApplication.progressStep = 3; + spSystemTrace!.loadDatabaseUrl(loadPath + res, (command: string, percent: number) => { + setProgress(command) + }, (res) => { + info("loadDatabaseUrl success"); litSearch.setPercent("", 101); progressEL.loading = false; that.freshMenuDisable(false) }) + } else { + litSearch.setPercent("", 101) + progressEL.loading = false; + that.freshMenuDisable(false) } + spInfoAndStats.initInfoAndStatsData(); }) - return; + }) + } + + function setProgress(command: string){ + if(command == "database ready" && SpApplication.loadingProgress < 50){ + SpApplication.progressStep = 6 } - if (that.wasm) { - litSearch.setPercent("", 1); - threadPool.init("wasm").then(res => { - let reader = new FileReader(); - reader.readAsArrayBuffer(ev as any) - reader.onloadend = function (ev) { - litSearch.setPercent("ArrayBuffer loaded ", 2); - that.freshMenuDisable(true) - let menus = [ - { - title: `${fileName.substring(0, fileName.lastIndexOf('.'))} (${fileSize}M)`, - icon: "file-fill", - clickHandler: function () { - that.search = true - showContent(spSystemTrace!) + if(command == "process" && SpApplication.loadingProgress < 92){ + SpApplication.loadingProgress = 92 + Math.round(Math.random() * SpApplication.progressStep) + }else{ + SpApplication.loadingProgress += Math.round(Math.random() * SpApplication.progressStep + Math.random()) + } + if(SpApplication.loadingProgress > 99){ + SpApplication.loadingProgress = 99 + } + info("setPercent :" + command + "percent :" + SpApplication.loadingProgress); + litSearch.setPercent(command + ' ', SpApplication.loadingProgress); + } + + function handleWasmMode(ev: any, showFileName: string, fileSize: string, fileName: string) { + litSearch.setPercent("", 1); + threadPool.init("wasm").then(res => { + let reader = new FileReader(); + reader.readAsArrayBuffer(ev as any) + reader.onloadend = function (ev) { + info("read file onloadend"); + litSearch.setPercent("ArrayBuffer loaded ", 2); + that.freshMenuDisable(true) + let menus = [ + { + title: `${showFileName} (${fileSize}M)`, + icon: "file-fill", + clickHandler: function () { + that.search = true + showContent(spSystemTrace!) + } + }, + { + title: "DownLoad", + icon: "download", + clickHandler: function () { + if (that.vs) { + that.vsDownload(mainMenu, fileName, false); + } else { + that.download(mainMenu, fileName, false); } } - ]; - if (that.querySql) { + } + ]; + if (that.querySql) { + if (spQuerySQL) { + spQuerySQL.reset() menus.push({ - title: "Query (SQL)", icon: "file", clickHandler: () => { - showContent(spQuerySQL!) + title: "Query (SQL)", icon: "filesearch", clickHandler: () => { + showContent(spQuerySQL) } }); } - mainMenu.menus!.splice(1, 1, { - collapsed: false, - title: "Current Trace", - describe: "Actions on the current trace", - children: menus - }) - spSystemTrace!.loadDatabaseArrayBuffer(this.result as ArrayBuffer, (command: string, percent: number) => { - litSearch.setPercent(command + ' ', percent); - }, (res) => { - if (res.status) { + + if (spMetrics) { + spMetrics.reset() + menus.push({ + title: "Metrics", icon: "metric", clickHandler: () => { + showContent(spMetrics) + } + }); + } + + if (spInfoAndStats) { + menus.push({ + title: "Info and stats", icon: "info", clickHandler: () => { + showContent(spInfoAndStats) + } + }); + } + } + mainMenu.menus!.splice(1, 1, { + collapsed: false, + title: "Current Trace", + describe: "Actions on the current trace", + children: menus + }) + mainMenu.menus!.splice(2, 1, { + collapsed: false, + title: 'Support', + describe: 'Support', + children: [ + { + title: "Help Documents", + icon: "smart-help", + clickHandler: function (item: MenuItem) { + that.search = false + that.spHelp!.dark = that.dark + showContent(that.spHelp!) + } + }, + ] + }) + let wasmUrl = `https://${window.location.host.split(':')[0]}:${window.location.port}/application/wasm.json` + if (that.vs) { + wasmUrl = `http://${window.location.host.split(':')[0]}:${window.location.port}/wasm.json` + } + SpApplication.loadingProgress = 0; + SpApplication.progressStep = 3; + spSystemTrace!.loadDatabaseArrayBuffer(this.result as ArrayBuffer, wasmUrl,(command: string, percent: number) => { + setProgress(command) + }, (res) => { + if (res.status) { + info("loadDatabaseArrayBuffer success"); + showContent(spSystemTrace!) + litSearch.setPercent("", 101); + progressEL.loading = false; + that.freshMenuDisable(false) + } else { + info("loadDatabaseArrayBuffer failed"); + litSearch.setPercent("This File is not supported!", -1) + progressEL.loading = false; + that.freshMenuDisable(false) + mainMenu.menus!.splice(1, 1); + mainMenu.menus = mainMenu.menus!; + } + spInfoAndStats.initInfoAndStatsData(); + }) + } + }) + } + + function openTraceFile(ev: any, isClickHandle?: boolean) { + info("openTraceFile") + if (that.vs && isClickHandle) { + Cmd.openFileDialog().then((res: string) => { + if (res != "") { + litSearch.clear(); + showContent(spSystemTrace!) + that.search = true + progressEL.loading = true + let openResult = JSON.parse(res) + let fileName = openResult.fileName + let fileSize = (openResult.fileSize / 1048576).toFixed(1) + let showFileName = fileName.lastIndexOf('.') == -1 ? fileName : fileName.substring(0, fileName.lastIndexOf('.')) + document.title = `${showFileName} (${fileSize}M)` + TraceRow.rangeSelectObject = undefined; + if (that.server) { + info("Parse trace using server mode ") + handleServerMode(openResult.filePath, showFileName, fileSize, fileName, isClickHandle); + return; + } + if (that.wasm) { + info("Parse trace using wasm mode ") + const vsUpload = new FormData(); + vsUpload.append("convertType", "vsUpload"); + vsUpload.append("isTransform", ""); + vsUpload.append('filePath', openResult.filePath) + info("openResult.filePath ", openResult.filePath) + litSearch.setPercent("upload file ", 1); + Cmd.uploadFile(vsUpload, (response:Response) => { + if (response.ok) { + response.text().then(traceFile => { + let traceFilePath = `http://${window.location.host.split(':')[0]}:${window.location.port}` + traceFile + fetch(traceFilePath).then(res => { + res.arrayBuffer().then(arrayBuf => { + handleWasmMode( new File([arrayBuf],fileName), showFileName, fileSize, fileName); + }) + }) + }); + } + }) + return; + } + } else { + return; + } + }) + } else { + litSearch.clear(); + showContent(spSystemTrace!) + that.search = true + progressEL.loading = true + let fileName = (ev as any).name + let fileSize = ((ev as any).size / 1048576).toFixed(1) + postLog(fileName, fileSize) + let showFileName = fileName.lastIndexOf('.') == -1 ? fileName : fileName.substring(0, fileName.lastIndexOf('.')) + document.title = `${showFileName} (${fileSize}M)` + TraceRow.rangeSelectObject = undefined; + if (that.server) { + info("Parse trace using server mode ") + handleServerMode(ev, showFileName, fileSize, fileName); + return; + } + if (that.sqlite) { + info("Parse trace using sql mode") + litSearch.setPercent("", 0); + threadPool.init("sqlite").then(res => { + let reader = new FileReader(); + reader.readAsArrayBuffer(ev as any) + reader.onloadend = function (ev) { + SpApplication.loadingProgress = 0; + SpApplication.progressStep = 3; + spSystemTrace!.loadDatabaseArrayBuffer(this.result as ArrayBuffer, "",(command: string, percent: number) => { + setProgress(command) + }, () => { litSearch.setPercent("", 101); progressEL.loading = false; that.freshMenuDisable(false) - } else { - litSearch.setPercent("This File is not supported!", -1) - progressEL.loading = false; - that.freshMenuDisable(false) - mainMenu.menus!.splice(1, 1); - mainMenu.menus = mainMenu.menus!; - } - }) - } - }) - return; + }) + } + }) + return; + } + if (that.wasm) { + info("Parse trace using wasm mode ") + handleWasmMode(ev, showFileName, fileSize, fileName); + return; + } } } @@ -555,19 +823,41 @@ export class SpApplication extends BaseElement { { title: "Open trace file", icon: "folder", - fileChoose: true, + fileChoose: !that.vs, fileHandler: function (ev: InputEvent) { openTraceFile(ev.detail as any); + }, + clickHandler: function (hand: any) { + openTraceFile(hand, true); } }, { title: "Record new trace", icon: "copyhovered", clickHandler: function (item: MenuItem) { - that.search = false + if (that.vs) { + spRecordTrace!.vs = true; + spRecordTrace!.startRefreshDeviceList() + } showContent(spRecordTrace!) } } ] }, + { + collapsed: false, + title: 'Support', + describe: 'Support', + children: [ + { + title: "Help Documents", + icon: "smart-help", + clickHandler: function (item: MenuItem) { + that.search = false + that.spHelp!.dark = that.dark + showContent(that.spHelp!) + } + }, + ] + } ] let body = document.querySelector("body"); @@ -608,6 +898,166 @@ export class SpApplication extends BaseElement { } } }, false); + document.addEventListener("keydown", (event) => { + const e = event || window.event; + const ctrlKey = e.ctrlKey || e.metaKey; + if (ctrlKey && (this.keyCodeMap as any)[e.keyCode]) { + e.preventDefault(); + } else if (e.detail) { // Firefox + event.returnValue = false; + } + }) + document.body.addEventListener('wheel', (e) => { + if (e.ctrlKey) { + if (e.deltaY < 0) { + e.preventDefault(); + return false; + } + if (e.deltaY > 0) { + e.preventDefault(); + return false; + } + } + }, {passive: false}); + + let urlParams = this.getUrlParams(window.location.href); + if(urlParams && urlParams.trace && urlParams.link){ + litSearch.clear(); + showContent(spSystemTrace!) + that.search = true + progressEL.loading = true + let path = urlParams.trace as string + let fileName = path.split("/").reverse()[0] + let showFileName = fileName.lastIndexOf('.') == -1 ? fileName : fileName.substring(0, fileName.lastIndexOf('.')) + TraceRow.rangeSelectObject = undefined; + fetch(urlParams.trace).then(res => { + res.arrayBuffer().then(arrayBuf => { + let fileSize = (arrayBuf.byteLength / 1048576).toFixed(1) + postLog(fileName, fileSize) + document.title = `${showFileName} (${fileSize}M)` + info("Parse trace using wasm mode ") + handleWasmMode( new File([arrayBuf],fileName), showFileName, fileSize, fileName); + }) + }) + } + } + + private getUrlParams(url:string) { + const _url = url || window.location.href; + const _urlParams = _url.match(/([?&])(.+?=[^&]+)/igm); + return _urlParams ? _urlParams.reduce((a:any, b) => { + const value = b.slice(1).split('='); + a[`${value[0]}`] = decodeURIComponent(value[1]) + return a; + }, {}) : {}; + } + + private download(mainMenu: LitMainMenu, fileName: string, isServer: boolean, dbName?: string) { + let a = document.createElement("a"); + if (isServer) { + if (dbName != "") { + let file = dbName?.substring(0, dbName?.lastIndexOf(".")) + fileName.substring(fileName.lastIndexOf(".")); + a.href = `https://${window.location.host.split(':')[0]}:9000` + file + } else { + return; + } + } else { + a.href = URL.createObjectURL(new Blob([DbPool.sharedBuffer!])); + } + a.download = fileName; + a.click() + let querySelectorAll = mainMenu.shadowRoot?.querySelectorAll("lit-main-menu-group"); + querySelectorAll!.forEach((menuGroup) => { + let attribute = menuGroup.getAttribute("title"); + if (attribute === "Current Trace") { + let querySelectors = menuGroup.querySelectorAll("lit-main-menu-item"); + querySelectors.forEach(item => { + if (item.getAttribute("title") == "DownLoad") { + item!.setAttribute("icon", "convert-loading"); + let querySelector1 = + item!.shadowRoot?.querySelector(".icon") as LitIcon; + querySelector1.setAttribute('spin', '') + } + }) + } + }) + window.URL.revokeObjectURL(a.href); + let timer = setInterval(function () { + let querySelectorAll = mainMenu.shadowRoot?.querySelectorAll("lit-main-menu-group"); + querySelectorAll!.forEach((menuGroup) => { + let attribute = menuGroup.getAttribute("title"); + if (attribute === "Current Trace") { + let querySelectors = menuGroup.querySelectorAll("lit-main-menu-item"); + querySelectors.forEach(item => { + if (item.getAttribute("title") == "DownLoad") { + item!.setAttribute("icon", "download"); + let querySelector1 = + item!.shadowRoot?.querySelector(".icon") as LitIcon; + querySelector1.removeAttribute("spin"); + } + }) + clearInterval(timer); + } + }) + }, 4000); + } + + private vsDownload(mainMenu: LitMainMenu, fileName: string, isServer: boolean, dbName?: string) { + Cmd.showSaveFile((filePath: string) => { + if (filePath != "") { + let querySelectorAll = mainMenu.shadowRoot?.querySelectorAll("lit-main-menu-group"); + querySelectorAll!.forEach((menuGroup) => { + let attribute = menuGroup.getAttribute("title"); + if (attribute === "Current Trace") { + let querySelectors = menuGroup.querySelectorAll("lit-main-menu-item"); + querySelectors.forEach(item => { + if (item.getAttribute("title") == "DownLoad") { + item!.setAttribute("icon", "convert-loading"); + let querySelector1 = + item!.shadowRoot?.querySelector(".icon") as LitIcon; + querySelector1.setAttribute('spin', '') + } + }) + } + }) + if (isServer) { + if (dbName != "") { + let file = dbName?.substring(0, dbName?.lastIndexOf(".")) + fileName.substring(fileName.lastIndexOf(".")); + Cmd.copyFile(file, filePath, (res: Response) => { + this.stopDownLoading(mainMenu); + }) + } + } else { + const fd = new FormData() + fd.append("convertType", "download") + fd.append("filePath", filePath) + fd.append('file', new File([DbPool.sharedBuffer!], fileName)) + Cmd.uploadFile(fd, (res: Response) => { + if (res.ok) { + this.stopDownLoading(mainMenu); + } + }) + } + } + }) + } + + private stopDownLoading(mainMenu: LitMainMenu) { + let querySelectorAll = mainMenu.shadowRoot?.querySelectorAll("lit-main-menu-group"); + querySelectorAll!.forEach((menuGroup) => { + let attribute = menuGroup.getAttribute("title"); + if (attribute === "Current Trace") { + let querySelectors = menuGroup.querySelectorAll("lit-main-menu-item"); + querySelectors.forEach(item => { + if (item.getAttribute("title") == "DownLoad") { + item!.setAttribute("icon", "download"); + let querySelector1 = + item!.shadowRoot?.querySelector(".icon") as LitIcon; + querySelector1.removeAttribute("spin"); + } + }) + } + }) } freshMenuDisable(disable: boolean) { @@ -616,4 +1066,4 @@ export class SpApplication extends BaseElement { mainMenu.menus[0].children[0].disabled = disable mainMenu.menus = mainMenu.menus; } -} +} \ No newline at end of file diff --git a/host/ide/src/trace/bean/AbilityMonitor.ts b/host/ide/src/trace/bean/AbilityMonitor.ts new file mode 100644 index 0000000000000000000000000000000000000000..d3228d4fc2000b313e7185eabafafab8e1ae3de1 --- /dev/null +++ b/host/ide/src/trace/bean/AbilityMonitor.ts @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class SystemCpuSummary { + startTime: number = -1 + startTimeStr: string = ""; + duration: number = -1 + durationStr: string = "" + totalLoad: number = -1 + totalLoadStr: string = "" + userLoad: number = -1 + userLoadStr: string = "" + systemLoad: number = -1 + systemLoadStr: string = "" + threads: number = -1 + threadsStr: string = "" +} + +export class SystemDiskIOSummary { + startTime: number = -1 + startTimeStr: string = "" + duration: number = -1 + durationStr: string = "" + dataRead: number = -1 + dataReadStr: string = "" + dataReadSec: number = -1 + dataReadSecStr: string = "" + dataWrite: number = -1 + dataWriteStr: string = "" + dataWriteSec: number = -1 + dataWriteSecStr: string = "" + readsIn: number = -1 + readsInStr: string = "" + readsInSec: number = -1 + readsInSecStr: string = "" + writeOut: number = -1 + writeOutStr: string = "" + writeOutSec: number = -1 + writeOutSecStr: string = "" + +} + +export class ProcessHistory { + processId: number = -1 + alive: string = '' // 0 alive and 1 dead + firstSeen: string = '' + firstSeenNumber: number = -1 + lastSeen: string = '' + lastSeenNumber: number = -1 + processName: string = "" + responsibleProcess: string = "" + userName: string = "" + cpuTime: string = '' + cpuTimeNumber: number = -1 + pss: number = -1 +} + +export class LiveProcess { + processId: number = -1 + processName: string = "" + responsibleProcess: string = "" + userName: string = "" + cpu: string = '' + threads: number = -1 + memory: string = '' + memoryNumber: number = -1; + diskWrite: number = -1 + diskReads: number = -1 + cpuTime: string = "" + cpuTimeNumber: number = -1; +} + +export class SystemNetworkSummary { + startTime: number = -1 + startTimeStr: string = "" + duration: number = -1 + durationStr: string = "" + dataReceived: number = -1 + dataReceivedStr: string = "" + dataReceivedSec: number = -1 + dataReceivedSecStr: string = "" + dataSend: number = -1 + dataSendStr: string = "" + dataSendSec: number = -1 + dataSendSecStr: string = "" + packetsIn: number = -1 + packetsInStr: string = "" + packetsInSec: number = -1 + packetsInSecStr: string = "" + packetsOut: number = -1 + packetsOutStr: string = "" + packetsOutSec: number = -1 + packetsOutSecStr: string = "" +} + +export class SystemMemorySummary { + startTimeStr: string = "0" + durationStr: string = "0" + durationNumber: number = -1 + memoryTotal: string = "0"; + memFree: string = "0"; + buffers: string = "0"; + cached: string = "0"; + shmem: string = "0"; + slab: string = "0"; + swapTotal: string = "0"; + swapFree: string = "0"; + mapped: string = "0"; + vmallocUsed: string = "0"; + pageTables: string = "0"; + kernelStack: string = "0"; + active: string = "0"; + inactive: string = "0"; + unevictable: string = "0"; + vmallocTotal: string = "0"; + sUnreclaim: string = "0"; + kReclaimable: string = "0"; + cmaTotal: string = "0"; + cmaFree: string = "0"; + zram: string = "0"; +} \ No newline at end of file diff --git a/host/ide/src/trace/bean/BoxSelection.ts b/host/ide/src/trace/bean/BoxSelection.ts index 788e3c1c035ae492fc446c81462967b02bcac4c2..85f9549597701212c8d17d838803335397018f4f 100644 --- a/host/ide/src/trace/bean/BoxSelection.ts +++ b/host/ide/src/trace/bean/BoxSelection.ts @@ -13,17 +13,53 @@ * limitations under the License. */ +import {CpuFreqLimitsStruct} from "../database/ui-worker/ProcedureWorkerCpuFreqLimits.js"; + export class SelectionParam { + recordStartNs:number = 0 + leftNs: number = 0; + rightNs: number = 0; + hasFps: boolean = false; + statisticsSelectData: any = undefined + fileSystemVMData: any = undefined; + fileSystemIoData: any = undefined; + fileSystemFsData: any = undefined; + perfAll: boolean = false; + fileSysVirtualMemory: boolean = false; + diskIOLatency:boolean = false; + fsCount:number = 0; + vmCount:number = 0; + cpus: Array = []; + cpuStateFilterIds: Array = []; + cpuFreqFilterIds: Array = []; + cpuFreqLimitDatas:Array> = []; threadIds: Array = []; - trackIds: Array = []; + processTrackIds: Array = []; + virtualTrackIds: Array = []; funTids: Array = []; + funAsync: Array<{name:string,pid:number}> = []; heapIds: Array = []; - nativeMemory:Array = []; - leftNs: number = 0; - rightNs: number = 0; - hasFps: boolean = false; - statisticsSelectData:any = undefined + nativeMemory: Array = []; + cpuAbilityIds: Array = [] + memoryAbilityIds: Array = [] + diskAbilityIds: Array = [] + networkAbilityIds: Array = [] + perfSampleIds: Array = []; + perfCpus: Array = []; + perfProcess: Array = []; + perfThread: Array = []; + fileSystemType:Array = []; + sdkCounterIds: Array = []; + sdkSliceIds: Array = []; + diskIOipids:Array = []; + diskIOReadIds:Array = [] + diskIOWriteIds:Array = [] + systemEnergy: Array = [] + powerEnergy: Array = [] + anomalyEnergy: Array = [] + smapsType:Array = []; + promiseList:Array> = [] } export class BoxJumpParam { diff --git a/host/ide/src/trace/bean/CpuAbilityMonitorStruct.ts b/host/ide/src/trace/bean/CpuAbilityMonitorStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..05b56c2c4978459bebab81681c7bc7bb83c267b5 --- /dev/null +++ b/host/ide/src/trace/bean/CpuAbilityMonitorStruct.ts @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseStruct} from "./BaseStruct.js"; + +export class CpuAbilityMonitorStruct extends BaseStruct { + static maxCpuUtilization: number = 0 + static maxCpuUtilizationName: string = "0 %" + static hoverCpuAbilityStruct: CpuAbilityMonitorStruct | undefined; + static selectCpuAbilityStruct: CpuAbilityMonitorStruct | undefined; + + type: number | undefined + value: number | undefined + startNS: number | undefined + dur: number | undefined +} diff --git a/host/ide/src/trace/bean/CpuFreqStruct.ts b/host/ide/src/trace/bean/CpuFreqStruct.ts index 19d3ed70fb9637762eddf36a2824d4aa5ffa9e0e..6dd18e889b9b69f68013957195a0076aebf23c85 100644 --- a/host/ide/src/trace/bean/CpuFreqStruct.ts +++ b/host/ide/src/trace/bean/CpuFreqStruct.ts @@ -13,8 +13,8 @@ * limitations under the License. */ +import { ColorUtils } from "../component/trace/base/ColorUtils.js"; import {BaseStruct} from "./BaseStruct.js"; -import {ColorUtils} from "../database/ProcedureWorkerCommon.js"; export class CpuFreqStruct extends BaseStruct { static maxFreq: number = 0 diff --git a/host/ide/src/trace/bean/DiskAbilityMonitorStruct.ts b/host/ide/src/trace/bean/DiskAbilityMonitorStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..ed49f97f17ae9a30fcd00c9610c23e1a88eeeca7 --- /dev/null +++ b/host/ide/src/trace/bean/DiskAbilityMonitorStruct.ts @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ColorUtils } from "../component/trace/base/ColorUtils.js"; +import {BaseStruct} from "./BaseStruct.js"; + +export class DiskAbilityMonitorStruct extends BaseStruct { + static maxDiskRate: number = 0 + static maxDiskRateName: string = "0 KB/S" + static hoverDiskAbilityStruct: DiskAbilityMonitorStruct | undefined; + static selectDiskAbilityStruct: DiskAbilityMonitorStruct | undefined; + cpu: number | undefined + value: number | undefined + startNS: number | undefined + dur: number | undefined + + static draw(context2D: any, data: DiskAbilityMonitorStruct) { + if (data.frame) { + let width = data.frame.width || 0; + let index = data.cpu || 0 + index += 2 + context2D.fillStyle = ColorUtils.colorForTid(index) + context2D.strokeStyle = ColorUtils.colorForTid(index) + if (data.startNS === DiskAbilityMonitorStruct.hoverDiskAbilityStruct?.startNS) { + context2D.lineWidth = 1; + context2D.globalAlpha = 0.6; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / DiskAbilityMonitorStruct.maxDiskRate); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + context2D.beginPath() + context2D.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight, 3, 0, 2 * Math.PI, true) + context2D.fill() + context2D.globalAlpha = 1.0; + context2D.stroke(); + context2D.beginPath() + context2D.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight); + context2D.lineWidth = 3; + context2D.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight) + context2D.stroke(); + } else { + context2D.globalAlpha = 0.6; + context2D.lineWidth = 1; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0)) / DiskAbilityMonitorStruct.maxDiskRate); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + } + } + context2D.globalAlpha = 1.0; + context2D.lineWidth = 1; + } +} diff --git a/host/ide/src/trace/bean/EnergyStruct.ts b/host/ide/src/trace/bean/EnergyStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..4ff7b41d87413783ed53a826ac6c25c2edbc4b08 --- /dev/null +++ b/host/ide/src/trace/bean/EnergyStruct.ts @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseStruct} from "./BaseStruct.js"; + +export class EnergyAnomalyStruct extends BaseStruct { + static hoverEnergyAnomalyStruct: EnergyAnomalyStruct | undefined; + static selectEnergyAnomalyStruct: EnergyAnomalyStruct | undefined; + type: number | undefined + startNS: number | undefined + height: number | undefined + eventName: string | undefined +} + +export class EnergySystemStruct extends BaseStruct { + static hoverEnergySystemStruct: EnergySystemStruct | undefined; + static selectEnergySystemStruct: EnergySystemStruct | undefined; + type: number | undefined + startNs: number | undefined + dur: number | undefined + count: number | undefined + workScheduler: string | undefined + power: string | undefined + location: string | undefined +} + +export class EnergyPowerStruct extends BaseStruct { + static maxPower: number = 0 + static maxPowerName: string = "0 %" + static powerItemNumber: number = 9 + static colorIndex: number = 2; + static currentTextWidth: number = 0 + static rowHeight: number = 200 + static appName: string | undefined + static hoverEnergyPowerStruct: EnergyPowerStruct | undefined; + static selectEnergyPowerStruct: EnergyPowerStruct | undefined; + name: string | undefined // appName + ts: number = 0 + cpu: number = 0 + location: number = 0 + gpu: number = 0 + display: number = 0 + camera: number = 0 + bluetooth: number = 0 + flashlight: number = 0 + audio: number = 0 + wifiscan: number = 0 +} + +export class EnergyStateStruct extends BaseStruct { + static maxState: number = 0 + static maxStateName: string = "0" + static hoverEnergyStateStruct: EnergyStateStruct | undefined; + static selectEnergyStateStruct: EnergyStateStruct | undefined; + type: string | undefined + value: number | undefined + startNs: number | undefined + dur: number | undefined + + sensorType: number | undefined + pkg_name: string | undefined + deviceState: number | undefined + deviceType: number | undefined +} + +export class PowerDetailsEnergy { + constructor(eventName: string) { + this.event = eventName; + } + + event: string = "" + charge: number = 0 + background_time: number = 0 + screen_on_time: number = 0 + screen_off_time: number = 0 + load: string = "-" + usage: number = 0 + duration: number = 0 + camera_id: number = 0 + foreground_count: number = 0 + background_count: number = 0 + screen_on_count: number = 0 + screen_off_count: number = 0 + count: number = 0 + appName: string = "" + uid: number = 0 + foreground_duration: number = 0 + foreground_energy: number = 0 + background_duration: number = 0 + background_energy: number = 0 + screen_on_duration: number = 0 + screen_on_energy: number = 0 + screen_off_duration: number = 0 + screen_off_energy: number = 0 + energy: number = 0 + energyConsumptionRatio: string = "" + + getTotalEnergy(isSimpleEnergy: boolean): number { + if (isSimpleEnergy) { + return this.energy + } + return this.foreground_energy + this.background_energy + this.screen_on_energy + this.screen_off_energy + } +} + + +export class PowerBatteryEnergy { + gasGauge: number = -1 + charge: number = -1 + screen: number = -1 + level: number = -1 + current: number = -1 + capacity: number = -1 + appName: string = "" + uid: number = -1 +} + +export class SystemDetailsEnergy { + ts: number = 0 + eventName: string = "" + type: string = "" + pid: number = -1 + uid: number = -1 + state: number = -1 + workId: string = "" + name: string = "" + interval: number = -1 + level: number = -1 + tag: string = "" + message: string = "" + log_level: string = "" +} + + diff --git a/host/ide/src/trace/bean/FrameChartStruct.ts b/host/ide/src/trace/bean/FrameChartStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..5df31fe64012795547a933cf4e01472e0e00abaf --- /dev/null +++ b/host/ide/src/trace/bean/FrameChartStruct.ts @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { SpApplication } from "../SpApplication.js"; +import { BaseStruct } from "./BaseStruct.js"; +import { Rect } from "../component/trace/timer-shaft/Rect.js"; +import { info } from "../../log/Log.js"; + +const padding: number = 1; + +export class ChartStruct extends BaseStruct { + static hoverFuncStruct: ChartStruct | undefined; + static selectFuncStruct: ChartStruct | undefined; + static lastSelectFuncStruct: ChartStruct | undefined; + needShow = false; + depth: number = 0; + symbol: string = ''; + lib: string = ''; + size: number = 0; + count: number = 0; + dur: number = 0; + type: ChartMode = ChartMode.Call; + parent: ChartStruct | undefined; + children: Array = []; + percent: number = 0; + addr : string = ""; +} + + +export enum ChartMode { + Call, + Byte, + Count, + Duration, +} + +export function setFuncFrame(node: ChartStruct, canvas_frame: Rect, total: number, mode: ChartMode) { + if (!node.frame) { + node.frame = new Rect(0, 0, 0, 0); + } + // filter depth is 0 + if (node.parent) { + let idx = node.parent.children.indexOf(node); + if (idx == 0) { + node.frame!.x = node.parent.frame!.x; + } else { + // set x by left frame. left frame is parent.children[idx - 1] + node.frame.x = node.parent.children[idx - 1].frame!.x + node.parent.children[idx - 1].frame!.width + } + switch (mode) { + case ChartMode.Byte: + node.frame!.width = Math.floor(node.size / total * canvas_frame.width); + break; + case ChartMode.Count: + node.frame!.width = Math.floor(node.count / total * canvas_frame.width); + break; + case ChartMode.Duration: + node.frame!.width = Math.floor(node.dur / total * canvas_frame.width); + break; + default: + info('not match ChartMode'); + } + node.frame!.y = node.parent.frame!.y + 20; + node.frame!.height = 20; + } +} + + +/** + * draw rect + * @param ctx CanvasRenderingContext2D + * @param data rect which is need draw + * @param percent function size or count / total size or count + */ +export function draw(ctx: CanvasRenderingContext2D, data: ChartStruct) { + let spApplication = document.getElementsByTagName("sp-application")[0] + if (data.frame) { + // draw rect + let miniHeight = 20; + if (isSelected(data)) { + ctx.fillStyle = `rgba(${82}, ${145}, ${255}, 0.9)`; + } else { + let color = getHeatColor(data.percent); + ctx.fillStyle = `rgba(${color.r}, ${color.g}, ${color.b}, 0.9)`; + } + ctx.fillRect(data.frame.x, data.frame.y, data.frame.width, miniHeight - padding * 2); + //draw border + if (isHover(data)) { + if (spApplication.dark) { + ctx.strokeStyle = "#fff"; + } else { + ctx.strokeStyle = "#000"; + } + } else { + if (spApplication.dark) { + ctx.strokeStyle = "#000"; + } else { + ctx.strokeStyle = "#fff"; + } + } + ctx.lineWidth = 0.4; + ctx.strokeRect(data.frame.x, data.frame.y, data.frame.width, miniHeight - padding * 2); + + //draw symbol name + if (data.frame.width > 10) { + if (data.percent > 0.6 || isSelected(data)) { + ctx.fillStyle = "#fff"; + } else { + ctx.fillStyle = "#000"; + } + drawString(ctx, data.symbol || '', 5, data.frame); + } + } +} + +/** + * get frame chart color by percent + * @param widthPercentage proportion of function + * @returns rbg + */ +function getHeatColor(widthPercentage: number) { + return { + r: Math.floor(245 + 10 * (1 - widthPercentage)), + g: Math.floor(110 + 105 * (1 - widthPercentage)), + b: 100, + }; +} + +/** + * draw function string in rect + * @param ctx CanvasRenderingContext2D + * @param str function Name + * @param textPadding textPadding + * @param frame canvas area + * @returns is draw + */ +function drawString(ctx: CanvasRenderingContext2D, str: string, textPadding: number, frame: Rect): boolean { + let textMetrics = ctx.measureText(str); + let charWidth = Math.round(textMetrics.width / str.length) + if (textMetrics.width < frame.width - textPadding * 2) { + let x2 = Math.floor(frame.width / 2 - textMetrics.width / 2 + frame.x + textPadding) + ctx.fillText(str, x2, Math.floor(frame.y + frame.height / 2 + 2), frame.width - textPadding * 2) + return true; + } + if (frame.width - textPadding * 2 > charWidth * 4) { + let chatNum = (frame.width - textPadding * 2) / charWidth; + let x1 = frame.x + textPadding + ctx.fillText(str.substring(0, chatNum - 4) + '...', x1, Math.floor(frame.y + frame.height / 2 + 2), frame.width - textPadding * 2) + return true; + } + return false; +} + +function isHover(data: ChartStruct): boolean { + return ChartStruct.hoverFuncStruct == data; +} + +function isSelected(data: ChartStruct): boolean { + return ChartStruct.lastSelectFuncStruct == data; +} diff --git a/host/ide/src/trace/bean/FuncStruct.ts b/host/ide/src/trace/bean/FuncStruct.ts index d4b2ca911db1475a5dbd30f71548315397aeafe3..9905c9b0a669bd43046efc51ffbbd3179b9911ec 100644 --- a/host/ide/src/trace/bean/FuncStruct.ts +++ b/host/ide/src/trace/bean/FuncStruct.ts @@ -31,6 +31,7 @@ export class FuncStruct extends BaseStruct { startTs: number | undefined threadName: string | undefined tid: number | undefined + identify:number |undefined track_id: number | undefined static draw(ctx: CanvasRenderingContext2D, data: FuncStruct) { @@ -88,6 +89,18 @@ export class FuncStruct extends BaseStruct { return false; } } + + static isBinderAsync(data: FuncStruct): boolean { + if (data.funName != null && + ( + data.funName.toLowerCase().includes("async") + ) + ) { + return true; + } else { + return false; + } + } } const padding = 1; diff --git a/host/ide/src/trace/bean/HeapBean.ts b/host/ide/src/trace/bean/HeapBean.ts index ec7541f0fec433d4d134b3c515edc51642117279..b001dfdfcd468e68afd620a0ff60474f36883421 100644 --- a/host/ide/src/trace/bean/HeapBean.ts +++ b/host/ide/src/trace/bean/HeapBean.ts @@ -13,15 +13,15 @@ * limitations under the License. */ -export class HeapBean{ - MoudleName:string|undefined - AllocationFunction:string|undefined - Allocations:number|string = 0 - Deallocations:number|string= 0 - AllocationSize:number|string= 0 - DeAllocationSize:number|string= 0 - Total:number|string= 0 - RemainingSize:number|string= 0 - children:HeapBean[] = [] - depth:number = 0 +export class HeapBean { + MoudleName: string | undefined + AllocationFunction: string | undefined + Allocations: number | string = 0 + Deallocations: number | string = 0 + AllocationSize: number | string = 0 + DeAllocationSize: number | string = 0 + Total: number | string = 0 + RemainingSize: number | string = 0 + children: HeapBean[] = [] + depth: number = 0 } \ No newline at end of file diff --git a/host/ide/src/trace/bean/HeapStruct.ts b/host/ide/src/trace/bean/HeapStruct.ts index 123ed31c6ab43f75a7e2f2afa679ea8ece08fb25..9a0bd5aa971d046774429d98558266135bf2845a 100644 --- a/host/ide/src/trace/bean/HeapStruct.ts +++ b/host/ide/src/trace/bean/HeapStruct.ts @@ -22,8 +22,9 @@ export class HeapStruct extends BaseStruct { startTime: number | undefined endTime: number | undefined dur: number | undefined - eventType:string | undefined + eventType: string | undefined heapsize: number | undefined + density: number | undefined maxHeapSize: number = 0 minHeapSize: number = 0 diff --git a/host/ide/src/trace/bean/HeapTreeDataBean.ts b/host/ide/src/trace/bean/HeapTreeDataBean.ts index a155a5865f7b112c7b9a4e52ed0b4d2cf5a07ae7..3c2d226558c15a2e01dc2d8ff78f586cfb0b2330 100644 --- a/host/ide/src/trace/bean/HeapTreeDataBean.ts +++ b/host/ide/src/trace/bean/HeapTreeDataBean.ts @@ -13,13 +13,15 @@ * limitations under the License. */ -export class HeapTreeDataBean{ - MoudleName:string|undefined - AllocationFunction:string|undefined - startTs:number = 0 - endTs:number = 0 - eventType:string|undefined - depth:number = 0 - heapSize:number = 0 - eventId:string="" +export class HeapTreeDataBean { + MoudleName: string | undefined + AllocationFunction: string | undefined + symbolId: number = 0 + fileId: number = 0 + startTs: number = 0 + endTs: number = 0 + eventType: string | undefined + depth: number = 0 + heapSize: number = 0 + eventId: string = "" } \ No newline at end of file diff --git a/host/ide/src/trace/bean/MemoryAbilityMonitorStruct.ts b/host/ide/src/trace/bean/MemoryAbilityMonitorStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..49fa2984fc2dccccd561fb7fe83281c0554663e8 --- /dev/null +++ b/host/ide/src/trace/bean/MemoryAbilityMonitorStruct.ts @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ColorUtils } from "../component/trace/base/ColorUtils.js"; +import {BaseStruct} from "./BaseStruct.js"; + +export class MemoryAbilityMonitorStruct extends BaseStruct { + static maxMemoryByte: number = 0 + static maxMemoryByteName: string = "0 MB" + static hoverMemoryAbilityStruct: MemoryAbilityMonitorStruct | undefined; + static selectMemoryAbilityStruct: MemoryAbilityMonitorStruct | undefined; + cpu: number | undefined + value: number | undefined + startNS: number | undefined + dur: number | undefined + + static draw(context2D: any, data: MemoryAbilityMonitorStruct) { + if (data.frame) { + let width = data.frame.width || 0; + let index = data.cpu || 0 + index += 2 + context2D.fillStyle = ColorUtils.colorForTid(index) + context2D.strokeStyle = ColorUtils.colorForTid(index) + if (data.startNS === MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct?.startNS) { + context2D.lineWidth = 1; + context2D.globalAlpha = 0.6; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / MemoryAbilityMonitorStruct.maxMemoryByte); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + context2D.beginPath() + context2D.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight, 3, 0, 2 * Math.PI, true) + context2D.fill() + context2D.globalAlpha = 1.0; + context2D.stroke(); + context2D.beginPath() + context2D.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight); + context2D.lineWidth = 3; + context2D.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight) + context2D.stroke(); + } else { + context2D.globalAlpha = 0.6; + context2D.lineWidth = 1; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0)) / MemoryAbilityMonitorStruct.maxMemoryByte); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + } + } + context2D.globalAlpha = 1.0; + context2D.lineWidth = 1; + } +} diff --git a/host/ide/src/trace/bean/NativeHook.ts b/host/ide/src/trace/bean/NativeHook.ts index 99168e0009843c259d8ab533fbc0ec995c41ecd4..15068824d6435a98af36c082724373aef72bdee4 100644 --- a/host/ide/src/trace/bean/NativeHook.ts +++ b/host/ide/src/trace/bean/NativeHook.ts @@ -14,103 +14,102 @@ */ import {Utils} from "../component/trace/base/Utils.js"; +import {ChartStruct} from "../bean/FrameChartStruct.js"; -export class NativeHookStatistics{ - eventId:number = 0; - eventType:string = ""; - subType:string = ""; - heapSize:number = 0; - addr:string = ""; - startTs:number = 0; - endTs:number = 0; - sumHeapSize:number = 0; - max:number = 0; - count:number = 0; - tid:number = 0; - isSelected:boolean = false; -} - -export class NativeHookMalloc{ - eventType:string = ""; - subType:string = ""; - heapSize:number = 0; - allocByte:number = 0; - allocCount:number = 0; - freeByte:number = 0; - freeCount:number = 0; +export class NativeHookStatistics { + eventId: number = 0; + eventType: string = ""; + subType: string = ""; + subTypeId: number = 0; + heapSize: number = 0; + addr: string = ""; + startTs: number = 0; + endTs: number = 0; + sumHeapSize: number = 0; + max: number = 0; + count: number = 0; + tid: number = 0; + threadName: string = ""; + isSelected: boolean = false; } -export class NativeEventHeap{ - eventType:string = ""; - sumHeapSize:number = 0 +export class NativeHookMalloc { + eventType: string = ""; + subType: string = ""; + subTypeId: number = 0; + heapSize: number = 0; + allocByte: number = 0; + allocCount: number = 0; + freeByte: number = 0; + freeCount: number = 0; + max: number = 0; } -export class NativeHookProcess{ - ipid:number = 0; - pid:number = 0; - name:String = "" +export class NativeEventHeap { + eventType: string = ""; + sumHeapSize: number = 0 } -export class NativeHookStatisticsTableData{ - memoryTap:string = ""; - existing:number = 0; - existingString:string = ""; - allocCount:number = 0; - freeCount:number = 0; - totalBytes:number = 0 - totalBytesString:string = ""; - maxStr:string = ""; - max:number = 0 - totalCount:number = 0; - existingValue:Array = []; +export class NativeHookProcess { + ipid: number = 0; + pid: number = 0; + name: String = "" } -export class NativeMemory{ - index:number = 0; - eventId:number = 0; - eventType:string = ""; - subType:string = ""; - addr:string = ""; - startTs:number = 0; - timestamp:string = "" - heapSize:number = 0; - heapSizeUnit:string = ""; - symbol:string = ""; - library:string = ""; +export class NativeHookStatisticsTableData { + memoryTap: string = ""; + existing: number = 0; + existingString: string = ""; + freeByteString: string = ""; + allocCount: number = 0; + freeCount: number = 0; + freeByte: number = 0; + totalBytes: number = 0 + totalBytesString: string = ""; + maxStr: string = ""; + max: number = 0 + totalCount: number = 0; + existingValue: Array = []; } -export class NativeHookCallInfo{ - id:string = ""; - pid:string | undefined; +export class NativeMemory { + index: number = 0; + eventId: number = 0; + eventType: string = ""; + subType: string = ""; + addr: string = ""; + startTs: number = 0; + endTs: number = 0; + timestamp: string = "" + heapSize: number = 0; + heapSizeUnit: string = ""; + symbol: string = ""; + library: string = ""; + isSelected: boolean = false; + state:string = ""; threadId:number = 0; - symbol:string = ""; - library:string = ""; - title:string = ""; - count:number = 0; - type:number = 0; - heapSize:number = 0; - heapSizeStr:string = ""; - eventId:number = 0 - depth:number = 0; - children:Array = []; + threadName:string = ""; } export class NativeHookSamplerInfo { - current:string = "" - currentSize:number = 0 - startTs:number = 0; - heapSize:number = 0; - snapshot:string = ""; - growth:string = ""; - total:number = 0; - totalGrowth:string = "" - existing:number = 0; - children:Array = []; - tempList:Array = []; - timestamp:string = "" - eventId:number = -1 - merageObj(merageObj:NativeHookSamplerInfo){ - this.currentSize+=merageObj.currentSize + current: string = "" + currentSize: number = 0 + startTs: number = 0; + heapSize: number = 0; + snapshot: string = ""; + growth: string = ""; + total: number = 0; + totalGrowth: string = "" + existing: number = 0; + children: Array = []; + tempList: Array = []; + timestamp: string = "" + eventId: number = -1 + threadId:number = 0; + threadName:string = ""; + + merageObj(merageObj: NativeHookSamplerInfo) { + this.currentSize += merageObj.currentSize this.heapSize += merageObj.heapSize this.existing += merageObj.existing this.total += merageObj.total @@ -121,15 +120,43 @@ export class NativeHookSamplerInfo { } export class NativeHookSampleQueryInfo { - eventId:number = -1 - current:number = 0 + eventId: number = -1 + current: number = 0 + eventType: string = ""; + subType: string = ""; + subTypeId: number = 0; + growth: number = 0; + existing: number = 0; + addr: string = ""; + startTs: number = 0; + endTs: number = 0; + total: number = 0; + threadId:number = 0; + threadName:string = ""; + children: Array = []; +} + +export class NativeHookCallInfo extends ChartStruct { + id: string = ""; + pid: string | undefined; + library: string = ""; + symbolId:number = 0; + title: string = ""; + count: number = 0; + countValue:string = "" + countPercent: string = ""; + type: number = 0; + heapSize: number = 0; + heapPercent: string = ""; + heapSizeStr: string = ""; + eventId: number = 0; + threadId: number = 0; + threadName: string = ""; + isSelected: boolean = false; +} + +export class NativeEvent { + startTime:number = 0; + heapSize:number = 0; eventType:string = ""; - subType:string = ""; - growth:number = 0; - existing:number = 0; - addr:string = ""; - startTs:number = 0; - endTs:number = 0; - total:number = 0; - children:Array = []; } \ No newline at end of file diff --git a/host/ide/src/trace/bean/NetworkAbilityMonitorStruct.ts b/host/ide/src/trace/bean/NetworkAbilityMonitorStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..ff2f563d0c9ada6b04d49a155a97bd3a6bd4f8aa --- /dev/null +++ b/host/ide/src/trace/bean/NetworkAbilityMonitorStruct.ts @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ColorUtils } from "../component/trace/base/ColorUtils.js"; +import {BaseStruct} from "./BaseStruct.js"; + +export class NetworkAbilityMonitorStruct extends BaseStruct { + static maxNetworkRate: number = 0 + static maxNetworkRateName: string = "0 KB/S" + static hoverNetworkAbilityStruct: NetworkAbilityMonitorStruct | undefined; + static selectNetworkAbilityStruct: NetworkAbilityMonitorStruct | undefined; + value: number | undefined + startNS: number | undefined + dur: number | undefined + + static draw(context2D: any, data: NetworkAbilityMonitorStruct) { + if (data.frame) { + let width = data.frame.width || 0; + let index = 0 + index += 2 + context2D.fillStyle = ColorUtils.colorForTid(index) + context2D.strokeStyle = ColorUtils.colorForTid(index) + if (data.startNS === NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct?.startNS) { + context2D.lineWidth = 1; + context2D.globalAlpha = 0.6; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / NetworkAbilityMonitorStruct.maxNetworkRate); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + context2D.beginPath() + context2D.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight, 3, 0, 2 * Math.PI, true) + context2D.fill() + context2D.globalAlpha = 1.0; + context2D.stroke(); + context2D.beginPath() + context2D.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight); + context2D.lineWidth = 3; + context2D.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight) + context2D.stroke(); + } else { + context2D.globalAlpha = 0.6; + context2D.lineWidth = 1; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0)) / NetworkAbilityMonitorStruct.maxNetworkRate); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + } + } + context2D.globalAlpha = 1.0; + context2D.lineWidth = 1; + } +} diff --git a/host/ide/src/trace/bean/PerfProfile.ts b/host/ide/src/trace/bean/PerfProfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..d7b738c090b3ab1d425bb74b9819cff26fb8575b --- /dev/null +++ b/host/ide/src/trace/bean/PerfProfile.ts @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {Utils} from "../component/trace/base/Utils.js"; +import {ChartStruct} from "../../trace/bean/FrameChartStruct.js"; +import {SpHiPerf} from "../component/chart/SpHiPerf.js"; + +export class PerfFile { + fileId: number = 0; + symbol: string = "" + path: string = "" + fileName: string = "" + + static setFileName(data: PerfFile) { + if (data.path) { + let number = data.path.lastIndexOf("/"); + if (number > 0) { + data.fileName = data.path.substring(number + 1) + return + } + } + data.fileName = data.path + } + + setFileName() { + if (this.path) { + let number = this.path.lastIndexOf("/"); + if (number > 0) { + this.fileName = this.path.substring(number + 1) + return + } + } + this.fileName = this.path + } +} + +export class PerfThread { + tid: number = 0; + pid: number = 0; + threadName: string = ""; + processName: string = ""; +} + +export class PerfCall{ + sampleId: number = 0; + depth: number = 0; + name: string = ""; +} + +export class PerfCallChain { + tid: number = 0; + pid: number = 0; + name: string = "" + fileName: string = ""; + threadState: string = ""; + startNS: number = 0; + dur: number = 0; + sampleId: number = 0; + callChainId: number = 0; + vaddrInFile: number = 0; + fileId: number = 0; + symbolId: number = 0; + path: string = ""; + parentId: string = ""//合并之后区分的id + id: string = "" + topDownMerageId: string = ""//top down合并使用的id + topDownMerageParentId: string = ""//top down合并使用的id + bottomUpMerageId: string = ""//bottom up合并使用的id + bottomUpMerageParentId: string = ""//bottom up合并使用的id + depth: number = 0; + canCharge:boolean = true + previousNode: PerfCallChain | undefined = undefined;//将list转换为一个链表结构 + nextNode: PerfCallChain | undefined = undefined; + + static setNextNode(currentNode: PerfCallChain, nextNode: PerfCallChain) { + currentNode.nextNode = nextNode + nextNode.previousNode = currentNode + } + + static setPreviousNode(currentNode: PerfCallChain, prevNode: PerfCallChain) { + currentNode.previousNode = prevNode + prevNode.nextNode = currentNode + } + + static merageCallChain(currentNode: PerfCallChain, callChain: PerfCallChain) { + currentNode.startNS = callChain.startNS + currentNode.tid = callChain.tid + currentNode.pid = callChain.pid + currentNode.sampleId = callChain.sampleId + currentNode.dur = callChain.dur + } + +} + +export class PerfCallChainMerageData extends ChartStruct { + #parentNode: PerfCallChainMerageData | undefined = undefined + #total = 0 + id: string = ""; + parentId: string = ""; + currentTreeParentNode: PerfCallChainMerageData | undefined = undefined; + symbolName: string = ""; + symbol: string = "" + libName: string = "" + path: string = "" + self: string = "0s" + weight: string = "" + weightPercent: string = "" + selfDur: number = 0; + dur: number = 0; + tid: number = 0; + pid: number = 0; + isStore = 0; + canCharge:boolean = true + children: PerfCallChainMerageData[] = [] + initChildren: PerfCallChainMerageData[] = [] + type: number = 0; + vaddrInFile: number = 0; + isSelected: boolean = false; + searchShow: boolean = true; + + set parentNode(data: PerfCallChainMerageData | undefined) { + this.currentTreeParentNode = data; + this.#parentNode = data; + } + + get parentNode() { + return this.#parentNode + } + + set total(data: number) { + this.#total = data; + this.weight = `${Utils.timeMsFormat2p(this.dur * (SpHiPerf.stringResult?.fValue || 1))}` + this.weightPercent = `${(this.dur / data * 100).toFixed(1)}%` + } + + get total() { + return this.#total; + } + + static merageCallChain(currentNode: PerfCallChainMerageData, callChain: PerfCallChain, isTopDown: boolean) { + if (currentNode.symbolName == "") { + currentNode.symbol = `${callChain.name} ${callChain.fileName ? `(${callChain.fileName})` : ""}` + currentNode.symbolName = callChain.name + currentNode.pid = callChain.pid + currentNode.tid = callChain.tid + currentNode.libName = callChain.fileName + currentNode.vaddrInFile = callChain.vaddrInFile; + currentNode.canCharge = callChain.canCharge + if (callChain.path) { + currentNode.path = callChain.path + } + } + if (callChain[isTopDown ? "nextNode" : "previousNode"] == undefined) { + currentNode.selfDur++; + currentNode.self = Utils.timeMsFormat2p(currentNode.selfDur) + } + currentNode.dur++; + currentNode.count++; + } +} + +export class PerfSample { + sampleId: number = 0; + time: number = 0; + timeString: string = ""; + core: number = 0; + coreName: string = ""; + state: string = ""; + pid: number = 0; + processName: string = ""; + tid: number = 0; + threadName: string = ""; + depth: number = 0; + addr: string = ""; + fileId: number = 0; + symbolId: number = 0; + backtrace: Array = []; +} + +export class PerfStack { + symbol: string = ""; + symbolId: number = 0; + path: string = ""; + fileId: number = 0; + type: number = 0; + vaddrInFile: number = 0; +} + +export class PerfCmdLine { + report_value: string = ""; +} \ No newline at end of file diff --git a/host/ide/src/trace/bean/ProcessMemStruct.ts b/host/ide/src/trace/bean/ProcessMemStruct.ts index 636722b714d5906408c63d0c75d9bb58ec8023ce..05384e7d09034a426be41194c5656be06ad01f27 100644 --- a/host/ide/src/trace/bean/ProcessMemStruct.ts +++ b/host/ide/src/trace/bean/ProcessMemStruct.ts @@ -17,6 +17,7 @@ import {BaseStruct} from "./BaseStruct.js"; import {ColorUtils} from "../component/trace/base/ColorUtils.js"; export class ProcessMemStruct extends BaseStruct { + static hoverProcessMemStruct: ProcessMemStruct | undefined; trackId: number | undefined processName: string | undefined pid: number | undefined @@ -33,12 +34,29 @@ export class ProcessMemStruct extends BaseStruct { static draw(ctx: CanvasRenderingContext2D, data: ProcessMemStruct) { if (data.frame) { let width = data.frame.width || 0; - ctx.fillStyle = ColorUtils.colorForTid(data.maxValue || 0) - ctx.strokeStyle = ColorUtils.colorForTid(data.maxValue || 0) - ctx.globalAlpha = 0.6; - ctx.lineWidth = 1; - let drawHeight: number = ((data.value || 0) * (data.frame.height || 0) * 1.0) / (data.maxValue || 1); - ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + if (data.startTime === ProcessMemStruct.hoverProcessMemStruct?.startTime) { + ctx.lineWidth = 1; + ctx.globalAlpha = 0.6; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / (data.maxValue || 0)); + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + ctx.beginPath() + ctx.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight, 3, 0, 2 * Math.PI, true) + ctx.fill() + ctx.globalAlpha = 1.0; + ctx.stroke(); + ctx.beginPath() + ctx.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight); + ctx.lineWidth = 3; + ctx.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight) + ctx.stroke(); + } else { + ctx.fillStyle = ColorUtils.colorForTid(data.maxValue || 0) + ctx.strokeStyle = ColorUtils.colorForTid(data.maxValue || 0) + ctx.globalAlpha = 0.6; + ctx.lineWidth = 1; + let drawHeight: number = ((data.value || 0) * (data.frame.height || 0) * 1.0) / (data.maxValue || 1); + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + } } ctx.globalAlpha = 1.0; ctx.lineWidth = 1; diff --git a/host/ide/src/trace/bean/ProcessStruct.ts b/host/ide/src/trace/bean/ProcessStruct.ts index f9844f7e8299d7b1820248d2acb4a9c840f9b880..d66066a16a5204453962897baafc7a688cb5ae67 100644 --- a/host/ide/src/trace/bean/ProcessStruct.ts +++ b/host/ide/src/trace/bean/ProcessStruct.ts @@ -14,8 +14,8 @@ */ import {ColorUtils} from "../component/trace/base/ColorUtils.js"; -import {CpuStruct} from "./CpuStruct.js"; import {BaseStruct} from "./BaseStruct.js"; +import {CpuStruct} from "../database/ui-worker/ProcedureWorkerCPU.js"; const padding = 1; diff --git a/host/ide/src/trace/bean/SdkStruct.ts b/host/ide/src/trace/bean/SdkStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..4197545e3ca96ea314e7320eccb032716fafde17 --- /dev/null +++ b/host/ide/src/trace/bean/SdkStruct.ts @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseStruct} from "./BaseStruct.js"; + +export class SdkSliceStruct extends BaseStruct { + static maxSdkSlice: number = 0 + static maxSdkSliceName: string = "" + static hoverSdkSliceStruct: SdkSliceStruct | undefined; + static selectSdkSliceStruct: SdkSliceStruct | undefined; + static sdkName: number = 0 + + + value: number | undefined + start_ts: number | undefined + end_ts: number | undefined + slice_message: string | undefined +} + +export class CounterStruct extends BaseStruct { + static maxCounter: number = 0 + static maxCounterName: string = "" + static hoverCounterStruct: CounterStruct | undefined; + static selectCounterStruct: CounterStruct | undefined; + + value: number | undefined + ts: number | undefined + counter_id: number | undefined +} \ No newline at end of file diff --git a/host/ide/src/trace/bean/SdkSummary.ts b/host/ide/src/trace/bean/SdkSummary.ts new file mode 100644 index 0000000000000000000000000000000000000000..7d899e219224c31442cb08f669af946351634b90 --- /dev/null +++ b/host/ide/src/trace/bean/SdkSummary.ts @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class CounterSummary { + value: number = 0 + ts: number = 0 + counter_id: number = 0 +} + +export class SdkSliceSummary { + start_ts: number = 0 + startTime: number = 0; + end_ts: number = 0 + endTime: number = 0; + value: number = 0 + slice_id: number = 0 + slice_name: string = '' + slice_message: string = '' +} \ No newline at end of file diff --git a/host/ide/src/trace/bean/SearchFuncBean.ts b/host/ide/src/trace/bean/SearchFuncBean.ts new file mode 100644 index 0000000000000000000000000000000000000000..e2bbad0e0e41475fbb32beae09248bc74d6b23fa --- /dev/null +++ b/host/ide/src/trace/bean/SearchFuncBean.ts @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import exp from "constants"; + +export class SearchFuncBean { + depth: number | undefined // 0 + dur: number | undefined // 570000 + funName: string | undefined //"binder transaction" + id: number | undefined // 92749 + startTime: number | undefined // 9729867000 + tid: number | undefined // + pid: number | undefined // 2785 + type: string | undefined +} + +export class SearchThreadProcessBean { + type: string | undefined + rowId:string | undefined | null + name:string | undefined + rowType:string | undefined | null + rowParentId:string | undefined | null +} + +export class SearchSdkBean { + type: string | undefined + rowId:string | undefined | null + startTime: number | undefined + dur: number | undefined + name:string | undefined + rowType:string | undefined | null + rowParentId:string | undefined | null +} diff --git a/host/ide/src/trace/bean/SmapsShowStruct.ts b/host/ide/src/trace/bean/SmapsShowStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..aa75be4b99a8abb5eecd787f433fa8e9859071d3 --- /dev/null +++ b/host/ide/src/trace/bean/SmapsShowStruct.ts @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseStruct} from "./BaseStruct.js"; + +export class SmapsShowStruct extends BaseStruct { + static hoverStruct: SmapsShowStruct | undefined; + static selectStruct: SmapsShowStruct | undefined; + value: number | undefined + startNS: number | undefined + dur: number | undefined +} \ No newline at end of file diff --git a/host/ide/src/trace/bean/SmapsStruct.ts b/host/ide/src/trace/bean/SmapsStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..fe578cc8558eaca664e4fa2c49d007e3a1d62e49 --- /dev/null +++ b/host/ide/src/trace/bean/SmapsStruct.ts @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class Smaps { + tsNS: number = -1 + start_addr: string = "" + end_addr: string = "" + permission: string = "" + path: string = "" + size: number = 0 + rss: number = 0 + pss: number = 0 + reside: number = 0 + dirty: number = 0 + swapper: number = 0 + + address: string = "" + type: string = "" + dirtyStr: string = "" + swapperStr: string = "" + rssStr: string = "" + pssStr: string = "" + sizeStr: string = "" + resideStr: string = "" +} + + +export class SmapsTreeObj { + constructor(id: string, pid: string, type: string) { + this.id = id + this.pid = pid + this.type = type; + } + id: string = "" + pid: string = "" + rsspro: number = 0 + rssproStr: string = "" + type: string = "" + reg: number = 0 + regStr: string = "" + path: string = "" + rss: number = 0 + rssStr: string = "" + dirty: number = 0 + dirtyStr: string = "" + swapper: number = 0 + swapperStr: string = "" + pss: number = 0 + pssStr: string = "" + size: number = 0 + sizeStr: string = "" + respro: number = 0 + resproStr: string = "" + children: Array = []; +} + diff --git a/host/ide/src/trace/bean/StateProcessThread.ts b/host/ide/src/trace/bean/StateProcessThread.ts index 642d399ef9d84abbf1cb5511ae45e05e4cf1abde..42b28c48ae6930445dad97ebab2328f9d47af5e9 100644 --- a/host/ide/src/trace/bean/StateProcessThread.ts +++ b/host/ide/src/trace/bean/StateProcessThread.ts @@ -41,6 +41,7 @@ export class SPTChild { state: string = "" startNs: number = 0 startTime: string = "" + absoluteTime:number = 0 duration: number = 0 cpu: number | undefined = undefined core: string = "" @@ -61,4 +62,28 @@ export class SPT { cpu: number = 0; priority: string = "-" note: string = "-" +} + +export class ThreadState{ + itid:number = 0 + state:string = "" + dur:number = 0 + ts:number = 0 + end_ts:number = 0 + start_ts:number = 0 + cpu:number = 0 +} + +export class ThreadProcess{ + id:number = 0 + threadId :number = 0 + thread :string = "" + processId : number = 0 + process : string = "" +} + +export class SptSlice{ + itid :number = 0 + ts : number = 0 + priority : number = 0 } \ No newline at end of file diff --git a/host/ide/src/trace/bean/WakeupBean.ts b/host/ide/src/trace/bean/WakeupBean.ts index f8d6fbc30562f034ca1c864976725a2b255dc25a..f5c23003132af085c1248a8b9ca0950f6cfa4acc 100644 --- a/host/ide/src/trace/bean/WakeupBean.ts +++ b/host/ide/src/trace/bean/WakeupBean.ts @@ -22,4 +22,5 @@ export class WakeupBean { tid: number | undefined schedulingLatency: number | undefined schedulingDesc: string | undefined + ts: number | undefined } \ No newline at end of file diff --git a/host/ide/src/trace/component/DisassemblingWindow.ts b/host/ide/src/trace/component/DisassemblingWindow.ts new file mode 100644 index 0000000000000000000000000000000000000000..0353d2e23f0e227e1f30dc08b893169bceca75fd --- /dev/null +++ b/host/ide/src/trace/component/DisassemblingWindow.ts @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BaseElement, element } from "../../base-ui/BaseElement.js"; + +@element('tab-native-data-modal') +export class DisassemblingWindow extends BaseElement { + private canvas: HTMLCanvasElement | undefined | null; + private window: HTMLElement | undefined | null; + private loading: HTMLElement | undefined | null; + private ctx: CanvasRenderingContext2D | null | undefined; + private hintLine = 0; + private addrArray = new Array(); + private maxBinSize = 0; + private close: Function | undefined | null; + setCloseListener(callback:Function){ + this.close = callback; + } + + removeCloseListener(){ + this.close = null; + }; + + private getMap(content: string, hintAttr: string) { + let lines = content.split('\n'); + this.addrArray = new Array(); + let lineMap = new Map(); + let effectLint = 0; + this.maxBinSize = 0; + for (let line of lines) { + let lineContents = line.split(':'); + if (lineContents.length === 2) { + let addrHex = lineContents[0].trim(); + let addr = '0x' + addrHex; + let value = lineContents[1].split('\t'); + try { + let binary = value[0]; + let lineStruct = new Disassembling(); + if (binary === '') { + if (line.includes('Disassembly') || line.includes('file format')) { + continue + } else { + if (addr.includes(' ')) { + let funcs = addr.split(' '); + lineStruct.addr = funcs[0]; + lineStruct.binary = funcs[1]; + } + } + } else { + lineStruct.addr = addr; + lineStruct.binary = value[0].trim(); + lineStruct.type = value.length > 1 ? value[1] : ''; + lineStruct.code = value.length > 2 ? value[2] : ''; + } + lineMap.set(addrHex, lineStruct); + this.maxBinSize = Math.max(this.ctx!.measureText(lineStruct.addr + lineStruct.binary).width, this.maxBinSize); + this.addrArray.push(addrHex); + if (addrHex === hintAttr) this.hintLine = effectLint; + effectLint++; + } catch (e) { + console.log(e); + } + } + } + return lineMap; + } + + public showContent(content: string, hintAddr: string): void { + this.loading!.style.display = "none"; + this.window!.style.display = "block"; + if (content.startsWith('error')) { + this.window!.innerHTML = `${content}`; + return; + } + let lineMap = this.getMap(content, hintAddr); + this.maxBinSize = this.maxBinSize * 1.7; + this.window!.innerHTML = ''; + for (let addr of this.addrArray) { + if (!lineMap.has(addr)) continue; + let struct = lineMap.get(addr); + if (this.addrArray[this.hintLine] == addr) { + this.window!.innerHTML += `
+ ${struct!.addr} : ${struct!.binary} + ${struct!.type} + ${struct!.code}
`; + (this.window!.querySelector("#emphasis") as HTMLElement)!.style.width = this.window!.scrollWidth + 'px'; + (this.window!.querySelector("#emphasis") as HTMLElement)!.style.background = '#0A59F7'; + } else { + this.window!.innerHTML += `
+ ${struct!.addr} : ${struct!.binary} + ${struct!.type} + ${struct!.code}
`; + } + } + this.window!.scrollTo(0, (this.hintLine - 1) * (this.shadowRoot!.querySelector("#window>.line")!.clientHeight) - this.window!.clientHeight / 2); + } + + private resetCanvas(styleWidth: number, styleHeight: number, width: number, height: number): void { + this.canvas!.style.width = styleWidth + "px"; + this.canvas!.style.height = styleHeight + "px"; + this.canvas!.width = width; + this.canvas!.height = height; + } + + public showLoading(): void { + this.loading!.style.display = 'block'; + this.window!.style.display = 'none'; + this.style.display = 'block'; + this.style.position = 'absolute'; + this.style.left = '0px'; + this.style.border = '1px solid #d8d8d8'; + } + + initElements(): void { + this.canvas = this.shadowRoot?.querySelector("#canvas"); + let close = this.shadowRoot?.querySelector("#close"); + this.window = this.shadowRoot?.querySelector("#window"); + this.loading = this.shadowRoot?.querySelector("#loading"); + this.ctx = this.canvas!.getContext('2d'); + this.resetCanvas(0, 0, 0, 0); + close!.addEventListener("click", () => { + if(this.close){ + this.close(); + } + return true; + }); + } + + initHtml(): string { + return ` + + + `; + } +} + +class Disassembling { + addr = ''; + binary = ''; + type = ''; + code = ''; +} \ No newline at end of file diff --git a/host/ide/src/trace/component/SpFilter.ts b/host/ide/src/trace/component/SpFilter.ts new file mode 100644 index 0000000000000000000000000000000000000000..985fbdb76579b32c7e7f592bdd276fcb3fbdc2f1 --- /dev/null +++ b/host/ide/src/trace/component/SpFilter.ts @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../base-ui/BaseElement.js"; + +@element('sp-filter') +export class SpFilter extends BaseElement { + initElements(): void { + } + + initHtml(): string { + return ` + +
+ Input Filter + +
+ `; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/SpHelp.ts b/host/ide/src/trace/component/SpHelp.ts new file mode 100644 index 0000000000000000000000000000000000000000..a874ed0d840afe84e14893b6291ce5c5405af538 --- /dev/null +++ b/host/ide/src/trace/component/SpHelp.ts @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../base-ui/BaseElement.js"; +import {LitMainMenuGroup} from "../../base-ui/menu/LitMainMenuGroup.js"; +import {LitMainMenu, MenuItem} from "../../base-ui/menu/LitMainMenu.js"; +import {LitMainMenuItem} from "../../base-ui/menu/LitMainMenuItem"; + +@element('sp-help') +export class SpHelp extends BaseElement { + private appContent: HTMLElement | undefined | null + + get dark() { + return this.hasAttribute("dark"); + } + + set dark(dark: boolean) { + if (dark) { + this.setAttribute("dark", '' + dark); + } else { + this.removeAttribute("dark") + } + this.appContent!.innerHTML = "" + } + + initElements(): void { + let that = this + let parentElement = this.parentNode as HTMLElement; + parentElement.style.overflow = 'hidden' + this.appContent = this.shadowRoot?.querySelector('#app-content') as HTMLElement + let mainMenu = this.shadowRoot?.querySelector('#main-menu') as LitMainMenu + let header = mainMenu.shadowRoot?.querySelector('.header') as HTMLDivElement + let version = mainMenu.shadowRoot?.querySelector('.version') as HTMLDivElement + header.style.display = 'none' + version.style.display = 'none' + mainMenu.menus = [ + { + collapsed: false, + title: 'QuickStart', + describe: '', + children: [ + { + title: "快速抓取trace说明", icon: "", clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = + "" + } + }, + { + title: "网页加载trace说明", icon: "", clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = + "" + } + }, + { + title: "Native Memory抓取和展示说明", icon: "", clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = + "" + } + }, + { + title: "Ability Monitor抓取和展示说明", icon: "", clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = + "" + } + }, + { + title: "Perf的抓取和展示说明", icon: "", clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = + "" + } + }, + { + title: "Sql分析和Metrics说明", icon: "", clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = + "" + } + }, + { + title: "在线抓取trace说明", icon: "", clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = + "" + } + }, + { + title: "FileSystem抓取和展示说明", icon: "", clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = + "" + } + }, + { + title: "页内存抓取和展示说明", icon: "", clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = + "" + } + }, + { + title: "Bio抓取和展示说明", icon: "", clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = + "" + } + }, + { + title: "进程smaps抓取和展示说明", icon: "", clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = + "" + } + }, + { + title: "HiSystemEvent抓取和展示说明", icon: "", clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = + "" + } + } + ] + }, + { + collapsed: false, + title: 'TraceStreamer', + describe: '', + children: [ + { + title: "TraceStreamer数据库说明", + icon: "", + clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = "" + } + }, + { + title: "编译Trace_streamer", + icon: "", + clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = "" + } + }, + { + title: "TraceStreamer 解析数据状态表", + icon: "", + clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = "" + } + }, + { + title: "TraceStreamer支持解析事件列表", + icon: "", + clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = "" + } + }, + { + title: "trace_streamer工具说明", + icon: "", + clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = "" + } + }, + { + title: "binder事件上下文如何关联", icon: "", clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = + "" + } + }, + { + title: "wakeup唤醒说明", + icon: "", + clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = "" + } + } + ] + }, + { + collapsed: false, + title: 'SmartPerf', + describe: '', + children: [ + { + title: "SmartPerf 编译指导", + icon: "", + clickHandler: function (item: MenuItem) { + that.appContent!.innerHTML = "" + } + }, + ] + }, + ] + mainMenu.style.width = '290px' + let body = mainMenu.shadowRoot?.querySelector('.menu-body') as HTMLDivElement + let groups = body.querySelectorAll('lit-main-menu-group') + groups.forEach(value => { + let items = value.querySelectorAll('lit-main-menu-item') + items.forEach(item => { + item.style.width = '290px' + }) + if(value.title == 'TraceStreamer'){ + let items = value.querySelectorAll('lit-main-menu-item'); + items.forEach(i =>{ + if(i.title != 'TraceStreamer数据库说明'){ + i.style.display = 'none'; + } + }) + } + if(value.title == 'SmartPerf'){ + value.style.display = 'none'; + } + }) + } + + initHtml(): string { + return ` + +
+
+ +
+
+
+
+ `; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/SpInfoAndStas.ts b/host/ide/src/trace/component/SpInfoAndStas.ts index a450ef9e5a21674e81df606200b19bc826e87482..4c83dc41c4e2d1f4f5f63c25cfa06ff26359f33f 100644 --- a/host/ide/src/trace/component/SpInfoAndStas.ts +++ b/host/ide/src/trace/component/SpInfoAndStas.ts @@ -14,15 +14,268 @@ */ import {BaseElement, element} from "../../base-ui/BaseElement.js"; +import {querySelectTraceStats, queryTraceMetaData,} from "../database/SqlLite.js"; +import {LitTable} from "../../base-ui/table/lit-table.js"; +import "../../base-ui/table/lit-table.js"; +import {info} from "../../log/Log.js"; +import {LitProgressBar} from "../../base-ui/progress-bar/LitProgressBar.js"; @element('sp-info-and-stats') export class SpInfoAndStats extends BaseElement { + private metaData: Array = []; + private infoData: Array = []; + private metaTableEl: LitTable | undefined; + private infoTableEl: LitTable | undefined; + private th: HTMLElement | undefined; + private backgroundMetaTable: HTMLDivElement | undefined; + private backgroundInfoTable: HTMLDivElement | undefined; + private progressLoad: LitProgressBar | undefined; + + static get observedAttributes() { + return [] + } + initElements(): void { + this.progressLoad = this.shadowRoot?.querySelector(".load-metric") as LitProgressBar; + this.metaTableEl = this.shadowRoot!.querySelector('#metaData-table') as LitTable; + this.infoTableEl = this.shadowRoot!.querySelector('#stats-table') as LitTable; + + this.infoTableEl.style.overflow = 'visible' + this.metaTableEl.style.overflow = 'visible' + this.infoTableEl.style.width = 'auto' + this.metaTableEl.style.width = 'auto' + this.th = this.shadowRoot!.querySelector('.th') as HTMLElement; + } + + initInfoAndStatsData() { + this.progressLoad!.loading = true + let time = new Date().getTime(); + this.initMetricItemData().then(() => { + let durTime = new Date().getTime() - time; + info("InfoAndStatsData query time is: " + durTime + "ms") + if (this.metaData.length > 0) { + this.metaTableEl!.recycleDataSource = this.metaData; + } else { + this.metaTableEl!.recycleDataSource = []; + } + new ResizeObserver(() => { + if (this.parentElement?.clientHeight != 0) { + this.metaTableEl!.style.height = '100%' + this.metaTableEl!.reMeauseHeight() + } + }).observe(this.parentElement!) + info("metaData(metric) size is: ", this.metaData.length) + if (this.infoData.length > 0) { + this.infoTableEl!.recycleDataSource = this.infoData; + } else { + this.infoTableEl!.recycleDataSource = [] + } + new ResizeObserver(() => { + if (this.parentElement?.clientHeight != 0) { + this.infoTableEl!.reMeauseHeight() + } + }).observe(this.parentElement!) + info("infoData(metric) size is: ", this.infoData.length) + let metaDataStyle: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('#metaData-table')?.shadowRoot?.querySelector('div.body') as HTMLDivElement + let metaDataHeadStyle: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('#metaData-table')?.shadowRoot?.querySelector('div.thead') as HTMLDivElement + let statsStyle: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('#stats-table')?.shadowRoot?.querySelector('div.body') as HTMLDivElement + let statsHeadStyle: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('#stats-table')?.shadowRoot?.querySelector('div.thead') as HTMLDivElement + + setTimeout(()=>{ + this.initDataTableStyle(metaDataStyle!); + this.initDataTableStyle(metaDataHeadStyle!); + this.initDataTableStyle(statsStyle!); + this.initDataTableStyle(statsHeadStyle!); + }, 20) + + this.progressLoad!.loading = false + }); + } + + initDataTableStyle(styleTable: HTMLDivElement): void { + for (let index = 0; index < styleTable.children.length; index++) { + // @ts-ignore + styleTable.children[index].style.backgroundColor = 'var(--dark-background5,#F6F6F6)' + } + this.metaTableEl!.style.height = 'auto' + this.metaTableEl!.style.minHeight = '80%' + this.metaTableEl!.style.borderRadius = '16' + this.infoTableEl!.style.height = 'auto' + this.infoTableEl!.style.minHeight = '80%' + this.infoTableEl!.style.borderRadius = '16' + } + + async initMetricItemData() { + this.metaData = [] + this.infoData = [] + let mete = await queryTraceMetaData(); + if (mete) { + for (let index = 0; index < mete.length; index++) { + this.metaData.push({name: mete[index].name, value: mete[index].valueText}) + } + } + let info = await querySelectTraceStats(); + if (info) { + for (let index = 0; index < info.length; index++) { + this.infoData.push({ + event_name: info[index].event_name, + stat_type: info[index].stat_type, + count: info[index].count + }) + } + } + } + + connectedCallback() { + } + + disconnectedCallback() { + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { } initHtml(): string { return ` -
System info and metadata
+ + +
+ + +
`; } } + +export class MetaDataTable { + name: string | undefined; + value: string | undefined; + type?: string | undefined; +} + +export class InfoDataTable { + event_name: string | undefined; + stat_type: string | undefined; + count: number | undefined; + source?: string | undefined; + serverity?: string | undefined; +} diff --git a/host/ide/src/trace/component/SpMetrics.ts b/host/ide/src/trace/component/SpMetrics.ts index 3e06d04c8d084a51f7eb3e9349518d2e64fd896c..9c96af787b22fa9fad24cef285c7727c364c0c64 100644 --- a/host/ide/src/trace/component/SpMetrics.ts +++ b/host/ide/src/trace/component/SpMetrics.ts @@ -15,41 +15,334 @@ import {BaseElement, element} from "../../base-ui/BaseElement.js"; +import { + queryDistributedTerm, + querySelectTraceStats, + querySystemCalls, + querySystemCallsTop, + queryTraceCpu, + queryTraceCpuTop, + queryTraceMemory, + queryTraceMemoryTop, + queryTraceMemoryUnAgg, + queryTraceMetaData, + queryTraceTaskName +} from "../database/SqlLite.js"; + +import "../../base-ui/table/lit-table.js"; +import {initCpuStrategyData, initTest} from "./metrics/CpuStrategy.js"; +import {initDistributedTermData} from "./metrics/DistributeTermStrategy.js"; +import {initMemoryAggStrategy} from "./metrics/MemAggStrategy.js"; +import {initMemoryStrategy} from "./metrics/MemStrategy.js"; +import {initSysCallsStrategy} from "./metrics/SysCallsStrategy.js"; +import {initSysCallsTopStrategy} from "./metrics/SysCallsTopStrategy.js"; +import {initTraceStateStrategy} from "./metrics/TraceStatsStrategy.js"; +import {initTraceTaskStrategy} from "./metrics/TraceTaskStrategy.js"; +import {initMetaDataStrategy} from "./metrics/MetaDataStrategy.js"; +import {PluginConvertUtils} from "./setting/utils/PluginConvertUtils.js"; +import {info} from "../../log/Log.js"; +import {LitProgressBar} from "../../base-ui/progress-bar/LitProgressBar.js"; + @element('sp-metrics') export class SpMetrics extends BaseElement { + private _metric?: string; + private _metricResult?: string; + private selectMetricEl: HTMLSelectElement | undefined; + private runButtonEl: HTMLButtonElement | undefined | null; + private responseJson: HTMLPreElement | undefined | null; + private metricOptionalSelects: Array | undefined; + private progressLoad: LitProgressBar | undefined; + + static get observedAttributes() { + return ["metric", "metricResult"] + } + + get metric(): string { + return this.getAttribute("metric") || ""; + } + + set metric(value: string) { + this._metric = value; + } + + get metricResult(): string { + return this.getAttribute("metricResult") || ""; + } + + set metricResult(value: string) { + this._metricResult = value; + this.setAttribute("metricResult", value); + } + + reset() { + this.selectMetricEl!.selectedIndex = 0 + this.responseJson!.textContent = '' + } + initElements(): void { + this.progressLoad = this.shadowRoot?.querySelector(".load-metric") as LitProgressBar; + this.selectMetricEl = this.shadowRoot?.querySelector(".sql-select") as HTMLSelectElement; + this.runButtonEl = this.shadowRoot?.querySelector(".sql-select-button") as HTMLButtonElement; + this.responseJson = this.shadowRoot?.querySelector(".response-json") as HTMLPreElement; + if (this.selectMetricEl) { + this.selectMetricEl.addEventListener("selectionchange", () => { + if (this.selectMetricEl) this.selectMetricEl.textContent = ""; + }) + } + this.initMetricDataHandle(); + this.initMetricSelectOption(); + } + + async initMetric(queryItem: MetricQueryItem) { + this.initMetricData(queryItem).then(item => { + this.progressLoad!.loading = false + }) + } + + async initMetricData(queryItem: MetricQueryItem) { + let metricQuery = queryItem.metricQuery; + let queryList = await metricQuery(); + info("current Metric Data size is: ", queryList!.length) + let metric = queryItem.metricResultHandle; + let resultData = metric(queryList); + let jsonText = PluginConvertUtils.BeanToCmdTxtWithObjName(resultData, true, queryItem.metricName, 4); + this.responseJson!.textContent = jsonText; + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + switch (name) { + case "metric": + if (this.selectMetricEl) this.selectMetricEl.textContent = newValue + break; + case "metricResult": + if (this.selectMetricEl) this.selectMetricEl.textContent = newValue + break; + } + } + + runClickListener = (event: any) => { + this.progressLoad!.loading = true + let selectedIndex = this.selectMetricEl!.selectedIndex; + let value = this.selectMetricEl!.options[selectedIndex].value; + let resultQuery = this.metricOptionalSelects?.filter((item) => { + return item.metricName == value + }) + if (!resultQuery || resultQuery.length < 1) return + this.initMetric(resultQuery[0]); + } + + + connectedCallback() { + // Run metric button to add listener + this.runButtonEl?.addEventListener('click', this.runClickListener); + } + + disconnectedCallback() { + this.runButtonEl?.removeEventListener('click', this.runClickListener); + } + + initMetricSelectOption() { + for (let index = 0; index < this.metricOptionalSelects!.length; index++) { + let htmlElement = document.createElement('option'); + if (this.metricOptionalSelects) { + htmlElement.textContent = this.metricOptionalSelects[index].metricName; + this.selectMetricEl?.appendChild(htmlElement); + } + } + } + + initMetricDataHandle() { + this.metricOptionalSelects = [ + { + metricName: 'trace_mem', + metricQuery: queryTraceMemory, + metricResultHandle: initMemoryStrategy + }, + { + metricName: 'trace_mem_top10', + metricQuery: queryTraceMemoryTop, + metricResultHandle: initMemoryStrategy + }, + { + metricName: 'trace_mem_unagg', + metricQuery: queryTraceMemoryUnAgg, + metricResultHandle: initMemoryAggStrategy + }, + { + metricName: 'trace_task_names', + metricQuery: queryTraceTaskName, + metricResultHandle: initTraceTaskStrategy + }, + { + metricName: 'trace_stats', + metricQuery: querySelectTraceStats, + metricResultHandle: initTraceStateStrategy + }, + { + metricName: 'trace_metadata', + metricQuery: queryTraceMetaData, + metricResultHandle: initMetaDataStrategy + }, + { + metricName: 'sys_calls', + metricQuery: querySystemCalls, + metricResultHandle: initSysCallsStrategy + }, + ] } initHtml(): string { return ` - + +
+
+

Select a metric

+ + + +
+
+ +
+
+ `; + } } -xmp{ - color: #121212; - background-color: #eeeeee; - padding: 30px; - margin: 30px; - overflow: auto; - border-radius: 20px; + +export interface MetricQueryItem { + metricName: string + metricQuery: Function + metricResultHandle: Function } - -
- - trace_metadata: { - trace_duration_ns: 14726175738 - trace_uuid: "00000000-0000-0000-c0bd-eb5c5728bf40" - statsd_triggering_subscription_id: 0 - unique_session_name: "" - trace_size_bytes: 57202082 - trace_config_pbtxt: "buffers: { size_kb: 63488\\n fill_policy: DISCARD\\n}\\nbuffers: {\\n size_kb: 2048\\n fill_policy: DISCARD\\n}\\ndata_sources: {\\n config: {\\n name: \\"linux.process_stats\\"\\n target_buffer: 1\\n trace_duration_ms: 0\\n tracing_session_id: 0\\n enable_extra_guardrails: false\\n ftrace_config: {\\n buffer_size_kb: 0\\n drain_period_ms: 0\\n }\\n chrome_config: {\\n trace_config: \\"\\"\\n privacy_filtering_enabled: false\\n }\\n inode_file_config: {\\n scan_interval_ms: 0\\n scan_delay_ms: 0\\n scan_batch_size: 0\\n do_not_scan: false\\n }\\n process_stats_config: {\\n scan_all_processes_on_start: true\\n record_thread_names: false\\n proc_stats_poll_ms: 1000\\n proc_stats_cache_ttl_ms: 0\\n }\\n sys_stats_config: {\\n meminfo_period_ms: 0\\n vmstat_period_ms: 0\\n stat_period_ms: 0\\n }\\n heapprofd_config: {\\n sampling_interval_bytes: 0\\n all: false\\n continuous_dump_config: {\\n dump_phase_ms: 0\\n dump_interval_ms: 0\\n }\\n shmem_size_bytes: 0\\n block_client: false\\n }\\n android_power_config: {\\n battery_poll_ms: 0\\n collect_power_rails: false\\n }\\n android_log_config: {\\n min_prio: PRIO_UNSPECIFIED\\n }\\n packages_list_config: {\\n }\\n legacy_config: \\"\\"\\n }\\n}\\ndata_sources: {\\n config: {\\n name: \\"linux.ftrace\\"\\n target_buffer: 0\\n trace_duration_ms: 0\\n tracing_session_id: 0\\n enable_extra_guardrails: false\\n ftrace_config: {\\n ftrace_events: \\"sched/sched_switch\\"\\n ftrace_events: \\"power/suspend_resume\\"\\n ftrace_events: \\"sched/sched_wakeup\\"\\n ftrace_events: \\"sched/sched_wakeup_new\\"\\n ftrace_events: \\"sched/sched_waking\\"\\n ftrace_events: \\"power/cpu_frequency\\"\\n ftrace_events: \\"power/cpu_idle\\"\\n ftrace_events: \\"sched/sched_process_exit\\"\\n ftrace_events: \\"sched/sched_process_free\\"\\n ftrace_events: \\"task/task_newtask\\"\\n ftrace_events: \\"task/task_rename\\"\\n ftrace_events: \\"lowmemorykiller/lowmemory_kill\\"\\n ftrace_events: \\"oom/oom_score_adj_update\\"\\n ftrace_events: \\"ftrace/print\\"\\n atrace_categories: \\"gfx\\"\\n atrace_apps: \\"lmkd\\"\\n buffer_size_kb: 0\\n drain_period_ms: 0\\n }\\n chrome_config: {\\n trace_config: \\"\\"\\n privacy_filtering_enabled: false\\n }\\n inode_file_config: {\\n scan_interval_ms: 0\\n scan_delay_ms: 0\\n scan_batch_size: 0\\n do_not_scan: false\\n }\\n process_stats_config: {\\n scan_all_processes_on_start: false\\n record_thread_names: false\\n proc_stats_poll_ms: 0\\n proc_stats_cache_ttl_ms: 0\\n }\\n sys_stats_config: {\\n meminfo_period_ms: 0\\n vmstat_period_ms: 0\\n stat_period_ms: 0\\n }\\n heapprofd_config: {\\n sampling_interval_bytes: 0\\n all: false\\n continuous_dump_config: {\\n dump_phase_ms: 0\\n dump_interval_ms: 0\\n }\\n shmem_size_bytes: 0\\n block_client: false\\n }\\n android_power_config: {\\n battery_poll_ms: 0\\n collect_power_rails: false\\n }\\n android_log_config: {\\n min_prio: PRIO_UNSPECIFIED\\n }\\n packages_list_config: {\\n }\\n legacy_config: \\"\\"\\n }\\n}\\nduration_ms: 15000\\nenable_extra_guardrails: false\\nlockdown_mode: LOCKDOWN_UNCHANGED\\nstatsd_metadata: {\\n triggering_alert_id: 0\\n triggering_config_uid: 0\\n triggering_config_id: 0\\n triggering_subscription_id: 0\\n}\\nwrite_into_file: false\\nfile_write_period_ms: 0\\nmax_file_size_bytes: 0\\nguardrail_overrides: {\\n max_upload_per_day_bytes: 0\\n}\\ndeferred_start: false\\nflush_period_ms: 0\\nflush_timeout_ms: 0\\nnotify_traceur: false\\ntrigger_config: {\\n trigger_mode: UNSPECIFIED\\n trigger_timeout_ms: 0\\n}\\nallow_user_build_tracing: false\\nbuiltin_data_sources: {\\n disable_clock_snapshotting: false\\n disable_trace_config: false\\n disable_system_info: false\\n}\\nincremental_state_config: {\\n clear_period_ms: 0\\n}\\nunique_session_name: \\"\\"\\ncompression_type: COMPRESSION_TYPE_UNSPECIFIED\\nincident_report_config: {\\n destination_package: \\"\\"\\n destination_class: \\"\\"\\n privacy_level: 0\\n skip_dropbox: false\\n}" - sched_duration_ns: 14726119124 + +export class SpMetricsItem { + itemTip: string | undefined + itemValue: any[] | undefined } - -
- `; - } -} \ No newline at end of file diff --git a/host/ide/src/trace/component/SpQuerySQL.ts b/host/ide/src/trace/component/SpQuerySQL.ts index 291793d293b1daf8b70c4b5afcb69743302504df..edf8e8fb794140cce19f1eef379119d054ceaefa 100644 --- a/host/ide/src/trace/component/SpQuerySQL.ts +++ b/host/ide/src/trace/component/SpQuerySQL.ts @@ -14,55 +14,534 @@ */ import {BaseElement, element} from "../../base-ui/BaseElement.js"; -import {querySql, queryThreadsByPid} from "../database/SqlLite.js"; +import {queryCustomizeSelect, querySelectTraceStats} from "../database/SqlLite.js"; +import {LitTable} from "../../base-ui/table/lit-table.js"; +import "../../base-ui/table/lit-table.js"; +import {LitTableColumn} from "../../base-ui/table/lit-table-column.js"; +import {info} from "../../log/Log.js"; +import {LitProgressBar} from "../../base-ui/progress-bar/LitProgressBar.js"; @element('sp-query-sql') export class SpQuerySQL extends BaseElement { + private queryTableEl: LitTable | undefined; + private queryText: string | undefined; + private resultText: string | undefined; + private notSupportList: Array | undefined; + private querySize: HTMLElement | undefined; + private keyList: Array | undefined; + private selector: HTMLTextAreaElement | undefined; + private isSupportSql: boolean = true; + private querySelectTables: string = ''; + private response: HTMLDivElement | undefined; + private statDataArray: any = [] + private querySqlErrorText: string = '' + private progressLoad: LitProgressBar | undefined; + initElements(): void { - let sqlInput: HTMLInputElement | undefined | null = this.shadowRoot?.querySelector('#sql-input'); - let contentEL: HTMLPreElement | undefined | null = this.shadowRoot?.querySelector('#content'); - if (sqlInput) { - sqlInput.addEventListener('change', e => { - let dateA = new Date().getTime(); - if(sqlInput&&sqlInput.value) { - querySql(sqlInput.value).then(res=>{ - let dur = new Date().getTime() - dateA; - contentEL!.innerHTML = `耗时:${dur}ms 记录:${res.length}条\n${JSON.stringify(res,null,4)}` - }) + this.progressLoad = this.shadowRoot?.querySelector(".load-metric") as LitProgressBar; + this.selector = this.shadowRoot?.querySelector('.sql-select') as HTMLTextAreaElement; + this.queryTableEl = new LitTable() + this.querySize = this.shadowRoot?.querySelector('.query_size') as HTMLElement; + this.response = this.shadowRoot?.querySelector('#dataResult') as HTMLDivElement; + this.notSupportList?.push('insert', 'delete', 'update', 'drop', 'alter', 'truncate', 'create'); + let htmlDivElement = this.queryTableEl.shadowRoot?.querySelector('.table') as HTMLDivElement; + htmlDivElement.style.overflowX = "scroll" + + window.addEventListener('resize',()=>{ + this.freshTableHeadResizeStyle() + }) + + let copyButtonEl = this.shadowRoot?.querySelector('#copy-button') as HTMLButtonElement; + copyButtonEl.addEventListener('click',()=>{ + this.copyTableData() + }) + + let closeButtonEl = this.shadowRoot?.querySelector('#close-button') as HTMLButtonElement; + closeButtonEl.addEventListener('click',()=>{ + this.querySize!.textContent = 'Query result - 0 counts' + this.queryTableEl!.dataSource = [] + this.response!.innerHTML = '' + }) + } + + freshTableHeadResizeStyle(){ + let th = this.queryTableEl!.shadowRoot?.querySelector(".th") + if (th) { + let td = th.querySelectorAll(".td") + let firstChild = this.queryTableEl!.shadowRoot?.querySelector(".body")!.firstElementChild + if(firstChild){ + let bodyList = firstChild.querySelectorAll('.td'); + for (let index = 0; index < bodyList.length; index++) { + td[index].style.width = bodyList[index].offsetWidth + 'px' + td[index].style.overflow = 'hidden' + } + } + } + } + + copyTableData(){ + let copyResult = '' + for (let keyListKey of this.keyList!) { + copyResult += keyListKey + "\t" + } + copyResult += "\n" + for (const value of this.statDataArray) { + this.keyList?.forEach((key) =>{ + copyResult += value[key] + "\t"; + }) + copyResult += "\n" + } + let textarea = document.createElement('textarea'); + document.body.appendChild(textarea); + textarea.textContent = copyResult + textarea.select(); + document.execCommand('copy'); + document.body.removeChild(textarea); + } + + selectEventListener = (event: any) => { + if (event.ctrlKey && event.keyCode == 13) { + if (!this.isSupportSql) { + this.querySize!.textContent = this.querySqlErrorText + this.queryTableEl!.dataSource = [] + this.response!.innerHTML = '' + return + } + this.progressLoad!.loading = true + let startData = new Date().getTime(); + this.getInputSqlResult(this.selector!.value).then(resultList => { + let dur = new Date().getTime() - startData; + this.statDataArray = [] + this.keyList = []; + for (let index = 0; index < resultList.length; index++) { + const dataResult = resultList[index]; + let keys = Object.keys(dataResult); + let values = Object.values(dataResult); + let jsonText = '{'; + for (let keyIndex = 0; keyIndex < keys.length; keyIndex++) { + let key = keys[keyIndex]; + if (this.keyList.indexOf(key) <= -1) { + this.keyList.push(key) + } + let value = values[keyIndex]; + if (typeof value == "string") { + value = value.replace(//gi, ">") + } + jsonText += '"' + key + '"' + ': ' + '"' + value + '"'; + if (keyIndex != keys.length - 1) { + jsonText += ',' + } else { + jsonText += '}'; + } + } + this.statDataArray.push(JSON.parse(jsonText)) + } + + this.queryTableEl!.innerHTML = '' + this.queryText = this.selector!.value; + this.initDataElement(); + this.response!.appendChild(this.queryTableEl!); + + setTimeout(() => { + this.queryTableEl!.recycleDataSource = this.statDataArray; + this.freshTableHeadResizeStyle() + new ResizeObserver(() => { + if (this.parentElement?.clientHeight != 0) { + this.queryTableEl!.style.height = '100%' + this.queryTableEl!.reMeauseHeight() + } + }).observe(this.parentElement!) + info("metric query Sql result Data size is: ", this.statDataArray!.length) + this.initData() + this.progressLoad!.loading = false + },200) + }) + } + } + + reset() { + this.response!.innerHTML = '' + this.keyList = []; + this.statDataArray = []; + this.selector!.value = '' + this.querySize!.textContent = 'Query result - ' + ' 0 counts' + this.resizeSqlHeight().then(()=>{}); + } + + initDataTableStyle(styleTable: HTMLDivElement): void { + for (let index = 0; index < styleTable.children.length; index++) { + // @ts-ignore + styleTable.children[index].style.backgroundColor = 'var(--dark-background5,#F6F6F6)' + } + } + + async initMetricData(): Promise { + if (!this.selector || this.selector.value == null) { + return []; + } + if (this.queryText == '' || this.queryText == null) { + let statList = await querySelectTraceStats(); + for (let index = 0; index < statList.length; index++) { + const statsResult = statList[index]; + let indexArray = { + event_name: statsResult.event_name, + start_type: statsResult.stat_type, + count: statsResult.count, + serverity: statsResult.serverity, + source: statsResult.source, + }; + } + if (this.querySize) { + this.querySize!.textContent = 'Query result - ' + statList.length + ' counts'; + } + this.resultText = 'Query result - ' + statList.length + ' counts'; + } else { + return this.statDataArray + } + } + + checkSupportSqlAbility(): boolean { + let noSupportChart = ['insert', 'delete', 'update', 'drop', 'alter', 'truncate', 'create'] + let result = noSupportChart.filter(item => { + return this.selector!.value.indexOf(item) > -1; + }); + if(result.length > 0){ + this.querySqlErrorText = 'Error: Statement contains a change action keyword,The change operation is not supported.'; + this.isSupportSql = false; + return true + } else { + return false + } + } + + checkSafetySelectSql(): boolean { + let split = this.selector?.value.trim().split(' '); + if (split) { + this.querySqlErrorText = 'Error: Incomplete query statement: ' + this.selector!.value; + this.isSupportSql = false; + return !split[0].toLowerCase().startsWith('select'); + } + return false; + } + + getSelectSqlField(): string { + if (this.selector!.value.indexOf('from') < 0) { + return ''; + } + let splitSql = this.selector?.value.split('from'); + if (splitSql) { + if (splitSql[0].indexOf('*') > -1) { + return '*' + } else { + let fields = splitSql[0].split(',') + return fields[0]; + } + } + return ''; + } + + getSelectSqlTableName(str: string): Array { + if (this.selector!.value.indexOf(str) < 0) { + return []; + } + let tableNameList = []; + let splitSql = this.selector?.value.split(str); + if (splitSql) { + for (let index = 1; index < splitSql?.length; index++) { + let splitSqlItem = splitSql[index].trim(); + let tableItem = splitSqlItem.split(' '); + let tableName = tableItem[0].trim(); + tableNameList.push(tableName); + if (tableName.indexOf('(') >= 0) { + tableNameList.pop(); + } else if (tableName.indexOf(')') >= 0) { + tableNameList.pop(); + let unitTableName = tableName.split(')'); + let tableNewName = unitTableName[0]; + tableNameList.push(tableNewName); } + } + } + return tableNameList + } + + initDataElement() { + if (this.keyList) { + info("Metric query Table Colum size is: ", this.keyList.length) + this.keyList.forEach((item) => { + let htmlElement = document.createElement('lit-table-column') as LitTableColumn; + htmlElement.setAttribute('title', item); + htmlElement.setAttribute('data-index', item); + htmlElement.setAttribute('key', item); + htmlElement.setAttribute('align', 'flex-start'); + htmlElement.setAttribute('height', '32px'); + this.queryTableEl!.appendChild(htmlElement); }) } } connectedCallback() { + let selectQuery = this.shadowRoot?.querySelector('.query_select'); + if (selectQuery) { + let querySql = selectQuery.textContent; + } + // Listen to the sql execution of the query + this.addEventListener("keydown", this.selectEventListener); + this.selector!.addEventListener('input', this.inputSqlListener) + this.selector!.addEventListener('change', this.inputSqlListener) + this.selector!.addEventListener('keydown', this.deleteSqlListener) + } + + deleteSqlListener = (event: any) => { + if (event.key == 'Backspace') { + this.resizeSqlHeight().then(()=>{}); + } + } + + async resizeSqlHeight() { + let valueLength = this.selector?.value.split('\n').length; + let rowNumber = Number(valueLength) - 1; + let selectHeight = '3.2em' + if (rowNumber > 0) { + if (rowNumber <= 10) { + let allLength = 1.2 * rowNumber + 2; + selectHeight = allLength + 'em'; + } else { + selectHeight = '14em' + } + } + // @ts-ignore + this.selector?.style.height = selectHeight + } + + inputSqlListener = async (event: any) => { + this.resizeSqlHeight().then(()=>{}); + let startData = new Date().getTime(); + if (this.selector!.value.trim() == '') { + this.querySqlErrorText = 'Please enter a query'; + this.querySize!.textContent = this.querySqlErrorText + return + } + this.checkSafetySelectSql() + this.checkSupportSqlAbility() + if (this.selector!.value.length < 15) { + return; + } + this.querySelectTables = this.getSelectSqlTableName('from').concat(this.getSelectSqlTableName('join')).toLocaleString(); + info("metric query sql table size is: ", this.querySelectTables.length) + this.isSupportSql = true; + } + + async getInputSqlResult(sql: string): Promise { + return await queryCustomizeSelect(sql); + } + + disconnectedCallback() { + this.removeEventListener("keydown", this.selectEventListener); + this.selector!.removeEventListener('input', this.inputSqlListener) + this.selector!.removeEventListener('change', this.inputSqlListener) + this.selector!.removeEventListener('keydown', this.deleteSqlListener) + } + + initData() { + if (this.statDataArray.length > 0) { + this.querySize!.textContent = 'Error: ' + this.selector?.value; + } + if (this.isSupportSql) { + let sqlField = this.keyList?.length == 0 ? '*' : this.keyList?.toLocaleString(); + this.querySize!.textContent = 'Query result - ' + this.statDataArray.length + ' counts'; + } else { + this.querySize!.textContent = this.querySqlErrorText; + } + + let queryHeadStyle: HTMLDivElement | undefined | null = this.queryTableEl?.shadowRoot?.querySelector('div.th') as HTMLDivElement + if (queryHeadStyle && queryHeadStyle.hasChildNodes()) { + for (let index = 0; index < queryHeadStyle.children.length; index++) { + // @ts-ignore + queryHeadStyle.children[index].style.gridArea = null + } + } + + this.queryTableEl!.style.height = '100%' + } + + static get observedAttributes() { + return ["queryStr"] + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + let queryDataSty: HTMLDivElement | undefined | null = this.queryTableEl?.shadowRoot?.querySelector('div.tbody') as HTMLDivElement + if (queryDataSty && queryDataSty.hasChildNodes()) { + for (let index = 0; index < queryDataSty.children.length; index++) { + // @ts-ignore + queryDataSty.children[index].style.backgroundColor = 'var(--dark-background5,#F6F6F6)' + } + } + } + + private _queryStr?: string; + + get queryStr(): string { + return this.queryStr; + } + + set queryStr(value: string) { + this._queryStr = value; } initHtml(): string { return ` - -
- -

-
+ +
+
+

Enter query and press cmd/ctrl + Enter

+ + +
+
+
+

Query result - 0 counts

+
+ + +
+
+
+
+
`; } - -} \ No newline at end of file +} diff --git a/host/ide/src/trace/component/SpRecordTrace.ts b/host/ide/src/trace/component/SpRecordTrace.ts index 2e7674f29cb55bc413555cf7415ec06e3d34e778..077313ecb2bc29ce6ef2d52aa236dc180a14859a 100644 --- a/host/ide/src/trace/component/SpRecordTrace.ts +++ b/host/ide/src/trace/component/SpRecordTrace.ts @@ -15,19 +15,26 @@ import {BaseElement, element} from "../../base-ui/BaseElement.js"; import "../../base-ui/popover/LitPopover.js" +import "../../base-ui/button/LitButton.js"; import {LitMainMenuGroup} from "../../base-ui/menu/LitMainMenuGroup.js"; import {LitMainMenuItem} from "../../base-ui/menu/LitMainMenuItem.js"; import {SpRecordSetting} from "./setting/SpRecordSetting.js"; -import {MenuItem} from "../../base-ui/menu/LitMainMenu.js"; +import {LitMainMenu, MenuGroup, MenuItem} from "../../base-ui/menu/LitMainMenu.js"; import {SpProbesConfig} from "./setting/SpProbesConfig.js"; import {SpTraceCommand} from "./setting/SpTraceCommand.js"; + import { + CpuConfig, CreateSessionRequest, + DiskioConfig, FileSystemConfig, FpsConfig, HilogConfig, + HiperfPluginConfig, HiSystemEventConfig, levelFromJSON, MemoryConfig, NativeHookConfig, + NetworkConfig, + ProcessConfig, ProfilerPluginConfig, ProfilerSessionConfig, ProfilerSessionConfigBufferConfig, @@ -40,9 +47,42 @@ import { } from "./setting/bean/ProfilerServiceTypes.js"; import {PluginConvertUtils} from "./setting/utils/PluginConvertUtils.js"; import {SpAllocations} from "./setting/SpAllocations.js"; +import {SpRecordPerf} from "./setting/SpRecordPerf.js"; +import {HdcDeviceManager} from "../../hdc/HdcDeviceManager.js"; +import {LitButton} from "../../base-ui/button/LitButton.js"; +import {SpApplication} from "../SpApplication.js"; +import {LitSearch} from "./trace/search/Search.js"; +import {LitProgressBar} from "../../base-ui/progress-bar/LitProgressBar.js"; +import {info, log} from "../../log/Log.js"; +import {CmdConstant} from "../../command/CmdConstant.js"; +import {Cmd} from "../../command/Cmd.js"; +import {SpFileSystem} from "./setting/SpFileSystem.js"; +import {SpSdkConfig} from "./setting/SpSdkConfig.js"; +import {SpVmTracker} from "./setting/SpVmTracker.js"; +import {SpHisysEvent} from "./setting/SpHisysEvent.js"; @element('sp-record-trace') export class SpRecordTrace extends BaseElement { + public static serialNumber: string = ''; + // 1GB + public static MaxFileSize: number = 1024 * 1024 * 1024; + public static isVscode = false; + public static stopRecord = false; + + set vs(vs: boolean) { + if (vs) { + SpRecordTrace.isVscode = true; + this.setAttribute("vs", '') + } else { + SpRecordTrace.isVscode = false; + this.removeAttribute("vs"); + } + } + + get vs(): boolean { + return this.hasAttribute("vs"); + } + static MEM_INFO = ["MEMINFO_ACTIVE", "MEMINFO_ACTIVE_ANON", "MEMINFO_ACTIVE_FILE", "MEMINFO_ANON_PAGES", "MEMINFO_BUFFERS", "MEMINFO_CACHED", "MEMINFO_CMA_FREE", "MEMINFO_CMA_TOTAL", "MEMINFO_COMMIT_LIMIT", "MEMINFO_COMMITED_AS", "MEMINFO_DIRTY", "MEMINFO_INACTIVE", "MEMINFO_INACTIVE_ANON", "MEMINFO_INACTIVE_FILE", @@ -50,7 +90,7 @@ export class SpRecordTrace extends BaseElement { "MEMINFO_MLOCKED", "MEMINFO_PAGE_TABLES", "MEMINFO_SHMEM", "MEMINFO_SLAB", "MEMINFO_SLAB_RECLAIMABLE", "MEMINFO_SLAB_UNRECLAIMABLE", "MEMINFO_SWAP_CACHED", "MEMINFO_SWAP_FREE", "MEMINFO_SWAP_TOTAL", "MEMINFO_UNEVICTABLE", "MEMINFO_VMALLOC_CHUNK", "MEMINFO_VMALLOC_TOTAL", "MEMINFO_VMALLOC_USED", - "MEMINFO_WRITEBACK"] + "MEMINFO_WRITEBACK", "MEMINFO_KERNEL_RECLAIMABLE"] static VMEM_INFO = ["VMEMINFO_UNSPECIFIED", "VMEMINFO_NR_FREE_PAGES", "VMEMINFO_NR_ALLOC_BATCH", "VMEMINFO_NR_INACTIVE_ANON", "VMEMINFO_NR_ACTIVE_ANON", "VMEMINFO_NR_INACTIVE_FILE", "VMEMINFO_NR_ACTIVE_FILE", "VMEMINFO_NR_UNEVICTABLE", "VMEMINFO_NR_MLOCK", "VMEMINFO_NR_ANON_PAGES", @@ -93,6 +133,16 @@ export class SpRecordTrace extends BaseElement { "VMEMINFO_PGSKIP_NORMAL", "VMEMINFO_PGSTEAL_DIRECT", "VMEMINFO_PGSTEAL_KSWAPD", "VMEMINFO_SWAP_RA", "VMEMINFO_SWAP_RA_HIT", "VMEMINFO_WORKINGSET_RESTORE" ] + // sys.mem.total sys.mem.free sys.mem.buffers sys.mem.cached sys.mem.shmem sys.mem.slab sys.mem.swap.total + // sys.mem.swap.free sys.mem.mapped sys.mem.vmalloc.used sys.mem.page.tables sys.mem.kernel.stack + // sys.mem.active sys.mem.inactive sys.mem.unevictable sys.mem.vmalloc.total sys.mem.slab.unreclaimable + // sys.mem.cma.total sys.mem.cma.free + static ABALITY_MEM_INFO = ["MEMINFO_MEM_TOTAL", "MEMINFO_MEM_FREE", "MEMINFO_BUFFERS", "MEMINFO_CACHED", + "MEMINFO_SHMEM", "MEMINFO_SLAB", "MEMINFO_SWAP_TOTAL", "MEMINFO_SWAP_FREE", "MEMINFO_MAPPED", + "MEMINFO_VMALLOC_USED", "MEMINFO_PAGE_TABLES", "MEMINFO_KERNEL_STACK", "MEMINFO_ACTIVE", "MEMINFO_INACTIVE", + "MEMINFO_UNEVICTABLE", "MEMINFO_VMALLOC_TOTAL", "MEMINFO_SLAB_UNRECLAIMABLE", "MEMINFO_CMA_TOTAL", + "MEMINFO_CMA_FREE", "MEMINFO_KERNEL_RECLAIMABLE"] + schedulingEvents = [ "sched/sched_switch", "power/suspend_resume", @@ -164,25 +214,251 @@ export class SpRecordTrace extends BaseElement { ] private _menuItems: Array | undefined + public deviceSelect: HTMLSelectElement | undefined; + + private stopButtonEl: HTMLButtonElement | null | undefined; + + private recordButton: LitButton | undefined; + private sp: SpApplication | undefined; + private progressEL: LitProgressBar | undefined; + private litSearch: LitSearch | undefined; + private addButton: LitButton | undefined | null; + private disconnectButton: LitButton | undefined | null; + + private recordSetting: SpRecordSetting | undefined; + private probesConfig: SpProbesConfig | undefined; + private traceCommand: SpTraceCommand | undefined; + private spAllocations: SpAllocations | undefined; + private spRecordPerf: SpRecordPerf | undefined; + private spFileSystem: SpFileSystem | undefined; + private spSdkConfig: SpSdkConfig | undefined; + private spVmTracker: SpVmTracker | undefined; + private spHisysEvent: SpHisysEvent | undefined; + + private menuGroup: LitMainMenuGroup | undefined | null; + private appContent: HTMLElement | undefined | null; + + compareArray(devs: Array): boolean { + let clearFlag: boolean = false; + if (devs.length != this.deviceSelect!.options.length) { + clearFlag = true + } else { + let optionArray = new Array(); + for (let i = 0; i < this.deviceSelect!.options.length; i++) { + optionArray.push(this.deviceSelect!.options[i].value) + } + devs.forEach(value => { + if (optionArray.indexOf(value) == -1) { + clearFlag = true + } + }) + } + return clearFlag; + } + + refreshDeviceList() { + if (this.vs) { + Cmd.execHdcCmd(CmdConstant.CMD_HDC_DEVICES, (res: string) => { + let devs: string[] = res.trim().replace(/\r\n/g, "\r").replace(/\n/g, "\r").split(/\r/); + if (devs.length == 1 && devs[0].indexOf("Empty") != -1) { + this.deviceSelect!.innerHTML = ''; + return; + } + let clearFlag = this.compareArray(devs); + if (clearFlag) { + this.deviceSelect!.innerHTML = ''; + for (let i = 0; i < devs.length; i++) { + let dev = devs[i]; + let option = document.createElement("option") + option.className = 'select' + option.textContent = dev; + this.deviceSelect!.appendChild(option) + if (i == 0) { + SpRecordTrace.serialNumber = option.value; + } + } + } + }); + } else { + this.deviceSelect!.innerHTML = ''; + HdcDeviceManager.getDevices().then((devs: USBDevice[]) => { + for (let len = 0; len < devs.length; len++) { + let dev = devs[len]; + let option = document.createElement("option") + option.className = 'select' + if (typeof dev.serialNumber === "string") { + option.value = dev.serialNumber; + } + option.textContent = dev!.serialNumber ? dev!.serialNumber!.toString() : 'hdc Device'; + this.deviceSelect!.appendChild(option) + if (len == 0) { + SpRecordTrace.serialNumber = option.value; + HdcDeviceManager.connect(option.value).then(() => { + }); + } + } + }); + } + } + + freshMenuDisable(disable: boolean) { + let mainMenu = this.sp!.shadowRoot?.querySelector('#main-menu') as LitMainMenu + mainMenu.menus?.forEach(men => { + men.children.forEach(child => { + // @ts-ignore + child.disabled = disable + } + ) + } + ) + mainMenu.menus = mainMenu.menus; + } + + set showHint(bool: boolean) { + if (bool) { + this.setAttribute("show_hint", ''); + } else { + this.removeAttribute("show_hint"); + } + } + + private refreshDeviceTimer: any; + initElements(): void { - let that = this let parentElement = this.parentNode as HTMLElement; parentElement.style.overflow = 'hidden' - let recordSetting = new SpRecordSetting(); - let probesConfig = new SpProbesConfig(); - let traceCommand = new SpTraceCommand(); - let spAllocations = new SpAllocations(); - let menuGroup = this.shadowRoot?.querySelector('#menu-group') as LitMainMenuGroup - let appContent = this.shadowRoot?.querySelector('#app-content') as HTMLElement - appContent.append(recordSetting) + this.addButton = this.shadowRoot?.querySelector(".add"); + this.addButton!.addEventListener("click", () => { + if (this.vs) { + this.refreshDeviceList(); + } else { + HdcDeviceManager.findDevice().then(usbDevices => { + log(usbDevices) + this.refreshDeviceList(); + }); + } + }) + this.deviceSelect = this.shadowRoot?.querySelector("#device-select") as HTMLSelectElement; + this.deviceSelect!.onchange = () => { + let value = this.deviceSelect!.options[this.deviceSelect!.selectedIndex].value; + SpRecordTrace.serialNumber = value; + if (!this.vs) { + HdcDeviceManager.connect(value).then(() => { + }); + } + } + if (navigator.usb) { + navigator.usb.addEventListener('connect', (ev: USBConnectionEvent) => { + this.usbConnectionListener(ev); + }); + navigator.usb.addEventListener('disconnect', (ev: USBConnectionEvent) => { + this.usbDisConnectionListener(ev) + }); + } + this.disconnectButton = this.shadowRoot?.querySelector(".disconnect"); + this.disconnectButton?.addEventListener('click',evt => { + let index = this.deviceSelect!.selectedIndex + if (index != -1) { + let selectOption = this.deviceSelect!.options[index] + let value = selectOption.value; + HdcDeviceManager.disConnect(value).then((re) => { + this.deviceSelect!.removeChild(selectOption); + if (this.deviceSelect!.selectedIndex != -1) { + SpRecordTrace.serialNumber = this.deviceSelect!.options[this.deviceSelect!.selectedIndex].value + } else { + SpRecordTrace.serialNumber = '' + } + }) + } + }) + this.recordSetting = new SpRecordSetting(); + this.probesConfig = new SpProbesConfig(); + this.traceCommand = new SpTraceCommand(); + this.spAllocations = new SpAllocations(); + this.spRecordPerf = new SpRecordPerf(); + this.spFileSystem = new SpFileSystem(); + this.spSdkConfig = new SpSdkConfig(); + this.spVmTracker = new SpVmTracker(); + this.spHisysEvent = new SpHisysEvent(); + this.recordButton = this.shadowRoot?.querySelector(".record") as LitButton; + this.sp = document.querySelector("sp-application") as SpApplication; + this.progressEL = this.sp.shadowRoot?.querySelector('.progress') as LitProgressBar + this.litSearch = this.sp.shadowRoot?.querySelector('#lit-search') as LitSearch; + this.recordButton!.addEventListener("click", () => { + this.recordButtonListener() + }) + this.spRecordPerf!.addEventListener("addProbe", (event: any) => { + this.showHint = false; + }) + this.spAllocations!.addEventListener("addProbe", (event: any) => { + this.showHint = false; + }) + this.probesConfig!.addEventListener("addProbe", (event: any) => { + this.showHint = false; + }) + + this.stopButtonEl = this.traceCommand!.shadowRoot?.querySelector('#stop-button'); + this.stopButtonEl!.addEventListener('click', ev => { + this.stopRecordListener(); + }) + this.menuGroup = this.shadowRoot?.querySelector('#menu-group') as LitMainMenuGroup + this.appContent = this.shadowRoot?.querySelector('#app-content') as HTMLElement + this.appContent.append(this.recordSetting) + this.initMenuItems(); + } + + stopRecordListener() { + if (this.vs) { + let cmd = Cmd.formatString(CmdConstant.CMS_HDC_STOP, [SpRecordTrace.serialNumber]); + Cmd.execHdcCmd(cmd, (res: string) => { + this.freshMenuDisable(false) + this.freshConfigMenuDisable(false) + this.progressEL!.loading = false + this.sp!.search = false; + this.litSearch!.clear(); + this.disconnectButton!.style.pointerEvents = 'auto'; + this.recordButton!.style.pointerEvents = 'auto'; + this.addButton!.style.pointerEvents = 'auto'; + this.deviceSelect!.style.pointerEvents = 'auto'; + this.traceCommand!.show = false; + }) + } else { + let selectedOption = this.deviceSelect!.options[this.deviceSelect!.selectedIndex] as HTMLOptionElement; + HdcDeviceManager.connect(selectedOption.value).then(result => { + if (result) { + this.freshMenuDisable(false) + this.freshConfigMenuDisable(false) + try { + this.progressEL!.loading = false + this.sp!.search = false; + this.litSearch!.clear(); + this.disconnectButton!.style.pointerEvents = 'auto'; + this.recordButton!.style.pointerEvents = 'auto'; + this.addButton!.style.pointerEvents = 'auto'; + this.deviceSelect!.style.pointerEvents = 'auto'; + SpRecordTrace.stopRecord = true; + HdcDeviceManager.stopHiprofiler(CmdConstant.CMS_STOP, true).then(result => { + }) + } catch (exception) { + log(exception) + } + this.traceCommand!.show = false; + } + }) + } + } + + private initMenuItems() { + let that = this this._menuItems = [ { title: "Record setting", icon: "properties", fileChoose: false, clickHandler: function (ev: InputEvent) { - appContent!.innerHTML = "" - appContent.append(recordSetting) + that.appContent!.innerHTML = "" + that.appContent!.append(that.recordSetting!) + that.freshMenuItemsStatus('Record setting') } }, { @@ -190,64 +466,71 @@ export class SpRecordTrace extends BaseElement { icon: "dbsetbreakpoint", fileChoose: false, clickHandler: function (ev: InputEvent) { - let maxDur = recordSetting.maxDur; - let bufferSize = recordSetting.bufferSize; - let bufferConfig: ProfilerSessionConfigBufferConfig = { - pages: bufferSize * 256, - policy: ProfilerSessionConfigBufferConfigPolicy.RECYCLE - } - let sessionConfig: ProfilerSessionConfig = { - buffers: [bufferConfig], - sessionMode: ProfilerSessionConfigMode.OFFLINE, - resultFile: "/data/local/tmp/hiprofiler_data.htrace", - resultMaxSize: 0, - sampleDuration: maxDur * 1000, - keepAliveTime: 0 - } - let request: CreateSessionRequest = { - requestId: 1, - sessionConfig: sessionConfig, - pluginConfigs: [] - } - if (probesConfig.traceConfig.length > 0) { - request.pluginConfigs.push(that.createHtracePluginConfig(that, probesConfig, recordSetting)) - if (probesConfig.traceConfig.indexOf("FPS") != -1) { - request.pluginConfigs.push(that.createFpsPluginConfig()) - } - } - let reportingFrequency: number; - if (maxDur > 20) { - reportingFrequency = 5 - } else { - reportingFrequency = 2 - } - if (probesConfig.memoryConfig.length > 0) { - request.pluginConfigs.push(that.createMemoryPluginConfig(probesConfig, that, reportingFrequency)) - } - if (spAllocations.appProcess != "") { - request.pluginConfigs.push(that.createNativePluginConfig(spAllocations, reportingFrequency)) - } - appContent!.innerHTML = "" - appContent.append(traceCommand) - traceCommand.hdcCommon = + that.freshMenuItemsStatus('Trace command') + let request = that.makeRequest(); + that.appContent!.innerHTML = "" + that.appContent!.append(that.traceCommand!) + that.traceCommand!.hdcCommon = PluginConvertUtils.createHdcCmd( - PluginConvertUtils.BeanToCmdTxt(request, false), maxDur) + PluginConvertUtils.BeanToCmdTxt(request, false), that.recordSetting!.output, that.recordSetting!.maxDur) } }, { title: "Probes config", icon: "realIntentionBulb", fileChoose: false, clickHandler: function (ev: InputEvent) { - appContent!.innerHTML = "" - appContent.append(probesConfig) + that.appContent!.innerHTML = "" + that.appContent!.append(that.probesConfig!) + that.freshMenuItemsStatus('Probes config') } }, { - title: "Allocations", + title: "Native Memory", icon: "externaltools", fileChoose: false, clickHandler: function (ev: InputEvent) { - appContent!.innerHTML = "" - appContent.append(spAllocations) + that.appContent!.innerHTML = "" + that.appContent!.append(that.spAllocations!) + that.freshMenuItemsStatus('Native Memory') + } + }, + { + title: "Hiperf", icon: "realIntentionBulb", fileChoose: false, + clickHandler: function (ev: InputEvent) { + that.appContent!.innerHTML = "" + that.appContent!.append(that.spRecordPerf!) + that.freshMenuItemsStatus('Hiperf') + } + }, + { + title: "eBPF Config", icon: "file-config", fileChoose: false, + clickHandler: function (ev: InputEvent) { + that.appContent!.innerHTML = "" + that.appContent!.append(that.spFileSystem!) + that.freshMenuItemsStatus('eBPF Config') + } + }, + { + title: "VM Tracker", icon: "vm-tracker", fileChoose: false, + clickHandler: function (ev: InputEvent) { + that.appContent!.innerHTML = "" + that.appContent!.append(that.spVmTracker!) + that.freshMenuItemsStatus('VM Tracker') + } + }, + { + title: "HiSystemEvent", icon: "externaltools", fileChoose: false, + clickHandler: function (ev: InputEvent) { + that.appContent!.innerHTML = "" + that.appContent!.append(that.spHisysEvent!) + that.freshMenuItemsStatus('HiSystemEvent') + } + }, + { + title: "SDK Config", icon: "file-config", fileChoose: false, + clickHandler: function (ev: InputEvent) { + that.appContent!.innerHTML = "" + that.appContent!.append(that.spSdkConfig!) + that.freshMenuItemsStatus('SDK Config') } } ] @@ -260,17 +543,360 @@ export class SpRecordTrace extends BaseElement { th.style.fontSize = "16px" th.style.lineHeight = "28px" th.style.fontWeight = "700" - th.style.opacity = "0.9" th.removeAttribute('file'); th.addEventListener('click', e => { if (item.clickHandler) { item.clickHandler(item) } }) - menuGroup.appendChild(th); + this.menuGroup!.appendChild(th); }) } + usbConnectionListener(event: USBConnectionEvent) { + if (event.isTrusted) { + let usbDevice: USBDevice = event.device; + let option = document.createElement("option") + option.className = 'select' + if (typeof usbDevice.serialNumber === "string") { + option.value = usbDevice.serialNumber; + } + option.selected = true; + option.textContent = usbDevice!.serialNumber ? usbDevice!.serialNumber.replace(/"/g, "") + : 'hdc Device'; + this.deviceSelect!.appendChild(option) + SpRecordTrace.serialNumber = option.value; + } + } + + usbDisConnectionListener(event: USBConnectionEvent) { + let disConnectDevice: USBDevice = event.device; + for (let index = 0; index < this.deviceSelect!.children.length; index++) { + let option = this.deviceSelect!.children[index] as HTMLOptionElement; + if (option.value == disConnectDevice.serialNumber) { + let optValue = option.value; + HdcDeviceManager.disConnect(optValue).then(() => { + }); + this.deviceSelect!.removeChild(option); + if (SpRecordTrace.serialNumber == optValue) { + let options = this.deviceSelect!.options + if (options.length > 0) { + let selectedOpt = options[this.deviceSelect!.selectedIndex] + SpRecordTrace.serialNumber = selectedOpt.value; + } else { + SpRecordTrace.serialNumber = ''; + } + } + } + } + } + + recordButtonListener() { + SpRecordTrace.stopRecord = false; + let request = this.makeRequest(); + if (request.pluginConfigs.length == 0) { + this.showHint = true; + return; + } else { + this.showHint = false; + } + let traceCommandStr = PluginConvertUtils.createHdcCmd( + PluginConvertUtils.BeanToCmdTxt(request, false), this.recordSetting!.output, this.recordSetting!.maxDur) + let selectedOption = this.deviceSelect!.options[this.deviceSelect!.selectedIndex] as HTMLOptionElement; + if (selectedOption) { + SpRecordTrace.serialNumber = selectedOption.value; + } else { + this.sp!.search = true; + this.litSearch!.clear(); + this.progressEL!.loading = false + this.litSearch!.setPercent("please connect device", -1); + } + if (this.vs) { + this.appContent!.innerHTML = "" + this.appContent!.append(this.traceCommand!) + let config = this.makeRequest(); + this.traceCommand!.hdcCommon = + PluginConvertUtils.createHdcCmd( + PluginConvertUtils.BeanToCmdTxt(config, false), this.recordSetting!.output, this.recordSetting!.maxDur) + this.freshMenuItemsStatus('Trace command') + Cmd.execHdcCmd(Cmd.formatString(CmdConstant.CMS_HDC_STOP, [SpRecordTrace.serialNumber]), (stopRes: string) => { + let cmd = Cmd.formatString(CmdConstant.CMD_MOUNT_DEVICES, [SpRecordTrace.serialNumber]); + Cmd.execHdcCmd(cmd, (res: string) => { + this.sp!.search = true; + this.progressEL!.loading = true + this.litSearch!.clear(); + this.litSearch!.setPercent("tracing " + this.recordSetting!.maxDur * 1000 + "ms", -1); + this.buttonDisable(true); + this.traceCommand!.show = true; + this.freshMenuDisable(true) + this.freshConfigMenuDisable(true) + Cmd.execHdcTraceCmd(traceCommandStr, SpRecordTrace.serialNumber, (traceResult: string) => { + if (traceResult.indexOf("DestroySession done") != -1) { + this.litSearch!.setPercent("tracing htrace down", -1); + let cmd = Cmd.formatString(CmdConstant.CMD_FIEL_RECV_DEVICES, [SpRecordTrace.serialNumber, this.recordSetting!.output]) + Cmd.execFileRecv(cmd, this.recordSetting!.output, (rt: ArrayBuffer) => { + this.litSearch!.setPercent("downloading Hitrace file ", 101); + let fileName = this.recordSetting!.output.substring(this.recordSetting!.output.lastIndexOf("/") + 1) + let file = new File([rt], fileName); + let main = this!.parentNode!.parentNode!.querySelector("lit-main-menu") as LitMainMenu + let children = main.menus as Array; + let child = children[0].children as Array + let fileHandler = child[0].fileHandler; + if (fileHandler && !SpRecordTrace.stopRecord) { + this.freshMenuDisable(false) + this.freshConfigMenuDisable(false) + fileHandler({detail: file}) + } else { + SpRecordTrace.stopRecord = false + } + }) + } else { + this.litSearch!.setPercent("tracing htrace failed, please check your config ", -1); + this.traceCommand!.show = false; + this.freshMenuDisable(false); + this.freshConfigMenuDisable(false); + this.progressEL!.loading = false; + } + this.buttonDisable(false); + }) + }) + }) + } else { + HdcDeviceManager.connect(selectedOption.value).then(result => { + log("result is " + result); + if (result) { + this.appContent!.innerHTML = "" + this.appContent!.append(this.traceCommand!) + let config = this.makeRequest(); + this.traceCommand!.hdcCommon = + PluginConvertUtils.createHdcCmd( + PluginConvertUtils.BeanToCmdTxt(config, false), this.recordSetting!.output, this.recordSetting!.maxDur) + this.freshMenuItemsStatus('Trace command') + try { + HdcDeviceManager.stopHiprofiler(CmdConstant.CMS_STOP, true).then(() => { + HdcDeviceManager.shellResultAsString(CmdConstant.CMD_MOUNT, true).then(() => { + this.sp!.search = true; + this.progressEL!.loading = true + this.litSearch!.clear(); + this.litSearch!.setPercent("tracing " + this.recordSetting!.maxDur * 1000 + "ms", -1); + this.buttonDisable(true); + this.traceCommand!.show = true; + this.freshMenuDisable(true) + this.freshConfigMenuDisable(true) + HdcDeviceManager.shellResultAsString(CmdConstant.CMD_SHELL + traceCommandStr, false).then(traceResult => { + let re = this.isSuccess(traceResult) + if (re == 0) { + this.traceCommand!.show = false; + this.litSearch!.setPercent("tracing htrace down", -1); + HdcDeviceManager.shellResultAsString(CmdConstant.CMD_TRACE_FILE_SIZE + this.recordSetting!.output, false).then(traceFileSize => { + if (traceFileSize.indexOf("No such") != -1) { + this.litSearch!.setPercent("No such file or directory", -1); + } else if (Number(traceFileSize) <= SpRecordTrace.MaxFileSize) { + HdcDeviceManager.fileRecv(this.recordSetting!.output, (perNumber: number) => { + this.litSearch!.setPercent("downloading Hitrace file ", perNumber); + }).then(pullRes => { + this.litSearch!.setPercent("downloading Hitrace file ", 101); + pullRes.arrayBuffer().then(buffer => { + let fileName = this.recordSetting!.output.substring(this.recordSetting!.output.lastIndexOf("/") + 1) + let file = new File([buffer], fileName); + let main = this!.parentNode!.parentNode!.querySelector("lit-main-menu") as LitMainMenu + let children = main.menus as Array; + let child = children[0].children as Array + let fileHandler = child[0].fileHandler; + if (fileHandler && !SpRecordTrace.stopRecord) { + this.freshConfigMenuDisable(false); + this.freshMenuDisable(false) + this.buttonDisable(false); + fileHandler({detail: file}) + } else { + SpRecordTrace.stopRecord = false; + } + }) + }); + } else { + this.litSearch!.setPercent("htrace file is too big", -1); + } + }) + } else if (re == 2) { + this.litSearch!.setPercent("stop tracing htrace ", -1); + this.freshConfigMenuDisable(false); + this.freshMenuDisable(false) + this.buttonDisable(false); + } else if (re == -1) { + this.litSearch!.setPercent("The device is abnormal", -1); + this.progressEL!.loading = false + this.freshConfigMenuDisable(false); + this.freshMenuDisable(false) + this.buttonDisable(false); + } else { + this.litSearch!.setPercent("tracing htrace failed, please check your config ", -1); + this.freshConfigMenuDisable(false); + this.freshMenuDisable(false) + this.buttonDisable(false); + } + }); + }); + }) + } catch (e) { + this.traceCommand!.show = false; + this.freshMenuDisable(false) + this.freshConfigMenuDisable(false) + this.buttonDisable(false); + } + } else { + this.sp!.search = true; + this.litSearch!.clear(); + this.litSearch!.setPercent("please kill other hdc-server !", -1); + } + } + ); + } + } + + private isSuccess(traceResult: string): number { + if (traceResult.indexOf("CreateSession FAIL") != -1 || traceResult.indexOf("failed") != -1) { + return 1; + } else if (traceResult.indexOf("Signal") != -1) { + return 2; + } else if (traceResult.indexOf("The device is abnormal") != -1) { + return -1 + } else { + return 0; + } + } + + private makeRequest = () => { + let request = this.createSessionRequest(); + let hasMonitorMemory = false; + let hasSamps = false; + if (this.probesConfig!.traceConfig.length > 0) { + if (this.probesConfig!.traceConfig.find(value => { + return value != "FPS" + })) { + request.pluginConfigs.push(this.createHtracePluginConfig()) + } + if (this.probesConfig!.traceConfig.indexOf("FPS") != -1) { + request.pluginConfigs.push(this.createFpsPluginConfig()) + } + } + if (this.probesConfig!.recordAbility) { + hasMonitorMemory = true; + this.createMonitorPlugin(this, request); + } + let reportingFrequency: number; + if (this.recordSetting!.maxDur > 20) { + reportingFrequency = 5 + } else { + reportingFrequency = 2 + } + if (this.spVmTracker!.startSamp && this.spVmTracker!.process != "") { + hasSamps = true; + } + if (this.probesConfig!.memoryConfig.length > 0 || hasMonitorMemory || hasSamps) { + request.pluginConfigs.push(this.createMemoryPluginConfig(reportingFrequency, this.probesConfig!.memoryConfig.length > 0, hasMonitorMemory, hasSamps)) + } + if (this.spAllocations!.appProcess != "") { + request.pluginConfigs.push(this.createNativePluginConfig(reportingFrequency)) + } + if (this.spRecordPerf!.startSamp) { + request.pluginConfigs.push(this.createHiperConfig(reportingFrequency)) + } + if (this.spFileSystem!.startRecord) { + request.pluginConfigs.push(this.createSystemConfig(reportingFrequency)) + } + if (this.spSdkConfig!.startSamp && this.spSdkConfig!.getPlugName() != "") { + request.pluginConfigs.push(this.createSdkConfig(reportingFrequency)) + } + if (this.spHisysEvent?.startSamp) { + request.pluginConfigs.push(this.createHiSystemEventPluginConfig(this.spHisysEvent.process)) + } + return request; + } + + private createSessionRequest() { + let bufferConfig: ProfilerSessionConfigBufferConfig = { + pages: this.recordSetting!.bufferSize * 256, + policy: ProfilerSessionConfigBufferConfigPolicy.RECYCLE + } + let sessionConfig: ProfilerSessionConfig = { + buffers: [bufferConfig], + sessionMode: ProfilerSessionConfigMode.OFFLINE, + resultFile: this.recordSetting!.output, + resultMaxSize: 0, + sampleDuration: this.recordSetting!.maxDur * 1000, + keepAliveTime: 0 + } + let request: CreateSessionRequest = { + requestId: 1, + sessionConfig: sessionConfig, + pluginConfigs: [] + } + return request; + } + + private createMonitorPlugin(that: this, request: CreateSessionRequest) { + let processPlugin = that.createProcessPlugin(); + let cpuPlugin = that.createCpuPlugin(); + let diskIoPlugin = that.createDiskIOPlugin(); + let netWorkPlugin = that.createNetworkPlugin(); + request.pluginConfigs.push(processPlugin) + request.pluginConfigs.push(cpuPlugin) + request.pluginConfigs.push(diskIoPlugin) + request.pluginConfigs.push(netWorkPlugin) + } + + private createNetworkPlugin() { + let netWorkConfig: NetworkConfig = { + testFile: "/data/local/tmp/" + } + let netWorkPlugin: ProfilerPluginConfig = { + pluginName: "network-plugin", + sampleInterval: 1000, + configData: netWorkConfig + } + return netWorkPlugin; + } + + private createDiskIOPlugin() { + let diskIoConfig: DiskioConfig = { + reportIoStats: "IO_REPORT" + } + let diskIoPlugin: ProfilerPluginConfig = { + pluginName: "diskio-plugin", + sampleInterval: 1000, + configData: diskIoConfig + } + return diskIoPlugin; + } + + private createCpuPlugin() { + let cpuConfig: CpuConfig = { + pid: 0, + reportProcessInfo: true + } + let cpuPlugin: ProfilerPluginConfig = { + pluginName: "cpu-plugin", + sampleInterval: 1000, + configData: cpuConfig + } + return cpuPlugin; + } + + private createProcessPlugin() { + let processConfig: ProcessConfig = { + report_process_tree: true, + report_cpu: true, + report_diskio: true, + report_pss: true, + } + let processPlugin: ProfilerPluginConfig = { + pluginName: "process-plugin", + sampleInterval: 1000, + configData: processConfig + } + return processPlugin; + } + createTraceEvents(traceConfig: Array): Array { let traceEvents = new Set(); traceConfig.forEach(config => { @@ -309,6 +935,7 @@ export class SpRecordTrace extends BaseElement { } ) let ftraceEventsArray: string[] = []; + info("traceEvents length is: ", traceEvents.size) for (const ftraceEvent of traceEvents) { ftraceEventsArray.push(ftraceEvent) } @@ -317,141 +944,135 @@ export class SpRecordTrace extends BaseElement { initHtml(): string { return ` - +
+
+
+ Target Platform: + + Add HDC Device +
+ Disconnect + Record +
+
+
+ It looks like you didn't add any probes. Please add at least one +
+
-.menugroup{ - height: 100%; - background: var(--dark-background3,#FFFFFF); -} -.menuitem{ - background: var(--dark-background3,#FFFFFF); -} -.content{ - background: var(--dark-background3,#FFFFFF); - border-style: none none none solid; - border-width: 1px; - border-color: rgba(166,164,164,0.2); - border-radius: 0px 16px 16px 0px; -} - -
- -
- -
-
-
-
-`; +
+ +
+
+
+
+ `; } private createHilogConfig(probesConfig: SpProbesConfig, reportingFrequency: number) { @@ -468,13 +1089,124 @@ export class SpRecordTrace extends BaseElement { return hilogConfigProfilerPluginConfig; } - private createNativePluginConfig(spAllocations: SpAllocations, reportingFrequency: number) { - let appProcess = spAllocations.appProcess; + private isNumber(str:string) { + return !isNaN(Number(str)) + } + + private createHiperConfig(reportingFrequency: number) { + let perfConfig = this.spRecordPerf!.getPerfConfig(); + let recordArgs = ""; + recordArgs = recordArgs + "-f " + perfConfig?.frequency; + if (perfConfig?.process && !perfConfig?.process.includes("ALL") && perfConfig?.process.length > 0) { + let process = perfConfig.process; + if (this.isNumber(process)) { + recordArgs = recordArgs + " -p " + perfConfig?.process; + } else { + recordArgs = recordArgs + " --app " + perfConfig?.process; + } + } else { + recordArgs = recordArgs + " -a "; + } + if (perfConfig?.cpu && !perfConfig?.cpu.includes("ALL") && perfConfig?.cpu.length > 0) { + recordArgs = recordArgs + " -c " + perfConfig?.cpu; + } + if (perfConfig?.cpuPercent != 0) { + recordArgs = recordArgs + " --cpu-limit " + perfConfig?.cpuPercent; + } + if (perfConfig?.eventList && !perfConfig?.eventList.includes("NONE") && perfConfig?.eventList.length > 0) { + recordArgs = recordArgs + " -e " + perfConfig?.eventList; + if (perfConfig?.isOffCpu) { + recordArgs = recordArgs + ",sched:sched_waking"; + } + } else { + recordArgs = recordArgs + " -e hw-cpu-cycles" + if (perfConfig?.isOffCpu) { + recordArgs = recordArgs + ",sched:sched_waking"; + } + } + if (perfConfig?.callStack != "none") { + recordArgs = recordArgs + " --call-stack " + perfConfig?.callStack + } + + if (perfConfig?.branch != "none") { + recordArgs = recordArgs + " -j " + perfConfig?.branch + } + + if (perfConfig?.clockType) { + recordArgs = recordArgs + " --clockid " + perfConfig?.clockType + } + + if (perfConfig?.isOffCpu) { + recordArgs = recordArgs + " --offcpu" + } + + if (perfConfig?.noInherit) { + recordArgs = recordArgs + " --no-inherit" + } + + if (perfConfig?.mmap) { + recordArgs = recordArgs + " -m " + perfConfig.mmap; + } + info("record config Args is: ", recordArgs) + let hiPerf: HiperfPluginConfig = { + isRoot: false, + outfileName: "/data/local/tmp/perf.data", + recordArgs: recordArgs + } + let hiPerfPluginConfig: ProfilerPluginConfig = { + pluginName: "hiperf-plugin", + sampleInterval: reportingFrequency * 1000, + configData: hiPerf, + } + return hiPerfPluginConfig; + } + + private createSystemConfig(reportingFrequency: number) { + let systemConfig = this.spFileSystem!.getSystemConfig(); + let recordArgs = "hiebpf"; + let recordEvent = []; + if (this.spFileSystem?.startFileSystem) { + recordEvent.push("fs") + } + if (this.spFileSystem?.startVirtualMemory) { + recordEvent.push("ptrace"); + } + if (this.spFileSystem?.startIo) { + recordEvent.push("bio"); + } + if (recordEvent.length > 0) { + recordArgs += " --events " + recordEvent.toString() + } + recordArgs += " --duration " + this.recordSetting?.maxDur + if (systemConfig?.process && !systemConfig?.process.includes("ALL") && systemConfig?.process.length > 0) { + recordArgs = recordArgs + " --pids " + systemConfig?.process; + } + recordArgs += " --max_stack_depth " + systemConfig?.unWindLevel + let systemPluginConfig: FileSystemConfig = { + cmdLine: recordArgs, + outfileName: "/data/local/tmp/ebpf.data", + } + let ebpfPluginConfig: ProfilerPluginConfig = { + pluginName: "hiebpf-plugin", + sampleInterval: 1000, + configData: systemPluginConfig, + } + return ebpfPluginConfig; + } + + private createNativePluginConfig(reportingFrequency: number) { + let appProcess = this.spAllocations!.appProcess; let re = /^[0-9]+.?[0-9]*/; let pid = 0; let processName = ""; - if (re.test(appProcess)) { - pid = Number(appProcess); + let processId = ""; + if (appProcess.indexOf("(") != -1) { + processId = appProcess.slice(appProcess.lastIndexOf("(") + 1, appProcess.lastIndexOf(")")) + } else { + processId = appProcess; + } + if (re.test(processId)) { + pid = Number(processId); } else { processName = appProcess; } @@ -482,10 +1214,15 @@ export class SpRecordTrace extends BaseElement { pid: pid, saveFile: false, fileName: "", - filterSize: spAllocations.filter, - smbPages: spAllocations.shared, - maxStackDepth: spAllocations.unwind, - processName: processName + filterSize: this.spAllocations!.filter, + smbPages: this.spAllocations!.shared, + maxStackDepth: this.spAllocations!.unwind, + processName: processName, + mallocFreeMatchingInterval: 1000, + mallocFreeMatchingCnt: 1000, + stringCompressed: true, + fpUnwind: this.spAllocations!.fp_unwind, + blocked: true } let nativePluginConfig: ProfilerPluginConfig = { pluginName: "nativehook", @@ -495,20 +1232,39 @@ export class SpRecordTrace extends BaseElement { return nativePluginConfig; } - private createMemoryPluginConfig(probesConfig: SpProbesConfig, that: this, reportingFrequency: number) { + private createMemoryPluginConfig(reportingFrequency: number, hasmemoryConfig: boolean, hasMonitorMemory: boolean, hasSmaps: boolean) { let memoryconfig: MemoryConfig = { - reportProcessTree: true, - reportSysmemMemInfo: true, + reportProcessTree: false, + reportSysmemMemInfo: false, sysMeminfoCounters: [], - reportSysmemVmemInfo: true, + reportSysmemVmemInfo: false, sysVmeminfoCounters: [], - reportProcessMemInfo: true, + reportProcessMemInfo: false, reportAppMemInfo: false, reportAppMemByMemoryService: false, pid: [] } - probesConfig.memoryConfig.forEach(value => { + if (hasmemoryConfig || hasMonitorMemory) { + memoryconfig.reportProcessTree = true; + memoryconfig.reportSysmemMemInfo = true; + memoryconfig.reportSysmemVmemInfo = true; + memoryconfig.reportProcessMemInfo = true; + } + if (hasSmaps) { + memoryconfig.reportSmapsMemInfo = true + let pid = Number(this.spVmTracker?.process); + memoryconfig.pid.push(pid) + } + if (hasMonitorMemory) { + SpRecordTrace.ABALITY_MEM_INFO.forEach(va => { + memoryconfig.sysMeminfoCounters.push(sysMeminfoTypeFromJSON(va)); + }) + } + this.probesConfig!.memoryConfig.forEach(value => { if (value.indexOf("Kernel meminfo") != -1) { + if (hasMonitorMemory) { + memoryconfig.sysMeminfoCounters = []; + } SpRecordTrace.MEM_INFO.forEach(va => { memoryconfig.sysMeminfoCounters.push(sysMeminfoTypeFromJSON(va)); }) @@ -545,9 +1301,21 @@ export class SpRecordTrace extends BaseElement { return fpsPlugin; } - private createHtracePluginConfig(that: this, probesConfig: SpProbesConfig, recordSetting: SpRecordSetting) { + private createHiSystemEventPluginConfig(appName:string) { + let hiSystemEventConfig: HiSystemEventConfig = { + msg: 'hisysevent-plugin', + processName: appName + } + let hiSystemEventPlugin: ProfilerPluginConfig = { + pluginName: "hisysevent-plugin", + configData: hiSystemEventConfig + } + return hiSystemEventPlugin; + } + + private createHtracePluginConfig() { let tracePluginConfig: TracePluginConfig = { - ftraceEvents: that.createTraceEvents(probesConfig.traceConfig), + ftraceEvents: this.createTraceEvents(this.probesConfig!.traceConfig), hitraceCategories: [], hitraceApps: [], bufferSizeKb: 2048, @@ -559,10 +1327,10 @@ export class SpRecordTrace extends BaseElement { rawDataPrefix: "", traceDurationMs: 0, debugOn: false, - hitraceTime: recordSetting.maxDur + hitraceTime: this.recordSetting!.maxDur } - if (probesConfig.traceEvents.length > 0) { - tracePluginConfig.hitraceCategories = probesConfig.traceEvents + if (this.probesConfig!.traceEvents.length > 0) { + tracePluginConfig.hitraceCategories = this.probesConfig!.traceEvents } let htraceProfilerPluginConfig: ProfilerPluginConfig = { pluginName: "ftrace-plugin", @@ -571,4 +1339,59 @@ export class SpRecordTrace extends BaseElement { } return htraceProfilerPluginConfig; } -} \ No newline at end of file + + private createSdkConfig(reportingFrequency: number) { + let gpuConfig = this.spSdkConfig!.getGpuConfig(); + let gpuPluginConfig: ProfilerPluginConfig = { + pluginName: this.spSdkConfig!.getPlugName(), + sampleInterval: this.spSdkConfig!.getSampleInterval(), + configData: gpuConfig, + } + return gpuPluginConfig; + } + + + freshConfigMenuDisable(disable: boolean) { + let querySelectors = this.shadowRoot?.querySelectorAll('lit-main-menu-item') + querySelectors!.forEach(item => { + if (disable) { + item.style.pointerEvents = 'none' + this.traceCommand!.show = true; + } else { + item.style.pointerEvents = 'auto' + this.traceCommand!.show = false; + } + item.disabled = disable; + }) + } + + public startRefreshDeviceList() { + if (this.refreshDeviceTimer == null) { + this.refreshDeviceTimer = setInterval(() => { + this.refreshDeviceList(); + }, 5000) + } + } + + buttonDisable(disable: boolean) { + if (disable) { + this.disconnectButton!.style.pointerEvents = 'none'; + this.recordButton!.style.pointerEvents = 'none'; + this.addButton!.style.pointerEvents = 'none'; + this.deviceSelect!.style.pointerEvents = 'none'; + } else { + this.disconnectButton!.style.pointerEvents = 'auto'; + this.recordButton!.style.pointerEvents = 'auto'; + this.addButton!.style.pointerEvents = 'auto'; + this.deviceSelect!.style.pointerEvents = 'auto'; + } + } + + freshMenuItemsStatus(currentValue: string) { + let litMainMenuGroup = this.shadowRoot?.querySelector('lit-main-menu-group'); + let litMainMenuItemNodeListOf = litMainMenuGroup!.querySelectorAll('lit-main-menu-item'); + litMainMenuItemNodeListOf.forEach(item =>{ + item.back = item.title == currentValue; + }) + } +} diff --git a/host/ide/src/trace/component/SpRecyclerSystemTrace.ts b/host/ide/src/trace/component/SpRecyclerSystemTrace.ts index a0a4ed179770527b4804ca2c8c72391e4c2839af..a6bb5293abe97c536ca58dfabe9ca0cd9c978020 100644 --- a/host/ide/src/trace/component/SpRecyclerSystemTrace.ts +++ b/host/ide/src/trace/component/SpRecyclerSystemTrace.ts @@ -28,8 +28,6 @@ import { queryCpuFreqData, queryCpuMax, queryCpuMaxFreq, - queryHeapByPid, - queryHeapPid, queryProcess, queryProcessData, queryProcessMem, @@ -95,7 +93,7 @@ export class SpRecyclerSystemTrace extends BaseElement { // 款选的函数的 线程id ,无则不传 selection.funTids = []; // 框选的 内存 trackId ,无则不传 - selection.trackIds = []; + selection.processTrackIds = []; // 框选的起始时间 selection.leftNs = 0; // 框选的结束时间 @@ -121,7 +119,7 @@ export class SpRecyclerSystemTrace extends BaseElement { selection.rightNs = it.rangeSelect.endNS; } }) - this.traceSheetEL?.boxSelection(selection) + this.traceSheetEL?.rangeSelect(selection) } // @ts-ignore new ResizeObserver((entries) => { @@ -521,7 +519,6 @@ export class SpRecyclerSystemTrace extends BaseElement { initProcess = async () => { let objs = []; let processList = await queryProcess(); - let heapPidList = await queryHeapPid() for (let i = 0; i < processList.length; i++) { const it = processList[i]; let processRow = new TraceRowObject(); @@ -553,75 +550,6 @@ export class SpRecyclerSystemTrace extends BaseElement { }) } objs.push(processRow); - if (heapPidList != undefined && Array.isArray(heapPidList) && heapPidList.filter((item) => { - return item.pid == it.pid - }).length > 0) { - /** - * 添加heap信息 - */ - let allHeapRow = new TraceRowObject(); - allHeapRow.rowParentId = `${it.pid}` - allHeapRow.rowHidden = !processRow.expansion - allHeapRow.rowHeight = 40 - allHeapRow.name = "All Heap Allocations"; - allHeapRow.folder = false; - allHeapRow.rowType = TraceRow.ROW_TYPE_HEAP - allHeapRow.frame = new Rect(0, 0, this.rowsEL.clientWidth - 248, allHeapRow.rowHeight) - allHeapRow.children = true - allHeapRow.supplier = () => queryHeapByPid(0, TraceRow.range?.totalNS || 0, it.pid || 0).then((res) => { - let heapList: HeapStruct[] = [] - let allocMap: Map = new Map() - let currentHeapSize = 0 - let maxHeapSize = 0; - for (let j = 0; j < res.length; j++) { - let struct = new HeapStruct(); - if (res[j].eventType == "AllocEvent") { - currentHeapSize += (res[j].heapsize || 0) - if (allocMap.has(res[j].addr || "")) { - allocMap.get(res[j].addr || "")?.push(res[j]) - } else { - allocMap.set(res[j].addr || "", [res[j]]) - } - } else if (res[j].eventType == "FreeEvent") { - if (allocMap.has(res[j].addr || "")) { - let allocList = allocMap.get(res[j].addr || ""); - if (allocList != undefined && allocList.length > 0) { - currentHeapSize -= allocList[allocList.length - 1].heapsize || 0 - } - } - } - if (currentHeapSize > maxHeapSize) { - maxHeapSize = currentHeapSize - } - struct.pid = it.pid + "" - struct.startTime = res[j].startTime - if (j != res.length - 1) { - struct.endTime = res[j + 1].startTime - } else { - struct.endTime = allHeapRow.range?.totalNS || 0 - } - struct.duration = (struct.endTime || 0) - (struct.startTime || 0) - struct.heapsize = currentHeapSize - heapList.push(struct) - } - for (let j = 0; j < heapList.length; j++) { - heapList[j].maxHeapSize = maxHeapSize - } - return heapList - }) - allHeapRow.onDrawHandler = ctx => { - if (allHeapRow.dataList) { - for (let i = 0; i < allHeapRow.dataList.length; i++) { - let it = allHeapRow.dataList[i]; - if ((it.startTime || 0) + (it.duration || 0) > (TraceRow.range?.startNS || 0) && (it.startTime || 0) < (TraceRow.range?.endNS || 0)) { - HeapStruct.setFrame(allHeapRow.dataList[i], 5, TraceRow.range?.startNS || 0, TraceRow.range?.endNS || 0, TraceRow.range?.totalNS || 0, allHeapRow.frame) - HeapStruct.draw(ctx, allHeapRow.dataList[i]) - } - } - } - } - objs.push(allHeapRow); - } /** * 添加进程内存信息 @@ -765,40 +693,43 @@ export class SpRecyclerSystemTrace extends BaseElement { initHtml(): string { return ` - -
- - - -
+ +
+ + + + + + +
`; } diff --git a/host/ide/src/trace/component/SpSystemTrace.ts b/host/ide/src/trace/component/SpSystemTrace.ts index 9b8d6294092fddb4e9e23a9cfb71a2e1758d0437..6e73be18d93dc9624b572024f903d537bb976718 100644 --- a/host/ide/src/trace/component/SpSystemTrace.ts +++ b/host/ide/src/trace/component/SpSystemTrace.ts @@ -17,67 +17,63 @@ import {BaseElement, element} from "../../base-ui/BaseElement.js"; import "./trace/TimerShaftElement.js"; import "./trace/base/TraceRow.js"; import { - getAsyncEvents, - getCpuUtilizationRate, - getFps, - getFunDataByTid, - getStatesProcessThreadData, - getStatesProcessThreadDataCount, - queryCpuData, - queryCpuFreq, - queryCpuFreqData, - queryCpuMax, - queryCpuMaxFreq, - queryHeapAllTable, - queryHeapByEventType, - queryHeapByPid, - queryHeapFrameCount, - queryHeapGroupByEvent, - queryHeapPid, - queryNativeHookProcess, - queryProcess, - queryProcessData, - queryProcessMem, - queryProcessMemData, - queryProcessThreads, - queryThreadData, - queryTotalTime, + queryEbpfSamplesCount, + querySearchFunc, threadPool } from "../database/SqlLite.js"; import {TraceRow} from "./trace/base/TraceRow.js"; import {TimerShaftElement} from "./trace/TimerShaftElement.js"; -import {CpuStruct} from "../bean/CpuStruct.js"; -import {CpuFreqStruct} from "../bean/CpuFreqStruct.js"; -import {ProcessStruct} from "../bean/ProcessStruct.js"; -import {ColorUtils} from "./trace/base/ColorUtils.js"; import "./trace/base/TraceSheet.js"; import {TraceSheet} from "./trace/base/TraceSheet.js"; -import {ThreadStruct} from "../bean/ThreadStruct.js"; -import {ProcessMemStruct} from "../bean/ProcessMemStruct.js"; -import {FuncStruct} from "../bean/FuncStruct.js"; -import {FpsStruct} from "../bean/FpsStruct.js"; import {RangeSelect} from "./trace/base/RangeSelect.js"; import {SelectionParam} from "../bean/BoxSelection.js"; -import {HeapStruct} from "../bean/HeapStruct.js"; import {procedurePool} from "../database/Procedure.js"; -import {Utils} from "./trace/base/Utils.js"; import {SpApplication} from "../SpApplication.js"; import {SPT} from "../bean/StateProcessThread.js"; -import {HeapTreeDataBean} from "../bean/HeapTreeDataBean.js"; import {Flag} from "./trace/timer-shaft/Flag.js"; import {SportRuler} from "./trace/timer-shaft/SportRuler.js"; -import {NativeEventHeap} from "../bean/NativeHook.js"; +import {SpHiPerf} from "./chart/SpHiPerf.js"; +import {SearchSdkBean, SearchThreadProcessBean} from "../bean/SearchFuncBean.js"; +import {error, info} from "../../log/Log.js"; +import { + drawFlagLineSegment, + drawLines, + drawWakeUp, isFrameContainPoint, + ns2x, Rect +} from "../database/ui-worker/ProcedureWorkerCommon.js"; +import {SpChartManager} from "./chart/SpChartManager.js"; +import {CpuStruct} from "../database/ui-worker/ProcedureWorkerCPU.js"; +import {ProcessStruct} from "../database/ui-worker/ProcedureWorkerProcess.js"; +import {CpuFreqStruct} from "../database/ui-worker/ProcedureWorkerFreq.js"; +import {CpuFreqLimitsStruct} from "../database/ui-worker/ProcedureWorkerCpuFreqLimits.js"; +import {ThreadStruct} from "../database/ui-worker/ProcedureWorkerThread.js"; +import {func, FuncStruct} from "../database/ui-worker/ProcedureWorkerFunc.js"; +import {CpuStateStruct} from "../database/ui-worker/ProcedureWorkerCpuState.js"; +import {HiPerfCpuStruct} from "../database/ui-worker/ProcedureWorkerHiPerfCPU.js"; +import {HiPerfProcessStruct} from "../database/ui-worker/ProcedureWorkerHiPerfProcess.js"; +import {HiPerfThreadStruct} from "../database/ui-worker/ProcedureWorkerHiPerfThread.js"; +import {HiPerfEventStruct} from "../database/ui-worker/ProcedureWorkerHiPerfEvent.js"; +import {HiPerfReportStruct} from "../database/ui-worker/ProcedureWorkerHiPerfReport.js"; +import {FpsStruct} from "../database/ui-worker/ProcedureWorkerFPS.js"; +import {CpuAbilityMonitorStruct} from "../database/ui-worker/ProcedureWorkerCpuAbility.js"; +import {DiskAbilityMonitorStruct} from "../database/ui-worker/ProcedureWorkerDiskIoAbility.js"; +import {MemoryAbilityMonitorStruct} from "../database/ui-worker/ProcedureWorkerMemoryAbility.js"; +import {NetworkAbilityMonitorStruct} from "../database/ui-worker/ProcedureWorkerNetworkAbility.js"; @element('sp-system-trace') export class SpSystemTrace extends BaseElement { static scrollViewWidth = 0 static isCanvasOffScreen = true; static SPT_DATA: Array = []; - static EVENT_HEAP: Array = []; - static HEAP_FRAME_DATA: Array = []; + static DATA_DICT: Map = new Map(); + static SDK_CONFIG_MAP: any; + tipEL: HTMLDivElement | undefined | null; rowsEL: HTMLDivElement | undefined | null; + rowsPaneEL: HTMLDivElement | undefined | null; spacerEL: HTMLDivElement | undefined | null; + favoriteRowsEL:HTMLDivElement | undefined | null; visibleRows: Array> = []; + collectRows: Array> = []; keyboardEnable = true; currentRowType = "";/*保存当前鼠标所在行的类型*/ observerScrollHeightEnable: boolean = false; @@ -94,19 +90,26 @@ export class SpSystemTrace extends BaseElement { public timerShaftEL: TimerShaftElement | null | undefined; private traceSheetEL: TraceSheet | undefined | null; private rangeSelect!: RangeSelect; - private processThreads: Array = [] - private processAsyncEvent: Array = [] - private processMem: Array = [] + private chartManager: SpChartManager | undefined | null; + private loadTraceCompleted: boolean = false; + canvasFavoritePanel: HTMLCanvasElement | null | undefined;//绘制收藏泳道图 + canvasFavoritePanelCtx: CanvasRenderingContext2D | null | undefined; + canvasPanel: HTMLCanvasElement | null | undefined; //绘制取消收藏后泳道图 + canvasPanelCtx: CanvasRenderingContext2D | undefined | null; initElements(): void { this.rowsEL = this.shadowRoot?.querySelector('.rows'); + this.tipEL = this.shadowRoot?.querySelector('.tip'); + this.rowsPaneEL = this.shadowRoot?.querySelector('.rows-pane'); this.spacerEL = this.shadowRoot?.querySelector('.spacer'); + this.canvasFavoritePanel = this.shadowRoot?.querySelector('.panel-canvas-favorite'); this.timerShaftEL = this.shadowRoot?.querySelector('.timer-shaft'); this.traceSheetEL = this.shadowRoot?.querySelector('.trace-sheet'); - this.rangeSelect = new RangeSelect(this.timerShaftEL); - this.rangeSelect.rowsEL = this.rowsEL; + this.favoriteRowsEL = this.shadowRoot?.querySelector('.favorite-rows'); + this.rangeSelect = new RangeSelect(this); document?.addEventListener("triangle-flag", (event: any) => { - this.timerShaftEL?.drawTriangle(event.detail.time, event.detail.type); + let temporaryTime = this.timerShaftEL?.drawTriangle(event.detail.time, event.detail.type); + if (event.detail.timeCallback && temporaryTime) event.detail.timeCallback(temporaryTime); }) document?.addEventListener("flag-change", (event: any) => { @@ -114,93 +117,371 @@ export class SpSystemTrace extends BaseElement { if (event.detail.hidden) { this.selectFlag = undefined; this.traceSheetEL?.setAttribute("mode", 'hidden'); - this.visibleRows.forEach(it => it.draw(true)); + this.refreshCanvas(true); } }) - + if(this.timerShaftEL?.collecBtn){ + this.timerShaftEL.collecBtn.onclick = ()=>{ + if(this.timerShaftEL!.collecBtn!.hasAttribute('close')){ + this.timerShaftEL!.collecBtn!.removeAttribute('close'); + }else { + this.timerShaftEL!.collecBtn!.setAttribute('close',''); + } + if(this.collectRows.length > 0){ + this.collectRows.forEach((row)=>{ + row?.collectEL?.onclick?.(new MouseEvent("auto-collect",undefined)) + }) + } + } + } + document?.addEventListener("collect",(event: any)=>{ + let currentRow = event.detail.row; + if(currentRow.collect){ + if(!this.collectRows.find((find)=>{ + return find === currentRow + })){ + this.collectRows.push(currentRow) + } + if(event.detail.type !== "auto-collect"&&this.timerShaftEL!.collecBtn!.hasAttribute('close')){ + currentRow.collect = false; + this.timerShaftEL!.collecBtn!.click() + return + } + let replaceRow = document.createElement("div") + replaceRow.setAttribute("row-id",currentRow.rowId+"-"+currentRow.rowType); + replaceRow.setAttribute("type","replaceRow") + replaceRow.style.display = 'none'; + this.rowsEL!.replaceChild(replaceRow,currentRow); + this.favoriteRowsEL!.append(currentRow) + }else { + this.favoriteRowsEL!.removeChild(currentRow); + if(event.detail.type !== "auto-collect"){ + let rowIndex = this.collectRows.indexOf(currentRow); + if(rowIndex !== -1){ + this.collectRows.splice(rowIndex,1) + } + } + let replaceRow = this.rowsEL!.querySelector(`div[row-id='${currentRow.rowId}-${currentRow.rowType}']`) + if(replaceRow!=null){ + this.expansionAllParentRow(currentRow) + this.rowsEL!.replaceChild(currentRow,replaceRow) + currentRow.style.boxShadow = `0 10px 10px #00000000`; + } + this.canvasFavoritePanel!.style.transform = `translateY(${this.favoriteRowsEL!.scrollTop - currentRow.clientHeight}px)`; + } + if(this.collectRows.length === 0){ + this.timerShaftEL?.displayCollect(false) + }else { + this.timerShaftEL?.displayCollect(true) + } + this.freshFavoriteCavans() + this.refreshCanvas(true); + }) SpSystemTrace.scrollViewWidth = this.getScrollWidth(); this.rangeSelect.selectHandler = (rows, refreshCheckBox) => { if (rows.length == 0) { - this.rowsEL!.querySelectorAll>("trace-row").forEach(it => { + this.shadowRoot!.querySelectorAll>("trace-row").forEach(it => { it.checkType = "-1" }) - this.getVisibleRows().forEach(it => { - it.draw(true); - }); + this.getVisibleRows(); + this.refreshCanvas(true); this.traceSheetEL?.setAttribute("mode", 'hidden'); return; } if (refreshCheckBox) { if (rows.length > 0) { - this.rowsEL?.querySelectorAll>("trace-row").forEach(row => row.checkType = "0") + this.shadowRoot?.querySelectorAll>("trace-row").forEach(row => row.checkType = "0") rows.forEach(it => it.checkType = "2") } else { - this.rowsEL?.querySelectorAll>("trace-row").forEach(row => row.checkType = "-1") + this.shadowRoot?.querySelectorAll>("trace-row").forEach(row => row.checkType = "-1") return } } let selection = new SelectionParam(); - selection.cpus = []; - selection.threadIds = []; - selection.funTids = []; - selection.trackIds = []; selection.leftNs = 0; selection.rightNs = 0; + selection.recordStartNs = (window as any).recordStartNS let native_memory = ["All Heap & Anonymous VM", "All Heap", "All Anonymous VM"]; rows.forEach(it => { if (it.rowType == TraceRow.ROW_TYPE_CPU) { selection.cpus.push(parseInt(it.rowId!)) + info("load CPU traceRow id is : ", it.rowId) + } else if (it.rowType == TraceRow.ROW_TYPE_CPU_STATE) { + let filterId = parseInt(it.rowId!); + if (selection.cpuStateFilterIds.indexOf(filterId) == -1) { + selection.cpuStateFilterIds.push(filterId); + } + } else if (it.rowType == TraceRow.ROW_TYPE_CPU_FREQ) { + let filterId = parseInt(it.rowId!); + if (selection.cpuFreqFilterIds.indexOf(filterId) == -1) { + selection.cpuFreqFilterIds.push(filterId); + } + } else if (it.rowType == TraceRow.ROW_TYPE_CPU_FREQ_LIMIT) { + selection.cpuFreqLimitDatas.push(it.dataList!) } else if (it.rowType == TraceRow.ROW_TYPE_PROCESS) { - this.rowsEL?.querySelectorAll>(`trace-row[row-parent-id='${it.rowId}']`).forEach(th => { + this.shadowRoot?.querySelectorAll>(`trace-row[row-parent-id='${it.rowId}']`).forEach(th => { th.rangeSelect = true; th.checkType = "2" - selection.threadIds.push(parseInt(th.rowId!)) + if (th.rowType == TraceRow.ROW_TYPE_THREAD) { + selection.threadIds.push(parseInt(th.rowId!)) + } else if (th.rowType == TraceRow.ROW_TYPE_FUNC) { + if (th.asyncFuncName) { + selection.funAsync.push({ + name: th.asyncFuncName, + pid: th.asyncFuncNamePID || 0, + }) + } else { + selection.funTids.push(parseInt(th.rowId!)) + } + } else if (th.rowType == TraceRow.ROW_TYPE_MEM) { + selection.processTrackIds.push(parseInt(th.rowId!)) + } }) + info("load process traceRow id is : ", it.rowId) } else if (it.rowType == TraceRow.ROW_TYPE_NATIVE_MEMORY) { - this.rowsEL?.querySelectorAll>(`trace-row[row-parent-id='${it.rowId}']`).forEach(th => { + this.shadowRoot?.querySelectorAll>(`trace-row[row-parent-id='${it.rowId}']`).forEach(th => { th.rangeSelect = true; th.checkType = "2" selection.nativeMemory.push(th.rowId!); }) - }else if (it.rowType == TraceRow.ROW_TYPE_THREAD) { + info("load nativeMemory traceRow id is : ", it.rowId) + } else if (it.rowType == TraceRow.ROW_TYPE_THREAD) { selection.threadIds.push(parseInt(it.rowId!)) + info("load thread traceRow id is : ", it.rowId) } else if (it.rowType == TraceRow.ROW_TYPE_FUNC) { - selection.funTids.push(parseInt(it.rowId!)) - } else if (it.rowType == TraceRow.ROW_TYPE_MEM) { - selection.trackIds.push(parseInt(it.rowId!)) + if (it.asyncFuncName) { + selection.funAsync.push({ + name: it.asyncFuncName, + pid: it.asyncFuncNamePID || 0, + }) + } else { + selection.funTids.push(parseInt(it.rowId!)) + } + info("load func traceRow id is : ", it.rowId) + } else if (it.rowType == TraceRow.ROW_TYPE_MEM || it.rowType == TraceRow.ROW_TYPE_VIRTUAL_MEMORY) { + if (it.rowType == TraceRow.ROW_TYPE_MEM) { + selection.processTrackIds.push(parseInt(it.rowId!)) + } else { + selection.virtualTrackIds.push(parseInt(it.rowId!)) + } + info("load memory traceRow id is : ", it.rowId) } else if (it.rowType == TraceRow.ROW_TYPE_FPS) { selection.hasFps = true; + info("load FPS traceRow id is : ", it.rowId) } else if (it.rowType == TraceRow.ROW_TYPE_HEAP) { if (native_memory.indexOf(it.rowId ?? "") != -1) { selection.nativeMemory.push(it.rowId!); + info("load nativeMemory traceRow id is : ", it.rowId) } else { selection.heapIds.push(parseInt(it.rowId!)) + info("load heap traceRow id is : ", it.rowId) + } + } else if (it.rowType == TraceRow.ROW_TYPE_CPU_ABILITY) { + selection.cpuAbilityIds.push(it.rowId!) + info("load CPU Ability traceRow id is : ", it.rowId) + } else if (it.rowType == TraceRow.ROW_TYPE_MEMORY_ABILITY) { + selection.memoryAbilityIds.push(it.rowId!) + info("load Memory Ability traceRow id is : ", it.rowId) + } else if (it.rowType == TraceRow.ROW_TYPE_DISK_ABILITY) { + selection.diskAbilityIds.push(it.rowId!) + info("load DiskIo Ability traceRow id is : ", it.rowId) + } else if (it.rowType == TraceRow.ROW_TYPE_NETWORK_ABILITY) { + selection.networkAbilityIds.push(it.rowId!) + info("load Network Ability traceRow id is : ", it.rowId) + } else if (it.rowType?.startsWith(TraceRow.ROW_TYPE_SDK)) { + if (it.rowType == TraceRow.ROW_TYPE_SDK) { + this.shadowRoot?.querySelectorAll>(`trace-row[row-parent-id='${it.rowId}']`).forEach(th => { + th.rangeSelect = true; + th.checkType = "2" + }) + } + if (it.rowType == TraceRow.ROW_TYPE_SDK_COUNTER) { + selection.sdkCounterIds.push(it.rowId!) + } + if (it.rowType == TraceRow.ROW_TYPE_SDK_SLICE) { + selection.sdkSliceIds.push(it.rowId!) + } + } else if (it.rowType?.startsWith("hiperf")) { + if (it.rowType == TraceRow.ROW_TYPE_HIPERF_EVENT || it.rowType == TraceRow.ROW_TYPE_HIPERF_REPORT) { + return; + } + selection.perfSampleIds.push(1) + if (it.rowType == TraceRow.ROW_TYPE_HIPERF_PROCESS) { + this.shadowRoot?.querySelectorAll>(`trace-row[row-parent-id='${it.rowId}']`).forEach(th => { + th.rangeSelect = true; + th.checkType = "2" + }) + } + if (it.rowType == TraceRow.ROW_TYPE_HIPERF || it.rowId == "HiPerf-cpu-merge") { + selection.perfAll = true; + } + if (it.rowType == TraceRow.ROW_TYPE_HIPERF_CPU) { + selection.perfCpus.push(it.index); + } + if (it.rowType == TraceRow.ROW_TYPE_HIPERF_PROCESS) { + selection.perfProcess.push(parseInt(it.rowId!.split("-")[0])); + } + if (it.rowType == TraceRow.ROW_TYPE_HIPERF_THREAD) { + selection.perfThread.push(parseInt(it.rowId!.split("-")[0])); + } + } else if (it.rowType == TraceRow.ROW_TYPE_FILE_SYSTEM) { + if (it.rowId == "FileSystemLogicalWrite" ) { + if(selection.fileSystemType.length == 0){ + selection.fileSystemType = [0, 1, 3]; + }else { + if (selection.fileSystemType.indexOf(3) == -1) { + selection.fileSystemType.push(3) + } + } + } else if(it.rowId == "FileSystemLogicalRead"){ + if(selection.fileSystemType.length == 0){ + selection.fileSystemType = [0, 1, 2]; + }else { + if (selection.fileSystemType.indexOf(2) == -1) { + selection.fileSystemType.push(2) + } + } + } else if (it.rowId == "FileSystemVirtualMemory") { + selection.fileSysVirtualMemory = true; + } else if (it.rowId == "FileSystemDiskIOLatency") { + selection.diskIOLatency = true; + } else { + if(!selection.diskIOLatency){ + let arr = it.rowId!.split("-").reverse(); + let ipid = parseInt(arr[0]); + if (selection.diskIOipids.indexOf(ipid) == -1) { + selection.diskIOipids.push(ipid); + } + if(arr[1] == 'read'){ + selection.diskIOReadIds.indexOf(ipid) == -1?selection.diskIOReadIds.push(ipid):""; + } else if(arr[1] == 'write'){ + selection.diskIOWriteIds.indexOf(ipid) == -1?selection.diskIOWriteIds.push(ipid):""; + } + } } + } else if (it.rowType == TraceRow.ROW_TYPE_POWER_ENERGY) { + selection.powerEnergy.push(it.rowId!) + } else if (it.rowType == TraceRow.ROW_TYPE_SYSTEM_ENERGY) { + selection.systemEnergy.push(it.rowId!) + } else if (it.rowType == TraceRow.ROW_TYPE_ANOMALY_ENERGY) { + selection.anomalyEnergy.push(it.rowId!) + } else if (it.rowType == TraceRow.ROW_TYPE_SYSTEM_ENERGY) { + info("load anomaly Energy traceRow id is : ", it.rowId) + } else if (it.rowType == TraceRow.ROW_TYPE_SMAPS) { + selection.smapsType.push(it.rowId!) } }) + if (selection.diskIOipids.length > 0 && !selection.diskIOLatency) { + selection.promiseList.push(queryEbpfSamplesCount(TraceRow.rangeSelectObject?.startNS || 0, TraceRow.rangeSelectObject?.endNS || 0, selection.diskIOipids).then((res) => { + if (res.length > 0) { + selection.fsCount = res[0].fsCount; + selection.vmCount = res[0].vmCount; + } + return new Promise(resolve => resolve(1)) + })) + } selection.leftNs = TraceRow.rangeSelectObject?.startNS || 0; selection.rightNs = TraceRow.rangeSelectObject?.endNS || 0; - this.traceSheetEL?.boxSelection(selection); + this.selectStructNull(); + this.timerShaftEL?.removeTriangle("inverted") + if (selection.promiseList.length > 0) { + Promise.all(selection.promiseList).then(() => { + selection.promiseList = []; + this.traceSheetEL?.rangeSelect(selection); + }) + } else { + this.traceSheetEL?.rangeSelect(selection); + } } // @ts-ignore new ResizeObserver((entries) => { let width = entries[0].contentRect.width - 1 - SpSystemTrace.scrollViewWidth; requestAnimationFrame(() => { this.timerShaftEL?.updateWidth(width) - this.shadowRoot!.querySelectorAll>("trace-row").forEach(it => it.updateWidth(width)) + this.shadowRoot!.querySelectorAll>("trace-row").forEach(it => { + it.updateWidth(width) + }) }) }).observe(this); new ResizeObserver((entries) => { - this.getVisibleRows().forEach(it => { - it.draw(true); - }); + this.canvasPanelConfig(); if (this.traceSheetEL!.getAttribute("mode") == "hidden") { this.timerShaftEL?.removeTriangle("triangle") } - }).observe(this.rowsEL!); + this.freshFavoriteCavans() + this.getVisibleRows(); + this.refreshCanvas(true) + + }).observe(this.rowsPaneEL!); + window.addEventListener("keydown", ev => { + if (ev.key.toLocaleLowerCase() === "escape") { + this.shadowRoot?.querySelectorAll>("trace-row").forEach((it) => { + it.checkType = "-1" + }) + TraceRow.rangeSelectObject = undefined; + this.rangeSelect.rangeTraceRow = [] + this.selectStructNull(); + this.timerShaftEL?.setSlicesMark(); + this.traceSheetEL?.setAttribute("mode", 'hidden'); + } + }); + this.chartManager = new SpChartManager(this); + this.canvasPanel = this.shadowRoot!.querySelector("#canvas-panel")!; + this.canvasFavoritePanel = this.shadowRoot!.querySelector("#canvas-panel-favorite")!; + this.canvasPanelCtx = this.canvasPanel.getContext('2d'); + this.canvasFavoritePanelCtx = this.canvasFavoritePanel.getContext('2d'); + this.canvasPanelConfig(); + } + + freshFavoriteCavans(){ + let collectList = this.favoriteRowsEL?.querySelectorAll>(`trace-row[collect-type]`)||[]; + let height = 0; + collectList.forEach((row, index) =>{ + height+=row.offsetHeight + if(index == collectList.length -1){ + row.style.boxShadow = `0 10px 10px #00000044`; + }else { + row.style.boxShadow = `0 10px 10px #00000000`; + } + }) + if(height > this.rowsPaneEL!.offsetHeight){ + this.favoriteRowsEL!.style.height = this.rowsPaneEL!.offsetHeight + "px" + }else { + this.favoriteRowsEL!.style.height = height + "px" + } + this.favoriteRowsEL!.style.width = this.canvasPanel?.offsetWidth + 'px' + this.spacerEL!.style.height = height + "px" + this.canvasFavoritePanel!.style.height = this.favoriteRowsEL!.style.height; + this.canvasFavoritePanel!.style.width = this.canvasPanel?.offsetWidth + 'px' + this.canvasFavoritePanel!.width = this.canvasFavoritePanel!.offsetWidth * window.devicePixelRatio; + this.canvasFavoritePanel!.height = this.canvasFavoritePanel!.offsetHeight * window.devicePixelRatio; + this.canvasFavoritePanel!.getContext('2d')!.scale(window.devicePixelRatio, window.devicePixelRatio); } + expansionAllParentRow(currentRow:TraceRow){ + let parentRow = this.rowsEL!.querySelector>(`trace-row[row-id='${currentRow.rowParentId}'][folder]`) + if (parentRow) { + parentRow.expansion = true + if(this.rowsEL!.querySelector>(`trace-row[row-id='${parentRow.rowParentId}'][folder]`)){ + this.expansionAllParentRow(parentRow) + } + } + + } + + canvasPanelConfig() { + this.canvasPanel!.style.left = `${this.timerShaftEL!.canvas!.offsetLeft!}px` + this.canvasPanel!.width = this.canvasPanel!.offsetWidth * window.devicePixelRatio; + this.canvasPanel!.height = this.canvasPanel!.offsetHeight * window.devicePixelRatio; + this.canvasPanelCtx!.scale(window.devicePixelRatio, window.devicePixelRatio); + this.canvasFavoritePanel!.style.left = `${this.timerShaftEL!.canvas!.offsetLeft!}px`; + this.canvasFavoritePanel!.width = this.canvasFavoritePanel!.offsetWidth * window.devicePixelRatio; + this.canvasFavoritePanel!.height = this.canvasFavoritePanel!.offsetHeight * window.devicePixelRatio; + this.canvasFavoritePanelCtx!.scale(window.devicePixelRatio, window.devicePixelRatio); + } + + getScrollWidth() { let totalScrollDiv, scrollDiv, overflowDiv = document.createElement('div'); overflowDiv.style.cssText = 'position:absolute; top:-2000px;width:200px; height:200px; overflow:hidden;'; @@ -212,12 +493,12 @@ export class SpSystemTrace extends BaseElement { } getVisibleRows(): Array> { - let scrollTop = this.rowsEL?.scrollTop || 0; - let scrollHeight = this.rowsEL?.clientHeight || 0; + let scrollTop = this.rowsPaneEL?.scrollTop || 0; + let scrollHeight = this.rowsPaneEL?.clientHeight || 0; let res = [...this.rowsEL!.querySelectorAll>("trace-row")].filter((it) => { let tr = (it as TraceRow); let top = it.offsetTop - (this.rowsEL?.offsetTop || 0); - if ((top + it.clientHeight > scrollTop && top + it.clientHeight < scrollTop + scrollHeight + it.clientHeight) || it.collect) { + if ((top + it.clientHeight > scrollTop && top + it.clientHeight < scrollTop + scrollHeight + it.clientHeight)) { it.sleeping = false; return true } else { @@ -227,8 +508,22 @@ export class SpSystemTrace extends BaseElement { return false; } }) - this.visibleRows = res; - return res; + let favoriteScrollTop = this.favoriteRowsEL?.scrollTop || 0; + let favoriteScrollHeight = this.favoriteRowsEL?.clientHeight || 0; + let favoriteRes = [...this.favoriteRowsEL!.querySelectorAll>("trace-row")].filter((it) => { + let tr = (it as TraceRow); + let top = it.offsetTop + if ((top + it.clientHeight > favoriteScrollTop && top + it.clientHeight < favoriteScrollTop + favoriteScrollHeight + it.clientHeight)) { + it.sleeping = false; + return true + } else { + it.sleeping = true; + return false; + } + }) + this.visibleRows = [...res,...favoriteRes]; + info("Visible TraceRow size is :", this.visibleRows!.length) + return this.visibleRows; } timerShaftELFlagClickHandler = (flag: Flag | undefined | null) => { @@ -242,54 +537,160 @@ export class SpSystemTrace extends BaseElement { timerShaftELFlagChange = (hoverFlag: Flag | undefined | null, selectFlag: Flag | undefined | null) => { this.hoverFlag = hoverFlag; this.selectFlag = selectFlag; - this.visibleRows.forEach(it => it.draw(true)); + this.refreshCanvas(true); } timerShaftELRangeChange = (e: any) => { TraceRow.range = e; - //在rowsEL显示范围内的 trace-row组件将收到时间区间变化通知 - for (let i = 0; i < this.visibleRows.length; i++) { - this.visibleRows[i].draw(); + if (TraceRow.rangeSelectObject) { + TraceRow.rangeSelectObject!.startX = Math.floor(ns2x(TraceRow.rangeSelectObject!.startNS!, TraceRow.range?.startNS!, TraceRow.range?.endNS!, TraceRow.range?.totalNS!, this.timerShaftEL!.sportRuler!.frame)); + TraceRow.rangeSelectObject!.endX = Math.floor(ns2x(TraceRow.rangeSelectObject!.endNS!, TraceRow.range?.startNS!, TraceRow.range?.endNS!, TraceRow.range?.totalNS!, this.timerShaftEL!.sportRuler!.frame)); } + //在rowsEL显示范围内的 trace-row组件将收到时间区间变化通知 + this.refreshCanvas(false); } - + tim: number = -1; + top: number = 0; rowsElOnScroll = (e: any) => { this.hoverStructNull(); + if (TraceRow.range) { + TraceRow.range.refresh = true; + } this.visibleRows = this.getVisibleRows(); for (let index = 0; index < this.visibleRows.length; index++) { if (index == 0 || index == this.visibleRows.length - 1) { this.visibleRows[index].isHover = false; } } + requestAnimationFrame(()=>{ + this.refreshCanvas(false); + }) + + } + + favoriteRowsElOnScroll = (e: any) => { + this.rowsElOnScroll(e) + } + + offset = 147; + + getRowsContentHeight(): number { + return [...this.rowsEL!.querySelectorAll>(`trace-row:not([sleeping])`)] + .map(it => it.clientHeight) + .reduce((acr, cur) => acr + cur, 0); } + // refresh main canvas and favorite canvas + refreshCanvas(cache: boolean) { + if (this.visibleRows.length == 0) { + return; + } + //clear main canvas + this.canvasPanelCtx?.clearRect(0, 0, this.canvasPanel!.offsetWidth, this.canvasPanel!.offsetHeight); + //clear favorite canvas + this.canvasFavoritePanelCtx?.clearRect(0, 0, this.canvasFavoritePanel!.offsetWidth, this.canvasFavoritePanel!.offsetHeight); + //draw lines for main canvas + var rowsContentHeight = this.getRowsContentHeight(); + let canvasHeight = rowsContentHeight > this.canvasPanel!.clientHeight ? this.canvasPanel!.clientHeight : rowsContentHeight; + canvasHeight += this.canvasFavoritePanel!.clientHeight; + drawLines(this.canvasPanelCtx!, TraceRow.range?.xs || [], canvasHeight, this.timerShaftEL!.lineColor()); + //draw lines for favorite canvas + drawLines(this.canvasFavoritePanelCtx!, TraceRow.range?.xs || [], this.canvasFavoritePanel!.clientHeight, this.timerShaftEL!.lineColor()); + //canvas translate + this.canvasPanel!.style.transform = `translateY(${this.rowsPaneEL!.scrollTop}px)`; + this.canvasFavoritePanel!.style.transform = `translateY(${this.favoriteRowsEL!.scrollTop}px)`; + //draw trace row + + this.visibleRows.forEach((v, i) => { + if (v.collect) { + v.translateY = v.getBoundingClientRect().top - 195; + } else { + v.translateY = v.offsetTop - this.rowsPaneEL!.scrollTop; + } + + v.draw(cache) + }) + //draw flag line segment for canvas + drawFlagLineSegment(this.canvasPanelCtx, this.hoverFlag, this.selectFlag, { + x: 0, y: 0, width: this.timerShaftEL?.canvas?.clientWidth, height: this.canvasPanel?.clientHeight + }); + //draw flag line segment for favorite canvas + drawFlagLineSegment(this.canvasFavoritePanelCtx, this.hoverFlag, this.selectFlag, { + x: 0, y: 0, width: this.timerShaftEL?.canvas?.clientWidth, height: this.canvasFavoritePanel?.clientHeight + }); + + //draw wakeup for main canvas + drawWakeUp(this.canvasPanelCtx, CpuStruct.wakeupBean, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, { + x: 0, y: 0, width: this.timerShaftEL!.canvas!.clientWidth, height: this.canvasPanel!.clientHeight! + } as Rect); + //draw wakeup for favorite canvas + drawWakeUp(this.canvasFavoritePanelCtx, CpuStruct.wakeupBean, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, { + x: 0, y: 0, width: this.timerShaftEL!.canvas!.clientWidth, height: this.canvasFavoritePanel!.clientHeight! + } as Rect); + } + + documentOnMouseDown = (ev: MouseEvent) => { + if (!this.loadTraceCompleted) return; + TraceRow.isUserInteraction = true; if (this.isMouseInSheet(ev)) return; this.observerScrollHeightEnable = false; if (ev.offsetX > this.timerShaftEL!.canvas!.offsetLeft) { - this.rangeSelect.mouseDown(ev) - this.timerShaftEL?.documentOnMouseDown(ev) - this.visibleRows.forEach(it => { - it.draw(); - }) + let x = ev.offsetX - this.timerShaftEL!.canvas!.offsetLeft; + let y = ev.offsetY; + this.timerShaftEL?.documentOnMouseDown(ev); + if (this.timerShaftEL!.sportRuler!.frame.contains(x, y) && x > (TraceRow.rangeSelectObject?.startX || 0) && x < (TraceRow.rangeSelectObject?.endX || 0)) { + let time = Math.round((x * (TraceRow.range?.endNS! - TraceRow.range?.startNS!) / this.timerShaftEL!.canvas!.offsetWidth) + TraceRow.range?.startNS!); + this.timerShaftEL!.sportRuler!.drawTriangle(time, "triangle") + } else { + this.rangeSelect.mouseDown(ev) + this.rangeSelect.drag = true; + } + } else { + this.rangeSelect.drag = false; } } documentOnMouseUp = (ev: MouseEvent) => { + if (!this.loadTraceCompleted) return; + TraceRow.isUserInteraction = false; this.rangeSelect.isMouseDown = false; if (this.isMouseInSheet(ev)) return; + let x = ev.offsetX - this.timerShaftEL!.canvas!.offsetLeft; + let y = ev.offsetY; + if (this.timerShaftEL!.sportRuler!.frame.contains(x, y) && x > (TraceRow.rangeSelectObject?.startX || 0) && x < (TraceRow.rangeSelectObject?.endX || 0)) { + } else { this.rangeSelect.mouseUp(ev); this.timerShaftEL?.documentOnMouseUp(ev) + } } documentOnMouseOut = (ev: MouseEvent) => { + if (!this.loadTraceCompleted) return; + TraceRow.isUserInteraction = false; if (this.isMouseInSheet(ev)) return; if (ev.offsetX > this.timerShaftEL!.canvas!.offsetLeft) { + this.rangeSelect.mouseOut(ev) this.timerShaftEL?.documentOnMouseOut(ev) } } documentOnKeyPress = (ev: KeyboardEvent) => { + if (!this.loadTraceCompleted) return; + TraceRow.isUserInteraction = true; + if (ev.key.toLocaleLowerCase() == "m") { + if (CpuStruct.selectCpuStruct) { + this.timerShaftEL?.setSlicesMark((CpuStruct.selectCpuStruct.startTime || 0), (CpuStruct.selectCpuStruct.startTime || 0) + (CpuStruct.selectCpuStruct.dur || 0)); + } else if (ThreadStruct.selectThreadStruct) { + this.timerShaftEL?.setSlicesMark((ThreadStruct.selectThreadStruct.startTime || 0), (ThreadStruct.selectThreadStruct.startTime || 0) + (ThreadStruct.selectThreadStruct.dur || 0)); + } else if (FuncStruct.selectFuncStruct) { + this.timerShaftEL?.setSlicesMark((FuncStruct.selectFuncStruct.startTs || 0), (FuncStruct.selectFuncStruct.startTs || 0) + (FuncStruct.selectFuncStruct.dur || 0)); + } else if (TraceRow.rangeSelectObject) { + this.timerShaftEL?.setSlicesMark((TraceRow.rangeSelectObject.startNS || 0), (TraceRow.rangeSelectObject.endNS || 0)); + } else { + this.timerShaftEL?.setSlicesMark(); + } + } if (this.isMousePointInSheet) { return; } @@ -298,19 +699,20 @@ export class SpSystemTrace extends BaseElement { } documentOnKeyUp = (ev: KeyboardEvent) => { - if (this.isMousePointInSheet) { - return; - } + if (!this.loadTraceCompleted) return; + TraceRow.isUserInteraction = false; this.observerScrollHeightEnable = false; this.keyboardEnable && this.timerShaftEL!.documentOnKeyUp(ev); if (ev.code == "Enter") { if (ev.shiftKey) { this.dispatchEvent(new CustomEvent("previous-data", { - detail: {} + detail: {}, + composed: false })); } else { this.dispatchEvent(new CustomEvent("next-data", { - detail: {} + detail: {}, + composed: false })); } } @@ -322,6 +724,7 @@ export class SpSystemTrace extends BaseElement { } favoriteChangeHandler = (row: TraceRow) => { + info("favoriteChangeHandler", row.frame, row.offsetTop, row.offsetHeight); this.getVisibleRows(); } @@ -331,7 +734,12 @@ export class SpSystemTrace extends BaseElement { } documentOnMouseMove = (ev: MouseEvent) => { - if (this.isMouseInSheet(ev)) return; + if ((window as any).isSheetMove) return; + if (!this.loadTraceCompleted || (window as any).flagInputFocus) return; + if (this.isMouseInSheet(ev)) { + this.hoverStructNull(); + return; + } let rows = this.visibleRows; if (this.timerShaftEL?.isScaling()) { return; @@ -339,72 +747,32 @@ export class SpSystemTrace extends BaseElement { this.timerShaftEL?.documentOnMouseMove(ev) this.rangeSelect.mouseMove(rows, ev); if (this.rangeSelect.isMouseDown) { - for (let i = 0; i < rows.length; i++) { - rows[i].tipEL!.style.display = "none"; - rows[i].draw(true); - } + this.refreshCanvas(true); } else { - for (let i = 0; i < rows.length; i++) { - let tr = rows[i]; - let rowsELScrollTop = this.rowsEL?.scrollTop || 0; - let x = ev.offsetX - (tr.canvasContainer?.offsetLeft || 0); - let y = ev.offsetY - (tr.canvasContainer?.offsetTop || 0) + rowsELScrollTop; - if ((!tr.collect && x > tr.frame.x && x < tr.frame.x + tr.frame.width && ev.offsetY + rowsELScrollTop > tr.offsetTop && ev.offsetY + rowsELScrollTop < tr.offsetTop + tr.frame.height) || - (tr.collect && x > tr.frame.x && x < tr.frame.x + tr.frame.width && ev.offsetY > tr.offsetTop - 48 && ev.offsetY < tr.offsetTop - 48 + tr.frame.height)) { - tr.isHover = true; - tr.hoverX = x; - tr.hoverY = tr.collect ? (ev.offsetY + 48 - tr.offsetTop) : y; - if (tr.rowType === TraceRow.ROW_TYPE_CPU) { - this.currentRowType = TraceRow.ROW_TYPE_CPU; - if (CpuStruct.hoverCpuStruct) { - tr.tip = `P:${CpuStruct.hoverCpuStruct.processName || "Process"} [${CpuStruct.hoverCpuStruct.processId}]T:${CpuStruct.hoverCpuStruct.name} [${CpuStruct.hoverCpuStruct.tid}]`; - } - tr.setTipLeft(x, CpuStruct.hoverCpuStruct) - } else if (tr.rowType === TraceRow.ROW_TYPE_CPU_FREQ) { - this.currentRowType = TraceRow.ROW_TYPE_CPU_FREQ; - if (CpuFreqStruct.hoverCpuFreqStruct) { - tr.tip = `${ColorUtils.formatNumberComma(CpuFreqStruct.hoverCpuFreqStruct.value!)} kHz` - } - tr.setTipLeft(x, CpuFreqStruct.hoverCpuFreqStruct) - } else if (tr.rowType === TraceRow.ROW_TYPE_THREAD) { - this.currentRowType = TraceRow.ROW_TYPE_THREAD; - } else if (tr.rowType === TraceRow.ROW_TYPE_FUNC) { - this.currentRowType = TraceRow.ROW_TYPE_FUNC; - } else if (tr.rowType === TraceRow.ROW_TYPE_HEAP) { - this.currentRowType = TraceRow.ROW_TYPE_HEAP; - if (HeapStruct.hoverHeapStruct) { - if (tr.drawType === 1) { - tr.tip = `${HeapStruct.hoverHeapStruct.heapsize}` - } else { - tr.tip = `${Utils.getByteWithUnit(HeapStruct.hoverHeapStruct.heapsize!)}` - } + if (!this.rowsPaneEL!.containPoint(ev, {left: 248})) { + this.tipEL!.style.display = "none"; + this.hoverStructNull(); + } + rows.filter(it => it.focusContain(ev)).forEach(tr => { + if (this.currentRowType != tr.rowType) { + this.hoverStructNull(); + this.tipEL!.style.display = "none"; + this.currentRowType = tr.rowType || ""; + } + if (tr.rowType == TraceRow.ROW_TYPE_CPU) { + CpuStruct.hoverCpuStruct = undefined; + for (let re of tr.dataListCache) { + if (re.frame && isFrameContainPoint(re.frame, tr.hoverX, tr.hoverY)) { + CpuStruct.hoverCpuStruct = re; + break } - tr.setTipLeft(x, HeapStruct.hoverHeapStruct) - } else { - this.hoverStructNull(); } - tr.draw(true); } else { - tr.onMouseLeave(x, y); - tr.isHover = false; - tr.hoverX = x; - tr.hoverY = y; - } - - } - if (ev.offsetX > this.timerShaftEL!.canvas!.offsetLeft! - && ev.offsetX < this.timerShaftEL!.canvas!.offsetLeft! + this.timerShaftEL!.canvas!.offsetWidth! - && ev.offsetY > this.rowsEL!.offsetTop - && ev.offsetY < this.rowsEL!.offsetTop + this.rowsEL!.offsetHeight - ) { - } else { - this.hoverStructNull(); - for (let i = 0, len = rows.length; i < len; i++) { - if (!(rows[i].rowType === TraceRow.ROW_TYPE_PROCESS) && this.currentRowType === rows[i].rowType) { // - rows[i].draw(true); - } + CpuStruct.hoverCpuStruct = undefined; } - } + tr.focusHandler?.(ev); + }) + this.refreshCanvas(true); } } @@ -413,6 +781,18 @@ export class SpSystemTrace extends BaseElement { CpuFreqStruct.hoverCpuFreqStruct = undefined; ThreadStruct.hoverThreadStruct = undefined; FuncStruct.hoverFuncStruct = undefined; + HiPerfCpuStruct.hoverStruct = undefined; + HiPerfProcessStruct.hoverStruct = undefined; + HiPerfThreadStruct.hoverStruct = undefined; + HiPerfEventStruct.hoverStruct = undefined; + HiPerfReportStruct.hoverStruct = undefined; + CpuStateStruct.hoverStateStruct = undefined; + CpuAbilityMonitorStruct.hoverCpuAbilityStruct = undefined; + DiskAbilityMonitorStruct.hoverDiskAbilityStruct = undefined; + MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = undefined; + NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = undefined; + CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = undefined; + FpsStruct.hoverFpsStruct = undefined; } selectStructNull() { @@ -421,94 +801,128 @@ export class SpSystemTrace extends BaseElement { CpuFreqStruct.selectCpuFreqStruct = undefined; ThreadStruct.selectThreadStruct = undefined; FuncStruct.selectFuncStruct = undefined; + SpHiPerf.selectCpuStruct = undefined; + CpuStateStruct.selectStateStruct = undefined; + CpuFreqLimitsStruct.selectCpuFreqLimitsStruct = undefined } documentOnClick = (ev: MouseEvent) => { + if (!this.loadTraceCompleted) return; if (this.isMouseInSheet(ev)) return; + if ((window as any).isPackUpTable) { + (window as any).isPackUpTable = false; + return; + } if (this.rangeSelect.isDrag()) { return; } - this.onClickHandler(); - this.documentOnMouseMove(ev) + let x = ev.offsetX - this.timerShaftEL!.canvas!.offsetLeft; + let y = ev.offsetY; + if (this.timerShaftEL!.sportRuler!.frame.contains(x, y) && x > (TraceRow.rangeSelectObject?.startX || 0) && x < (TraceRow.rangeSelectObject?.endX || 0)) { + } else { + this.onClickHandler(); + this.documentOnMouseMove(ev) + } } - onClickHandler(){ - this.rowsEL?.querySelectorAll>("trace-row").forEach(it => it.rangeSelect = false) + onClickHandler() { + if (!this.loadTraceCompleted) return; + this.shadowRoot?.querySelectorAll>("trace-row").forEach(it => it.rangeSelect = false) this.selectStructNull(); let threadClickHandler: any; let cpuClickHandler: any; threadClickHandler = (d: ThreadStruct) => { this.observerScrollHeightEnable = false; - this.goProcess(`${d.cpu}`, "", "cpu", true); - let row = this.shadowRoot!.querySelector>(`trace-row[row-id='${d.pid}'][row-type='process'][folder]`); - if (row) { - row.expansion = false; + this.scrollToProcess(`${d.cpu}`, "", "cpu-data", true); + let cpuRow = this.shadowRoot?.querySelectorAll>(`trace-row[row-id='${d.cpu}'][row-type='cpu-data']`)[0]; + let findEntry = cpuRow!.dataList!.find((dat: any) => dat.startTime === d.startTime); + if (findEntry!.startTime! + findEntry!.dur! < TraceRow.range!.startNS || findEntry!.startTime! > TraceRow.range!.endNS) { + this.timerShaftEL?.setRangeNS(findEntry!.startTime! - findEntry!.dur! * 2, findEntry!.startTime! + findEntry!.dur! + findEntry!.dur! * 2); } - let cpuRow = this.rowsEL?.querySelectorAll>(`trace-row[row-id='${d.cpu}'][row-type='cpu']`)[0]; - let findEntry = cpuRow!.dataList!.find(it => it.startTime === d.startTime); this.hoverStructNull(); this.selectStructNull(); CpuStruct.hoverCpuStruct = findEntry; CpuStruct.selectCpuStruct = findEntry; - cpuRow!.draw(); + this.timerShaftEL?.drawTriangle(findEntry!.startTime || 0, "inverted"); this.traceSheetEL?.displayCpuData(CpuStruct.selectCpuStruct!, (wakeUpBean) => { CpuStruct.wakeupBean = wakeUpBean; - this.visibleRows.forEach(it => it.draw()); + this.refreshCanvas(true); }, cpuClickHandler); } - let scrollTimer: any; + cpuClickHandler = (d: CpuStruct) => { this.observerScrollHeightEnable = true; - let threadRow = this.rowsEL?.querySelectorAll>(`trace-row[row-id='${d.tid}'][row-type='thread']`)[0]; - this.goProcess(`${d.tid}`, `${d.processId}`, "thread", true) - this.observerScrollHeightCallback = () => { - if (threadRow!.isComplete) { + let threadRow = this.shadowRoot?.querySelectorAll>(`trace-row[row-id='${d.tid}'][row-type='thread']`)[0]; + let task = () => { + if (threadRow) { let findEntry = threadRow!.dataList!.find((dat) => dat.startTime === d.startTime); + if (findEntry!.startTime! + findEntry!.dur! < TraceRow.range!.startNS || findEntry!.startTime! > TraceRow.range!.endNS) { + this.timerShaftEL?.setRangeNS(findEntry!.startTime! - findEntry!.dur! * 2, findEntry!.startTime! + findEntry!.dur! + findEntry!.dur! * 2); + } this.hoverStructNull(); this.selectStructNull(); ThreadStruct.hoverThreadStruct = findEntry; ThreadStruct.selectThreadStruct = findEntry; - threadRow!.draw(); - this.traceSheetEL?.displayThreadData(ThreadStruct.selectThreadStruct!, threadClickHandler); - // clearTimeout(scrollTimer); - this.goProcess(`${d.tid}`, `${d.processId}`, "thread", true) - } else { - threadRow!.onComplete = () => { - let findEntry = threadRow!.dataList!.find((dat) => dat.startTime === d.startTime); - this.hoverStructNull(); - this.selectStructNull(); - ThreadStruct.hoverThreadStruct = findEntry; - ThreadStruct.selectThreadStruct = findEntry; - threadRow!.draw(); - this.traceSheetEL?.displayThreadData(ThreadStruct.selectThreadStruct!, threadClickHandler); - clearTimeout(scrollTimer); - scrollTimer = setTimeout(() => this.goProcess(`${d.tid}`, `${d.processId}`, "thread", false), 100) - } + this.closeAllExpandRows(d.processId + "") + this.timerShaftEL?.drawTriangle(findEntry!.startTime || 0, "inverted"); + this.traceSheetEL?.displayThreadData(ThreadStruct.selectThreadStruct!, threadClickHandler, cpuClickHandler); + this.scrollToProcess(`${d.tid}`, `${d.processId}`, "thread", true); } } + if (threadRow) { + this.scrollToProcess(`${d.tid}`, `${d.processId}`, "process", false); + this.scrollToProcess(`${d.tid}`, `${d.processId}`, "thread", true); + } + if (threadRow!.isComplete) { + task() + } else { + threadRow!.onComplete = task + } } if (CpuStruct.hoverCpuStruct) { CpuStruct.selectCpuStruct = CpuStruct.hoverCpuStruct + this.timerShaftEL?.drawTriangle(CpuStruct.selectCpuStruct!.startTime || 0, "inverted"); this.traceSheetEL?.displayCpuData(CpuStruct.selectCpuStruct, (wakeUpBean) => { CpuStruct.wakeupBean = wakeUpBean; - this.visibleRows.forEach(it => it.draw()); + this.refreshCanvas(false); }, cpuClickHandler); this.timerShaftEL?.modifyFlagList(undefined); } else if (ThreadStruct.hoverThreadStruct) { ThreadStruct.selectThreadStruct = ThreadStruct.hoverThreadStruct; - this.traceSheetEL?.displayThreadData(ThreadStruct.selectThreadStruct, threadClickHandler); + this.timerShaftEL?.drawTriangle(ThreadStruct.selectThreadStruct!.startTime || 0, "inverted"); + this.traceSheetEL?.displayThreadData(ThreadStruct.selectThreadStruct, threadClickHandler, cpuClickHandler); this.timerShaftEL?.modifyFlagList(undefined); } else if (FuncStruct.hoverFuncStruct) { FuncStruct.selectFuncStruct = FuncStruct.hoverFuncStruct; - this.traceSheetEL?.displayFuncData(FuncStruct.hoverFuncStruct) + let hoverFuncStruct = FuncStruct.hoverFuncStruct + this.timerShaftEL?.drawTriangle(FuncStruct.selectFuncStruct!.startTs || 0, "inverted"); + FuncStruct.selectFuncStruct = hoverFuncStruct + this.traceSheetEL?.displayFuncData(FuncStruct.selectFuncStruct, (funcStract: any) => { + this.observerScrollHeightEnable = true; + this.moveRangeToCenter(funcStract.startTime!, funcStract.dur!) + this.scrollToActFunc(funcStract, false) + }) + this.timerShaftEL?.modifyFlagList(undefined); + } else if (CpuFreqStruct.hoverCpuFreqStruct) { + CpuFreqStruct.selectCpuFreqStruct = CpuFreqStruct.hoverCpuFreqStruct + this.traceSheetEL?.displayFreqData() + this.timerShaftEL?.modifyFlagList(undefined); + } else if (CpuStateStruct.hoverStateStruct) { + CpuStateStruct.selectStateStruct = CpuStateStruct.hoverStateStruct; + this.traceSheetEL?.displayCpuStateData() + this.timerShaftEL?.modifyFlagList(undefined); + } else if (CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct) { + CpuFreqLimitsStruct.selectCpuFreqLimitsStruct = CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct + this.traceSheetEL?.displayFreqLimitData() this.timerShaftEL?.modifyFlagList(undefined); } else { this.observerScrollHeightEnable = false; this.selectFlag = null; + this.timerShaftEL?.removeTriangle("inverted"); if (!SportRuler.isMouseInSportRuler) { this.traceSheetEL?.setAttribute("mode", 'hidden'); - this.getVisibleRows().forEach(it => it.draw(true)); + this.refreshCanvas(true); } } } @@ -523,7 +937,8 @@ export class SpSystemTrace extends BaseElement { /** * 监听rowsEL的滚动时间,刷新可见区域的trace-row组件的时间区间(将触发trace-row组件重绘) */ - this.rowsEL?.addEventListener('scroll', this.rowsElOnScroll) + this.rowsPaneEL?.addEventListener('scroll', this.rowsElOnScroll, {passive: true}) + this.favoriteRowsEL?.addEventListener('scroll', this.favoriteRowsElOnScroll, {passive: true}) /** * 监听document的mousemove事件 坐标通过换算后找到当前鼠标所在的trace-row组件,将坐标传入 */ @@ -536,30 +951,88 @@ export class SpSystemTrace extends BaseElement { document.addEventListener('keyup', this.documentOnKeyUp) SpApplication.skinChange2 = (val: boolean) => { this.timerShaftEL?.render() - this.rowsEL!.querySelectorAll>(`trace-row:not([sleeping])`).forEach(it => { - this.hoverStructNull(); - it.draw(); + // this.rowsEL!.querySelectorAll>(`trace-row:not([sleeping])`).forEach(it => { + // it.draw(); + // }) + // this.hoverStructNull(); + // this.refreshCanvas(true) + } + } + + scrollToProcess(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true) { + let rootRow = this.shadowRoot!.querySelector>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`); + if(rootRow?.collect){ + this.favoriteRowsEL!.scroll({ + top: (rootRow?.offsetTop || 0) - this.canvasFavoritePanel!.offsetHeight + (rootRow?.offsetHeight || 0), + left: 0, + behavior: smooth ? "smooth" : undefined + }) + }else { + let row = this.shadowRoot!.querySelector>(`trace-row[row-id='${rowParentId}'][folder]`); + if (row) { + row.expansion = true + } + this.rowsPaneEL!.scroll({ + top: (rootRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + (rootRow?.offsetHeight || 0), + left: 0, + behavior: smooth ? "smooth" : undefined + }) + } + } + + scrollToDepth(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true, depth: number) { + let rootRow = this.shadowRoot!.querySelector>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`); + if(rootRow!.collect){ + this.favoriteRowsEL!.scroll({ + top: (rootRow?.offsetTop || 0) - this.canvasFavoritePanel!.offsetHeight + ((++depth) * 20 || 0), + left: 0, + behavior: smooth ? "smooth" : undefined + }) + }else { + let row = this.shadowRoot!.querySelector>(`trace-row[row-id='${rowParentId}'][folder]`); + if (row) { + row.expansion = true + } + this.rowsPaneEL!.scroll({ + top: (rootRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + ((++depth) * 20 || 0), + left: 0, + behavior: smooth ? "smooth" : undefined }) } } - goProcess(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true) { + scrollToFunction(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true, afterScroll: any) { let row = this.shadowRoot!.querySelector>(`trace-row[row-id='${rowParentId}'][folder]`); if (row) { row.expansion = true } - let rootRow = this.shadowRoot!.querySelector>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`); - this.rowsEL!.scroll({ - top: rootRow!.offsetTop - this.rowsEL!.offsetTop - this.rowsEL!.offsetHeight + rootRow!.offsetHeight, - left: 0, - behavior: smooth ? "smooth" : undefined - }) + let funcRow = this.shadowRoot!.querySelector>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`); + if (funcRow == null) { + let threadRow = this.shadowRoot!.querySelector>(`trace-row[row-id='${rowId}'][row-type='thread']`); + this.rowsPaneEL!.scroll({ + top: threadRow!.offsetTop - this.canvasPanel!.offsetHeight + threadRow!.offsetHeight + threadRow!.offsetHeight, + left: 0, + behavior: undefined + }) + if (threadRow != null) { + if (threadRow.isComplete) { + afterScroll() + } else { + threadRow.onComplete = () => { + funcRow = this.shadowRoot!.querySelector>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`); + afterScroll() + } + } + } + } else { + afterScroll() + } } rowScrollTo(offset: number, callback: Function) { const fixedOffset = offset; const onScroll = () => { - if (this.rowsEL!.scrollTop === fixedOffset) { + if (this.rowsPaneEL!.scrollTop === fixedOffset) { this.rowsEL!.removeEventListener('scroll', onScroll) callback() } @@ -567,7 +1040,7 @@ export class SpSystemTrace extends BaseElement { this.rowsEL!.addEventListener('scroll', onScroll) onScroll() - this.rowsEL!.scrollTo({ + this.rowsPaneEL!.scrollTo({ top: offset, behavior: 'smooth' }) @@ -575,7 +1048,8 @@ export class SpSystemTrace extends BaseElement { disconnectedCallback() { this.timerShaftEL?.removeEventListener('range-change', this.timerShaftELRangeChange); - this.rowsEL?.removeEventListener('scroll', this.rowsElOnScroll); + this.rowsPaneEL?.removeEventListener('scroll', this.rowsElOnScroll); + this.favoriteRowsEL?.removeEventListener('scroll', this.favoriteRowsElOnScroll) this.removeEventListener('mousemove', this.documentOnMouseMove); this.removeEventListener('click', this.documentOnClick); this.removeEventListener('mousedown', this.documentOnMouseDown) @@ -586,15 +1060,17 @@ export class SpSystemTrace extends BaseElement { } loadDatabaseUrl(url: string, progress: Function, complete?: ((res: { status: boolean, msg: string }) => void) | undefined) { - this.init({url: url}, progress).then((res) => { + this.observerScrollHeightEnable = false; + this.init({url: url}, "", progress).then((res) => { if (complete) { complete(res); } }) } - loadDatabaseArrayBuffer(buf: ArrayBuffer, progress: ((name: string, percent: number) => void), complete?: ((res: { status: boolean, msg: string }) => void) | undefined) { - this.init({buf}, progress).then((res) => { + loadDatabaseArrayBuffer(buf: ArrayBuffer, thirdPartyWasmConfigUrl: string, progress: ((name: string, percent: number) => void), complete?: ((res: { status: boolean, msg: string }) => void) | undefined) { + this.observerScrollHeightEnable = false; + this.init({buf}, thirdPartyWasmConfigUrl, progress).then((res) => { let scrollTop = this.rowsEL?.scrollTop || 0 let scrollHeight = this.rowsEL?.clientHeight || 0 this.rowsEL?.querySelectorAll("trace-row").forEach((it: any) => { @@ -613,7 +1089,11 @@ export class SpSystemTrace extends BaseElement { item.rowType == TraceRow.ROW_TYPE_CPU_FREQ || item.rowType == TraceRow.ROW_TYPE_NATIVE_MEMORY || item.rowType == TraceRow.ROW_TYPE_FPS || - item.rowType == TraceRow.ROW_TYPE_PROCESS) { + item.rowType == TraceRow.ROW_TYPE_PROCESS || + item.rowType == TraceRow.ROW_TYPE_CPU_ABILITY || + item.rowType == TraceRow.ROW_TYPE_MEMORY_ABILITY || + item.rowType == TraceRow.ROW_TYPE_DISK_ABILITY || + item.rowType == TraceRow.ROW_TYPE_NETWORK_ABILITY) { item.expansion = false; item.rowHidden = false; } else { @@ -632,10 +1112,10 @@ export class SpSystemTrace extends BaseElement { searchCPU(query: string): Array { let searchResults: Array = [] - this.rowsEL!.querySelectorAll>(`trace-row[row-type='cpu']`).forEach(item => { - let res = item!.dataList!.filter(it => (it.name && it.name.search(query) >= 0) || it.tid == query + this.shadowRoot!.querySelectorAll>(`trace-row[row-type='cpu-data']`).forEach(item => { + let res = item!.dataList!.filter(it => (it.name && it.name.indexOf(query) >= 0) || it.tid == query || it.processId == query - || (it.processName && it.processName.search(query) >= 0) + || (it.processName && it.processName.indexOf(query) >= 0) ) searchResults.push(...res); }) @@ -643,6 +1123,180 @@ export class SpSystemTrace extends BaseElement { return searchResults; } + async searchFunction(cpuList: Array, query: string): Promise> { + let list = await querySearchFunc(query) + cpuList = cpuList.concat(list) + cpuList.sort((a, b) => (a.startTime || 0) - (b.startTime || 0)); + return cpuList + } + + searchSdk(dataList: Array,query: string): Array{ + this.shadowRoot!.querySelectorAll>(`trace-row[row-type^='sdk']`).forEach((row)=>{ + if (row!.name.indexOf(query) >= 0) { + let searchSdkBean = new SearchSdkBean() + searchSdkBean.startTime = TraceRow.range!.startNS + searchSdkBean.dur = TraceRow.range!.totalNS + searchSdkBean.name = row.name + searchSdkBean.rowId = row.rowId + searchSdkBean.type = "sdk" + searchSdkBean.rowType = row.rowType + searchSdkBean.rowParentId = row.rowParentId + dataList.push(searchSdkBean) + } + }) + return dataList + } + + searchThreadsAndProcesses(query: string): Array { + let searchResults: Array = [] + this.rowsEL!.querySelectorAll>(`trace-row[row-type='thread'][row-type='process']`).forEach(item => { + if (item!.name.indexOf(query) >= 0) { + let searchBean = new SearchThreadProcessBean() + searchBean.name = item.name + searchBean.rowId = item.rowId + searchBean.type = "thread||process" + searchBean.rowType = item.rowType + searchBean.rowParentId = item.rowParentId + searchResults.push(searchBean) + } + }) + return searchResults + } + + showStruct(previous: boolean, currentIndex: number, structs: Array) { + if (structs.length == 0) { + return 0; + } + let findIndex = -1; + if (previous) { + for (let i = structs.length - 1; i >= 0; i--) { + let it = structs[i]; + if (i < currentIndex && (it.startTime!) >= (TraceRow.range!.startNS) && (it.startTime!) + (it.dur!) <= (TraceRow.range!.endNS)) { + findIndex = i; + break; + } + } + } else { + findIndex = structs.findIndex((it, idx) => { + return idx > currentIndex && (it.startTime!) >= (TraceRow.range!.startNS) && (it.startTime!) + (it.dur!) <= (TraceRow.range!.endNS) + }) + } + let findEntry: any + if (findIndex >= 0) { + findEntry = structs[findIndex]; + } else { + if (previous) { + for (let i = structs.length - 1; i >= 0; i--) { + let it = structs[i]; + if ((it.startTime! + it.dur!) < (TraceRow.range!.startNS)) { + findIndex = i; + break; + } + } + if (findIndex == -1) { + findIndex = structs.length - 1; + } + } else { + findIndex = structs.findIndex((it) => (it.startTime!) > (TraceRow.range!.endNS)) + if (findIndex == -1) { + findIndex = 0; + } + } + findEntry = structs[findIndex]; + this.moveRangeToCenter(findEntry.startTime!, findEntry.dur!) + } + this.shadowRoot!.querySelectorAll>(`trace-row`).forEach(item => { + item.highlight = false; + }) + if (findEntry.type == 'thread') { + CpuStruct.selectCpuStruct = findEntry; + CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct; + this.shadowRoot!.querySelectorAll>(`trace-row[row-type='cpu-data']`).forEach(item => { + item.highlight = item.rowId == `${findEntry.cpu}`; + item.draw(true) + }) + this.scrollToProcess(`${findEntry.cpu}`, "", "cpu-data", true) + this.onClickHandler(); + } else if (findEntry.type == "func") { + this.observerScrollHeightEnable = true; + this.scrollToActFunc(findEntry, true) + } else if (findEntry.type == "thread||process") { + let threadProcessRow = this.rowsEL?.querySelectorAll>(`trace-row[row-id='${findEntry.rowId}'][row-type='${findEntry.rowType}']`)[0]; + threadProcessRow!.highlight = true + this.closeAllExpandRows(findEntry.rowParentId) + this.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); + let completeEntry = () => { + let searchEntry = threadProcessRow!.dataList!.find((dat) => dat.startTime === findEntry.startTime); + this.hoverStructNull(); + this.selectStructNull(); + ThreadStruct.hoverThreadStruct = searchEntry; + ThreadStruct.selectThreadStruct = searchEntry; + this.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true) + } + if (threadProcessRow!.isComplete) { + completeEntry() + } else { + threadProcessRow!.onComplete = completeEntry + } + } else if(findEntry.type == "sdk"){ + let sdkRow = this.shadowRoot?.querySelectorAll>(`trace-row[row-id='${findEntry.rowId}'][row-type='${findEntry.rowType}']`)[0]; + sdkRow!.highlight = true + this.hoverStructNull(); + this.selectStructNull(); + this.onClickHandler(); + this.closeAllExpandRows(findEntry.rowParentId) + this.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); + } + this.timerShaftEL?.drawTriangle(findEntry.startTime || 0, "inverted"); + return findIndex; + } + + scrollToActFunc(funcStract: any, highlight: boolean) { + let funcRowID = funcStract.cookie == null?funcStract.tid:`${funcStract.funName}-${funcStract.pid}` + let funcRow = this.shadowRoot?.querySelector>(`trace-row[row-id='${funcRowID}'][row-type='func']`); + if (funcRow == null) return + funcRow!.highlight = highlight; + this.closeAllExpandRows(funcStract.pid) + let row = this.shadowRoot!.querySelector>(`trace-row[row-id='${funcStract.pid}'][folder]`); + if (row && !row.expansion) { + row.expansion = true + } + if(funcStract.cookie == null){ + this.scrollToProcess(`${funcStract.tid}`, `${funcStract.pid}`, "thread", false) + } + this.scrollToDepth(`${funcRowID}`, `${funcStract.pid}`, funcStract.type, true, funcStract.depth || 0) + let completeEntry = () => { + let searchEntry = funcRow!.dataList!.find((dat) => dat.startTs === funcStract.startTime); + this.hoverStructNull(); + this.selectStructNull(); + FuncStruct.hoverFuncStruct = searchEntry; + FuncStruct.selectFuncStruct = searchEntry; + this.onClickHandler(); + this.scrollToDepth(`${funcRowID}`, `${funcStract.pid}`, funcStract.type, true, funcStract.depth || 0) + } + if (funcRow!.isComplete) { + completeEntry() + } else { + funcRow!.onComplete = completeEntry + } + } + + closeAllExpandRows(pid: string) { + let expandRows = this.rowsEL?.querySelectorAll>(`trace-row[row-type='process'][expansion]`); + expandRows?.forEach((row) => { + if (row.rowId != pid) { + row.expansion = false + } + }) + } + + moveRangeToCenter(startTime: number, dur: number) { + let startNS = this.timerShaftEL?.getRange()?.startNS || 0; + let endNS = this.timerShaftEL?.getRange()?.endNS || 0; + let harfDur = Math.trunc((endNS - startNS) / 2 - dur / 2); + this.timerShaftEL?.setRangeNS(startTime - harfDur, startTime + dur + harfDur); + } + showPreCpuStruct(currentIndex: number, cpuStructs: Array): number { if (cpuStructs.length == 0) { return 0; @@ -658,11 +1312,11 @@ export class SpSystemTrace extends BaseElement { if (findIndex >= 0) { let findEntry = cpuStructs[findIndex]; CpuStruct.selectCpuStruct = findEntry; - this.rowsEL!.querySelectorAll>(`trace-row[row-type='cpu']`).forEach(item =>{ + this.rowsEL!.querySelectorAll>(`trace-row[row-type='cpu-data']`).forEach(item => { item.highlight = item.rowId == `${findEntry.cpu}`; item.draw(true); }) - this.timerShaftEL?.drawTriangle(findEntry.startTime||0, "inverted"); + this.timerShaftEL?.drawTriangle(findEntry.startTime || 0, "inverted"); } else { for (let i = cpuStructs.length - 1; i >= 0; i--) { let it = cpuStructs[i]; @@ -681,11 +1335,11 @@ export class SpSystemTrace extends BaseElement { let endNS = this.timerShaftEL?.getRange()?.endNS || 0; let harfDur = Math.trunc((endNS - startNS) / 2 - findEntry.dur! / 2); this.timerShaftEL?.setRangeNS(findEntry.startTime! - harfDur, findEntry.startTime! + findEntry.dur! + harfDur); - this.rowsEL!.querySelectorAll>(`trace-row[row-type='cpu']`).forEach(item => { + this.rowsEL!.querySelectorAll>(`trace-row[row-type='cpu-data']`).forEach(item => { item.highlight = item.rowId == `${findEntry.cpu}`; item.draw(true) }) - this.timerShaftEL?.drawTriangle(findEntry.startTime||0, "inverted"); + this.timerShaftEL?.drawTriangle(findEntry.startTime || 0, "inverted"); } CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct; this.onClickHandler(); @@ -702,11 +1356,11 @@ export class SpSystemTrace extends BaseElement { if (findIndex >= 0) { let findEntry = cpuStructs[findIndex]; CpuStruct.selectCpuStruct = findEntry; - this.rowsEL!.querySelectorAll>(`trace-row[row-type='cpu']`).forEach(item =>{ + this.rowsEL!.querySelectorAll>(`trace-row[row-type='cpu-data']`).forEach(item => { item.highlight = item.rowId == `${findEntry.cpu}`; item.draw(true); }) - this.timerShaftEL?.drawTriangle(findEntry.startTime||0, "inverted"); + this.timerShaftEL?.drawTriangle(findEntry.startTime || 0, "inverted"); } else { findIndex = cpuStructs.findIndex((it) => (it.startTime!) > (TraceRow.range!.endNS)) let findEntry: CpuStruct; @@ -719,11 +1373,11 @@ export class SpSystemTrace extends BaseElement { let endNS = this.timerShaftEL?.getRange()?.endNS || 0; let harfDur = Math.trunc((endNS - startNS) / 2 - findEntry.dur! / 2); this.timerShaftEL?.setRangeNS(findEntry.startTime! - harfDur, findEntry.startTime! + findEntry.dur! + harfDur); - this.rowsEL!.querySelectorAll>(`trace-row[row-type='cpu']`).forEach(item => { + this.rowsEL!.querySelectorAll>(`trace-row[row-type='cpu-data']`).forEach(item => { item.highlight = item.rowId == `${findEntry.cpu}`; item.draw(true); }) - this.timerShaftEL?.drawTriangle(findEntry.startTime||0, "inverted"); + this.timerShaftEL?.drawTriangle(findEntry.startTime || 0, "inverted"); } CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct; this.onClickHandler(); @@ -731,9 +1385,24 @@ export class SpSystemTrace extends BaseElement { } reset(progress: Function | undefined | null) { + this.visibleRows.length = 0; + this.tipEL!.style.display = 'none'; + this.canvasPanelCtx?.clearRect(0, 0, this.canvasPanel!.clientWidth, this.canvasPanel!.offsetHeight); + this.canvasFavoritePanelCtx?.clearRect(0, 0, this.canvasFavoritePanel!.clientWidth, this.canvasFavoritePanel!.clientHeight); + this.favoriteRowsEL!.style.height = '0' + this.canvasFavoritePanel!.style.height = '0'; + this.loadTraceCompleted = false; + if (this.favoriteRowsEL) { + this.favoriteRowsEL.querySelectorAll(`trace-row`).forEach((row)=>{ + this.favoriteRowsEL!.removeChild(row); + }) + } if (this.rowsEL) this.rowsEL.innerHTML = '' this.spacerEL!.style.height = '0px'; this.rangeSelect.rangeTraceRow = []; + this.collectRows = [] + this.timerShaftEL?.displayCollect(false) + this.timerShaftEL!.collecBtn!.removeAttribute('close'); CpuStruct.wakeupBean = undefined; this.selectStructNull(); this.hoverStructNull(); @@ -744,14 +1413,25 @@ export class SpSystemTrace extends BaseElement { procedurePool.clearCache(); } - init = async (param: { buf?: ArrayBuffer, url?: string }, progress: Function) => { + init = async (param: { buf?: ArrayBuffer, url?: string }, wasmConfigUri: string, progress: Function) => { progress("Load database", 6); + this.rowsPaneEL!.scroll({ + top: 0, + left: 0 + }) this.reset(progress); if (param.buf) { - let {status, msg} = await threadPool.initSqlite(param.buf, progress); + let configJson = ""; + try { + configJson = await fetch(wasmConfigUri).then(res => res.text()); + } catch (e) { + error("getWasmConfigFailed", e) + } + let {status, msg, sdkConfigMap} = await threadPool.initSqlite(param.buf, configJson, progress); if (!status) { return {status: false, msg: msg} } + SpSystemTrace.SDK_CONFIG_MAP = sdkConfigMap == undefined ? undefined : sdkConfigMap; } if (param.url) { let {status, msg} = await threadPool.initServer(param.url, progress); @@ -759,759 +1439,151 @@ export class SpSystemTrace extends BaseElement { return {status: false, msg: msg} } } - - progress("load process threads", 50); - this.processThreads = await queryProcessThreads(); - progress("process memory", 60); - this.processMem = await queryProcessMem() - progress("async event", 63); - this.processAsyncEvent = await getAsyncEvents() - progress("time range", 65); - await this.initTotalTime(); - progress("cpu", 70); - await this.initCpu(); - progress("cpu rate", 75); - await this.initCpuRate(); - progress("cpu freq", 80); - await this.initCpuFreq(); - progress("fps", 85); - await this.initFPS(); - progress("native memory", 87); - await this.initNativeMemory(); - progress("process", 90); - await this.initProcess(); - progress("process", 93); - await this.initProcessThreadStateData(progress); - await this.initHeapStateData(progress) - progress("display", 95); - this.getVisibleRows().forEach(it => { - it.draw(); - }); - this.processThreads.length = 0; - this.processMem.length = 0; - this.processAsyncEvent.length = 0; + await this.chartManager?.init(progress); this.rowsEL?.querySelectorAll>("trace-row").forEach((it: any) => { it.addEventListener('expansion-change', () => { - this.getVisibleRows().forEach(it2 => it2.draw()); + this.getVisibleRows(); + this.refreshCanvas(true); }) }) progress("completed", 100); + info("All TraceRow Data initialized") + this.loadTraceCompleted = true; + this.getVisibleRows(); + this.refreshCanvas(false); return {status: true, msg: "success"} } - initCpuRate = async () => { - let rates = await getCpuUtilizationRate(0, this.timerShaftEL?.totalNS || 0); - if (this.timerShaftEL) this.timerShaftEL.cpuUsage = rates; - } - - initTotalTime = async () => { - let res = await queryTotalTime(); - if (this.timerShaftEL) { - this.timerShaftEL.totalNS = res[0].total - this.timerShaftEL.loadComplete = true; + displayTip(row: TraceRow, struct: any, html: string) { + let x = row.hoverX + 248; + let y = row.getBoundingClientRect().top - 195 + (this.rowsPaneEL?.scrollTop ?? 0); + if ((struct == undefined || struct == null) && this.tipEL) { + this.tipEL.style.display = 'none'; + return } - } - - initCpu = async () => { - let array = await queryCpuMax(); - if (array && array.length > 0 && array[0]) { - let cpuMax = array[0].cpu - CpuStruct.cpuCount = cpuMax + 1; - for (let i1 = 0; i1 < CpuStruct.cpuCount; i1++) { - const cpuId = i1; - let traceRow = new TraceRow({ - canvasNumber: 1, - alpha: true, - contextId: '2d', - isOffScreen: SpSystemTrace.isCanvasOffScreen - }); - traceRow.rowId = `${cpuId}` - traceRow.rowType = TraceRow.ROW_TYPE_CPU - traceRow.rowParentId = '' - traceRow.style.height = '40px' - traceRow.name = `Cpu ${cpuId}` - traceRow.favoriteChangeHandler = this.favoriteChangeHandler; - traceRow.selectChangeHandler = this.selectChangeHandler; - traceRow.supplier = () => queryCpuData(cpuId, 0, this.timerShaftEL?.totalNS || 0) - traceRow.onThreadHandler = ((useCache: boolean) => { - procedurePool.submitWithName(`cpu${cpuId % procedurePool.cpusLen.length}`, `cpu${cpuId}`, { - list: traceRow.must ? traceRow.dataList : undefined, - offscreen: traceRow.must ? traceRow.offscreen[0] : undefined,//是否离屏 - dpr: traceRow.dpr,//屏幕dpr值 - xs: TraceRow.range?.xs,//线条坐标信息 - isHover: traceRow.isHover, - flagMoveInfo: this.hoverFlag, - flagSelectedInfo: this.selectFlag, - hoverX: traceRow.hoverX, - hoverY: traceRow.hoverY, - canvasWidth: traceRow.canvasWidth, - canvasHeight: traceRow.canvasHeight, - hoverCpuStruct: CpuStruct.hoverCpuStruct, - selectCpuStruct: CpuStruct.selectCpuStruct, - wakeupBean: CpuStruct.wakeupBean, - isRangeSelect: traceRow.rangeSelect, - rangeSelectObject: TraceRow.rangeSelectObject, - useCache: useCache, - lineColor: traceRow.getLineColor(), - startNS: TraceRow.range?.startNS || 0, - endNS: TraceRow.range?.endNS || 0, - totalNS: TraceRow.range?.totalNS || 0, - frame: traceRow.frame - }, traceRow.must && traceRow.args.isOffScreen ? traceRow.offscreen[0] : undefined, (res: any, hover: any) => { - traceRow.must = false; - if (traceRow.args.isOffScreen == true) { - if (traceRow.isHover) { - CpuStruct.hoverCpuStruct = hover; - this.visibleRows.filter(it => it.rowType === TraceRow.ROW_TYPE_CPU && it.name !== traceRow.name).forEach(it => it.draw(true)); - } - return; - } - }) - }) - this.rowsEL?.appendChild(traceRow) + if (this.tipEL) { + this.tipEL.innerHTML = html; + this.tipEL.style.display = 'flex'; + this.tipEL.style.height = row.style.height + if (x + this.tipEL.clientWidth > (this.canvasPanel!.clientWidth ?? 0)) { + this.tipEL.style.transform = `translateX(${x - this.tipEL.clientWidth - 1}px) translateY(${y}px)`; + } else { + this.tipEL.style.transform = `translateX(${x}px) translateY(${y}px)`; } } } - initCpuFreq = async () => { - let freqList = await queryCpuFreq(); - let freqMaxList = await queryCpuMaxFreq(); - CpuFreqStruct.maxFreq = freqMaxList[0].maxFreq; - let math = () => { - let units: Array = ["", "K", "M", "G", "T", "E"]; - let sb = " "; - CpuFreqStruct.maxFreqName = " "; - if (CpuFreqStruct.maxFreq > 0) { - let log10: number = Math.ceil(Math.log10(CpuFreqStruct.maxFreq)); - let pow10: number = Math.pow(10, log10); - let afterCeil: number = Math.ceil(CpuFreqStruct.maxFreq / (pow10 / 4)) * (pow10 / 4); - CpuFreqStruct.maxFreq = afterCeil; - let unitIndex: number = Math.floor(log10 / 3); - sb = `${afterCeil / Math.pow(10, unitIndex * 3)}${units[unitIndex + 1]}hz` - } - CpuFreqStruct.maxFreqName = sb.toString(); + initHtml(): string { + return ` + -
- -
-
- -
+ +
+ +
+
+ +
+ +
+
+
+
+ +
`; } } diff --git a/host/ide/src/trace/component/SpWelcomePage.ts b/host/ide/src/trace/component/SpWelcomePage.ts index 8da17c7e03409b23b747aab944f013461c0baba9..5b6e57a8908479dae808212a985209a07703cc5b 100644 --- a/host/ide/src/trace/component/SpWelcomePage.ts +++ b/host/ide/src/trace/component/SpWelcomePage.ts @@ -22,23 +22,22 @@ export class SpWelcomePage extends BaseElement { initHtml(): string { return ` - -
- -
+ +
+ +
`; } - } diff --git a/host/ide/src/trace/component/Sptext.ts b/host/ide/src/trace/component/Sptext.ts index f0b089aa105f695adff15cbac60f151f6fc6004c..960e737f5ee35382eaf7bf0434dc6c65de7f0976 100644 --- a/host/ide/src/trace/component/Sptext.ts +++ b/host/ide/src/trace/component/Sptext.ts @@ -18,7 +18,7 @@ import "../../base-ui/popover/LitPopover.js" import {LitPopover} from "../../base-ui/popover/LitPopover.js"; @element('sp-text') -export class Sptext extends BaseElement { +export class SpText extends BaseElement { initElements(): void { let litPopover = this.shadowRoot?.querySelector('lit-popover'); litPopover!.dataSource = [{ @@ -29,31 +29,31 @@ export class Sptext extends BaseElement { initHtml(): string { return ` - -
-
- - - - -
-
`; + +
+
+ + + + +
+
+ `; } - } \ No newline at end of file diff --git a/host/ide/src/trace/component/StackBar.ts b/host/ide/src/trace/component/StackBar.ts index 9c9a0b259bdad2aa04f54ba8b2a1e6a38838472d..26700c1c0280f28501053f293e4610525caffe5f 100644 --- a/host/ide/src/trace/component/StackBar.ts +++ b/host/ide/src/trace/component/StackBar.ts @@ -62,20 +62,21 @@ export class StackBar extends BaseElement { initHtml(): string { return ` - -
-
`; + +
+
+ `; } getStateWidth(state: string): number { diff --git a/host/ide/src/trace/component/chart/FrameChart.ts b/host/ide/src/trace/component/chart/FrameChart.ts new file mode 100644 index 0000000000000000000000000000000000000000..d0f0c0d2657b81867186c957b55b9e5d7de217b9 --- /dev/null +++ b/host/ide/src/trace/component/chart/FrameChart.ts @@ -0,0 +1,762 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BaseElement, element } from "../../../base-ui/BaseElement.js"; +import { Rect } from "../trace/timer-shaft/Rect.js"; +import { ChartMode, ChartStruct, draw, setFuncFrame } from "../../bean/FrameChartStruct.js"; +import { SpApplication } from "../../SpApplication.js"; +import { Utils } from "../trace/base/Utils.js"; + +const TAG: string = "FrameChart"; +const scaleHeight = 30; +const depthHeight = 20; +const filterPixel = 2; +const sideLength = 8; + +@element('tab-framechart') +export class FrameChart extends BaseElement { + private canvas: HTMLCanvasElement | undefined | null; + private canvasContext: CanvasRenderingContext2D | undefined | null; + private floatHint: HTMLDivElement | undefined | null; + + private rect: Rect = new Rect(0, 0, 0, 0); + private _mode = ChartMode.Call; + private startX = 0; // canvas start x coord + private startY = 0; // canvas start y coord + private canvasX = -1; // canvas current x + private canvasY = -1; // canvas current y + private hintContent = ""; // float hint inner html content + + private historyList: Array> = []; + private currentSize = 0; + private currentCount = 0; + private currentDuration = 0; + private currentData: Array = []; + private xPoint = 0; // x in rect + private isFocusing = false; + private canvasScrollTop = 0; + private _maxDepth = 0; + private chartClickListenerList: Array = []; + private isUpdateCanvas = false; + + static get observedAttributes() { + return [] + } + + /** + * set chart mode + * @param mode chart format for data mode + */ + set mode(mode: ChartMode) { + this._mode = mode; + } + + set data(val: Array | any) { + this.historyList = []; + ChartStruct.lastSelectFuncStruct = undefined; + this.currentData = val; + this.resetTrans(); + this.calDrawArgs(true); + for (let callback of this.chartClickListenerList) { + callback(true); + } + + } + + set tabPaneScrollTop(scrollTop: number) { + this.canvasScrollTop = scrollTop; + this.hideFloatHint(); + } + + /** + * add callback of chart click + * @param callback function of chart click + */ + public addChartClickListener(callback: Function) { + if (this.chartClickListenerList.indexOf(callback) < 0) { + this.chartClickListenerList.push(callback); + } + } + + /** + * remove callback of chart click + * @param callback function of chart click + */ + public removeChartClickListener(callback: Function) { + let index = this.chartClickListenerList.indexOf(callback); + if (index > -1) { + this.chartClickListenerList.splice(index, 1); + } + } + + /** + * cal total count size and max Depth + * @param isCalRoot use depth 1 node to cal depth 0 node size/count/dur + */ + private calDrawArgs(isCalRoot: boolean): void { + this.currentCount = 0; + this.currentSize = 0; + this.currentDuration = 0; + this._maxDepth = 0; + for (let rootNode of this.currentData!) { + let depth = 0; + this.calMaxDepth(rootNode, depth, isCalRoot); + this.currentCount += rootNode.count; + this.currentSize += rootNode.size; + this.currentDuration += rootNode.dur; + } + this.rect.width = this.canvas!.width + this.rect.height = (this._maxDepth + 1) * 20 + scaleHeight; // 20px/depth and 30 is scale height + this.canvas!.style.height = this.rect!.height + "px"; + this.canvas!.height = Math.ceil(this.rect!.height); + } + + + /** + * cal max Depth + * @param node every child node + * @param depth current depth + * @param isCalRoot use depth 1 node to cal depth 0 node size/count/dur + */ + private calMaxDepth(node: ChartStruct, depth: number, isCalRoot: boolean): void { + node.depth = depth; + depth++; + if (node.children && node.children.length > 0) { + let parentSize, parentCount, parentDuration; + parentSize = parentCount = parentDuration = 0; + for (let children of node.children) { + if (node.depth == 0 && isCalRoot) { + parentSize += children.size; + parentCount += children.count; + parentDuration += children.dur; + } + this.calMaxDepth(children, depth, isCalRoot); + } + if (node.depth == 0 && isCalRoot) { + node.size = parentSize; + node.count = parentCount; + node.dur = parentDuration; + } + } else { + this._maxDepth = Math.max(depth, this._maxDepth); + } + } + + /** + * calculate Data and draw chart + */ + async calculateChartData() { + this.clearCanvas(); + this.canvasContext?.beginPath(); + this.drawScale(); + let x = this.xPoint; + switch (this._mode) { + case ChartMode.Byte: + for (let node of this.currentData!) { + let width = Math.ceil(node.size / this.currentSize * this.rect!.width); + let height = depthHeight; // 20px / depth + // ensure the data for first depth frame + if (!node.frame) { + node.frame = new Rect(x, scaleHeight, width, height) + } else { + node.frame!.x = x; + node.frame!.y = scaleHeight; + node.frame!.width = width; + node.frame!.height = height; + } + // not draw when rect not in canvas + if (x + width >= 0 && x < this.canvas!.width) { + node.percent = node.size / this.currentSize; + draw(this.canvasContext!, node); + } + this.drawFrameChart(node); + x += width; + } + break; + case ChartMode.Count: + for (let node of this.currentData!) { + let width = Math.ceil(node.count / this.currentCount * this.rect!.width); + let height = depthHeight; // 20px / depth + // ensure the data for first depth frame + if (!node.frame) { + node.frame = new Rect(x, scaleHeight, width, height) + } else { + node.frame!.x = x; + node.frame!.y = scaleHeight; + node.frame!.width = width; + node.frame!.height = height; + } + // not draw when rect not in canvas + if (x + width >= 0 && x < this.canvas!.width) { + node.percent = node.count / this.currentCount; + draw(this.canvasContext!, node); + } + this.drawFrameChart(node); + x += width; + } + break; + case ChartMode.Duration: + for (let node of this.currentData!) { + let width = Math.ceil(node.dur / this.currentDuration * this.rect!.width); + let height = depthHeight; // 20px / depth + // ensure the data for first depth frame + if (!node.frame) { + node.frame = new Rect(x, scaleHeight, width, height) + } else { + node.frame!.x = x; + node.frame!.y = scaleHeight; + node.frame!.width = width; + node.frame!.height = height; + } + // not draw when rect not in canvas + if (x + width >= 0 && x < this.canvas!.width) { + node.percent = node.dur / this.currentDuration; + draw(this.canvasContext!, node); + } + this.drawFrameChart(node); + x += width; + } + break; + } + this.drawTriangleOnScale(); + this.canvasContext?.closePath(); + } + + /** + * draw last selected reset position on scale + */ + private drawTriangleOnScale(): void { + if (ChartStruct.lastSelectFuncStruct) { + this.canvasContext!.fillStyle = `rgba(${82}, ${145}, ${255})`; + let x = Math.ceil(ChartStruct.lastSelectFuncStruct.frame!.x + + ChartStruct.lastSelectFuncStruct.frame!.width / 2) + if (x < 0) x = sideLength / 2; + if (x > this.canvas!.width) x = this.canvas!.width - sideLength; + this.canvasContext!.moveTo(x - sideLength / 2, scaleHeight - sideLength); + this.canvasContext!.lineTo(x + sideLength / 2, scaleHeight - sideLength); + this.canvasContext!.lineTo(x, scaleHeight); + this.canvasContext!.lineTo(x - sideLength / 2, scaleHeight - sideLength); + this.canvasContext?.fill(); + } + } + + /** + * clear canvas all data + */ + public clearCanvas(): void { + this.canvasContext?.clearRect(0, 0, this.canvas!.width, this.canvas!.height); + } + + /** + * update canvas size + */ + public updateCanvas(updateWidth: boolean, newWidth?: number): void { + if (this.canvas instanceof HTMLCanvasElement) { + this.canvas.style.width = 100 + "%"; + this.canvas.style.height = this.rect!.height + "px"; + if (this.canvas.clientWidth == 0 && newWidth) { + this.canvas.width = newWidth - 40; + } else { + this.canvas.width = this.canvas.clientWidth; + } + this.canvas.height = Math.ceil(this.rect!.height); + this.updateCanvasCoord(); + } + if (this.rect.width == 0 || updateWidth || + Math.round(newWidth!) != this.canvas!.width + 40 || newWidth! > this.rect.width) { + this.rect.width = this.canvas!.width + } + } + + /** + * updateCanvasCoord + */ + private updateCanvasCoord(): void { + if (this.canvas instanceof HTMLCanvasElement) { + this.isUpdateCanvas = this.canvas.clientWidth != 0; + if (this.canvas.getBoundingClientRect()) { + let box = this.canvas.getBoundingClientRect(); + let D = document.documentElement; + this.startX = box.left + Math.max(D.scrollLeft, document.body.scrollLeft) - D.clientLeft; + this.startY = box.top + Math.max(D.scrollTop, document.body.scrollTop) - D.clientTop + this.canvasScrollTop; + } + } + } + + /** + * draw top Scale Into 100 pieces + */ + private drawScale(): void { + let spApplication = document.getElementsByTagName("sp-application")[0]; + // line + this.canvasContext!.lineWidth = 0.5; + this.canvasContext?.moveTo(0, 0); + this.canvasContext?.lineTo(this.canvas!.width, 0); + + for (let i = 0; i <= 10; i++) { + let startX = Math.floor(this.canvas!.width / 10 * i); + for (let j = 0; j < 10; j++) { + // children scale + this.canvasContext!.lineWidth = 0.5; + let startItemX = startX + Math.floor(this.canvas!.width / 100 * j); + this.canvasContext?.moveTo(startItemX, 0); + this.canvasContext?.lineTo(startItemX, 10); + } + if (i == 0) continue; // skip first Size is 0 + // long line every 10 count + this.canvasContext!.lineWidth = 1; + let sizeRatio = this.canvas!.width / this.rect.width; // scale ratio + if (spApplication.dark) { + this.canvasContext!.strokeStyle = "#888"; + } else { + this.canvasContext!.strokeStyle = "#ddd"; + } + this.canvasContext?.moveTo(startX, 0); + this.canvasContext?.lineTo(startX, this.canvas!.height); + if (spApplication.dark) { + this.canvasContext!.fillStyle = "#fff"; + } else { + this.canvasContext!.fillStyle = "#000"; + } + let scale = ''; + switch (this._mode) { + case ChartMode.Byte: + scale = Utils.getByteWithUnit(this.currentSize * sizeRatio / 10 * i); + break; + case ChartMode.Count: + scale = (this.currentCount * sizeRatio / 10 * i).toFixed(0) + ''; + break; + case ChartMode.Duration: + scale = Utils.getProbablyTime(this.currentDuration * sizeRatio / 10 * i); + break; + } + let size = this.canvasContext!.measureText(scale).width; + this.canvasContext?.fillText(scale, startX - size - 5, depthHeight, 50); // 50 is Text max Length + this.canvasContext?.stroke(); + } + } + + /** + * draw chart + * @param node draw chart by every piece + */ + drawFrameChart(node: ChartStruct) { + let effectChildList = []; + let ignoreSize,ignoreCount,ignoreDur; + ignoreSize = ignoreCount = ignoreDur = 0; + + if (node.children && node.children.length > 0) { + for (let children of node.children) { + children.parent = node; + switch (this._mode) { + case ChartMode.Byte: + setFuncFrame(children, this.rect, this.currentSize, this._mode); + children.percent = children.size / this.currentSize; + break; + case ChartMode.Count: + setFuncFrame(children, this.rect, this.currentCount, this._mode); + children.percent = children.count / this.currentCount; + break; + case ChartMode.Duration: + setFuncFrame(children, this.rect, this.currentDuration, this._mode); + children.percent = children.dur / this.currentDuration; + break; + } + // not draw when rect not in canvas + if ((children.frame!.x + children.frame!.width >= 0 && //less than canvas left + children.frame!.x < this.canvas!.width && // more than canvas right + children.frame!.width > filterPixel) || // filter px + children.needShow) { // click and back + effectChildList.push(children); + } else { + ignoreSize += children.size; + ignoreCount += children.count; + ignoreDur += children.dur; + } + } + let x = node.frame!.x; + for (let children of effectChildList) { + children.frame!.x = x; + switch (this._mode) { + case ChartMode.Byte: + children.frame!.width = Math.ceil(children.size / (node.size - ignoreSize) * node.frame!.width); + break; + case ChartMode.Count: + children.frame!.width = Math.ceil(children.count / (node.count - ignoreCount) * node.frame!.width); + break; + case ChartMode.Duration: + children.frame!.width = Math.ceil(children.dur / (node.dur - ignoreDur) * node.frame!.width); + break; + } + x += children.frame!.width; + draw(this.canvasContext!, children); + this.drawFrameChart(children); + } + } + } + + /** + * find target node from tree by mouse position + * + * @param nodes tree nodes + * @param canvasX x coord of canvas + * @param canvasY y coord of canvas + * @returns target node + */ + private searchData(nodes: Array, canvasX: number, canvasY: number): any { + for (let node of nodes) { + if (node.frame?.contains(canvasX, canvasY)) { + return node; + } else { + let result = this.searchData(node.children, canvasX, canvasY); + if (!result) continue; // if not found in this branch;search another branch + return result; + } + } + return null; + } + + /** + * show float hint and update position + */ + private updateFloatHint(): void { + this.floatHint!.innerHTML = this.hintContent; + this.floatHint!.style.display = 'block'; + let x = this.canvasX; + let y = this.canvasY - this.canvasScrollTop; + //right rect hint show left + if (this.canvasX + this.floatHint!.clientWidth > (this.canvas?.clientWidth || 0)) { + x -= this.floatHint!.clientWidth - 1; + } else { + x += scaleHeight; + } + //bottom rect hint show top + y -= this.floatHint!.clientHeight - 1; + + this.floatHint!.style.transform = `translate(${x}px,${y}px)`; + } + + /** + * redraw Chart while click to scale chart + * @param selectData select Rect data as array + */ + private redrawChart(selectData: Array): void { + this.currentData = selectData; + if (selectData.length == 0) return; + this.calDrawArgs(false); + this.calculateChartData(); + } + + /** + * press w to zoom in, s to zoom out + * @param index < 0 zoom out , > 0 zoom in + */ + private scale(index: number): void { + let newWidth = 0; + // zoom in + let deltaWidth = this.rect!.width * 0.2; + if (index > 0) { + newWidth = this.rect!.width + deltaWidth; + // max scale + let sizeRatio = this.canvas!.width / this.rect.width; + switch (this._mode) { + case ChartMode.Byte: + //limit 10 byte + if (Math.round(this.currentSize * sizeRatio / 1.2) <= 10) { + if (this.xPoint == 0) { + return; + } + newWidth = this.canvas!.width / (10 / this.currentSize); + } + break; + case ChartMode.Count: + //limit 10 counts + if (Math.round(this.currentCount * sizeRatio / 1.2) <= 10) { + if (this.xPoint == 0) { + return; + } + newWidth = this.canvas!.width / (10 / this.currentCount); + } + break; + case ChartMode.Duration: + //limit 10ms + if (Math.round(this.currentDuration * sizeRatio / 1.2) <= 10_000_000) { + if (this.xPoint == 0) { + return; + } + newWidth = this.canvas!.width / (10_000_000 / this.currentDuration); + } + break; + } + deltaWidth = newWidth - this.rect!.width; + } else { // zoom out + newWidth = this.rect!.width - deltaWidth; + // min scale + if (newWidth < this.canvas!.width) { + newWidth = this.canvas!.width; + this.resetTrans(); + } + deltaWidth = this.rect!.width - newWidth; + } + // width not change + if (newWidth == this.rect.width) return; + this.translationByScale(index, deltaWidth, newWidth); + } + + private resetTrans() { + this.xPoint = 0; + } + + /** + * translation after scale + * @param index is zoom in + * @param deltaWidth scale delta width + * @param newWidth rect width after scale + */ + private translationByScale(index: number, deltaWidth: number, newWidth: number): void { + let translationValue = deltaWidth * (this.canvasX - this.xPoint) / this.rect.width; + if (index > 0) { + this.xPoint -= translationValue; + } else { + this.xPoint += translationValue; + } + this.rect!.width = newWidth; + this.translationDraw(); + } + + /** + * press a/d to translate rect + * @param index left or right + */ + private translation(index: number): void { + let offset = this.canvas!.width / 10; + if (index < 0) { + this.xPoint += offset; + } else { + this.xPoint -= offset; + } + this.translationDraw(); + } + + /** + * judge position ro fit canvas and draw + */ + private translationDraw(): void { + // right trans limit + if (this.xPoint > 0) { + this.xPoint = 0; + } + // left trans limit + if (this.rect.width + this.xPoint < this.canvas!.width) { + this.xPoint = this.canvas!.width - this.rect.width; + } + this.calculateChartData(); + } + + /** + * canvas click + * @param e MouseEvent + */ + private onMouseClick(e: MouseEvent): void { + if (e.button == 0) { // mouse left button + if (ChartStruct.hoverFuncStruct && ChartStruct.hoverFuncStruct != ChartStruct.selectFuncStruct) { + this.drawDataSet(ChartStruct.lastSelectFuncStruct!, false); + ChartStruct.lastSelectFuncStruct = undefined; + ChartStruct.selectFuncStruct = ChartStruct.hoverFuncStruct; + this.historyList.push(this.currentData!); + let selectData = new Array(); + selectData.push(ChartStruct.selectFuncStruct!); + // reset scale and translation + this.rect.width = this.canvas!.clientWidth; + this.resetTrans(); + this.redrawChart(selectData); + for (let callback of this.chartClickListenerList) { + callback(false); + } + } + } else if (e.button == 2) { // mouse right button + ChartStruct.selectFuncStruct = undefined; + ChartStruct.hoverFuncStruct = undefined; + if (this.currentData.length == 1 && this.historyList.length > 0) { + ChartStruct.lastSelectFuncStruct = this.currentData[0]; + this.drawDataSet(ChartStruct.lastSelectFuncStruct, true); + } + if (this.historyList.length > 0) { + // reset scale and translation + this.rect.width = this.canvas!.clientWidth; + this.resetTrans(); + this.redrawChart(this.historyList.pop()!); + } + if (this.historyList.length === 0) { + for (let callback of this.chartClickListenerList) { + callback(true); + } + } + } + this.hideFloatHint(); + } + + private hideFloatHint() { + if (this.floatHint) { + this.floatHint.style.display = 'none'; + } + } + + /** + * set current select rect parents will show + * @param data current node + * @param isShow is show in chart + */ + private drawDataSet(data: ChartStruct, isShow: boolean): void { + if (data) { + data.needShow = isShow; + if (data.parent) { + this.drawDataSet(data.parent, isShow); + } + } + } + + /** + * mouse on canvas move event + */ + private onMouseMove(): void { + let lastNode = ChartStruct.hoverFuncStruct; + let searchResult = this.searchData(this.currentData!, this.canvasX, this.canvasY); + if (searchResult && (searchResult.frame!.width > filterPixel || + searchResult.needShow || searchResult.depth == 0)) { + ChartStruct.hoverFuncStruct = searchResult; + // judge current node is hover redraw chart + if (searchResult != lastNode) { + let name = ChartStruct.hoverFuncStruct?.symbol; + switch (this._mode) { + case ChartMode.Byte: + let size = Utils.getByteWithUnit(ChartStruct.hoverFuncStruct!.size); + this.hintContent = ` + Symbol: ${name}
+ Lib: ${ChartStruct.hoverFuncStruct?.lib}
+ Addr: ${ChartStruct.hoverFuncStruct?.addr}
+ Size: ${size}
+ Count: ${ChartStruct.hoverFuncStruct?.count}`; + break; + case ChartMode.Count: + let count = ChartStruct.hoverFuncStruct!.count; + this.hintContent = ` + Name: ${name}
+ Count: ${count}`; + break; + case ChartMode.Duration: + let duration = Utils.getProbablyTime(ChartStruct.hoverFuncStruct!.dur); + this.hintContent = ` + Name: ${name}
+ Duration: ${duration}`; + break; + } + this.calculateChartData(); + } + // prevent float hint trigger onmousemove event + this.updateFloatHint(); + } else { + this.hideFloatHint(); + ChartStruct.hoverFuncStruct = undefined; + } + } + + initElements(): void { + this.canvas = this.shadowRoot?.querySelector("#canvas"); + this.canvasContext = this.canvas?.getContext("2d"); + this.floatHint = this.shadowRoot?.querySelector('#float_hint'); + + this.canvas!.oncontextmenu = () => { + return false; + }; + this.canvas!.onmouseup = (e) => { + this.onMouseClick(e); + } + + this.canvas!.onmousemove = (e) => { + if (!this.isUpdateCanvas) { + this.updateCanvasCoord(); + } + this.canvasX = e.clientX - this.startX; + this.canvasY = e.clientY - this.startY + this.canvasScrollTop; + this.isFocusing = true; + this.onMouseMove(); + }; + + this.canvas!.onmouseleave = () => { + ChartStruct.selectFuncStruct = undefined; + this.isFocusing = false; + this.hideFloatHint(); + }; + + document.addEventListener('keydown', (e) => { + if (!this.isFocusing) return; + switch (e.key.toLocaleLowerCase()) { + case 'w': + this.scale(1); + break; + case 's': + this.scale(-1); + break; + case 'a': + this.translation(-1); + break; + case 'd': + this.translation(1); + break; + } + }); + new ResizeObserver((entries) => { + if (this.canvas!.getBoundingClientRect()) { + let box = this.canvas!.getBoundingClientRect(); + let D = document.documentElement; + this.startX = box.left + Math.max(D.scrollLeft, document.body.scrollLeft) - D.clientLeft; + this.startY = box.top + Math.max(D.scrollTop, document.body.scrollTop) - D.clientTop + this.canvasScrollTop; + } + }).observe(document.documentElement); + } + + + initHtml(): string { + return ` + + +
`; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/chart/PerfDataQuery.ts b/host/ide/src/trace/component/chart/PerfDataQuery.ts new file mode 100644 index 0000000000000000000000000000000000000000..9e367a98a96eb27dad58ced3b1982e5cc90b8b10 --- /dev/null +++ b/host/ide/src/trace/component/chart/PerfDataQuery.ts @@ -0,0 +1,372 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + queryPerfFiles, + query, threadPool, +} from "../../database/SqlLite.js"; +import {PerfCall, PerfCallChain, PerfCallChainMerageData, PerfFile} from "../../bean/PerfProfile.js"; +import {info} from "../../../log/Log.js"; +import {SpHiPerf} from "./SpHiPerf.js"; +import {procedurePool} from "../../database/Procedure.js"; + +export class PerfDataQuery { + + filesData: any = {} + samplesData: any = {} + threadData: any = {} + callChainData: any = {} + splitMapData: any = {} + currentTreeMapData: any = {} + currentTreeList: any[] = [] + searchValue: string = "" + callChainMap: Map = new Map() + + async initPerfCache(){ + await this.initPerfCallChainMap() + await this.initPerfFiles(); + } + + async initPerfCallChainMap(){ + this.callChainMap.clear(); + } + + async initPerfFiles() { + let files = await queryPerfFiles() + info("PerfFiles Data size is: ", files!.length) + files.forEach((file) => { + this.filesData[file.fileId] = this.filesData[file.fileId] || [] + PerfFile.setFileName(file) + this.filesData[file.fileId].push(file) + }) + let results = await new Promise((resolve, reject) => { + procedurePool.submitWithName("logic0","perf-init",SpHiPerf.stringResult,undefined,(res:any)=>{ + resolve(res) + }) + }) + this.callChainMap = (results as any) + info("Perf Files Data initialized") + } + + initCallChainBottomUp(callChains: PerfCallChain[]) { + callChains.forEach((callChain, index) => { + if (this.threadData[callChain.tid] == undefined) { + return + } + callChain.name = this.setCallChainName(callChain) + this.addGroupData(callChain) + if (index + 1 < callChains.length && callChains[index + 1].sampleId == callChain.sampleId) { + PerfCallChain.setPreviousNode(callChain, callChains[index + 1]) + } + if (callChains.length == index + 1 || callChains[index + 1].sampleId != callChain.sampleId) { + this.addProcessThreadStateData(callChain) + } + }) + } + + setCallChainName(callChain: PerfCallChain): string {//设置调用栈的名称 + callChain.pid = this.threadData[callChain.tid]?.pid; + callChain.canCharge = true; + if (callChain.symbolId == -1) { + if (this.filesData[callChain.fileId] && this.filesData[callChain.fileId].length > 0) { + callChain.fileName = this.filesData[callChain.fileId][0].fileName + callChain.path = this.filesData[callChain.fileId][0].path + return this.filesData[callChain.fileId][0].fileName + "+0x" + callChain.vaddrInFile + } else { + callChain.fileName = "unkown" + return "+0x" + callChain.vaddrInFile + } + } else { + if (this.filesData[callChain.fileId] && this.filesData[callChain.fileId].length > callChain.symbolId) { + callChain.fileName = this.filesData[callChain.fileId][callChain.symbolId].fileName + callChain.path = this.filesData[callChain.fileId][callChain.symbolId].path + return this.filesData[callChain.fileId][callChain.symbolId].symbol + } else { + callChain.fileName = "unkown" + return "+0x" + callChain.vaddrInFile + } + } + } + + addProcessThreadStateData(callChain: PerfCallChain) {//当调用栈为调用的根节点时 + let threadCallChain = new PerfCallChain()//新增的线程数据 + threadCallChain.depth = 0 + PerfCallChain.merageCallChain(threadCallChain, callChain) + threadCallChain.canCharge = false + threadCallChain.name = this.threadData[callChain.tid].threadName||"Thead" + "(" + callChain.tid + ")" + let threadStateCallChain = new PerfCallChain()//新增的线程状态数据 + PerfCallChain.merageCallChain(threadStateCallChain, callChain) + threadStateCallChain.name = callChain.threadState || "Unkown State" + threadStateCallChain.fileName = threadStateCallChain.name == "-" ? "Unkown Thead State" : "" + threadStateCallChain.canCharge = false + this.addGroupData(threadStateCallChain) + this.addGroupData(threadCallChain) + PerfCallChain.setNextNode(threadCallChain, threadStateCallChain) + PerfCallChain.setNextNode(threadStateCallChain, callChain) + } + + addGroupData(callChain: PerfCallChain) { + this.callChainData[callChain.sampleId] = this.callChainData[callChain.sampleId] || [] + this.callChainData[callChain.sampleId].push(callChain) + } + + getCallChainsBySampleIds(sampleIds: string[], isTopDown: boolean) { + return this.groupNewTreeNoId(sampleIds, isTopDown) + } + + + groupNewTreeNoId(sampleIds: string[], isTopDown: boolean) { + this.currentTreeMapData = {} + this.currentTreeList = [] + for (let i = 0; i < sampleIds.length; i++) { + let callChains = this.callChainData[sampleIds[i]] + if (callChains == undefined) continue + let topIndex = isTopDown ? (callChains.length - 1) : 0; + if (callChains.length > 0) { + let root = this.currentTreeMapData[callChains[topIndex].name + callChains[topIndex].pid]; + if (root == undefined) { + root = new PerfCallChainMerageData(); + this.currentTreeMapData[callChains[topIndex].name + callChains[topIndex].pid] = root; + this.currentTreeList.push(root) + } + PerfCallChainMerageData.merageCallChain(root, callChains[topIndex], isTopDown); + this.merageChildren(root, callChains[topIndex], isTopDown); + } + } + let rootMerageMap: any = {} + Object.values(this.currentTreeMapData).forEach((merageData: any) => { + if (rootMerageMap[merageData.pid] == undefined) { + let processMerageData = new PerfCallChainMerageData()//新增进程的节点数据 + processMerageData.canCharge = false + processMerageData.symbolName = this.threadData[merageData.tid].processName||`Process(${merageData.pid})` + processMerageData.symbol = processMerageData.symbolName + processMerageData.tid = merageData.tid + processMerageData.children.push(merageData) + processMerageData.initChildren.push(merageData) + processMerageData.dur = merageData.dur; + processMerageData.count = merageData.dur; + processMerageData.total = sampleIds.length; + rootMerageMap[merageData.pid] = processMerageData + } else { + rootMerageMap[merageData.pid].children.push(merageData) + rootMerageMap[merageData.pid].initChildren.push(merageData) + rootMerageMap[merageData.pid].dur += merageData.dur; + rootMerageMap[merageData.pid].count += merageData.dur; + rootMerageMap[merageData.pid].total = sampleIds.length; + } + merageData.parentNode = rootMerageMap[merageData.pid]//子节点添加父节点的引用 + }) + let id = 0; + this.currentTreeList.forEach((node) => { + node.total = sampleIds.length; + if (node.id == "") { + node.id = id + "" + id++ + } + if(node.parentNode){ + if (node.parentNode.id == "") { + node.parentNode.id = id + "" + id++ + } + node.parentId = node.parentNode.id + } + }) + return Object.values(rootMerageMap) + } + + merageChildren(currentNode: PerfCallChainMerageData, callChain: any, isTopDown: boolean) { + let nextNodeKey = isTopDown ? "nextNode" : "previousNode" + if (callChain[nextNodeKey] == undefined) return + let node; + if (currentNode.initChildren.filter((child: PerfCallChainMerageData) => { + if (child.symbolName == callChain[nextNodeKey]?.name) { + node = child; + PerfCallChainMerageData.merageCallChain(child, callChain[nextNodeKey], isTopDown) + return true; + } + return false; + }).length == 0) { + node = new PerfCallChainMerageData() + PerfCallChainMerageData.merageCallChain(node, callChain[nextNodeKey], isTopDown) + currentNode.children.push(node) + currentNode.initChildren.push(node) + this.currentTreeList.push(node) + node.parentNode = currentNode + } + if (node) this.merageChildren(node, callChain[nextNodeKey], isTopDown) + } + + //所有的操作都是针对整个树结构的 不区分特定的数据 + splitTree(data: PerfCallChainMerageData[], name: string, isCharge: boolean, isSymbol: boolean) { + data.forEach((process) => { + process.children = [] + if (isCharge) { + this.recursionChargeInitTree(process, name, isSymbol) + } else { + this.recursionPruneInitTree(process, name, isSymbol) + } + }) + this.resetAllNode(data) + } + + recursionChargeInitTree(node: PerfCallChainMerageData, symbolName: string, isSymbol: boolean) { + if ((isSymbol && node.symbolName == symbolName) || (!isSymbol && node.libName == symbolName)) { + (this.splitMapData[symbolName] = this.splitMapData[symbolName] || []).push(node) + node.isStore++; + } + if (node.initChildren.length > 0) { + node.initChildren.forEach((child) => { + this.recursionChargeInitTree(child, symbolName, isSymbol) + }) + } + } + + //symbol lib charge + recursionChargeTree(node: PerfCallChainMerageData, symbolName: string, isSymbol: boolean) { + if ((isSymbol && node.symbolName == symbolName) || (!isSymbol && node.libName == symbolName)) { + node.currentTreeParentNode && node.currentTreeParentNode.children.splice(node.currentTreeParentNode.children.indexOf(node), 1, ...node.children); + node.children.forEach((child) => { + child.currentTreeParentNode = node.currentTreeParentNode + }) + } + if (node.children.length > 0) { + node.children.forEach((child) => { + this.recursionChargeTree(child, symbolName, isSymbol) + }) + } + } + + recursionPruneInitTree(node: PerfCallChainMerageData, symbolName: string, isSymbol: boolean) { + if (isSymbol && node.symbolName == symbolName || (!isSymbol && node.libName == symbolName)) { + (this.splitMapData[symbolName] = this.splitMapData[symbolName] || []).push(node) + node.isStore++; + this.pruneChildren(node, symbolName) + } else if (node.initChildren.length > 0) { + node.initChildren.forEach((child) => { + this.recursionPruneInitTree(child, symbolName, isSymbol) + }) + } + } + + //symbol lib prune + recursionPruneTree(node: PerfCallChainMerageData, symbolName: string, isSymbol: boolean) { + if (isSymbol && node.symbolName == symbolName || (!isSymbol && node.libName == symbolName)) { + node.currentTreeParentNode && node.currentTreeParentNode.children.splice(node.currentTreeParentNode.children.indexOf(node), 1); + } else { + node.children.forEach((child) => { + this.recursionPruneTree(child, symbolName, isSymbol) + }) + } + } + + recursionChargeByRule(node: PerfCallChainMerageData, ruleName: string, rule: (node: PerfCallChainMerageData) => boolean) { + if (node.initChildren.length > 0) { + node.initChildren.forEach((child) => { + if (rule(child)) { + (this.splitMapData[ruleName] = this.splitMapData[ruleName] || []).push(child) + child.isStore++; + } + this.recursionChargeByRule(child, ruleName, rule) + }) + } + } + + pruneChildren(node: PerfCallChainMerageData, symbolName: string) { + if (node.initChildren.length > 0) { + node.initChildren.forEach((child) => { + child.isStore++; + (this.splitMapData[symbolName] = this.splitMapData[symbolName] || []).push(child); + this.pruneChildren(child, symbolName) + }) + } + } + + clearSplitMapData(symbolName: string) { + delete this.splitMapData[symbolName] + } + + resotreAllNode(symbols: string[]) { + symbols.forEach((symbol) => { + let list = this.splitMapData[symbol]; + if (list != undefined) { + list.forEach((item: any) => { + item.isStore-- + }) + } + }) + } + + resetAllNode(data: PerfCallChainMerageData[]) { + this.clearSearchNode() + data.forEach((process) => { + process.searchShow = true + }) + this.resetNewAllNode(data) + if (this.searchValue != "") { + this.findSearchNode(data, this.searchValue, false) + this.resetNewAllNode(data) + } + } + + resetNewAllNode(data: PerfCallChainMerageData[]) { + data.forEach((process) => { + process.children = [] + }) + let values = this.currentTreeList.map((item: any) => { + item.children = [] + return item + }) + values.forEach((item: any) => { + if (item.parentNode != undefined) { + if (item.isStore == 0 && item.searchShow) { + let parentNode = item.parentNode + while (parentNode != undefined && !(parentNode.isStore == 0 && parentNode.searchShow)) { + parentNode = parentNode.parentNode + } + if (parentNode) { + item.currentTreeParentNode = parentNode + parentNode.children.push(item) + } + } + } + }) + } + + findSearchNode(data: PerfCallChainMerageData[], search: string, parentSearch: boolean) { + data.forEach((node) => { + if ((node.symbol&&node.symbol.includes(search)) || parentSearch) { + node.searchShow = true + let parentNode = node.currentTreeParentNode + while (parentNode != undefined && !parentNode.searchShow) { + parentNode.searchShow = true + parentNode = parentNode.currentTreeParentNode + } + } else { + node.searchShow = false + } + if (node.children.length > 0) { + this.findSearchNode(node.children, search, node.searchShow) + } + }) + } + + clearSearchNode() { + this.currentTreeList.forEach((node) => { + node.searchShow = true + }) + } +} + +export const perfDataQuery = new PerfDataQuery() diff --git a/host/ide/src/trace/component/chart/SmpsChart.ts b/host/ide/src/trace/component/chart/SmpsChart.ts new file mode 100644 index 0000000000000000000000000000000000000000..8e42d0866f365cbb2ae590d573f8500dadf5f102 --- /dev/null +++ b/host/ide/src/trace/component/chart/SmpsChart.ts @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SpSystemTrace} from "../SpSystemTrace.js"; +import {querySmapsData, querySmapsDataMax, querySmapsExits} from "../../database/SqlLite.js"; +import {TraceRow} from "../trace/base/TraceRow.js"; +import {BaseStruct} from "../../bean/BaseStruct.js"; +import {renders} from "../../database/ui-worker/ProcedureWorker.js"; +import {SmapsRender, SmapsStruct} from "../../database/ui-worker/ProcedureWorkerSmaps.js"; +import {Utils} from "../trace/base/Utils.js"; +import {EmptyRender} from "../../database/ui-worker/ProcedureWorkerCPU.js"; + +export class SmpsChart { + private trace: SpSystemTrace; + + constructor(trace: SpSystemTrace) { + this.trace = trace; + } + + async init() { + let result = await querySmapsExits(); + if (result.length <= 0) return; + let smapsRow = this.initSmapsRow(); + let rowNameList: Array = ['Dirty Size', 'Swapped Size', 'Resident Size'] + for (let rowName of rowNameList) { + await this.initRows(smapsRow, rowName); + } + } + + private initSmapsRow = () => { + let smapsRow = TraceRow.skeleton(); + smapsRow.rowId = `smapsRow` + smapsRow.rowType = TraceRow.ROW_TYPE_SMAPS + smapsRow.rowParentId = ''; + smapsRow.style.height = '40px' + smapsRow.folder = true; + smapsRow.name = 'VM Tracker'; + smapsRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + smapsRow.selectChangeHandler = this.trace.selectChangeHandler; + smapsRow.supplier = () => new Promise>((resolve) => resolve([])); + smapsRow.onThreadHandler = (useCache) => { + smapsRow.canvasSave(this.trace.canvasPanelCtx!); + if(smapsRow.expansion){ + this.trace.canvasPanelCtx?.clearRect(0, 0, smapsRow.frame.width, smapsRow.frame.height); + } else { + (renders["empty"] as EmptyRender).renderMainThread( + { + context: this.trace.canvasPanelCtx, + useCache: useCache, + type: ``, + }, + smapsRow, + ); + } + smapsRow.canvasRestore(this.trace.canvasPanelCtx!); + } + this.trace.rowsEL?.appendChild(smapsRow) + return smapsRow; + } + + private initRows = async (nodeRow: TraceRow, rowName:string ) => { + let traceRow = TraceRow.skeleton(); + traceRow.rowParentId = `smapsRow` + traceRow.rowHidden = !nodeRow.expansion + traceRow.rowId = rowName + traceRow.rowType = TraceRow.ROW_TYPE_SMAPS + traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + traceRow.selectChangeHandler = this.trace.selectChangeHandler; + traceRow.style.height = '40px' + traceRow.style.width = `100%`; + traceRow.setAttribute('children', ''); + traceRow.name = rowName; + let columnName = "" + if (rowName == "Dirty Size") { + columnName = "dirty" + } else if (rowName == "Swapped Size") { + columnName = "swapper" + } else { + columnName = "resident_size" + } + traceRow.supplier = () => querySmapsData(columnName) + let maxList = await querySmapsDataMax(columnName); + let maxValue = maxList[0].max_value; + traceRow.focusHandler = (ev)=>{ + this.trace?.displayTip(traceRow, SmapsStruct.hoverSmapsStruct, `${Utils.getBinaryByteWithUnit((SmapsStruct.hoverSmapsStruct?.value||0) * 1024)}`); + }; + traceRow.onThreadHandler = (useCache) => { + let context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + traceRow.canvasSave( context); + (renders["smaps"] as SmapsRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `smaps`, + rowName: columnName, + maxValue:maxValue + }, + traceRow + ); + traceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(traceRow) + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/chart/SpAbilityMonitorChart.ts b/host/ide/src/trace/component/chart/SpAbilityMonitorChart.ts new file mode 100644 index 0000000000000000000000000000000000000000..99055e9aa38f1700087ec5b1a8411a68d25916c0 --- /dev/null +++ b/host/ide/src/trace/component/chart/SpAbilityMonitorChart.ts @@ -0,0 +1,664 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SpSystemTrace} from "../SpSystemTrace.js"; +import { + queryAbilityExits, + queryBytesInAbilityData, + queryBytesOutAbilityData, + queryBytesReadAbilityData, + queryBytesWrittenAbilityData, + queryCachedFilesAbilityData, + queryCompressedAbilityData, + queryCpuAbilityData, + queryCPuAbilityMaxData, + queryCpuAbilitySystemData, + queryCpuAbilityUserData, + queryDiskIoMaxData, + queryMemoryMaxData, + queryMemoryUsedAbilityData, + queryNetWorkMaxData, + queryPacketsInAbilityData, queryPacketsOutAbilityData, + queryReadAbilityData, + queryWrittenAbilityData +} from "../../database/SqlLite.js"; +import {info} from "../../../log/Log.js"; +import {TraceRow} from "../trace/base/TraceRow.js"; +import {procedurePool} from "../../database/Procedure.js"; +import {Utils} from "../trace/base/Utils.js"; +import {CpuStruct, EmptyRender} from "../../database/ui-worker/ProcedureWorkerCPU.js"; +import {ProcessRender, ProcessStruct} from "../../database/ui-worker/ProcedureWorkerProcess.js"; +import {CpuFreqStruct, FreqRender} from "../../database/ui-worker/ProcedureWorkerFreq.js"; +import {CpuAbilityMonitorStruct, CpuAbilityRender} from "../../database/ui-worker/ProcedureWorkerCpuAbility.js"; +import { + MemoryAbilityMonitorStruct, + MemoryAbilityRender +} from "../../database/ui-worker/ProcedureWorkerMemoryAbility.js"; +import {DiskAbilityMonitorStruct, DiskIoAbilityRender} from "../../database/ui-worker/ProcedureWorkerDiskIoAbility.js"; +import { + NetworkAbilityMonitorStruct, + NetworkAbilityRender +} from "../../database/ui-worker/ProcedureWorkerNetworkAbility.js"; +import {renders} from "../../database/ui-worker/ProcedureWorker.js"; +import {ColorUtils} from "../trace/base/ColorUtils.js"; + +export class SpAbilityMonitorChart { + private trace: SpSystemTrace; + constructor(trace: SpSystemTrace) { + this.trace = trace; + } + memoryMath = (maxByte: number) => { + let maxByteName = "" + if (maxByte > 0) { + maxByteName = Utils.getBinaryByteWithUnit(maxByte) + } + return maxByteName; + } + + diskIOMath = (maxByte: number) => { + let maxByteName = "" + if (maxByte > 0) { + maxByteName = maxByte + "KB/S" + } + return maxByteName; + } + + networkMath = (maxValue: number) => { + let maxByteName = "" + if (maxValue > 0) { + maxByteName = Utils.getBinaryByteWithUnit(maxValue) + } + return maxByteName; + } + + async init(){ + let time = new Date().getTime(); + let result = await queryAbilityExits(); + info("Ability Monitor Exits Tables size is: ", result!.length) + if (result.length <= 0) return; + let processRow = this.initAbilityRow(); + if (this.hasTable(result, "trace_cpu_usage")) { + await this.initCpuAbility(processRow); + } + if (this.hasTable(result, "sys_memory")) { + await this.initMemoryAbility(processRow); + } + if (this.hasTable(result, "trace_diskio")) { + await this.initDiskAbility(processRow); + } + if (this.hasTable(result, "trace_network")) { + await this.initNetworkAbility(processRow); + } + let durTime = new Date().getTime() - time; + info('The time to load the AbilityMonitor data is: ', durTime) + } + + private hasTable(result: Array, tableName: string) { + return result.find((o) => { + return o.event_name === tableName + }) + } + + private initAbilityRow = () => { + let processRow = TraceRow.skeleton(); + processRow.rowId = `abilityMonitor` + processRow.rowType = TraceRow.ROW_TYPE_MONITOR + processRow.style.height = '40px' + processRow.rowParentId = ''; + processRow.folder = true; + processRow.name = 'Ability Monitor'; + processRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + processRow.selectChangeHandler = this.trace.selectChangeHandler; + processRow.supplier = () => new Promise>((resolve) => resolve([])); + processRow.onThreadHandler = (useCache) => { + processRow.canvasSave(this.trace.canvasPanelCtx!); + if(processRow.expansion){ + this.trace.canvasPanelCtx?.clearRect(0, 0, processRow.frame.width, processRow.frame.height); + } else { + (renders["empty"] as EmptyRender).renderMainThread( + { + context: this.trace.canvasPanelCtx, + useCache: useCache, + type: ``, + }, + processRow, + ); + } + processRow.canvasRestore(this.trace.canvasPanelCtx!); + } + this.trace.rowsEL?.appendChild(processRow) + return processRow; + } + + private initCpuAbility = async (processRow: TraceRow) => { + let time = new Date().getTime(); + let cpuMaxData = await queryCPuAbilityMaxData(); + let hasTotal = false; + let hasUserLoad = false; + let hasSystemLoad = false; + let userLoad = cpuMaxData[0].userLoad; + if (userLoad > 0) { + hasUserLoad = true; + } + let systemLoad = cpuMaxData[0].systemLoad; + if (systemLoad > 0) { + hasSystemLoad = true; + } + let totalLoad = cpuMaxData[0].totalLoad; + if (totalLoad > 0) { + hasTotal = true; + } + let cpuNameList: Array = ['Total', 'User', 'System'] + let traceRow = TraceRow.skeleton(); + traceRow.rowParentId = `abilityMonitor` + traceRow.rowHidden = !processRow.expansion + traceRow.rowId = cpuNameList[0] + traceRow.rowType = TraceRow.ROW_TYPE_CPU_ABILITY + traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + traceRow.selectChangeHandler = this.trace.selectChangeHandler; + traceRow.style.height = '40px' + traceRow.style.width = `100%`; + traceRow.setAttribute('children', ''); + traceRow.name = `CPU ${cpuNameList[0]} Load`; + traceRow.supplier = () => queryCpuAbilityData() + traceRow.focusHandler = (ev)=>{ + let monitorCpuTip = (CpuAbilityMonitorStruct.hoverCpuAbilityStruct?.value||0).toFixed(2) + "%" + this.trace?.displayTip(traceRow, CpuAbilityMonitorStruct.hoverCpuAbilityStruct, `${monitorCpuTip}`); + }; + traceRow.onThreadHandler = (useCache) => { + let context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + traceRow.canvasSave( context); + (renders["monitorCpu"] as CpuAbilityRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `monitorCpu0`, + maxCpuUtilization: 100, + maxCpuUtilizationName: hasTotal ? "100%" : '0%', + }, + traceRow + ); + traceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(traceRow) + let userTraceRow = TraceRow.skeleton(); + userTraceRow.rowParentId = `abilityMonitor` + userTraceRow.rowHidden = !processRow.expansion + userTraceRow.rowId = cpuNameList[1] + userTraceRow.rowType = TraceRow.ROW_TYPE_CPU_ABILITY + userTraceRow.style.height = '40px' + userTraceRow.style.width = `100%`; + userTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + userTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + userTraceRow.setAttribute('children', ''); + userTraceRow.name = `CPU ${cpuNameList[1]} Load`; + userTraceRow.supplier = () => queryCpuAbilityUserData() + userTraceRow.focusHandler = (ev)=>{ + let monitorCpuTip = (CpuAbilityMonitorStruct.hoverCpuAbilityStruct?.value||0).toFixed(2) + "%" + this.trace?.displayTip(userTraceRow, CpuAbilityMonitorStruct.hoverCpuAbilityStruct, `${monitorCpuTip}`); + }; + userTraceRow.onThreadHandler = (useCache) => { + let context = userTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + userTraceRow.canvasSave( context); + (renders["monitorCpu"] as CpuAbilityRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `monitorCpu1`, + maxCpuUtilization: 100, + maxCpuUtilizationName: hasUserLoad ? "100%" : '0%', + }, + userTraceRow + ); + userTraceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(userTraceRow) + let sysTraceRow = TraceRow.skeleton(); + sysTraceRow.rowParentId = `abilityMonitor` + sysTraceRow.rowHidden = !processRow.expansion + sysTraceRow.rowId = cpuNameList[2] + sysTraceRow.rowType = TraceRow.ROW_TYPE_CPU_ABILITY + sysTraceRow.style.height = '40px' + sysTraceRow.style.width = `100%`; + sysTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + sysTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + sysTraceRow.setAttribute('children', ''); + sysTraceRow.name = `CPU ${cpuNameList[2]} Load`; + sysTraceRow.supplier = () => queryCpuAbilitySystemData() + sysTraceRow.focusHandler = (ev)=>{ + let monitorCpuTip = (CpuAbilityMonitorStruct.hoverCpuAbilityStruct?.value||0).toFixed(2) + "%" + this.trace?.displayTip(sysTraceRow, CpuAbilityMonitorStruct.hoverCpuAbilityStruct, `${monitorCpuTip}`); + }; + sysTraceRow.onThreadHandler = (useCache) => { + let context = sysTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + sysTraceRow.canvasSave( context); + (renders["monitorCpu"] as CpuAbilityRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `monitorCpu2`, + maxCpuUtilization: 100, + maxCpuUtilizationName: hasSystemLoad ? "100%" : '0%', + }, + sysTraceRow + ); + sysTraceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(sysTraceRow) + let durTime = new Date().getTime() - time; + info('The time to load the Ability Cpu is: ', durTime) + } + + private initMemoryAbility = async (processRow: TraceRow) => { + let time = new Date().getTime(); + // sys.mem.total sys.mem.cached sys.mem.swap.total + let memoryNameList: Array = ['MemoryTotal', 'Cached', 'SwapTotal'] + let memoryTotal = await queryMemoryMaxData("sys.mem.total"); + let memoryTotalValue = memoryTotal[0].maxValue + let memoryTotalId = memoryTotal[0].filter_id + let memoryTotalValueName = this.memoryMath(memoryTotalValue); + let memoryUsedTraceRow = TraceRow.skeleton(); + memoryUsedTraceRow.rowParentId = `abilityMonitor` + memoryUsedTraceRow.rowHidden = !processRow.expansion + memoryUsedTraceRow.rowId = memoryNameList[0] + memoryUsedTraceRow.rowType = TraceRow.ROW_TYPE_MEMORY_ABILITY + memoryUsedTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + memoryUsedTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + memoryUsedTraceRow.style.height = '40px' + memoryUsedTraceRow.style.width = `100%`; + memoryUsedTraceRow.setAttribute('children', ''); + memoryUsedTraceRow.name = memoryNameList[0]; + memoryUsedTraceRow.supplier = () => queryMemoryUsedAbilityData(memoryTotalId) + memoryUsedTraceRow.focusHandler = (ev)=>{ + this.trace?.displayTip(memoryUsedTraceRow, MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct, `${Utils.getBinaryByteWithUnit(MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct?.value||0)}`); + }; + memoryUsedTraceRow.onThreadHandler = (useCache) => { + let context = memoryUsedTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + memoryUsedTraceRow.canvasSave( context); + (renders["monitorMemory"] as MemoryAbilityRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `monitorMemory0`, + maxMemoryByte: memoryTotalValue, + maxMemoryByteName: memoryTotalValueName, + }, + memoryUsedTraceRow + ); + memoryUsedTraceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(memoryUsedTraceRow) + + let cached = await queryMemoryMaxData("sys.mem.cached"); + let cachedValue = cached[0].maxValue + let cachedValueName = this.memoryMath(cachedValue); + let cachedId = cached[0].filter_id + let cachedFilesTraceRow = TraceRow.skeleton(); + cachedFilesTraceRow.rowParentId = `abilityMonitor` + cachedFilesTraceRow.rowHidden = !processRow.expansion + cachedFilesTraceRow.rowId = memoryNameList[1] + cachedFilesTraceRow.rowType = TraceRow.ROW_TYPE_MEMORY_ABILITY + cachedFilesTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + cachedFilesTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + cachedFilesTraceRow.style.height = '40px' + cachedFilesTraceRow.style.width = `100%`; + cachedFilesTraceRow.setAttribute('children', ''); + cachedFilesTraceRow.name = memoryNameList[1]; + cachedFilesTraceRow.supplier = () => queryCachedFilesAbilityData(cachedId) + cachedFilesTraceRow.focusHandler = (ev)=>{ + this.trace?.displayTip(cachedFilesTraceRow, MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct, `${Utils.getBinaryByteWithUnit(MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct?.value||0)}`); + }; + cachedFilesTraceRow.onThreadHandler = (useCache) => { + let context = cachedFilesTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + cachedFilesTraceRow.canvasSave( context); + (renders["monitorMemory"] as MemoryAbilityRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `monitorMemory1`, + maxMemoryByte: cachedValue, + maxMemoryByteName: cachedValueName, + }, + cachedFilesTraceRow + ); + cachedFilesTraceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(cachedFilesTraceRow) + + + let swap = await queryMemoryMaxData("sys.mem.swap.total"); + let swapValue = swap[0].maxValue + let swapValueName = this.memoryMath(swapValue); + let swapId = swap[0].filter_id + let compressedTraceRow = TraceRow.skeleton(); + compressedTraceRow.rowParentId = `abilityMonitor` + compressedTraceRow.rowHidden = !processRow.expansion + compressedTraceRow.rowId = memoryNameList[2] + compressedTraceRow.rowType = TraceRow.ROW_TYPE_MEMORY_ABILITY + compressedTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + compressedTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + compressedTraceRow.style.height = '40px' + compressedTraceRow.style.width = `100%`; + compressedTraceRow.setAttribute('children', ''); + compressedTraceRow.name = memoryNameList[2]; + compressedTraceRow.supplier = () => queryCompressedAbilityData(swapId) + compressedTraceRow.focusHandler = (ev)=>{ + this.trace?.displayTip(compressedTraceRow, MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct, `${Utils.getBinaryByteWithUnit(MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct?.value||0)}`); + }; + compressedTraceRow.onThreadHandler = (useCache) => { + let context = compressedTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + compressedTraceRow.canvasSave( context); + (renders["monitorMemory"] as MemoryAbilityRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `monitorMemory2`, + maxMemoryByte: swapValue, + maxMemoryByteName: swapValueName, + }, + compressedTraceRow + ); + compressedTraceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(compressedTraceRow) + let durTime = new Date().getTime() - time; + info('The time to load the Ability Memory is: ', durTime) + } + + private initDiskAbility = async (processRow: TraceRow) => { + let time = new Date().getTime(); + let maxList = await queryDiskIoMaxData(); + let maxBytesRead = maxList[0].bytesRead; + let maxBytesReadName = this.diskIOMath(maxBytesRead); + let diskIONameList: Array = ['Bytes Read/Sec', 'Bytes Written/Sec', 'Read Ops/Sec', 'Written Ops/Sec'] + let bytesReadTraceRow = TraceRow.skeleton(); + bytesReadTraceRow.rowParentId = `abilityMonitor` + bytesReadTraceRow.rowHidden = !processRow.expansion + bytesReadTraceRow.rowId = diskIONameList[0] + bytesReadTraceRow.rowType = TraceRow.ROW_TYPE_DISK_ABILITY + bytesReadTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + bytesReadTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + bytesReadTraceRow.style.height = '40px' + bytesReadTraceRow.style.width = `100%`; + bytesReadTraceRow.setAttribute('children', ''); + bytesReadTraceRow.name = 'Disk ' + diskIONameList[0]; + bytesReadTraceRow.supplier = () => queryBytesReadAbilityData() + bytesReadTraceRow.focusHandler = (ev)=>{ + this.trace?.displayTip(bytesReadTraceRow, DiskAbilityMonitorStruct.hoverDiskAbilityStruct, `${DiskAbilityMonitorStruct.hoverDiskAbilityStruct?.value||"0"} KB/S`); + }; + bytesReadTraceRow.onThreadHandler = (useCache) => { + let context = bytesReadTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + bytesReadTraceRow.canvasSave( context); + (renders["monitorDiskIo"] as DiskIoAbilityRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `monitorDiskIo0`, + maxDiskRate: maxBytesRead, + maxDiskRateName: maxBytesReadName, + }, + bytesReadTraceRow + ); + bytesReadTraceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(bytesReadTraceRow) + + let maxBytesWrite = maxList[0].bytesWrite; + let maxBytesWriteName = this.diskIOMath(maxBytesWrite); + let bytesWrittenTraceRow = TraceRow.skeleton(); + bytesWrittenTraceRow.rowParentId = `abilityMonitor` + bytesWrittenTraceRow.rowHidden = !processRow.expansion + bytesWrittenTraceRow.rowId = diskIONameList[1] + bytesWrittenTraceRow.rowType = TraceRow.ROW_TYPE_DISK_ABILITY + bytesWrittenTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + bytesWrittenTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + bytesWrittenTraceRow.style.height = '40px' + bytesWrittenTraceRow.style.width = `100%`; + bytesWrittenTraceRow.setAttribute('children', ''); + bytesWrittenTraceRow.name = 'Disk ' + diskIONameList[1]; + bytesWrittenTraceRow.supplier = () => queryBytesWrittenAbilityData() + bytesWrittenTraceRow.focusHandler = (ev)=>{ + this.trace?.displayTip(bytesWrittenTraceRow, DiskAbilityMonitorStruct.hoverDiskAbilityStruct, `${DiskAbilityMonitorStruct.hoverDiskAbilityStruct?.value||"0"} KB/S`); + }; + bytesWrittenTraceRow.onThreadHandler = (useCache) => { + let context = bytesWrittenTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + bytesWrittenTraceRow.canvasSave( context); + (renders["monitorDiskIo"] as DiskIoAbilityRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `monitorDiskIo1`, + maxDiskRate: maxBytesWrite, + maxDiskRateName: maxBytesWriteName, + }, + bytesWrittenTraceRow + ); + bytesWrittenTraceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(bytesWrittenTraceRow) + + + let maxReadOps = maxList[0].readOps; + let maxReadOpsName = this.diskIOMath(maxReadOps); + let readOpsTraceRow = TraceRow.skeleton(); + readOpsTraceRow.rowParentId = `abilityMonitor` + readOpsTraceRow.rowHidden = !processRow.expansion + readOpsTraceRow.rowId = diskIONameList[2] + readOpsTraceRow.rowType = TraceRow.ROW_TYPE_DISK_ABILITY + readOpsTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + readOpsTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + readOpsTraceRow.style.height = '40px' + readOpsTraceRow.style.width = `100%`; + readOpsTraceRow.setAttribute('children', ''); + readOpsTraceRow.name = 'Disk ' + diskIONameList[2]; + readOpsTraceRow.supplier = () => queryReadAbilityData() + readOpsTraceRow.focusHandler = (ev)=>{ + this.trace?.displayTip(readOpsTraceRow, DiskAbilityMonitorStruct.hoverDiskAbilityStruct, `${DiskAbilityMonitorStruct.hoverDiskAbilityStruct?.value||"0"} KB/S`); + }; + readOpsTraceRow.onThreadHandler = (useCache) => { + let context = readOpsTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + readOpsTraceRow.canvasSave( context); + (renders["monitorDiskIo"] as DiskIoAbilityRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `monitorDiskIo2`, + maxDiskRate: maxReadOps, + maxDiskRateName: maxReadOpsName, + }, + readOpsTraceRow + ); + readOpsTraceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(readOpsTraceRow) + let maxWriteOps = maxList[0].writeOps; + let maxWriteOpsName = this.diskIOMath(maxWriteOps); + let writtenOpsTraceRow = TraceRow.skeleton(); + writtenOpsTraceRow.rowParentId = `abilityMonitor` + writtenOpsTraceRow.rowHidden = !processRow.expansion + writtenOpsTraceRow.rowId = diskIONameList[3] + writtenOpsTraceRow.rowType = TraceRow.ROW_TYPE_DISK_ABILITY + writtenOpsTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + writtenOpsTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + writtenOpsTraceRow.style.height = '40px' + writtenOpsTraceRow.style.width = `100%`; + writtenOpsTraceRow.setAttribute('children', ''); + writtenOpsTraceRow.name = 'Disk ' + diskIONameList[3]; + writtenOpsTraceRow.supplier = () => queryWrittenAbilityData() + writtenOpsTraceRow.focusHandler = (ev)=>{ + this.trace?.displayTip(writtenOpsTraceRow, DiskAbilityMonitorStruct.hoverDiskAbilityStruct, `${DiskAbilityMonitorStruct.hoverDiskAbilityStruct?.value||"0"} KB/S`); + }; + writtenOpsTraceRow.onThreadHandler = (useCache) => { + let context = writtenOpsTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + writtenOpsTraceRow.canvasSave( context); + (renders["monitorDiskIo"] as DiskIoAbilityRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `monitorDiskIo3`, + maxDiskRate: maxWriteOps, + maxDiskRateName: maxWriteOpsName, + }, + writtenOpsTraceRow + ); + writtenOpsTraceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(writtenOpsTraceRow) + let durTime = new Date().getTime() - time; + info('The time to load the Ability DiskIO is: ', durTime) + } + + private initNetworkAbility = async (processRow: TraceRow) => { + let time = new Date().getTime(); + let maxList = await queryNetWorkMaxData(); + let maxBytesIn = maxList[0].maxIn; + let maxInByteName = this.networkMath(maxBytesIn); + let networkNameList: Array = ['Bytes In/Sec', 'Bytes Out/Sec', 'Packets In/Sec', 'Packets Out/Sec'] + let bytesInTraceRow = TraceRow.skeleton(); + bytesInTraceRow.rowParentId = `abilityMonitor` + bytesInTraceRow.rowHidden = !processRow.expansion + bytesInTraceRow.rowId = networkNameList[0] + bytesInTraceRow.rowType = TraceRow.ROW_TYPE_NETWORK_ABILITY + bytesInTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + bytesInTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + bytesInTraceRow.style.height = '40px' + bytesInTraceRow.style.width = `100%`; + bytesInTraceRow.setAttribute('children', ''); + bytesInTraceRow.name = 'Network ' + networkNameList[0]; + bytesInTraceRow.supplier = () => queryBytesInAbilityData() + bytesInTraceRow.focusHandler = (ev)=>{ + this.trace?.displayTip(bytesInTraceRow, NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct, `${Utils.getBinaryByteWithUnit(NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct?.value||0)}`); + }; + bytesInTraceRow.onThreadHandler = (useCache) => { + let context = bytesInTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + bytesInTraceRow.canvasSave( context); + (renders["monitorNetwork"] as NetworkAbilityRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `monitorNetwork0`, + maxNetworkRate: maxBytesIn, + maxNetworkRateName: maxInByteName, + }, + bytesInTraceRow + ); + bytesInTraceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(bytesInTraceRow) + let bytesOutTraceRow = TraceRow.skeleton(); + let maxBytesOut = maxList[0].maxOut; + let maxOutByteName = this.networkMath(maxBytesOut); + bytesOutTraceRow.rowParentId = `abilityMonitor` + bytesOutTraceRow.rowHidden = !processRow.expansion + bytesOutTraceRow.rowId = networkNameList[1] + bytesOutTraceRow.rowType = TraceRow.ROW_TYPE_NETWORK_ABILITY + bytesOutTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + bytesOutTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + bytesOutTraceRow.style.height = '40px' + bytesOutTraceRow.style.width = `100%`; + bytesOutTraceRow.setAttribute('children', ''); + bytesOutTraceRow.name = 'Network ' + networkNameList[1]; + bytesOutTraceRow.supplier = () => queryBytesOutAbilityData(); + bytesOutTraceRow.focusHandler = (ev)=>{ + this.trace?.displayTip(bytesOutTraceRow, NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct, `${Utils.getBinaryByteWithUnit(NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct?.value||0)}`); + }; + bytesOutTraceRow.onThreadHandler = (useCache) => { + let context = bytesOutTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + bytesOutTraceRow.canvasSave( context); + (renders["monitorNetwork"] as NetworkAbilityRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `monitorNetwork1`, + maxNetworkRate: maxBytesOut, + maxNetworkRateName: maxOutByteName, + }, + bytesOutTraceRow + ); + bytesOutTraceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(bytesOutTraceRow) + let packetInTraceRow = TraceRow.skeleton(); + let maxPacketIn = maxList[0].maxPacketIn; + let maxInPacketName = this.networkMath(maxPacketIn); + packetInTraceRow.rowParentId = `abilityMonitor` + packetInTraceRow.rowHidden = !processRow.expansion + packetInTraceRow.rowId = networkNameList[2] + packetInTraceRow.rowType = TraceRow.ROW_TYPE_NETWORK_ABILITY + packetInTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + packetInTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + packetInTraceRow.style.height = '40px' + packetInTraceRow.style.width = `100%`; + packetInTraceRow.setAttribute('children', ''); + packetInTraceRow.name = 'Network ' + networkNameList[2]; + packetInTraceRow.supplier = () => queryPacketsInAbilityData(); + packetInTraceRow.focusHandler = (ev)=>{ + this.trace?.displayTip(packetInTraceRow, NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct, `${Utils.getBinaryByteWithUnit(NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct?.value||0)}`); + }; + packetInTraceRow.onThreadHandler = (useCache) => { + let context = packetInTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + packetInTraceRow.canvasSave( context); + (renders["monitorNetwork"] as NetworkAbilityRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `monitorNetwork-Packet2`, + maxNetworkRate: maxPacketIn, + maxNetworkRateName: maxInPacketName, + }, + packetInTraceRow + ); + packetInTraceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(packetInTraceRow) + let packetOutTraceRow = TraceRow.skeleton(); + let maxPacketOut = maxList[0].maxPacketOut; + let maxOutPacketName = this.networkMath(maxPacketOut); + packetOutTraceRow.rowParentId = `abilityMonitor` + packetOutTraceRow.rowHidden = !processRow.expansion + packetOutTraceRow.rowId = networkNameList[3] + packetOutTraceRow.rowType = TraceRow.ROW_TYPE_NETWORK_ABILITY + packetOutTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + packetOutTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + packetOutTraceRow.style.height = '40px' + packetOutTraceRow.style.width = `100%`; + packetOutTraceRow.setAttribute('children', ''); + packetOutTraceRow.name = 'Network ' + networkNameList[3]; + packetOutTraceRow.supplier = () => queryPacketsOutAbilityData(); + packetOutTraceRow.focusHandler = (ev)=>{ + if(NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct){ + this.trace?.displayTip(packetOutTraceRow, NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct, `${Utils.getBinaryByteWithUnit(NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct!.value!)}`); + } + }; + packetOutTraceRow.onThreadHandler = (useCache) => { + let context = packetOutTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + packetOutTraceRow.canvasSave( context); + (renders["monitorNetwork"] as NetworkAbilityRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `monitorNetwork3`, + maxNetworkRate: maxPacketOut, + maxNetworkRateName: maxOutPacketName, + }, + packetOutTraceRow + ); + packetOutTraceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(packetOutTraceRow) + let durTime = new Date().getTime() - time; + info('The time to load the Ability Network is: ', durTime) + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/chart/SpChartManager.ts b/host/ide/src/trace/component/chart/SpChartManager.ts new file mode 100644 index 0000000000000000000000000000000000000000..aa10dca15aa0bf2c247ec9b30bfe4872bcd55fa2 --- /dev/null +++ b/host/ide/src/trace/component/chart/SpChartManager.ts @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SpSystemTrace} from "../SpSystemTrace.js"; +import {SpHiPerf} from "./SpHiPerf.js"; +import {SpCpuChart} from "./SpCpuChart.js"; +import {SpFreqChart} from "./SpFreqChart.js"; +import {SpFpsChart} from "./SpFpsChart.js"; +import { + getCpuUtilizationRate, queryDataDICT, + queryTotalTime +} from "../../database/SqlLite.js"; +import {info} from "../../../log/Log.js"; +import {SpNativeMemoryChart} from "./SpNativeMemoryChart.js"; +import {SpAbilityMonitorChart} from "./SpAbilityMonitorChart.js"; +import {SpProcessChart} from "./SpProcessChart.js"; +import {perfDataQuery} from "./PerfDataQuery.js"; +import {SpVirtualMemChart} from "./SpVirtualMemChart.js"; +import {SpFileSystemChart} from "./SpFileSystemChart.js"; +import {procedurePool} from "../../database/Procedure.js"; +import {SpSdkChart} from "./SpSdkChart.js"; +import {SpHiSysEventChart} from "./SpHiSysEventChart.js"; +import {SmpsChart} from "./SmpsChart.js"; + +export class SpChartManager { + private trace: SpSystemTrace; + public perf: SpHiPerf; + private cpu: SpCpuChart; + private freq: SpFreqChart; + private virtualMemChart:SpVirtualMemChart; + private fps: SpFpsChart + private nativeMemory: SpNativeMemoryChart; + private abilityMonitor: SpAbilityMonitorChart; + private process: SpProcessChart; + private fileSystem: SpFileSystemChart; + private sdkChart: SpSdkChart; + private hiSyseventChart: SpHiSysEventChart; + private smpsChart:SmpsChart; + + constructor(trace: SpSystemTrace) { + this.trace = trace; + this.perf = new SpHiPerf(trace); + this.fileSystem = new SpFileSystemChart(trace); + this.cpu = new SpCpuChart(trace); + this.freq = new SpFreqChart(trace); + this.virtualMemChart = new SpVirtualMemChart(trace); + this.fps = new SpFpsChart(trace); + this.nativeMemory = new SpNativeMemoryChart(trace); + this.abilityMonitor = new SpAbilityMonitorChart(trace); + this.process = new SpProcessChart(trace); + this.sdkChart = new SpSdkChart(trace); + this.hiSyseventChart = new SpHiSysEventChart(trace); + this.smpsChart = new SmpsChart(trace); + } + + async init(progress:Function){ + progress("load data dict", 50); + SpSystemTrace.DATA_DICT.clear(); + let dict = await queryDataDICT(); + dict.map((d) => SpSystemTrace.DATA_DICT.set(d['id'], d['data'])); + progress("time range", 65); + await this.initTotalTime(); + info("timerShaftEL Data initialized") + progress("cpu", 70); + await this.cpu.init(); + info("cpu Data initialized") + progress("process/thread state", 73); + await this.cpu.initProcessThreadStateData(progress); + info("ProcessThreadState Data initialized") + progress("cpu rate", 75); + await this.initCpuRate(); + info("Cpu Rate Data initialized") + progress("cpu freq", 80); + await this.freq.init(); + info("Cpu Freq Data initialized") + await this.virtualMemChart.init(); + progress("fps", 85); + await this.fps.init(); + info("FPS Data initialized") + progress("native memory", 86); + await this.nativeMemory.initNativeMemory() + progress("native memory", 87); + await this.nativeMemory.initChart(); + info("Native Memory Data initialized") + progress("ability monitor", 88); + await this.abilityMonitor.init(); + progress("hiSysevent", 88.2); + await this.hiSyseventChart.init(); + info("Perf Files Data initialized") + progress("vm tracker", 88.4); + await this.smpsChart.init(); + progress("sdk", 88.6); + await this.sdkChart.init(); + progress("perf", 88.8); + await this.perf!.init(); + progress("file system", 89); + await this.fileSystem!.init(); + info("Ability Monitor Data initialized") + await perfDataQuery.initPerfCache() + info("HiPerf Data initialized") + progress("process", 90); + await this.process.initAsyncFuncData() + await this.process.init(); + info("Process Data initialized") + progress("display", 95); + } + + initTotalTime = async () => { + let res = await queryTotalTime(); + if (this.trace.timerShaftEL) { + this.trace.timerShaftEL.totalNS = res[0].total; + (window as any).recordStartNS = res[0].recordStartNS; + (window as any).recordEndNS = res[0].recordEndNS; + this.trace.timerShaftEL.loadComplete = true; + } + } + + initCpuRate = async () => { + let rates = await getCpuUtilizationRate(0, this.trace.timerShaftEL?.totalNS || 0); + if (this.trace.timerShaftEL) this.trace.timerShaftEL.cpuUsage = rates; + info("Cpu UtilizationRate data size is: ", rates.length) + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/chart/SpCpuChart.ts b/host/ide/src/trace/component/chart/SpCpuChart.ts new file mode 100644 index 0000000000000000000000000000000000000000..f78be3b29a7fd39a593dbb3cadc303b3c8556c2a --- /dev/null +++ b/host/ide/src/trace/component/chart/SpCpuChart.ts @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SpSystemTrace} from "../SpSystemTrace.js"; +import {queryCpuData, queryCpuMax, threadPool} from "../../database/SqlLite.js"; +import {info, trace} from "../../../log/Log.js"; +import {TraceRow} from "../trace/base/TraceRow.js"; +import {procedurePool} from "../../database/Procedure.js"; +import {CpuRender, CpuStruct} from "../../database/ui-worker/ProcedureWorkerCPU.js"; +import {renders} from "../../database/ui-worker/ProcedureWorker.js"; + +export class SpCpuChart { + private trace: SpSystemTrace; + + constructor(trace: SpSystemTrace) { + this.trace = trace; + } + + async init() { + let CpuStartTime = new Date().getTime(); + let array = await queryCpuMax(); + info("Cpu trace row data size is: ", array.length) + if (array && array.length > 0 && array[0]) { + let cpuMax = array[0].cpu + CpuStruct.cpuCount = cpuMax + 1; + for (let i1 = 0; i1 < CpuStruct.cpuCount; i1++) { + const cpuId = i1; + let traceRow = TraceRow.skeleton(); + traceRow.rowId = `${cpuId}` + traceRow.rowType = TraceRow.ROW_TYPE_CPU + traceRow.rowParentId = '' + traceRow.style.height = '40px' + traceRow.name = `Cpu ${cpuId}` + traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + traceRow.selectChangeHandler = this.trace.selectChangeHandler; + traceRow.supplier = () => queryCpuData(cpuId, TraceRow.range?.startNS || 0, TraceRow.range?.endNS || 0) + traceRow.focusHandler = () => { + this.trace?.displayTip(traceRow,CpuStruct.hoverCpuStruct,`P:${CpuStruct.hoverCpuStruct?.processName || "Process"} [${CpuStruct.hoverCpuStruct?.processId}]T:${CpuStruct.hoverCpuStruct?.name} [${CpuStruct.hoverCpuStruct?.tid}] [Prio:${CpuStruct.hoverCpuStruct?.priority || 0}]`); + } + traceRow.onThreadHandler = ((useCache: boolean, buf: ArrayBuffer | undefined | null) => { + let context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + traceRow.canvasSave(context); + (renders["cpu-data"] as CpuRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `cpu-data-${i1}`, + }, + traceRow + ); + traceRow.canvasRestore(context); + }) + this.trace.rowsEL?.appendChild(traceRow); + + } + } + let CpuDurTime = new Date().getTime() - CpuStartTime; + info('The time to load the Cpu data is: ', CpuDurTime) + } + + initProcessThreadStateData = async (progress: Function) => { + let time = new Date().getTime(); + SpSystemTrace.SPT_DATA = []; + progress("StateProcessThread", 93); + procedurePool.submitWithName("logic1", "spt-init", {}, undefined, (res: any) => { + SpSystemTrace.SPT_DATA = Array.from(res); + }) + let durTime = new Date().getTime() - time; + info('The time to load the first ProcessThreadState data is: ', durTime) + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/chart/SpFileSystemChart.ts b/host/ide/src/trace/component/chart/SpFileSystemChart.ts new file mode 100644 index 0000000000000000000000000000000000000000..cfa3ae5e87d309b2d6132ab255b385b9924a70f6 --- /dev/null +++ b/host/ide/src/trace/component/chart/SpFileSystemChart.ts @@ -0,0 +1,321 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SpSystemTrace} from "../SpSystemTrace.js"; +import {TraceRow} from "../trace/base/TraceRow.js"; +import {procedurePool} from "../../database/Procedure.js"; +import { + getDiskIOLatencyChartDataByProcess, + getDiskIOProcess, + getFileSysChartDataByType, getFileSysVirtualMemoryChartData, + hasFileSysData +} from "../../database/SqlLite.js"; +import {FileSysChartStruct, FileSystemRender} from "../../database/ui-worker/ProcedureWorkerFileSystem.js"; +import { ColorUtils } from "../trace/base/ColorUtils.js"; +import {Utils} from "../trace/base/Utils.js"; +import {renders} from "../../database/ui-worker/ProcedureWorker.js"; +import {EmptyRender} from "../../database/ui-worker/ProcedureWorkerCPU.js"; + +export class SpFileSystemChart { + private trace: SpSystemTrace; + + constructor(trace: SpSystemTrace) { + this.trace = trace; + } + + async init() { + let sys = await hasFileSysData(); + if(sys.length > 0){ + let fsCount = sys[0]['fsCount'] ?? 0; + let vmCount = sys[0]['vmCount'] ?? 0; + let ioCount = sys[0]['ioCount'] ?? 0; + if(sys && sys.length > 0 && (fsCount > 0 || vmCount > 0 || ioCount > 0)){ + let folder = await this.initFolder(); + await this.initFileCallchain() + if(fsCount > 0){ + await this.initLogicalRead(folder); + await this.initLogicalWrite(folder); + } + if(vmCount > 0){ + await this.initVirtualMemoryTrace(folder); + } + if(ioCount > 0){ + await this.initDiskIOLatency(folder) + await this.initProcessDiskIOLatency(folder) + } + } + } + } + + async initFileCallchain(){ + return new Promise((resolve, reject) => { + procedurePool.submitWithName("logic0","fileSystem-init",SpSystemTrace.DATA_DICT,undefined,(res:any)=>{ + resolve(res) + }) + }) + } + + async initFolder():Promise>{ + let folder = TraceRow.skeleton(); + folder.rowId = `FileSystem`; + folder.index = 0; + folder.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM_GROUP + folder.rowParentId = ''; + folder.style.height = '40px' + folder.folder = true; + folder.name = `EBPF` ;/* & I/O Latency */ + folder.favoriteChangeHandler = this.trace.favoriteChangeHandler; + folder.selectChangeHandler = this.trace.selectChangeHandler; + folder.supplier = () => new Promise>((resolve) => resolve([])); + folder.onThreadHandler = (useCache) => { + folder.canvasSave(this.trace.canvasPanelCtx!); + if(folder.expansion){ + this.trace.canvasPanelCtx?.clearRect(0, 0, folder.frame.width, folder.frame.height); + } else { + (renders["empty"] as EmptyRender).renderMainThread( + { + context: this.trace.canvasPanelCtx, + useCache: useCache, + type: ``, + }, + folder, + ); + } + folder.canvasRestore(this.trace.canvasPanelCtx!); + } + this.trace.rowsEL?.appendChild(folder) + return folder; + } + + async initLogicalRead(folder:TraceRow){ + let row = TraceRow.skeleton(); + row.rowId = `FileSystemLogicalRead`; + row.index = 1; + row.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM + row.rowParentId = folder.rowId; + row.rowHidden = !folder.expansion + row.style.height = '40px' + row.setAttribute('children', ''); + row.name = `FileSystem Logical Read`; + row.supplier = () => getFileSysChartDataByType(2); + row.favoriteChangeHandler = this.trace.favoriteChangeHandler; + row.selectChangeHandler = this.trace.selectChangeHandler; + row.focusHandler = ()=> this.focusHandler(row); + row.onThreadHandler = (useCache) => { + let context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + row.canvasSave(context); + (renders[TraceRow.ROW_TYPE_FILE_SYSTEM] as FileSystemRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-logical-read`, + chartColor:ColorUtils.MD_PALETTE[0] + }, + row + ); + row.canvasRestore(context); + } + this.trace.rowsEL?.appendChild(row) + } + + async initLogicalWrite(folder:TraceRow){ + let row = TraceRow.skeleton(); + row.rowId = `FileSystemLogicalWrite`; + row.index = 2; + row.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM + row.rowParentId = folder.rowId; + row.rowHidden = !folder.expansion; + row.style.height = '40px' + row.setAttribute('children', ''); + row.name = `FileSystem Logical Write`; + row.supplier = () => getFileSysChartDataByType(3); + row.favoriteChangeHandler = this.trace.favoriteChangeHandler; + row.selectChangeHandler = this.trace.selectChangeHandler; + row.focusHandler = ()=> this.focusHandler(row); + row.onThreadHandler = (useCache) => { + let context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + row.canvasSave(context); + (renders[TraceRow.ROW_TYPE_FILE_SYSTEM] as FileSystemRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-logical-write`, + chartColor:ColorUtils.MD_PALETTE[8] + }, + row + ); + row.canvasRestore(context); + } + this.trace.rowsEL?.appendChild(row) + } + + async initDiskIOLatency(folder:TraceRow){ + let row = TraceRow.skeleton(); + row.rowId = `FileSystemDiskIOLatency`; + row.index = 4; + row.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM + row.rowParentId = folder.rowId; + row.rowHidden = !folder.expansion + row.style.height = '40px' + row.style.width = `100%`; + row.setAttribute('children', ''); + row.name = `Disk I/O Latency`; + row.supplier = () => getDiskIOLatencyChartDataByProcess(true,0,[1,2,3,4]); + row.favoriteChangeHandler = this.trace.favoriteChangeHandler; + row.selectChangeHandler = this.trace.selectChangeHandler; + row.focusHandler = ()=> this.focusHandler(row); + row.onThreadHandler = (useCache) => { + let context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + row.canvasSave(context); + (renders[TraceRow.ROW_TYPE_FILE_SYSTEM] as FileSystemRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-disk-io`, + chartColor:ColorUtils.MD_PALETTE[0] + }, + row + ); + row.canvasRestore(context); + } + this.trace.rowsEL?.appendChild(row) + } + + async initProcessDiskIOLatency(folder:TraceRow){ + let processes = await getDiskIOProcess() || []; + for (let i = 0,len = processes.length; i < len; i++) { + let process = processes[i]; + let rowRead = TraceRow.skeleton(); + rowRead.index = 5 + 2 * i; + rowRead.rowId = `FileSystemDiskIOLatency-read-${process['ipid']}`; + rowRead.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM + rowRead.rowParentId = folder.rowId; + rowRead.rowHidden = !folder.expansion + rowRead.style.height = '40px' + rowRead.style.width = `100%`; + rowRead.setAttribute('children', ''); + rowRead.name = `${process['name'] ?? 'Process'}(${process['pid']}) Max Read Latency`; + rowRead.supplier = () => getDiskIOLatencyChartDataByProcess(false,process['ipid'],[1,3]); + rowRead.favoriteChangeHandler = this.trace.favoriteChangeHandler; + rowRead.selectChangeHandler = this.trace.selectChangeHandler; + rowRead.focusHandler = ()=> this.focusHandler(rowRead); + rowRead.onThreadHandler = (useCache) => { + let context = rowRead.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + rowRead.canvasSave(context); + (renders[TraceRow.ROW_TYPE_FILE_SYSTEM] as FileSystemRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-disk-io-process-read-${process['pid']}`, + chartColor:ColorUtils.MD_PALETTE[0] + }, + rowRead + ); + rowRead.canvasRestore(context); + } + this.trace.rowsEL?.appendChild(rowRead) + let rowWrite = TraceRow.skeleton(); + rowWrite.index = 5 + 2 * i + 1; + rowWrite.rowId = `FileSystemDiskIOLatency-write-${process['ipid']}`; + rowWrite.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM + rowWrite.rowParentId = folder.rowId; + rowWrite.rowHidden = !folder.expansion + rowWrite.style.height = '40px' + rowWrite.style.width = `100%`; + rowWrite.setAttribute('children', ''); + rowWrite.name = `${process['name'] ?? 'Process'}(${process['pid']}) Max Write Latency`; + rowWrite.supplier = () => getDiskIOLatencyChartDataByProcess(false,process['ipid'],[2,4]); + rowWrite.favoriteChangeHandler = this.trace.favoriteChangeHandler; + rowWrite.selectChangeHandler = this.trace.selectChangeHandler; + rowWrite.focusHandler = ()=> this.focusHandler(rowWrite); + rowWrite.onThreadHandler = (useCache) => { + let context = rowWrite.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + rowWrite.canvasSave(context); + (renders[TraceRow.ROW_TYPE_FILE_SYSTEM] as FileSystemRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-disk-io-process-write-${process['pid']}`, + chartColor:ColorUtils.MD_PALETTE[8] + }, + rowWrite + ); + rowWrite.canvasRestore(context); + } + this.trace.rowsEL?.appendChild(rowWrite) + } + } + + async initVirtualMemoryTrace(folder:TraceRow){ + let row = TraceRow.skeleton(); + row.rowId = `FileSystemVirtualMemory`; + row.index = 3; + row.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM + row.rowParentId = folder.rowId; + row.rowHidden = !folder.expansion + row.rangeSelect = true; + row.style.height = '40px' + row.style.width = `100%`; + row.setAttribute('children', ''); + row.name = `Page Fault Trace`; + row.supplier = () => getFileSysVirtualMemoryChartData(); + row.favoriteChangeHandler = this.trace.favoriteChangeHandler; + row.selectChangeHandler = this.trace.selectChangeHandler; + row.focusHandler = ()=> this.focusHandler(row); + row.onThreadHandler = (useCache) => { + let context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + row.canvasSave(context); + (renders[TraceRow.ROW_TYPE_FILE_SYSTEM] as FileSystemRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-virtual-memory`, + chartColor:ColorUtils.MD_PALETTE[0] + }, + row + ); + row.canvasRestore(context); + } + this.trace.rowsEL?.appendChild(row) + } + + focusHandler(row:TraceRow){ + let num = 0; + let tip = ''; + if (FileSysChartStruct.hoverFileSysStruct) { + num = FileSysChartStruct.hoverFileSysStruct.size ?? 0; + let group10Ms = FileSysChartStruct.hoverFileSysStruct.group10Ms ?? false; + if (row.rowId!.startsWith("FileSystemDiskIOLatency")) { + if (num > 0) { + let tipStr = Utils.getProbablyTime(num); + if (group10Ms) { + tip = `${tipStr} (10.00ms)` + } else { + tip = `${tipStr}` + } + } + } else { + if (num > 0) { + if (group10Ms) { + tip = `${num} (10.00ms)` + } else { + tip = `${num}` + } + } + } + } + this.trace?.displayTip(row,FileSysChartStruct.hoverFileSysStruct,tip) + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/chart/SpFpsChart.ts b/host/ide/src/trace/component/chart/SpFpsChart.ts new file mode 100644 index 0000000000000000000000000000000000000000..e6e23115c7db1e01a976b7106cb2ec3a09ce795f --- /dev/null +++ b/host/ide/src/trace/component/chart/SpFpsChart.ts @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SpSystemTrace} from "../SpSystemTrace.js"; +import {getFps} from "../../database/SqlLite.js"; +import {TraceRow} from "../trace/base/TraceRow.js"; +import {info} from "../../../log/Log.js"; +import {renders} from "../../database/ui-worker/ProcedureWorker.js"; +import {FpsRender, FpsStruct} from "../../database/ui-worker/ProcedureWorkerFPS.js"; + +export class SpFpsChart { + private trace: SpSystemTrace; + + constructor(trace: SpSystemTrace) { + this.trace = trace; + } + + async init() { + let res = await getFps(); + if (res.length == 0) { + return; + } + let startTime = new Date().getTime(); + let fpsRow = TraceRow.skeleton(); + fpsRow.rowId = `fps` + fpsRow.rowType = TraceRow.ROW_TYPE_FPS + fpsRow.rowParentId = '' + FpsStruct.maxFps = 0 + fpsRow.style.height = '40px' + fpsRow.name = "FPS" + fpsRow.supplier = () => new Promise>((resolve, reject) => resolve(res)); + fpsRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + fpsRow.selectChangeHandler = this.trace.selectChangeHandler; + fpsRow.focusHandler = ev => { + let tip = ""; + if (FpsStruct.hoverFpsStruct) { + tip = `${FpsStruct.hoverFpsStruct.fps || 0} ` + } + this.trace?.displayTip(fpsRow,FpsStruct.hoverFpsStruct,tip) + } + + fpsRow.onThreadHandler = (useCache) => { + let context = fpsRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + fpsRow.canvasSave( context); + (renders["fps"] as FpsRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `fps0`, + }, + fpsRow + ); + fpsRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(fpsRow) + let durTime = new Date().getTime() - startTime; + info('The time to load the FPS data is: ', durTime) + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/chart/SpFreqChart.ts b/host/ide/src/trace/component/chart/SpFreqChart.ts new file mode 100644 index 0000000000000000000000000000000000000000..82dd8ab8e93a01289c6550eccd26a0aa3ca4c3b9 --- /dev/null +++ b/host/ide/src/trace/component/chart/SpFreqChart.ts @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SpSystemTrace} from "../SpSystemTrace.js"; +import { + getCpuLimitFreq, + getCpuLimitFreqId, getCpuLimitFreqMax, + queryCpuFreq, + queryCpuFreqData, + queryCpuMaxFreq, + queryCpuState, + queryCpuStateFilter +} from "../../database/SqlLite.js"; +import {info} from "../../../log/Log.js"; +import {TraceRow} from "../trace/base/TraceRow.js"; +import {procedurePool} from "../../database/Procedure.js"; +import { ColorUtils } from "../trace/base/ColorUtils.js"; +import {CpuFreqLimitRender, CpuFreqLimitsStruct} from "../../database/ui-worker/ProcedureWorkerCpuFreqLimits.js"; +import {renders} from "../../database/ui-worker/ProcedureWorker.js"; +import {CpuStruct} from "../../database/ui-worker/ProcedureWorkerCPU.js"; +import {CpuFreqStruct, FreqRender} from "../../database/ui-worker/ProcedureWorkerFreq.js"; +import {CpuStateRender, CpuStateStruct} from "../../database/ui-worker/ProcedureWorkerCpuState.js"; + +export class SpFreqChart { + private trace: SpSystemTrace; + + constructor(trace: SpSystemTrace) { + this.trace = trace; + } + + async init() { + let cpuFreqStartTime = new Date().getTime(); + let freqList = await queryCpuFreq(); + let cpuStateFilterIds = await queryCpuStateFilter(); + let cpuFreqLimits = await getCpuLimitFreqId() + let cpuFreqLimitsMax = await getCpuLimitFreqMax(cpuFreqLimits.map((limit)=>{ + return limit.maxFilterId + }).join(",")) + info("Cpu Freq data size is: ", freqList!.length) + let freqMaxList = await queryCpuMaxFreq(); + CpuFreqStruct.maxFreq = freqMaxList[0].maxFreq; + let maxFreqObj = this.math(freqMaxList[0].maxFreq); + CpuFreqStruct.maxFreq = maxFreqObj.maxFreq; + CpuFreqStruct.maxFreqName = maxFreqObj.maxFreqName; + for (let i = 0; i < freqList.length; i++) { + const it = freqList[i]; + let traceRow = TraceRow.skeleton(); + traceRow.rowId = `${it.filterId}` + traceRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ + traceRow.rowParentId = '' + traceRow.style.height = '40px' + traceRow.name = `Cpu ${it.cpu} Frequency`; + traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + traceRow.selectChangeHandler = this.trace.selectChangeHandler; + traceRow.supplier = () => queryCpuFreqData(it.cpu) + traceRow.focusHandler = (ev)=>{ + this.trace?.displayTip(traceRow, CpuFreqStruct.hoverCpuFreqStruct, `${ColorUtils.formatNumberComma(CpuFreqStruct.hoverCpuFreqStruct?.value!)} kHz`); + }; + traceRow.onThreadHandler = (useCache) => { + let context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + traceRow.canvasSave( context); + (renders["freq"] as FreqRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `freq${it.cpu}`, + }, + traceRow + ); + traceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(traceRow) + } + for (let it of cpuStateFilterIds) { + let cpuStateRow = TraceRow.skeleton(); + cpuStateRow.rowId = `${cpuStateFilterIds[it.cpu].filterId}` + cpuStateRow.rowType = TraceRow.ROW_TYPE_CPU_STATE + cpuStateRow.rowParentId = '' + cpuStateRow.style.height = '40px' + cpuStateRow.name = `Cpu ${it.cpu} State` + cpuStateRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + cpuStateRow.selectChangeHandler = this.trace.selectChangeHandler; + cpuStateRow.isHover = true; + cpuStateRow.supplier = () => queryCpuState(cpuStateFilterIds[it.cpu].filterId); + cpuStateRow.focusHandler = ev => { + this.trace.displayTip(cpuStateRow, CpuStateStruct.hoverStateStruct, `State: ${CpuStateStruct.hoverStateStruct?.value}`); + } + cpuStateRow.onThreadHandler = ((useCache: boolean) => { + let context = cpuStateRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + cpuStateRow.canvasSave(context); + (renders["cpu-state"] as CpuStateRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `cpu-state-${it.cpu}`, + cpu:it.cpu, + }, + cpuStateRow + ); + cpuStateRow.canvasRestore(context); + }) + this.trace.rowsEL?.appendChild(cpuStateRow); + } + let durTime = new Date().getTime() - cpuFreqStartTime; + info('The time to load the CpuFreq data is: ', durTime) + for(let limit of cpuFreqLimits){ + let findMax = this.math(cpuFreqLimitsMax.find((maxLimit)=>{ + return maxLimit.filterId == limit.maxFilterId + })?.maxValue||0) + let cpuFreqLimitRow = TraceRow.skeleton(); + cpuFreqLimitRow.rowId = `${limit.cpu}` + cpuFreqLimitRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ_LIMIT + cpuFreqLimitRow.rowParentId = '' + cpuFreqLimitRow.style.height = '40px' + cpuFreqLimitRow.name = `Cpu ${limit.cpu} Freq Limit` + cpuFreqLimitRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + cpuFreqLimitRow.selectChangeHandler = this.trace.selectChangeHandler; + cpuFreqLimitRow.isHover = true; + cpuFreqLimitRow.supplier = () => getCpuLimitFreq(limit.maxFilterId,limit.minFilterId,limit.cpu); + cpuFreqLimitRow.focusHandler = ev => { + this.trace.displayTip(cpuFreqLimitRow, CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct, `Max Freq: ${ColorUtils.formatNumberComma(CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct?.max||0)} kHzMin Freq: ${ColorUtils.formatNumberComma(CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct?.min||0)} kHz`); + } + cpuFreqLimitRow.onThreadHandler = ((useCache: boolean) => { + let context = cpuFreqLimitRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + cpuFreqLimitRow.canvasSave(context); + (renders["cpu-limit-freq"] as CpuFreqLimitRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `cpu-limit-freq-${limit.cpu}`, + cpu:limit.cpu, + maxFreq: findMax?.maxFreq||0, + maxFreqName: findMax?.maxFreqName||"", + }, + cpuFreqLimitRow + ); + cpuFreqLimitRow.canvasRestore(context); + }) + this.trace.rowsEL?.appendChild(cpuFreqLimitRow); + } + } + + math = (maxFreq:number) => { + let maxFreqObj = { + maxFreqName:" ", + maxFreq:0 + } + let units: Array = ["", "K", "M", "G", "T", "E"]; + let sb = " "; + if (maxFreq > 0) { + let log10: number = Math.ceil(Math.log10(maxFreq)); + let pow10: number = Math.pow(10, log10); + let afterCeil: number = Math.ceil(maxFreq / (pow10 / 4)) * (pow10 / 4); + maxFreqObj.maxFreq = afterCeil; + let unitIndex: number = Math.floor(log10 / 3); + sb = `${afterCeil / Math.pow(10, unitIndex * 3)}${units[unitIndex + 1]}hz` + } + maxFreqObj.maxFreqName = sb.toString(); + return maxFreqObj; + } +} + +export class CpuFreqRowLimit { + cpu: number = 0; + maxFilterId: number = 0; + minFilterId: number = 0; +} \ No newline at end of file diff --git a/host/ide/src/trace/component/chart/SpHiPerf.ts b/host/ide/src/trace/component/chart/SpHiPerf.ts new file mode 100644 index 0000000000000000000000000000000000000000..bcb173eb3010760c11ea7c36a3c3181e14ce6d10 --- /dev/null +++ b/host/ide/src/trace/component/chart/SpHiPerf.ts @@ -0,0 +1,386 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SpSystemTrace} from "../SpSystemTrace.js"; +import {TraceRow} from "../trace/base/TraceRow.js"; +import {procedurePool} from "../../database/Procedure.js"; +import { + queryHiPerfCpuData, + queryHiPerfCpuMergeData, + queryHiPerfCpuMergeData2, + queryHiPerfEventData, + queryHiPerfEventList, + queryHiPerfEventListData, + queryHiPerfProcessData, + queryHiPerfThreadData, + queryPerfCmdline, + queryPerfThread +} from "../../database/SqlLite.js"; +import {Utils} from "../trace/base/Utils.js"; +import {PerfThread} from "../../bean/PerfProfile.js"; +import {HiperfCpuRender, HiPerfCpuStruct} from "../../database/ui-worker/ProcedureWorkerHiPerfCPU.js"; +import {HiperfThreadRender, HiPerfThreadStruct} from "../../database/ui-worker/ProcedureWorkerHiPerfThread.js"; +import {HiperfProcessRender, HiPerfProcessStruct} from "../../database/ui-worker/ProcedureWorkerHiPerfProcess.js"; +import {info} from "../../../log/Log.js"; +import {HiperfEventRender, HiPerfEventStruct} from "../../database/ui-worker/ProcedureWorkerHiPerfEvent.js"; +import {perfDataQuery} from "./PerfDataQuery.js"; +import {renders} from "../../database/ui-worker/ProcedureWorker.js"; +import {CpuRender, EmptyRender} from "../../database/ui-worker/ProcedureWorkerCPU.js"; +import {HiperfReportRender, HiPerfReportStruct} from "../../database/ui-worker/ProcedureWorkerHiPerfReport.js"; +import {BaseStruct} from "../../database/ui-worker/ProcedureWorkerCommon.js"; +import {ProcessRender} from "../../database/ui-worker/ProcedureWorkerProcess.js"; + +export interface ResultData { + existA: boolean | null | undefined, + existF: boolean | null | undefined, + fValue: number +} + +export class SpHiPerf { + static selectCpuStruct: HiPerfCpuStruct | undefined; + static selectProcessStruct: HiPerfProcessStruct | undefined; + static selectThreadStruct: HiPerfThreadStruct | undefined; + static stringResult: ResultData | undefined; + + private cpuData: Array | undefined + public maxCpuId: number = 0 + private rowFolder!: TraceRow; + private perfThreads: Array | undefined; + private trace: SpSystemTrace; + private group: any; + private eventTypeList: Array<{ id: number, report_value: string }> = []; + + constructor(trace: SpSystemTrace) { + this.trace = trace; + } + + async init() { + await this.initCmdLine() + this.perfThreads = await queryPerfThread(); + this.eventTypeList = await queryHiPerfEventList(); + info("PerfThread Data size is: ", this.perfThreads!.length) + this.group = Utils.groupBy(this.perfThreads || [], "pid"); + this.cpuData = await queryHiPerfCpuMergeData2(); + this.maxCpuId = this.cpuData.length > 0 ? this.cpuData[0].cpu_id : -Infinity; + if (this.cpuData.length > 0) { + await this.initFolder(); + await this.initCpuMerge(); + await this.initCpu(); + // await this.initReport(); + await this.initProcess(); + } + info("HiPerf Data initialized") + } + + getStringResult(s: string = "") { + let list = s.split(" ").filter((e) => e); + let sA = list.findIndex((item) => item == "-a"); + let sF = list.findIndex((item) => item == "-f"); + SpHiPerf.stringResult = { + existA: sA !== -1, + existF: sF !== -1, + fValue: Number((1000 / (sF !== -1 ? parseInt(list[sF + 1]) : 1000)).toFixed(1)), + } + } + + async initCmdLine() { + let perfCmdLines = await queryPerfCmdline(); + if (perfCmdLines.length > 0) { + this.getStringResult(perfCmdLines[0].report_value) + } else { + SpHiPerf.stringResult = { + existA: true, + existF: false, + fValue: 1, + } + } + } + + async initFolder() { + let row = TraceRow.skeleton(); + row.setAttribute('disabled-check', '') + row.rowId = `HiPerf`; + row.index = 0; + row.rowType = TraceRow.ROW_TYPE_HIPERF + row.rowParentId = ''; + row.folder = true; + row.style.height = '40px' + if (SpHiPerf.stringResult?.existA === true) { + row.name = `HiPerf (All)`; + } else { + let names = Reflect.ownKeys(this.group).map((pid: any) => { + let array = this.group[pid] as Array; + let process = array.filter(th => th.pid === th.tid)[0]; + return process.processName; + }).join(','); + row.name = `HiPerf (${names})`; + } + row.supplier = () => new Promise>((resolve) => resolve([])); + row.onThreadHandler = (useCache) => { + row.canvasSave(this.trace.canvasPanelCtx!); + if (row.expansion) { + this.trace.canvasPanelCtx?.clearRect(0, 0, row.frame.width, row.frame.height); + } else { + (renders["empty"] as EmptyRender).renderMainThread( + { + context: this.trace.canvasPanelCtx, + useCache: useCache, + type: ``, + }, + row, + ); + } + row.canvasRestore(this.trace.canvasPanelCtx!); + } + this.rowFolder = row; + this.trace.rowsEL?.appendChild(row) + } + + async initCpuMerge() { + let row = TraceRow.skeleton() + row.rowId = `HiPerf-cpu-merge`; + row.index = 0; + row.rowType = TraceRow.ROW_TYPE_HIPERF_CPU + row.rowParentId = 'HiPerf'; + row.rowHidden = !this.rowFolder.expansion + row.folder = false; + row.name = `HiPerf`; + row.style.height = '40px' + row.setAttribute('children', '') + row.favoriteChangeHandler = this.trace.favoriteChangeHandler; + row.selectChangeHandler = this.trace.selectChangeHandler; + row.supplier = () => queryHiPerfCpuMergeData(); + row.focusHandler = () => this.hoverTip(row, HiPerfCpuStruct.hoverStruct); + row.onThreadHandler = (useCache) => { + let context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + row.canvasSave(context); + (renders["HiPerf-Cpu"] as HiperfCpuRender).renderMainThread( + { + context: context, + useCache: useCache, + scale: TraceRow.range?.scale || 50, + type: `HiPerf-Cpu-Merge`, + maxCpu: (this.maxCpuId + 1), + intervalPerf: SpHiPerf.stringResult?.fValue || 1, + range: TraceRow.range, + }, + row + ); + row.canvasRestore(context); + } + this.trace.rowsEL?.appendChild(row) + } + + async initCpu() { + for (let i = 0; i <= this.maxCpuId; i++) { + let row = TraceRow.skeleton() + row.rowId = `HiPerf-cpu-${i}`; + row.index = i; + row.rowType = TraceRow.ROW_TYPE_HIPERF_CPU + row.rowParentId = 'HiPerf'; + row.rowHidden = !this.rowFolder.expansion + row.folder = false; + row.name = `Cpu ${i}`; + row.setAttribute('children', '') + row.favoriteChangeHandler = this.trace.favoriteChangeHandler; + row.selectChangeHandler = this.trace.selectChangeHandler; + row.style.height = '40px' + row.supplier = () => queryHiPerfCpuData(i); + row.focusHandler = () => this.hoverTip(row, HiPerfCpuStruct.hoverStruct); + row.onThreadHandler = (useCache) => { + let context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + row.canvasSave(context); + (renders["HiPerf-Cpu"] as HiperfCpuRender).renderMainThread( + { + context: context, + useCache: useCache, + scale: TraceRow.range?.scale || 50, + type: `HiPerf-Cpu-${i}`, + maxCpu: (this.maxCpuId + 1), + intervalPerf: SpHiPerf.stringResult?.fValue || 1, + range: TraceRow.range, + }, + row + ); + row.canvasRestore(context); + } + this.trace.rowsEL?.appendChild(row) + } + } + + async initReport() { + this.eventTypeList.forEach((it, index) => { + let fold = TraceRow.skeleton() + fold.rowId = `Perf-Report-${it.id}-${it.report_value}`; + fold.index = index; + fold.rowType = TraceRow.ROW_TYPE_HIPERF_REPORT + fold.rowParentId = 'HiPerf'; + fold.rowHidden = !this.rowFolder.expansion + fold.folder = true; + fold.name = `Event :${it.report_value}`; + fold.folderPaddingLeft = 30; + fold.favoriteChangeHandler = this.trace.favoriteChangeHandler; + fold.selectChangeHandler = this.trace.selectChangeHandler; + fold.supplier = () => queryHiPerfEventListData(it.id); + fold.onThreadHandler = (useCache) => { + let context = fold.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + fold.canvasSave(context); + (renders["HiPerf-Report-Fold"] as HiperfReportRender).renderMainThread( + { + context: context, + useCache: useCache, + scale: TraceRow.range?.scale || 50, + type: `HiPerf-Report-Fold-${it.report_value}-${it.id}`, + maxCpu: (this.maxCpuId + 1), + intervalPerf: SpHiPerf.stringResult?.fValue || 1, + range: TraceRow.range, + }, + fold + ); + fold.canvasRestore(context); + } + this.trace.rowsEL?.appendChild(fold) + for (let i = 0; i <= this.maxCpuId; i++) { + let row = TraceRow.skeleton(); + row.rowId = `HiPerf-Report-Event-${it.report_value}-${i}`; + row.index = i; + row.rowType = TraceRow.ROW_TYPE_HIPERF_EVENT + row.rowParentId = fold.rowId; + row.rowHidden = !fold.expansion + row.folder = false; + row.name = `Cpu ${i}`; + row.style.height = '40px' + row.setAttribute('children', '') + row.favoriteChangeHandler = this.trace.favoriteChangeHandler; + row.selectChangeHandler = this.trace.selectChangeHandler; + row.supplier = () => queryHiPerfEventData(it.id, row.index); + row.focusHandler = () => this.hoverTip(row, HiPerfEventStruct.hoverStruct) + row.onThreadHandler = (useCache) => { + let context = fold.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + fold.canvasSave(context); + (renders["HiPerf-Report-Event"] as HiperfEventRender).renderMainThread( + { + context: context, + useCache: useCache, + scale: TraceRow.range?.scale || 50, + type: `HiPerf-Report-Event-${it.report_value}-${i}`, + maxCpu: (this.maxCpuId + 1), + intervalPerf: SpHiPerf.stringResult?.fValue || 1, + range: TraceRow.range, + }, + row + ); + fold.canvasRestore(context); + } + this.trace.rowsEL?.appendChild(row) + } + }) + } + + async initProcess() { + Reflect.ownKeys(this.group).forEach((key, index) => { + let array = this.group[key] as Array; + let process = array.filter(th => th.pid === th.tid)[0]; + let row = TraceRow.skeleton(); + row.rowId = `${process.pid}-Perf-Process`; + row.index = index; + row.rowType = TraceRow.ROW_TYPE_HIPERF_PROCESS + row.rowParentId = 'HiPerf'; + row.rowHidden = !this.rowFolder.expansion + row.folder = true; + row.name = `${process.processName || 'Process'} [${process.pid}]`; + row.folderPaddingLeft = 30; + row.style.height = '40px' + row.favoriteChangeHandler = this.trace.favoriteChangeHandler; + row.selectChangeHandler = this.trace.selectChangeHandler; + row.supplier = () => queryHiPerfProcessData(process.pid); + row.focusHandler = () => this.hoverTip(row, HiPerfProcessStruct.hoverStruct); + row.onThreadHandler = (useCache) => { + let context = this.trace.canvasPanelCtx!; + row.canvasSave(context); + if (row.expansion) { + this.trace.canvasPanelCtx?.clearRect(0, 0, row.frame.width, row.frame.height); + } else { + (renders["HiPerf-Process"] as HiperfProcessRender).renderMainThread( + { + context: context, + useCache: useCache, + scale: TraceRow.range?.scale || 50, + type: `HiPerf-Process-${row.index}`, + intervalPerf: SpHiPerf.stringResult?.fValue || 1, + range: TraceRow.range, + }, + row + ); + } + row.canvasRestore(context); + } + this.trace.rowsEL?.appendChild(row) + array.forEach((thObj, thIdx) => { + let thread = TraceRow.skeleton() + thread.rowId = `${thObj.tid}-Perf-Thread`; + thread.index = thIdx; + thread.rowType = TraceRow.ROW_TYPE_HIPERF_THREAD + thread.rowParentId = row.rowId; + thread.rowHidden = !row.expansion + thread.folder = false; + thread.name = `${thObj.threadName || 'Thread'} [${thObj.tid}]`; + thread.setAttribute('children', '') + thread.folderPaddingLeft = 30; + thread.style.height = '40px' + thread.favoriteChangeHandler = this.trace.favoriteChangeHandler; + thread.selectChangeHandler = this.trace.selectChangeHandler; + thread.supplier = () => queryHiPerfThreadData(thObj.tid); + thread.focusHandler = () => this.hoverTip(thread, HiPerfThreadStruct.hoverStruct); + thread.onThreadHandler = (useCache) => { + let context = thread.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + thread.canvasSave(context); + (renders["HiPerf-Thread"] as HiperfThreadRender).renderMainThread( + { + context: context, + useCache: useCache, + scale: TraceRow.range?.scale || 50, + type: `HiPerf-Thread-${row.index}-${thread.index}`, + intervalPerf: SpHiPerf.stringResult?.fValue || 1, + range: TraceRow.range, + }, + thread + ); + thread.canvasRestore(context); + } + this.trace.rowsEL?.appendChild(thread) + }); + }) + } + + hoverTip(row: TraceRow, struct: HiPerfThreadStruct | HiPerfProcessStruct | HiPerfEventStruct | HiPerfReportStruct | HiPerfCpuStruct | undefined) { + let tip = ""; + if (struct) { + let num = 0; + if (struct instanceof HiPerfEventStruct) { + num = Math.trunc((struct.sum || 0) / (struct.max || 0) * 100); + } else { + num = Math.trunc((struct.height || 0) / 40 * 100); + } + if (num > 0) { + tip = `${num * (this.maxCpuId + 1)}% (10.00ms)` + } else { + let perfCall = perfDataQuery.callChainMap.get(struct.callchain_id || 0); + tip = `${perfCall ? perfCall.name : ''} (${perfCall ? perfCall.depth : '0'} other frames)` + } + } + this.trace?.displayTip(row, struct, tip) + } +} diff --git a/host/ide/src/trace/component/chart/SpHiSysEventChart.ts b/host/ide/src/trace/component/chart/SpHiSysEventChart.ts new file mode 100644 index 0000000000000000000000000000000000000000..44bbcdee62f9bdd69afe8b8f0bcb56f1684eb294 --- /dev/null +++ b/host/ide/src/trace/component/chart/SpHiSysEventChart.ts @@ -0,0 +1,549 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SpSystemTrace} from "../SpSystemTrace.js"; +import { + queryAnomalyData, + queryConfigSysEventAppName, + queryHisystemEventExits, + queryMaxStateValue, + queryPowerData, + queryStateData, + queryStateInitValue, + querySyseventAppName, + querySystemLocationData, + querySystemLockData, + querySystemSchedulerData +} from "../../database/SqlLite.js"; +import {info} from "../../../log/Log.js"; +import {TraceRow} from "../trace/base/TraceRow.js"; +import {BaseStruct} from "../../bean/BaseStruct.js"; +import {LitPopover} from "../../../base-ui/popover/LitPopoverV.js"; +import {EnergyAnomalyRender, EnergyAnomalyStruct} from "../../database/ui-worker/ProcedureWorkerEnergyAnomaly.js"; +import {EnergySystemStruct, EnergySystemRender} from "../../database/ui-worker/ProcedureWorkerEnergySystem.js"; +import {EnergyPowerStruct, EnergyPowerRender} from "../../database/ui-worker/ProcedureWorkerEnergyPower.js"; +import {EnergyStateStruct, EnergyStateRender} from "../../database/ui-worker/ProcedureWorkerEnergyState.js"; +import {renders} from "../../database/ui-worker/ProcedureWorker.js"; +import {EmptyRender} from "../../database/ui-worker/ProcedureWorkerCPU.js"; + +export class SpHiSysEventChart { + static app_name: string | null + private trace: SpSystemTrace; + private energyTraceRow: TraceRow | undefined; + + constructor(trace: SpSystemTrace) { + this.trace = trace; + } + + async init() { + let result = await queryHisystemEventExits(); + if (result.length <= 0) return; + await this.initEnergyRow(); + await this.initAnomaly(); + await this.initSystem(); + await this.initPower(); + await this.initState(); + } + + private initEnergyRow = async () => { + SpHiSysEventChart.app_name = ''; + let appNameFromTable = await querySyseventAppName(); + let configAppName = await queryConfigSysEventAppName(); + if (configAppName.length > 0 && appNameFromTable.length > 0) { + let name = configAppName[0].process_name + if (name != null) { + let filterList = appNameFromTable.filter(appNameFromTableElement => { + return appNameFromTableElement.string_value?.trim() == name; + }) + if (filterList.length > 0) { + SpHiSysEventChart.app_name = name + } + } + } + if (appNameFromTable.length > 0 && SpHiSysEventChart.app_name == "") { + SpHiSysEventChart.app_name = appNameFromTable[0].string_value; + } + this.energyTraceRow = TraceRow.skeleton(); + let radioList; + let appNameList = this.energyTraceRow?.shadowRoot!.querySelector("#appNameList"); + let addFlag = false; + appNameList?.addEventListener('click', () => { + let itemDiv = appNameList!.querySelector("div"); + if (!addFlag) { + for (let index = 0; index < appNameFromTable.length; index++) { + let div = document.createElement("div"); + div.setAttribute("style", "margin-bottom: 5px"); + let appName = appNameFromTable[index].string_value; + // @ts-ignore + let formatAppName = "appName" + index; + div.setAttribute("id", formatAppName); + div.innerHTML = "" + appName; + itemDiv!.append(div); + this.energyTraceRow!.shadowRoot!.querySelector("#" + formatAppName)!.onclick = (e: any) => { + this.energyTraceRow?.shadowRoot!.querySelectorAll('input[type=radio][name=processoption]')!.forEach(item => { + if (item.checked) { + SpHiSysEventChart.app_name = item.getAttribute("value"); + } + }) + radioList = this.energyTraceRow?.shadowRoot!.querySelectorAll("input[type=radio][name=processoption]"); + if (radioList != undefined) { + for (let index = 0; index < radioList.length; index++) { + if (e.path[0].id == radioList[index]!.getAttribute("app_name")) { + SpHiSysEventChart.app_name = radioList[index]!.getAttribute("value"); + radioList[index]!.checked = true; + } + } + } + // @ts-ignore + appNameList!.visible = false + TraceRow.range!.refresh = true + this.trace.refreshCanvas(false) + } + } + addFlag = true; + } + }) + this.energyTraceRow.rowId = `energy` + this.energyTraceRow.rowType = TraceRow.ROW_TYPE_ENERGY + this.energyTraceRow.rowParentId = ''; + this.energyTraceRow.folder = true; + this.energyTraceRow.name = 'Energy'; + this.energyTraceRow.style.height = '40px' + this.energyTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + this.energyTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + this.energyTraceRow.supplier = () => new Promise>((resolve) => resolve([])); + this.energyTraceRow.onThreadHandler = (useCache) => { + this.energyTraceRow?.canvasSave(this.trace.canvasPanelCtx!); + if(this.energyTraceRow!.expansion){ + this.trace.canvasPanelCtx?.clearRect(0, 0, this.energyTraceRow!.frame.width, this.energyTraceRow!.frame.height); + } else { + (renders["empty"] as EmptyRender).renderMainThread( + { + context: this.trace.canvasPanelCtx, + useCache: useCache, + type: ``, + }, + this.energyTraceRow!, + ); + } + this.energyTraceRow?.canvasRestore(this.trace.canvasPanelCtx!); + } + this.trace.rowsEL?.appendChild(this.energyTraceRow!) + } + + private initAnomaly = async () => { + let time = new Date().getTime() + let anomalyTraceRow = TraceRow.skeleton(); + anomalyTraceRow.rowParentId = `energy` + anomalyTraceRow.rowHidden = true + anomalyTraceRow.rowId = "energy-anomaly" + anomalyTraceRow.rowType = TraceRow.ROW_TYPE_ANOMALY_ENERGY + anomalyTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + anomalyTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + anomalyTraceRow.setAttribute("height", `55px`); + let element = anomalyTraceRow.shadowRoot?.querySelector(".root") as HTMLDivElement; + element!.style.height = `55px`; + anomalyTraceRow.style.width = `100%`; + anomalyTraceRow.setAttribute('children', ''); + anomalyTraceRow.name = "Anomaly Event"; + anomalyTraceRow.supplier = () => queryAnomalyData() + anomalyTraceRow.focusHandler = ()=>{ + this.trace?.displayTip(anomalyTraceRow, EnergyAnomalyStruct.hoverEnergyAnomalyStruct, `AnomalyName:${EnergyAnomalyStruct.hoverEnergyAnomalyStruct?.eventName||""}`); + } + anomalyTraceRow.onThreadHandler = (useCache) => { + let context = anomalyTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + anomalyTraceRow.canvasSave( context); + (renders["energyAnomaly"] as EnergyAnomalyRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `energyAnomaly`, + appName:SpHiSysEventChart.app_name||"", + canvasWidth:this.trace.canvasPanel?.width||0 + }, + anomalyTraceRow + ); + anomalyTraceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(anomalyTraceRow) + let durTime = new Date().getTime() - time; + info('The time to load the anomaly is: ', durTime) + } + + private initSystem = async () => { + let time = new Date().getTime() + let systemTraceRow = TraceRow.skeleton(); + systemTraceRow.rowParentId = `energy` + systemTraceRow.rowHidden = true + systemTraceRow.rowId = "energy-system" + systemTraceRow.rowType = TraceRow.ROW_TYPE_SYSTEM_ENERGY + systemTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + systemTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + systemTraceRow.setAttribute("height", `80px`); + let element = systemTraceRow.shadowRoot?.querySelector(".root") as HTMLDivElement; + element!.style.height = `90px`; + systemTraceRow.style.width = `100%`; + systemTraceRow.setAttribute('children', ''); + systemTraceRow.name = "System Event"; + systemTraceRow.supplier = () => Promise.all([querySystemLocationData(), querySystemLockData(), querySystemSchedulerData()]).then(result => { + return this.getSystemData(result) + }) + systemTraceRow.focusHandler = ()=>{ + this.trace?.displayTip(systemTraceRow, EnergySystemStruct.hoverEnergySystemStruct, `
+
WORKSCHEDULER:
${EnergySystemStruct.hoverEnergySystemStruct?.workScheduler! || 0}
+
POWER_RUNNINGLOCK:
${EnergySystemStruct.hoverEnergySystemStruct?.power! || 0}
+
LOCATION:
${EnergySystemStruct.hoverEnergySystemStruct?.location! || 0}
+
`); + } + systemTraceRow.onThreadHandler = (useCache) => { + let context = systemTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + systemTraceRow.canvasSave( context); + (renders["energySystem"] as EnergySystemRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `energySystem`, + }, + systemTraceRow + ); + systemTraceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(systemTraceRow) + let durTime = new Date().getTime() - time; + info('The time to load the Ability Memory is: ', durTime) + } + + getSystemData(result: any): Promise { + let systemDataList: any = {}; + if(result.length == 0){ + return Promise.resolve([]); + } + systemDataList[0] = this.handleLockData(result) + systemDataList[1] = this.handleLocationData(result) + systemDataList[2] = this.handleWorkData(result); + return systemDataList + } + + private handleLocationData(result: Array>){ + let locationIndex = -1; + let locationCount = 0; + let locationData: any[] = []; + result[0].forEach((item: any) => { + let da: any = {} + if (item.Value == "stop") { + if (locationIndex == -1) { + da.startNs = 0 + da.count = 1 + } else { + da.startNs = item.ts + locationCount--; + da.count = locationCount + } + da.state = "stop" + } else { + da.startNs = item.ts + locationCount++; + da.count = locationCount + da.state = "start" + } + locationIndex = 0 + da.type = 2 + locationData.push(da) + }) + return locationData + } + + private handleLockData(result: Array>){ + let lockCount = 0 + let tokedIds: Array = [] + let lockData: any[] = [] + result[1].forEach((item: any) => { + let running: any = {} + let split = item.Value.split(","); + if (item.Value.indexOf("ADD") > -1) { + running.startNs = item.ts + lockCount++; + running.count = lockCount + running.token = split[0].split("=")[1] + running.type = 1 + tokedIds.push(running.token) + lockData.push(running) + } else { + running.startNs = item.ts + let toked = split[0].split("=")[1]; + let number = tokedIds.indexOf(toked); + if(number > -1){ + lockCount--; + running.count = lockCount + running.token = split[0].split("=")[1] + running.type = 1 + lockData.push(running) + delete tokedIds[number] + } + } + }) + + return lockData + } + + private handleWorkData(result: Array>) { + let workDataArray = result[2]; + let workCountMap: Map = new Map(); + let nameIdMap: Map> = new Map(); + let workData: any[] = [] + for (let i = 0; i < workDataArray.length; i++) { + let dd: any = {} + let item = workDataArray[i]; + let keys = item.appKey.split(","); + let values = item.Value.split(",") + for (let j = 0; j < keys.length; j++) { + let key = keys[j] + switch (key) { + case "NAME": + dd.appName = values[j] + break; + case "WORKID": + dd.workId = values[j] + break; + } + } + if (item.eventName == "WORK_START") { + let nameIdList = nameIdMap.get(dd.appName); + let workCount = 0; + if (nameIdList == undefined) { + workCount = 1; + nameIdMap.set(dd.appName, [dd.workId]) + } else { + nameIdList.push(dd.workId) + workCount = nameIdList.length; + } + let count = workCountMap.get(dd.appName) + if (count == undefined) { + workCountMap.set(dd.appName, 1); + } else { + workCountMap.set(dd.appName, count + 1); + } + dd.startNs = item.ts + dd.count = workCount; + dd.type = 0 + workData.push(dd) + } else if (item.eventName == "WORK_STOP") { + let nameIdList: any = nameIdMap.get(dd.appName); + let index = nameIdList.indexOf(dd.workId); + if (nameIdList != undefined && index> -1) { + delete nameIdList[index]; + let workCount = workCountMap.get(dd.appName) + if (workCount != undefined) { + workCount = workCount - 1; + workCountMap.set(dd.appName, workCount) + dd.startNs = item.startNS; + dd.count = workCount; + dd.type = 0 + workData.push(dd) + } + } + } + } + return workData + } + + private initPower = async () => { + let time = new Date().getTime(); + let powerTraceRow = TraceRow.skeleton(); + powerTraceRow.rowParentId = `energy` + powerTraceRow.rowHidden = true + powerTraceRow.rowId = "energy-power" + powerTraceRow.rowType = TraceRow.ROW_TYPE_POWER_ENERGY + powerTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + powerTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + powerTraceRow.setAttribute("height", `200px`); + let element = powerTraceRow.shadowRoot?.querySelector(".root") as HTMLDivElement; + element!.style.height = `200px`; + powerTraceRow.style.width = `100%`; + powerTraceRow.setAttribute('children', ''); + powerTraceRow.name = "Power" + powerTraceRow.supplier = () => queryPowerData().then(items => { + return this.getPowerData(items) + }) + powerTraceRow.focusHandler = ()=>{ + this.trace?.displayTip(powerTraceRow, EnergyPowerStruct.hoverEnergyPowerStruct, `
+
CPU:
${EnergyPowerStruct.hoverEnergyPowerStruct?.cpu! || 0}
+
location:
${EnergyPowerStruct.hoverEnergyPowerStruct?.location! || 0}
+
GPU:
${EnergyPowerStruct.hoverEnergyPowerStruct?.gpu! || 0}
+
display:
${EnergyPowerStruct.hoverEnergyPowerStruct?.display! || 0}
+
camera:
${EnergyPowerStruct.hoverEnergyPowerStruct?.camera! || 0}
+
bluetooth:
${EnergyPowerStruct.hoverEnergyPowerStruct?.bluetooth! || 0}
+
flashlight:
${EnergyPowerStruct.hoverEnergyPowerStruct?.flashlight! || 0}
+
audio:
${EnergyPowerStruct.hoverEnergyPowerStruct?.audio! || 0}
+
wifiScan:
${EnergyPowerStruct.hoverEnergyPowerStruct?.wifiscan! || 0}
+
`); + } + powerTraceRow.onThreadHandler = (useCache) => { + let context = powerTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + powerTraceRow.canvasSave( context); + (renders["energyPower"] as EnergyPowerRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `energyPower`, + appName:SpHiSysEventChart.app_name||"" + }, + powerTraceRow + ); + powerTraceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(powerTraceRow) + let durTime = new Date().getTime() - time; + info('The time to load the energy power is: ', durTime) + } + + async getPowerData(items: any): Promise { + let powerDataMap: any = {} + let appNameList: any = [] + items.forEach((item: any) => { + let dataItem = powerDataMap[item.startNS] + if (dataItem == undefined) { + if (item.appKey == "APPNAME") { + let appMap: any = {}; + let appNames = item.eventValue.split(",") + appNameList = appNames; + if (appNames.length > 0) { + for (let appNamesKey of appNames) { + appMap[appNamesKey] = new EnergyPowerStruct() + appMap[appNamesKey].name = appNamesKey + appMap[appNamesKey].ts = item.startNS + } + powerDataMap[item.startNS] = appMap; + } + } + } else { + if (item.appKey != "APPNAME") { + let values = item.eventValue.split(",") + for (let i = 0; i < values.length; i++) { + let appName = appNameList[i] + let obj = dataItem[appName] + if (obj != undefined) { + let eventName = item.eventName.split("_"); + let s = eventName[eventName.length - 1].toLocaleLowerCase(); + if (obj[s] == undefined) { + obj[s] = parseInt(values[i]) + } else { + obj[s] += parseInt(values[i]) + } + } + } + } else { + let dataMap = powerDataMap[item.startNS]; + let appNames = item.eventValue.split(",") + appNameList = appNames; + if (appNames.length > 0) { + for (let appNamesKey of appNames) { + dataMap[appNamesKey] = new EnergyPowerStruct() + dataMap[appNamesKey].name = appNamesKey + dataMap[appNamesKey].ts = item.startNS + } + } + } + } + }) + return Object.values(powerDataMap) + } + + + private initState = async () => { + let time = new Date().getTime(); + let stateList = ["Brightness Nit", "Signal Level", "Wifi Event Received", "Audio Stream Change", + "Audio Volume Change", "Wifi State", "Bluetooth Br Switch State", "Location Switch State", "Sensor State"] + let stateName = ["BRIGHTNESS_NIT", "SIGNAL_LEVEL", "WIFI_EVENT_RECEIVED", "AUDIO_STREAM_CHANGE", + "AUDIO_VOLUME_CHANGE", "WIFI_STATE", "BLUETOOTH_BR_SWITCH_STATE", "LOCATION_SWITCH_STATE", "SENSOR_STATE"] + let initValueList = ["brightness", "nocolumn", "nocolumn", "nocolumn", "nocolumn", "wifi", "bt_state", "location", "nocolumn"] + + for (let index = 0; index < stateList.length; index++) { + let maxStateData = await queryMaxStateValue(stateName[index]) + if (!maxStateData[0]) { + continue; + } + let maxStateTotal = maxStateData[0].maxValue.toString() + if (maxStateData[0].type.toLocaleLowerCase().includes("state") && maxStateData[0].type.toLocaleLowerCase() != ("bluetooth_br_switch_state")) { + if (maxStateData[0].maxValue == 0) { + maxStateTotal = "enable" + } else { + maxStateTotal = "disable" + } + } + let stateTraceRow = TraceRow.skeleton(); + stateTraceRow.rowParentId = `energy` + stateTraceRow.rowHidden = true + stateTraceRow.rowId = "energy-state" + stateTraceRow.rowType = TraceRow.ROW_TYPE_STATE_ENERGY + stateTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + stateTraceRow.selectChangeHandler = this.trace.selectChangeHandler; + stateTraceRow.style.height = '40px' + stateTraceRow.style.width = `100%`; + stateTraceRow.setAttribute('children', ''); + stateTraceRow.name = `${stateList[index]}` + stateTraceRow.supplier = () => Promise.all([queryStateInitValue(stateName[index], initValueList[index]), queryStateData(stateName[index])]).then(result => { + let stateInitValue = initValueList[index] == "nocolumn" ? [] : result[0]; + return stateInitValue.concat(result[1]); + }) + stateTraceRow.focusHandler = ()=>{ + let tip = ""; + if (EnergyStateStruct.hoverEnergyStateStruct?.type!.toLocaleLowerCase().includes("state")) { + tip = `Switch Status: ${EnergyStateStruct.hoverEnergyStateStruct?.value == 1 ? 'disable' : 'enable'}` + if (EnergyStateStruct.hoverEnergyStateStruct?.type!.toLocaleLowerCase() == "bluetooth_br_switch_state") { + tip = `${SpHiSysEventChart.getBlueToothState(EnergyStateStruct.hoverEnergyStateStruct?.value)}` + } + } else { + tip = `value: ${EnergyStateStruct.hoverEnergyStateStruct?.value || 0}` + } + this.trace?.displayTip(stateTraceRow, EnergyStateStruct.hoverEnergyStateStruct, tip); + } + stateTraceRow.onThreadHandler = (useCache) => { + let context = stateTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + stateTraceRow.canvasSave( context); + (renders["energyState"] as EnergyStateRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `energyState${index}`, + maxState: maxStateData[0].maxValue, + maxStateName: maxStateData[0].type.toLocaleLowerCase() == ("bluetooth_br_switch_state")? "-1" : maxStateTotal.toString() + }, + stateTraceRow + ); + stateTraceRow.canvasRestore( context); + } + this.trace.rowsEL?.appendChild(stateTraceRow) + let durTime = new Date().getTime() - time; + info('The time to load the Ability Memory is: ', durTime) + } + } + + public static getBlueToothState(num: number | undefined): string{ + switch (num) { + case 0: + return "STATE_TURNING_ON"; + case 1: + return "STATE_TURN_ON"; + case 2: + return "STATE_TURNING_OFF"; + case 3: + return "STATE_TURN_OFF"; + default: + return "UNKNOWN_STATE"; + } + } +} diff --git a/host/ide/src/trace/component/chart/SpNativeMemoryChart.ts b/host/ide/src/trace/component/chart/SpNativeMemoryChart.ts new file mode 100644 index 0000000000000000000000000000000000000000..3c023b7098c1279c3192ea172ffeffef1f3b52c6 --- /dev/null +++ b/host/ide/src/trace/component/chart/SpNativeMemoryChart.ts @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SpSystemTrace} from "../SpSystemTrace.js"; +import { + queryBootTime, + queryHeapGroupByEvent, + queryNativeHookProcess, + queryNativeMemoryRealTime +} from "../../database/SqlLite.js"; +import {TraceRow} from "../trace/base/TraceRow.js"; +import {info} from "../../../log/Log.js"; +import {procedurePool} from "../../database/Procedure.js"; +import {NativeEventHeap} from "../../bean/NativeHook.js"; +import {HeapRender, HeapStruct} from "../../database/ui-worker/ProcedureWorkerHeap.js"; +import {Utils} from "../trace/base/Utils.js"; +import {renders} from "../../database/ui-worker/ProcedureWorker.js"; +import {EmptyRender} from "../../database/ui-worker/ProcedureWorkerCPU.js"; + +export class SpNativeMemoryChart { + static EVENT_HEAP: Array = []; + static REAL_TIME_DIF:number = 0; + private trace: SpSystemTrace; + + constructor(trace: SpSystemTrace) { + this.trace = trace; + } + + initChart = async () => { + let time = new Date().getTime(); + let nativeProcess = await queryNativeHookProcess(); + info("NativeHook Process data size is: ", nativeProcess!.length) + if (nativeProcess.length == 0) { + return; + } + SpNativeMemoryChart.EVENT_HEAP = await queryHeapGroupByEvent(); + let nativeRow = TraceRow.skeleton(); + let process = ""; + if (nativeProcess.length > 0) { + process = ` ${nativeProcess[0].pid}` + } + nativeRow.rowId = `native-memory` + nativeRow.index = 0; + nativeRow.rowType = TraceRow.ROW_TYPE_NATIVE_MEMORY + nativeRow.drawType = 0; + nativeRow.style.height = '40px' + nativeRow.rowParentId = ''; + nativeRow.folder = true; + nativeRow.name = `Native Memory` + process; + nativeRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + nativeRow.selectChangeHandler = this.trace.selectChangeHandler; + nativeRow.onDrawTypeChangeHandler = (type) => { + this.trace.rowsEL?.querySelectorAll>(`trace-row[row-type='heap']`).forEach(it => { + it.drawType = type; + this.trace.refreshCanvas(false) + }) + }; + nativeRow.supplier = () => new Promise>((resolve) => resolve([])); + nativeRow.onThreadHandler = (useCache) => { + nativeRow.canvasSave(this.trace.canvasPanelCtx!); + if(nativeRow.expansion){ + this.trace.canvasPanelCtx?.clearRect(0, 0, nativeRow.frame.width, nativeRow.frame.height); + }else{ + (renders["empty"] as EmptyRender).renderMainThread( + { + context: this.trace.canvasPanelCtx, + useCache: useCache, + type: ``, + }, + nativeRow, + ); + } + nativeRow.canvasRestore(this.trace.canvasPanelCtx!); + } + this.trace.rowsEL?.appendChild(nativeRow) + /** + * 添加heap信息 + */ + let native_memory = ["All Heap & Anonymous VM", "All Heap", "All Anonymous VM"]; + for (let i = 0; i < native_memory.length; i++) { + let nm = native_memory[i]; + let allHeapRow = TraceRow.skeleton(); + allHeapRow.index = i; + allHeapRow.rowParentId = `native-memory` + allHeapRow.rowHidden = !nativeRow.expansion + allHeapRow.style.height = '40px' + allHeapRow.name = nm; + allHeapRow.rowId = nm; + allHeapRow.drawType = 0; + allHeapRow.isHover = true; + allHeapRow.folder = false; + allHeapRow.rowType = TraceRow.ROW_TYPE_HEAP; + allHeapRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + allHeapRow.selectChangeHandler = this.trace.selectChangeHandler; + allHeapRow.setAttribute('children', '') + allHeapRow.focusHandler = () =>{ + let tip = ''; + if (HeapStruct.hoverHeapStruct) { + if (allHeapRow.drawType === 1) { + tip = `${HeapStruct.hoverHeapStruct.density}` + } else { + tip = `${Utils.getByteWithUnit(HeapStruct.hoverHeapStruct.heapsize!)}` + } + } + this.trace?.displayTip(allHeapRow,HeapStruct.hoverHeapStruct,tip) + } + allHeapRow.supplier = () => { + return this.getNativeMemoryDataByChartType(i, allHeapRow.drawType) + } + allHeapRow.onThreadHandler = (useCache) => { + let context = allHeapRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + allHeapRow.canvasSave(context); + (renders["heap"] as HeapRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `heap`, + }, + allHeapRow + ); + allHeapRow.canvasRestore(context); + } + this.trace.rowsEL?.appendChild(allHeapRow) + } + let durTime = new Date().getTime() - time; + info('The time to load the Native Memory data is: ', durTime) + } + + getNativeMemoryDataByChartType = async (nativeMemoryType: number, chartType: number): Promise> => { + let args = new Map(); + args.set("nativeMemoryType",nativeMemoryType); + args.set("chartType",chartType); + args.set("totalNS",TraceRow.range?.totalNS!); + args.set("actionType","memory-chart"); + let arr:Array = []; + await new Promise>((resolve, reject) => { + procedurePool.submitWithName("logic1","native-memory-chart-action",args,undefined,(res:any)=>{ + arr = arr.concat(res.data) + res.data = null; + if(res.tag == "end"){ + resolve(arr) + } + }) + }) + return arr; + } + + initNativeMemory = async () => { + let time = new Date().getTime(); + let isRealtime = false; + let realTimeDif = 0; + SpNativeMemoryChart.REAL_TIME_DIF = 0; + let queryTime = await queryNativeMemoryRealTime(); + let bootTime = await queryBootTime(); + if(queryTime.length > 0){ + isRealtime = queryTime[0].clock_name == "realtime" + } + if(bootTime.length > 0&&isRealtime){ + realTimeDif = queryTime[0].ts - bootTime[0].ts + SpNativeMemoryChart.REAL_TIME_DIF = realTimeDif; + } + await new Promise((resolve, reject) => { + procedurePool.submitWithName("logic1","native-memory-init",{isRealtime,realTimeDif},undefined,(res:any)=>{ + resolve(res) + }) + }) + let durTime = new Date().getTime() - time; + info('The time to init the native memory data is: ', durTime) + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/chart/SpProcessChart.ts b/host/ide/src/trace/component/chart/SpProcessChart.ts new file mode 100644 index 0000000000000000000000000000000000000000..bf39f42a6b87444e0f1c18816a62c8f7047429d9 --- /dev/null +++ b/host/ide/src/trace/component/chart/SpProcessChart.ts @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SpSystemTrace} from "../SpSystemTrace.js"; +import { + getAsyncEvents, + getFunDataByTid, getMaxDepthByTid, + queryEventCountMap, + queryProcess, + queryProcessAsyncFunc, + queryProcessByTable, queryProcessContentCount, + queryProcessData, + queryProcessMem, + queryProcessMemData, + queryProcessThreads, + queryProcessThreadsByTable, + queryThreadData +} from "../../database/SqlLite.js"; +import {Utils} from "../trace/base/Utils.js"; +import {info} from "../../../log/Log.js"; +import {TraceRow} from "../trace/base/TraceRow.js"; +import {renders} from "../../database/ui-worker/ProcedureWorker.js"; +import {ProcessRender, ProcessStruct} from "../../database/ui-worker/ProcedureWorkerProcess.js"; +import {ThreadRender, ThreadStruct} from "../../database/ui-worker/ProcedureWorkerThread.js"; +import {FuncRender, FuncStruct} from "../../database/ui-worker/ProcedureWorkerFunc.js"; +import {MemRender, ProcessMemStruct} from "../../database/ui-worker/ProcedureWorkerMem.js"; + +export class SpProcessChart { + private trace: SpSystemTrace; + private processAsyncFuncMap: any = {} + private eventCountMap: any; + private processThreads: Array = [] + private processAsyncEvent: Array = [] + private processMem: Array = [] + private processThreadDataCountMap: Map = new Map(); + private processFuncDataCountMap: Map = new Map(); + private processMemDataCountMap: Map = new Map(); + private threadFuncMaxDepthMap: Map = new Map(); + + constructor(trace: SpSystemTrace) { + this.trace = trace; + } + + initAsyncFuncData = async () => { + let asyncFuncList: any[] = await queryProcessAsyncFunc(); + info("AsyncFuncData Count is: ", asyncFuncList!.length) + this.processAsyncFuncMap = Utils.groupBy(asyncFuncList, "pid"); + } + + async init() { + let threadFuncMaxDepthArray = await getMaxDepthByTid(); + threadFuncMaxDepthArray.forEach((it)=>{ + this.threadFuncMaxDepthMap.set(it.tid,it.maxDepth) + }) + let pidCountArray = await queryProcessContentCount(); + pidCountArray.forEach(it => { + this.processThreadDataCountMap.set(it.pid, it.switch_count); + this.processFuncDataCountMap.set(it.pid, it.slice_count); + this.processMemDataCountMap.set(it.pid, it.mem_count); + }) + let queryProcessThreadResult = await queryProcessThreads(); + let queryProcessThreadsByTableResult = await queryProcessThreadsByTable() + this.processAsyncEvent = await getAsyncEvents(); + info("The amount of initialized process Event data is : ", this.processAsyncEvent!.length) + this.processMem = await queryProcessMem(); + info("The amount of initialized process memory data is : ", this.processMem!.length) + let eventCountList: Array = await queryEventCountMap(); + this.eventCountMap = eventCountList.reduce((pre, current) => { + pre[`${current.eventName}`] = current.count; + return pre; + }, {}); + this.processThreads = Utils.removeDuplicates(queryProcessThreadResult, queryProcessThreadsByTableResult, "tid") + + info("The amount of initialized process threads data is : ", this.processThreads!.length) + if (this.eventCountMap["print"] == 0 && + this.eventCountMap["tracing_mark_write"] == 0 && + this.eventCountMap["sched_switch"] == 0) { + return; + } + let time = new Date().getTime(); + let processes = await queryProcess(); + let processFromTable = await queryProcessByTable(); + let processList = Utils.removeDuplicates(processes, processFromTable, "pid") + info("ProcessList Data size is: ", processList!.length) + for (let i = 0; i < processList.length; i++) { + const it = processList[i]; + if ((this.processThreadDataCountMap.get(it.pid) || 0) == 0 && + (this.processFuncDataCountMap.get(it.pid) || 0) == 0 && + (this.processMemDataCountMap.get(it.pid) || 0) == 0) { + continue; + } + let processRow = TraceRow.skeleton(); + processRow.rowId = `${it.pid}` + processRow.index = i; + processRow.rowType = TraceRow.ROW_TYPE_PROCESS + processRow.rowParentId = ''; + processRow.style.height = "40px"; + processRow.folder = true; + processRow.name = `${it.processName || "Process"} ${it.pid}`; + processRow.supplier = () => queryProcessData(it.pid || -1, 0, TraceRow.range?.totalNS || 0); + processRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + processRow.selectChangeHandler = this.trace.selectChangeHandler; + processRow.onThreadHandler = (useCache) => { + processRow.canvasSave(this.trace.canvasPanelCtx!); + if(processRow.expansion){ + this.trace.canvasPanelCtx?.clearRect(0, 0, processRow.frame.width, processRow.frame.height); + }else{ + (renders["process"] as ProcessRender).renderMainThread( + { + context: this.trace.canvasPanelCtx, + pid: it.pid, + useCache: useCache, + type: `process ${processRow.index} ${it.processName}`, + }, + processRow, + ); + } + processRow.canvasRestore(this.trace.canvasPanelCtx!); + } + this.trace.rowsEL?.appendChild(processRow) + /** + * Async Function + */ + let asyncFuncList = this.processAsyncFuncMap[it.pid] || []; + let asyncFuncGroup = Utils.groupBy(asyncFuncList, "funName"); + Reflect.ownKeys(asyncFuncGroup).map((key: any) => { + let asyncFunctions: Array = asyncFuncGroup[key]; + if (asyncFunctions.length > 0) { + let isIntersect = (a: any, b: any) => (Math.max(a.startTs + a.dur, b.startTs + b.dur) - Math.min(a.startTs, b.startTs) < a.dur + b.dur); + let depthArray: any = [] + let createDepth = (currentDepth: number, index: number) => { + if (depthArray[currentDepth] == undefined || !isIntersect(depthArray[currentDepth], asyncFunctions[index])) { + asyncFunctions[index].depth = currentDepth; + depthArray[currentDepth] = asyncFunctions[index] + } else { + createDepth(++currentDepth, index) + } + } + asyncFunctions.forEach((it, i) => { + if (it.dur == -1) { + it.dur = (TraceRow.range?.endNS || 0) - it.startTs; + it.flag = "Did not end" + } + createDepth(0, i); + }); + let max = Math.max(...asyncFunctions.map(it => it.depth || 0)) + 1 + let maxHeight = max * 20; + let funcRow = TraceRow.skeleton(); + funcRow.rowId = `${asyncFunctions[0].funName}-${it.pid}` + funcRow.asyncFuncName = asyncFunctions[0].funName; + funcRow.asyncFuncNamePID = it.pid; + funcRow.rowType = TraceRow.ROW_TYPE_FUNC + funcRow.rowParentId = `${it.pid}` + funcRow.rowHidden = !processRow.expansion + funcRow.style.width = `100%`; + funcRow.style.height = `${maxHeight}px` + funcRow.setAttribute("height", `${maxHeight}`); + funcRow.name = `${asyncFunctions[0].funName}`; + funcRow.setAttribute('children', '') + funcRow.supplier = () => new Promise((resolve) => resolve(asyncFunctions)) + funcRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + funcRow.selectChangeHandler = this.trace.selectChangeHandler; + funcRow.onThreadHandler = (useCache) => { + let context = funcRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + funcRow.canvasSave(context); + (renders["func"] as FuncRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `func-${asyncFunctions[0].funName}-${it.pid}`, + }, + funcRow + ); + funcRow.canvasRestore(context); + } + this.trace.rowsEL?.appendChild(funcRow); + } + }); + + /** + * 添加进程内存信息 + */ + let processMem = this.processMem.filter(mem => mem.pid === it.pid); + processMem.forEach(mem => { + let row = TraceRow.skeleton(); + row.rowId = `${mem.trackId}` + row.rowType = TraceRow.ROW_TYPE_MEM + row.rowParentId = `${it.pid}` + row.rowHidden = !processRow.expansion + row.style.height = '40px' + row.style.width = `100%`; + row.name = `${mem.trackName}`; + row.setAttribute('children', ''); + row.favoriteChangeHandler = this.trace.favoriteChangeHandler; + row.selectChangeHandler = this.trace.selectChangeHandler; + row.focusHandler = ()=>{ + this.trace.displayTip(row, ProcessMemStruct.hoverProcessMemStruct, `${ProcessMemStruct.hoverProcessMemStruct?.value||""}`); + } + row.supplier = () => queryProcessMemData(mem.trackId).then(res => { + let maxValue = Math.max(...res.map(it => it.value || 0)) + for (let j = 0; j < res.length; j++) { + res[j].maxValue = maxValue; + if (j == res.length - 1) { + res[j].duration = (TraceRow.range?.totalNS || 0) - (res[j].startTime || 0); + } else { + res[j].duration = (res[j + 1].startTime || 0) - (res[j].startTime || 0); + } + if (j > 0) { + res[j].delta = (res[j].value || 0) - (res[j - 1].value || 0); + } else { + res[j].delta = 0; + } + } + return res + }); + row.onThreadHandler = (useCache) => { + let context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + row.canvasSave(context); + (renders["mem"] as MemRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `mem ${mem.trackId} ${mem.trackName}`, + }, + row + ); + row.canvasRestore(context); + } + this.trace.rowsEL?.appendChild(row) + }); + /** + * add thread list + */ + let threads = this.processThreads.filter(thread => thread.pid === it.pid && thread.tid != 0); + for (let j = 0; j < threads.length; j++) { + let thread = threads[j]; + let threadRow = TraceRow.skeleton(); + threadRow.rowId = `${thread.tid}` + threadRow.rowType = TraceRow.ROW_TYPE_THREAD + threadRow.rowParentId = `${it.pid}` + threadRow.rowHidden = !processRow.expansion + threadRow.index = j + threadRow.style.height = '30px' + threadRow.style.width = `100%`; + threadRow.name = `${thread.threadName || 'Thread'} ${thread.tid}`; + threadRow.setAttribute('children', '') + threadRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + threadRow.selectChangeHandler = this.trace.selectChangeHandler; + threadRow.supplier = () => queryThreadData(thread.tid || 0).then(res=>{ + if (res.length <= 0) { + threadRow.rowDiscard = true; + this.trace.refreshCanvas(true) + } + return res; + }) + threadRow.focusHandler = ev => { + } + threadRow.onThreadHandler = (useCache) => { + let context = threadRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + threadRow.canvasSave(context); + (renders["thread"] as ThreadRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `thread ${thread.tid} ${thread.threadName}`, + }, + threadRow + ); + threadRow.canvasRestore(context); + } + if (threadRow.rowId == threadRow.rowParentId) { + this.insertAfter(threadRow, processRow) + } else { + this.trace.rowsEL?.appendChild(threadRow) + } + if(this.threadFuncMaxDepthMap.get(thread.tid!)!=undefined){ + let max = this.threadFuncMaxDepthMap.get(thread.tid!)||1; + let maxHeight = max * 20; + let funcRow = TraceRow.skeleton(); + funcRow.rowId = `${thread.tid}` + funcRow.rowType = TraceRow.ROW_TYPE_FUNC + funcRow.rowParentId = `${it.pid}` + funcRow.rowHidden = !processRow.expansion + funcRow.checkType = threadRow.checkType; + funcRow.style.width = `100%`; + funcRow.style.height = `${maxHeight}px`; + funcRow.name = `${thread.threadName || 'Thread'} ${thread.tid}`; + funcRow.setAttribute('children', '') + funcRow.supplier = () => getFunDataByTid(thread.tid || 0).then((funs: Array)=>{ + if (funs.length > 0) { + let isBinder = (data: FuncStruct): boolean => { + return data.funName != null && ( + data.funName.toLowerCase().startsWith("binder transaction async") //binder transaction + || data.funName.toLowerCase().startsWith("binder async") + || data.funName.toLowerCase().startsWith("binder reply") + ); + } + funs.forEach(fun => { + if (isBinder(fun)) { + } else { + if (fun.dur == -1) { + fun.dur = (TraceRow.range?.totalNS || 0) - (fun.startTs || 0); + fun.flag = "Did not end"; + } + } + }) + }else{ + funcRow.rowDiscard = true; + this.trace.refreshCanvas(true) + } + return funs + }) + funcRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + funcRow.selectChangeHandler = this.trace.selectChangeHandler; + funcRow.onThreadHandler = (useCache) => { + let context = funcRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + funcRow.canvasSave(context); + (renders["func"] as FuncRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `func${thread.tid}${thread.threadName}`, + }, + funcRow + ); + funcRow.canvasRestore(context); + } + this.insertAfter(funcRow, threadRow) + } + } + } + let durTime = new Date().getTime() - time; + info('The time to load the Process data is: ', durTime) + } + + insertAfter(newEl: HTMLElement, targetEl: HTMLElement) { + let parentEl = targetEl.parentNode; + if (parentEl!.lastChild == targetEl) { + parentEl!.appendChild(newEl); + } else { + parentEl!.insertBefore(newEl, targetEl.nextSibling); + } + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/chart/SpSdkChart.ts b/host/ide/src/trace/component/chart/SpSdkChart.ts new file mode 100644 index 0000000000000000000000000000000000000000..3f9f38c09e47c25da40eddfa05e0c3c739901150 --- /dev/null +++ b/host/ide/src/trace/component/chart/SpSdkChart.ts @@ -0,0 +1,355 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SpSystemTrace} from "../SpSystemTrace.js"; +import {TraceRow} from "../trace/base/TraceRow.js"; + +import {BaseStruct} from "../../bean/BaseStruct.js"; +import { + queryCounterMax, + querySdkCount, + querySdkCounterData, + querySdkSliceData, + queryStartTime, +} from "../../database/SqlLite.js"; +import {CounterStruct, SdkCounterRender} from "../../database/ui-worker/ProduceWorkerSdkCounter.js"; +import {renders} from "../../database/ui-worker/ProcedureWorker.js"; +import {SdkSliceRender, SdkSliceStruct} from "../../database/ui-worker/ProduceWorkerSdkSlice.js"; +import {EmptyRender} from "../../database/ui-worker/ProcedureWorkerCPU.js"; + +export class SpSdkChart { + private trace: SpSystemTrace; + private pluginName = "dubai-plugin" + + constructor(trace: SpSystemTrace) { + this.trace = trace; + } + + parseJson(startTime: number, map: Map) { + let tablesMap = new Map(); + let keys = map.keys(); + for (let key of keys) { + let table = [] + let configObj: any = map.get(key); + if (configObj != undefined) { + let configStr = configObj.jsonConfig; + let json = JSON.parse(configStr); + let tableConfig = json.tableConfig + if (tableConfig != null) { + let showTypes = tableConfig.showType; + for (let i = 0; i < showTypes.length; i++) { + let showType = showTypes[i]; + let type = this.getTableType(showType); + if (type == "counter") { + let chartSql = this.createSql(startTime, showType.tableName, showType.columns, "where counter_id" + + " = $counter_id"); + let maxValue = this.createMaxValueSql(showType.tableName, "where counter_id = $counter_id"); + let innerTable = showType.inner; + let countSql = this.createSql(startTime, innerTable.tableName, innerTable.columns); + table.push({ + countSql: countSql, + chartSql: chartSql, + maxSql: maxValue, + type: "counter", + name: configObj.disPlayName, + pluginName: configObj.pluginName + }) + } else if (type == "slice") { + let chartSql = this.createSliceSql(startTime, showType.tableName, showType.columns, "where" + + " slice_id = $column_id and (start_ts - " + startTime + ") between $startNS and $endNS;"); + let innerTable = showType.inner; + let countSql; + let countOtherSql = ""; + if (configObj.pluginName == this.pluginName) { + countSql = this.createSql(startTime, innerTable.tableName, innerTable.columns, "where slice_name like $suffix"); + countOtherSql = this.createSql(startTime, innerTable.tableName, innerTable.columns, "" + + "where slice_name not like '%_cpu' and slice_name not like '%_display' and slice_name not like '%_gpu'" + + "and slice_name not like '%_System_idle' and slice_name not like '%_wifi_data' " + + "and slice_name not like '%_sensor' and slice_name not like '%_audio' "); + } else { + countSql = this.createSql(startTime, innerTable.tableName, innerTable.columns); + } + table.push({ + countSql: countSql, + chartSql: chartSql, + type: "slice", + name: configObj.disPlayName, + pluginName: configObj.pluginName, + countOtherSql: countOtherSql + }) + } + } + tablesMap.set(key, table); + } + } + } + return tablesMap; + } + + private getTableType(showType: any) { + let columns = showType.columns; + for (let i = 0; i < columns.length; i++) { + let column = columns[i]; + let showType = column.showType + if (showType != null) { + if (showType.indexOf(1) != -1) { + return "counter" + } + if (showType.indexOf(2) != -1) { + return "slice" + } + } + } + return "" + } + + private createSliceSql(startTime: number, tableName: string, columns: Array, where?: string): string { + let selectSql = "select " + for (let i = 0; i < columns.length; i++) { + let column = columns[i]; + if (column.column == "start_ts") { + column.column = "(start_ts - " + startTime + ") AS start_ts" + } + if (column.column == "end_ts") { + column.column = "(end_ts - " + startTime + ") AS end_ts" + } + if (i == (columns.length - 1)) { + selectSql = selectSql + column.column + " " + } else { + selectSql = selectSql + column.column + ", " + } + } + selectSql = selectSql + "from " + tableName + if (where != undefined) { + selectSql = selectSql + " " + where + } + return selectSql; + } + + private createMaxValueSql(tableName: string, where?: string): string { + let selectSql = "select max(value) as max_value from " + tableName + if (where != undefined) { + selectSql = selectSql + " " + where + } + return selectSql; + } + + private createSql(startTime: number, tableName: string, columns: Array, where?: string): string { + let selectSql = "select " + for (let i = 0; i < columns.length; i++) { + let column = columns[i]; + if (column.column == "ts") { + column.column = "ts - " + startTime + " AS ts" + } + if (i == (columns.length - 1)) { + selectSql = selectSql + column.column + " " + } else { + selectSql = selectSql + column.column + ", " + } + } + selectSql = selectSql + "from " + tableName + if (where != undefined) { + selectSql = selectSql + " " + where + } + return selectSql; + } + + async init() { + let configMap = SpSystemTrace.SDK_CONFIG_MAP + if (configMap == undefined) return; + let res = await queryStartTime(); + let startTime = res[0].start_ts; + let tablesMap = this.parseJson(startTime, configMap) + let tableKeys = tablesMap.keys(); + for (let componentId of tableKeys) { + let table = tablesMap.get(componentId); + if (table != null) { + let nodeRow = this.initNodeRow(componentId, table[0].name); + for (let index = 0; index < table.length; index++) { + let sqlMap = table[index] + if (sqlMap.type == "counter") { + let result = await querySdkCount(sqlMap.countSql, componentId); + for (let i = 0; i < result.length; i++) { + await this.initCounter(nodeRow, i, result[i], sqlMap, componentId); + } + } else if (sqlMap.type == 'slice' && sqlMap.pluginName == this.pluginName) { + let suffixList = ["cpu", "display", "gpu", "System_idle", "wifi_data", "sensor", "audio"]; + for (let i = 0; i < suffixList.length; i++) { + let result = await querySdkCount(sqlMap.countSql, componentId, {$suffix: "%" +suffixList[i]}); + if (result.length > 0) { + let groupNodeRow = await this.initSecondaryRow(nodeRow, i, suffixList[i]); + for (let i = 0; i < result.length; i++) { + await this.initSlice(groupNodeRow, i, result[i], sqlMap, componentId); + } + } + } + let result = await querySdkCount(sqlMap.countOtherSql, componentId); + if (result.length > 0) { + let groupNodeRow = await this.initSecondaryRow(nodeRow, 7, "other"); + for (let i = 0; i < result.length; i++) { + await this.initSlice(groupNodeRow, i, result[i], sqlMap, componentId); + } + } + } else if (sqlMap.type == "slice") { + let result = await querySdkCount(sqlMap.countSql, componentId, {}); + for (let i = 0; i < result.length; i++) { + await this.initSlice(nodeRow, i, result[i], sqlMap, componentId); + } + } + } + } + } + } + + private initCounter = async (nodeRow: TraceRow, index: number, result: any, sqlMap: any, componentId: number) => { + let traceRow = TraceRow.skeleton(); + traceRow.rowParentId = `Sdk-${componentId}` + traceRow.rowHidden = !nodeRow.expansion + traceRow.rowId = result.counter_id + "-" + componentId + traceRow.rowType = TraceRow.ROW_TYPE_SDK_COUNTER + traceRow.folderPaddingLeft = 30; + traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + traceRow.selectChangeHandler = this.trace.selectChangeHandler; + traceRow.style.height = '40px' + traceRow.style.width = `100%`; + traceRow.setAttribute('children', ''); + traceRow.name = `${result.counter_name}`; + traceRow.supplier = () => querySdkCounterData(sqlMap.chartSql, result.counter_id, componentId) + traceRow.focusHandler = () => { + this.trace?.displayTip(traceRow, CounterStruct.hoverCounterStruct, `${CounterStruct.hoverCounterStruct?.value?.toFixed(2)}`) + } + let maxList = await queryCounterMax(sqlMap.maxSql, result.counter_id, componentId); + let maxCounter = maxList[0].max_value; + traceRow.onThreadHandler = (useCache) => { + let context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + traceRow.canvasSave(context); + (renders[TraceRow.ROW_TYPE_SDK_COUNTER] as SdkCounterRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `sdk-counter-${index}`, + maxName: `${maxCounter}`, + maxValue: maxCounter + }, + traceRow + ); + traceRow.canvasRestore(context); + } + this.trace.rowsEL?.appendChild(traceRow) + } + + private initNodeRow = (index: number, name: string) => { + let folder = TraceRow.skeleton(); + folder.rowId = `Sdk-${index}`; + folder.index = index; + folder.rowType = TraceRow.ROW_TYPE_SDK + folder.rowParentId = ''; + folder.style.height = '40px' + folder.folder = true; + folder.name = `${name}`; + folder.favoriteChangeHandler = this.trace.favoriteChangeHandler; + folder.selectChangeHandler = this.trace.selectChangeHandler; + folder.supplier = () => new Promise>((resolve) => resolve([])); + folder.onThreadHandler = (useCache) => { + folder.canvasSave(this.trace.canvasPanelCtx!); + if (folder.expansion) { + this.trace.canvasPanelCtx?.clearRect(0, 0, folder.frame.width, folder.frame.height); + } else { + (renders["empty"] as EmptyRender).renderMainThread( + { + context: this.trace.canvasPanelCtx, + useCache: useCache, + type: ``, + }, + folder, + ); + } + folder.canvasRestore(this.trace.canvasPanelCtx!); + } + this.trace.rowsEL?.appendChild(folder) + return folder; + } + + private initSecondaryRow = async (nodeRow: TraceRow, index: number, name: string) => { + let folder = TraceRow.skeleton(); + folder.rowId = `Sdk-${name}-${index}`; + folder.index = index; + folder.rowType = TraceRow.ROW_TYPE_SDK + folder.rowParentId = nodeRow.rowId; + folder.rowHidden = !nodeRow.expansion + folder.style.height = '40px' + folder.folder = true; + folder.folderPaddingLeft = 30; + folder.name = `${name}`; + folder.favoriteChangeHandler = this.trace.favoriteChangeHandler; + folder.selectChangeHandler = this.trace.selectChangeHandler; + folder.supplier = () => new Promise>((resolve) => resolve([])); + folder.onThreadHandler = (useCache) => { + folder.canvasSave(this.trace.canvasPanelCtx!); + if (folder.expansion) { + this.trace.canvasPanelCtx?.clearRect(0, 0, folder.frame.width, folder.frame.height); + } else { + (renders["empty"] as EmptyRender).renderMainThread( + { + context: this.trace.canvasPanelCtx, + useCache: useCache, + type: ``, + }, + folder, + ); + } + folder.canvasRestore(this.trace.canvasPanelCtx!); + } + this.trace.rowsEL?.appendChild(folder) + return folder; + } + + + private initSlice = async (nodeRow: TraceRow, index: number, result: any, sqlMap: any, componentId: number) => { + let traceRow = TraceRow.skeleton() + traceRow.rowType = TraceRow.ROW_TYPE_SDK_SLICE + traceRow.rowHidden = !nodeRow.expansion + traceRow.rowParentId = nodeRow.rowId + traceRow.folderPaddingLeft = 30; + traceRow.style.height = '40px' + traceRow.style.width = `100%`; + traceRow.name = `${result.slice_name}` + traceRow.setAttribute('children', ''); + traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + traceRow.selectChangeHandler = this.trace.selectChangeHandler; + traceRow.rowId = result.slice_id + "-" + componentId + traceRow.supplier = () => querySdkSliceData(sqlMap.chartSql, result.slice_id, TraceRow.range?.startNS || 0, TraceRow.range?.endNS || 0, componentId) + traceRow.focusHandler = () => { + this.trace?.displayTip(traceRow, SdkSliceStruct.hoverSdkSliceStruct, `${SdkSliceStruct.hoverSdkSliceStruct?.value}`) + } + traceRow.onThreadHandler = ((useCache: boolean) => { + let context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + traceRow.canvasSave(context); + (renders[TraceRow.ROW_TYPE_SDK_SLICE] as SdkSliceRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `sdk-slice-${index}`, + maxName: "", + maxValue: 0 + }, + traceRow + ); + traceRow.canvasRestore(context); + }) + this.trace.rowsEL?.appendChild(traceRow) + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/chart/SpVirtualMemChart.ts b/host/ide/src/trace/component/chart/SpVirtualMemChart.ts new file mode 100644 index 0000000000000000000000000000000000000000..989f802504e5b1d2a869115e733ed52063f8d9d0 --- /dev/null +++ b/host/ide/src/trace/component/chart/SpVirtualMemChart.ts @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SpSystemTrace} from "../SpSystemTrace.js"; +import {TraceRow} from "../trace/base/TraceRow.js"; +import { queryVirtualMemory, queryVirtualMemoryData} from "../../database/SqlLite.js"; +import {VirtualMemoryRender, VirtualMemoryStruct} from "../../database/ui-worker/ProcedureWorkerVirtualMemory.js"; +import {renders} from "../../database/ui-worker/ProcedureWorker.js"; +import {EmptyRender} from "../../database/ui-worker/ProcedureWorkerCPU.js"; + +export class SpVirtualMemChart { + private trace: SpSystemTrace; + + constructor(trace: SpSystemTrace) { + this.trace = trace; + } + + async init() { + let array = await queryVirtualMemory(); + if(array.length==0){ + return; + } + let folder = TraceRow.skeleton() + folder.rowId = `VirtualMemory`; + folder.index = 0; + folder.rowType = TraceRow.ROW_TYPE_VIRTUAL_MEMORY_GROUP + folder.rowParentId = ''; + folder.folder = true; + folder.name = `Virtual Memory`; + folder.style.height = '40px' + folder.favoriteChangeHandler = this.trace.favoriteChangeHandler; + folder.selectChangeHandler = this.trace.selectChangeHandler; + folder.supplier = () => new Promise>((resolve) => resolve([])); + folder.onThreadHandler = (useCache) => { + folder.canvasSave(this.trace.canvasPanelCtx!); + if(folder.expansion){ + this.trace.canvasPanelCtx?.clearRect(0, 0, folder.frame.width, folder.frame.height); + } else { + (renders["empty"] as EmptyRender).renderMainThread( + { + context: this.trace.canvasPanelCtx, + useCache: useCache, + type: ``, + }, + folder, + ); + } + folder.canvasRestore(this.trace.canvasPanelCtx!); + } + this.trace.rowsEL?.appendChild(folder) + array.forEach((it,idx)=> this.initVirtualMemoryRow(folder, it.id, it.name, idx)) + } + + initVirtualMemoryRow(folder:TraceRow,id:number,name:string,idx:number) { + let row = TraceRow.skeleton() + row.rowId = `${id}` + row.rowType = TraceRow.ROW_TYPE_VIRTUAL_MEMORY + row.rowParentId = folder.rowId + row.rowHidden = !folder.expansion + row.style.height = '40px' + row.name = `${name.substring(16)}`; + row.setAttribute('children', ''); + row.favoriteChangeHandler = this.trace.favoriteChangeHandler; + row.selectChangeHandler = this.trace.selectChangeHandler; + row.supplier = () => queryVirtualMemoryData(id).then(res => { + let maxValue = Math.max(...res.map(it => it.value || 0)) + for (let j = 0; j < res.length; j++) { + res[j].maxValue = maxValue; + if (j == res.length - 1) { + res[j].duration = (TraceRow.range?.totalNS || 0) - (res[j].startTime || 0); + } else { + res[j].duration = (res[j + 1].startTime || 0) - (res[j].startTime || 0); + } + if (j > 0) { + res[j].delta = (res[j].value || 0) - (res[j - 1].value || 0); + } else { + res[j].delta = 0; + } + } + return res + }); + row.focusHandler = () =>{ this.trace?.displayTip(row,VirtualMemoryStruct.hoverStruct,`value:${VirtualMemoryStruct.hoverStruct?.value}`) } + row.onThreadHandler = (useCache) => { + let context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + row.canvasSave(context); + (renders["virtual-memory-cell"] as VirtualMemoryRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `virtual-memory-cell-${id}`, + }, + row + ); + row.canvasRestore(context); + } + this.trace.rowsEL?.appendChild(row) + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/metrics/CpuStrategy.ts b/host/ide/src/trace/component/metrics/CpuStrategy.ts new file mode 100644 index 0000000000000000000000000000000000000000..4ee3842e316933a70b751d34b164f150726cccec --- /dev/null +++ b/host/ide/src/trace/component/metrics/CpuStrategy.ts @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {info} from "../../../log/Log.js"; + +export const initTest = (metricData: Array): ProcessInfoListItem => { + let processInfoListItems: Array = []; + for (let index = 0; index < metricData.length; index++) { + let eventName = metricData[index].event_name; + let stat_type = metricData[index].stat_type; + let count = metricData[index].count; + let source = metricData[index].source; + let serverity = metricData[index].serverity; + + let processInfoSource: ProcessInfoItem = { + // @ts-ignore + processName: eventName, + threads: { + // @ts-ignore + threadName: stat_type, + cpu: [{ + cpu: eventName, + minFreq: stat_type, + maxFreq: count, + avgFrequency: source, + duration: serverity, + }], + } + } + processInfoListItems?.push(processInfoSource) + } + return { + processInfo: processInfoListItems + } +} + +export const initCpuStrategyData = (metricData: Array): ProcessInfoListItem => { + info("Cpu Strategy data length is:", metricData.length) + let processInfoListItems: Array = []; + if (metricData.length == 10) { + + } else { + + } + const splitChar: string = ',' + for (let sqlIndex = 0; sqlIndex < metricData.length; sqlIndex++) { + if (metricData[sqlIndex].avg_frequency == null) { + continue + } + let cpus = metricData[sqlIndex].cpu.split(splitChar); + let minFrequencies = metricData[sqlIndex].min_freq.split(splitChar); + let maxFrequencies = metricData[sqlIndex].max_freq.split(splitChar); + let avgFrequencies = metricData[sqlIndex].avg_frequency.split(splitChar); + let durations = metricData[sqlIndex].dur.split(splitChar); + + let arrayCpu = []; + for (let index = 0; index < cpus.length; index++) { + let cpuIndex: CpuItem = { + cpu: cpus[index], + minFreq: minFrequencies[index], + maxFreq: maxFrequencies[index], + avgFrequency: avgFrequencies[index], + duration: durations[index], + } + arrayCpu.push(cpuIndex); + } + let processInfoSource: ProcessInfoItem = { + threads: { + cpu: arrayCpu, + } + } + processInfoListItems?.push(processInfoSource) + } + return { + processInfo: processInfoListItems + }; +} + +export interface ProcessInfoListItem { + processInfo: Array +} + +export interface ProcessInfoItem { + threads: ThreadsItem; +} + +export interface ThreadsItem { + cpu: Array; +} + +export interface CpuItem { + cpu: string; + minFreq: string; + maxFreq: string; + avgFrequency: string; + duration: string; +} diff --git a/host/ide/src/trace/component/metrics/DistributeTermStrategy.ts b/host/ide/src/trace/component/metrics/DistributeTermStrategy.ts new file mode 100644 index 0000000000000000000000000000000000000000..1d6cf851e9b45c843f0fbbc570498063a4019287 --- /dev/null +++ b/host/ide/src/trace/component/metrics/DistributeTermStrategy.ts @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {info} from "../../../log/Log.js"; + +export const initDistributedTermData = (metricData: Array): DistributedTermListItem => { + info("Distributed Term data length is:", metricData.length) + let distributedTermListItems: Array = [] + const splitChar = ',' + for (let sqlIndex = 0; sqlIndex < metricData.length; sqlIndex++) { + let threadIdsList = metricData[sqlIndex].threadId.split(splitChar); + let threadNamesList = metricData[sqlIndex].threadName.split(splitChar); + let processIdList = metricData[sqlIndex].processId.split(splitChar); + let processNameList = metricData[sqlIndex].processName === null ? threadIdsList.length + '' : metricData[sqlIndex].processName.split(splitChar); + + let funNameList = metricData[sqlIndex].funName.split(splitChar); + let timeList = metricData[sqlIndex].ts.split(splitChar); + let durList = metricData[sqlIndex].dur.split(splitChar); + let flag = metricData[sqlIndex].flag; + let flagList = flag.split(splitChar); + let traceNameList = metricData[sqlIndex].trace_name; + let chainIdList = metricData[sqlIndex].chainId; + let spanIdList = metricData[sqlIndex].spanId; + let parentSpanIdList = metricData[sqlIndex].parentSpanId; + + let distributedTermListItem: DistributedTermItem = {} + for (let index = 0; index < flagList.length; index++) { + let across: boolean = true; + let receiverTime: number = 0; + let senderTime: number = 0; + let delay: number = 0; + if (flag.indexOf('S,C') > -1 || flag.indexOf('C,S') > -1) { + across = false; + if (flagList[index] == 'S') receiverTime = timeList[index] + if (flagList[index] == 'C') senderTime = timeList[index] + delay = receiverTime - senderTime; + } + + let type = { + acrossTheDevice: across, + traceName: traceNameList, + traceId: { + chainID: chainIdList, + spanID: spanIdList, + parentSpanID: parentSpanIdList, + }, + functionName: funNameList[index], + processInfo: { + processId: processIdList[index], + processName: processNameList[index], + }, + threadInfoItem: { + threadId: threadIdsList[index], + threadName: threadNamesList[index], + }, + dur: durList[index], + delay: delay, + } + if ("C" == flagList[index]) { + distributedTermListItem.sender = type + } else { + distributedTermListItem.receiver = type + } + } + distributedTermListItems?.push(distributedTermListItem) + } + return { + distributedTermItem: distributedTermListItems + } +} + +export interface DistributedTermListItem { + distributedTermItem: Array +} + +export interface DistributedTermItem { + sender?: SenderOrReceiverItem; + receiver?: SenderOrReceiverItem; +} + +export interface SenderOrReceiverItem { + acrossTheDevice?: boolean + traceName: string + traceId: TraceIdItem + functionName: string + processInfo: ProcessInfoItem + threadInfoItem: ThreadInfoItem + dur: string + delay: number +} + +export interface TraceIdItem { + chainID: string + spanID: string + parentSpanID: string +} + +export interface ProcessInfoItem { + processId: string + processName: string +} + +export interface ThreadInfoItem { + threadId: string + threadName: string +} diff --git a/host/ide/src/trace/component/metrics/MemAggStrategy.ts b/host/ide/src/trace/component/metrics/MemAggStrategy.ts new file mode 100644 index 0000000000000000000000000000000000000000..eeddff68fe97a5344ee681340147edf7a3e588d2 --- /dev/null +++ b/host/ide/src/trace/component/metrics/MemAggStrategy.ts @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {info} from "../../../log/Log.js"; + +export const initMemoryAggStrategy = (metricData: Array): ProcessValuesListItem => { + info("Memory Agg Strategy data length is:", metricData.length) + let processValuesListItems: Array = [] + const splitChar: string = ',' + for (let sqlIndex = 0; sqlIndex < metricData.length; sqlIndex++) { + let processNames = metricData[sqlIndex].processName; + let processInfoSource: ProcessValuesItem = { + processName: processNames, + } + if (metricData[sqlIndex].name == null) { + let values = metricData[sqlIndex].value.split(splitChar); + let times = metricData[sqlIndex].ts.split(splitChar); + let oomScoreValue = 0; + for (let index = 0; index < values.length; index++) { + if (!processInfoSource) continue + processValuesListItems?.push(processInfoSource) + } + } else { + let names = metricData[sqlIndex].name.split(splitChar); + let values = metricData[sqlIndex].value.split(splitChar); + let times = metricData[sqlIndex].ts.split(splitChar); + let oomScoreValue = 0; + for (let indexScore = 0; indexScore < names.length; indexScore++) { + if ("oom_score_adj" === names[indexScore]) { + oomScoreValue = values[indexScore]; + break; + } + } + for (let index = 0; index < names.length; index++) { + let typeItem: TypeItem = { + ts: times[index], + oom_score: oomScoreValue, + value: values[index], + } + if (!processInfoSource) continue + if ("mem.rss.anon" === names[index]) { + processInfoSource.anonRss = typeItem + } + if ("mem.swap" === names[index]) { + processInfoSource.swap = typeItem + } + if ("mem.rss.file" === names[index]) { + processInfoSource.fileRss = typeItem + } + if ("oom_score_adj" === names[index]) { + processInfoSource.anonAndSwap = typeItem + } + } + } + processValuesListItems?.push(processInfoSource) + } + return { + processValues: processValuesListItems + } +} + +export interface ProcessValuesListItem { + processValues: Array +} + +export interface ProcessValuesItem { + processName: string; + anonRss?: TypeItem; + swap?: TypeItem; + fileRss?: TypeItem; + anonAndSwap?: TypeItem; +} + +export interface TypeItem { + ts: number; + oom_score: number; + value: number; +} diff --git a/host/ide/src/trace/component/metrics/MemStrategy.ts b/host/ide/src/trace/component/metrics/MemStrategy.ts new file mode 100644 index 0000000000000000000000000000000000000000..8dbcff4f5559d63db2ce592c7ef909b978858420 --- /dev/null +++ b/host/ide/src/trace/component/metrics/MemStrategy.ts @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {info} from "../../../log/Log.js"; + +export const initMemoryStrategy = (metricData: Array): ProcessMetricsListItems => { + info("Memory Strategy data length is:", metricData.length) + let processMetricsListItems: Array = [] + for (let sqlIndex = 0; sqlIndex < metricData.length; sqlIndex++) { + let processName = metricData[sqlIndex].processName; + let minNum = metricData[sqlIndex].minNum < 0 ? 0 : metricData[sqlIndex].minNum; + let maxNum = metricData[sqlIndex].maxNum; + let avgNum = metricData[sqlIndex].avgNum; + let processInfoSource: ProcessMetricsItems = { + processName: processName, + overallCounters: { + anonRss: { + min: minNum, + max: maxNum, + avg: avgNum, + } + } + } + processMetricsListItems?.push(processInfoSource); + } + return { + processMetrics: processMetricsListItems + } +} + +export interface ProcessMetricsListItems { + processMetrics: Array +} + +export interface ProcessMetricsItems { + processName: string + overallCounters: AnonRssItem +} + +export interface AnonRssItem { + anonRss: TypeItem +} + +export interface TypeItem { + min: number + max: number + avg: number +} diff --git a/host/ide/src/trace/component/metrics/MetaDataStrategy.ts b/host/ide/src/trace/component/metrics/MetaDataStrategy.ts new file mode 100644 index 0000000000000000000000000000000000000000..f3ff8cb37777d253f8d7ea449ebfd7e35fd58d6c --- /dev/null +++ b/host/ide/src/trace/component/metrics/MetaDataStrategy.ts @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {info} from "../../../log/Log.js"; + +export const initMetaDataStrategy = (metricData: Array): TraceMetadata => { + info("Meta Strategy data length is:", metricData.length) + let traceMetaDataList: Array = [] + let statDataArray = []; + let jsonText = `{`; + for (let index = 0; index < metricData.length; index++) { + let name = metricData[index].name; + let value = metricData[index].valueText; + if (!value.match('^-?\\d+$')) { + value = "\"" + value.replace('\r|\n', '') + '\"' + } + jsonText += `'` + name + `'` + `: ` + `'` + value.toString() + `'` + `,`; + if (index >= metricData.length - 1) { + jsonText += `}`; + } + } + + for (let sqlIndex = 0; sqlIndex < metricData.length; sqlIndex++) { + let name = metricData[sqlIndex].name; + let value = metricData[sqlIndex].valueText; + if (!value.match('^-?\\d+$')) { + value = "\"" + value.replace('\r|\n', '') + '\"' + } + let traceMetaData = { + name: name, + value: value + } + traceMetaDataList?.push(traceMetaData); + } + return { + traceMetadata: traceMetaDataList + } +} + +export interface TraceMetadata { + traceMetadata: Array +} + +export interface TraceMetadataItem { + name: string + value: string +} + diff --git a/host/ide/src/trace/component/metrics/SysCallsStrategy.ts b/host/ide/src/trace/component/metrics/SysCallsStrategy.ts new file mode 100644 index 0000000000000000000000000000000000000000..a91825d759176fc5c2f6356bf2daa595d1fa973e --- /dev/null +++ b/host/ide/src/trace/component/metrics/SysCallsStrategy.ts @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {info} from "../../../log/Log.js"; + +export const initSysCallsStrategy = (metricData: Array): FunctionListItem => { + info("System Calls Strategy data length is:", metricData.length) + let functionListItems: Array = [] + for (let sqlIndex = 0; sqlIndex < metricData.length; sqlIndex++) { + let functionNames = metricData[sqlIndex].funName; + let durMaxes = metricData[sqlIndex].maxDur; + let durMines = metricData[sqlIndex].minDur; + let durAvgs = Math.floor(metricData[sqlIndex].avgDur).toString(); + let functionItem: FunctionItem = { + functionName: functionNames, + durMax: durMaxes, + durMin: durMines, + durAvg: durAvgs, + } + functionListItems?.push(functionItem) + } + return { + function: functionListItems + } +} + +export interface FunctionListItem { + function: Array +} + +export interface FunctionItem { + functionName: string + durMax: string + durMin: string + durAvg: string +} diff --git a/host/ide/src/trace/component/metrics/SysCallsTopStrategy.ts b/host/ide/src/trace/component/metrics/SysCallsTopStrategy.ts new file mode 100644 index 0000000000000000000000000000000000000000..55324de9f87179c8ef8331150c558d4a971aca75 --- /dev/null +++ b/host/ide/src/trace/component/metrics/SysCallsTopStrategy.ts @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {info} from "../../../log/Log.js"; + +export const initSysCallsTopStrategy = (metricData: Array): ProcessInfoListItem => { + info("System Calls Strategy data length is:", metricData.length) + let ProcessInfoListItems: Array = [] + + for (let sqlIndex = 0; sqlIndex < metricData.length; sqlIndex++) { + let pidList = metricData[sqlIndex].pid; + let tidList = metricData[sqlIndex].tid; + let functionNames = metricData[sqlIndex].funName; + let durMaxes = metricData[sqlIndex].maxDur; + let durMines = metricData[sqlIndex].minDur < 0 ? 0 : metricData[sqlIndex].minDur; + let durAvgs = Math.floor(metricData[sqlIndex].avgDur).toString(); + + let processInfoItem: ProcessInfoItem = { + pid: pidList, + threads: { + tid: tidList, + function: { + functionName: functionNames, + durMax: durMaxes, + durMin: durMines, + durAvg: durAvgs, + }, + }, + } + ProcessInfoListItems?.push(processInfoItem) + } + return { + processInfo: ProcessInfoListItems + } +} + +export interface ProcessInfoListItem { + processInfo: Array +} + +export interface ProcessInfoItem { + pid: string + threads: ThreadsItem +} + + +export interface ThreadsItem { + tid: string + function: FunctionItem +} + +export interface FunctionItem { + functionName: string + durMax: string + durMin: string + durAvg: string +} diff --git a/host/ide/src/trace/component/metrics/TraceStatsStrategy.ts b/host/ide/src/trace/component/metrics/TraceStatsStrategy.ts new file mode 100644 index 0000000000000000000000000000000000000000..20b4bacb56dd892992d717cb18b1ad218ceb3568 --- /dev/null +++ b/host/ide/src/trace/component/metrics/TraceStatsStrategy.ts @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {info} from "../../../log/Log.js"; + +export const initTraceStateStrategy = (metricData: Array): StatListItem => { + info("Trace State Strategy data length is:", metricData.length) + let statListItems: Array = [] + for (let sqlIndex = 0; sqlIndex < metricData.length; sqlIndex++) { + let names = metricData[sqlIndex].event_name; + let counts = metricData[sqlIndex].count; + let sources = metricData[sqlIndex].source; + let severities = metricData[sqlIndex].serverity; + let statListItem: StatItem = { + name: names, + count: counts, + source: sources, + severity: severities + } + statListItems?.push(statListItem) + } + return { + stat: statListItems + } +} + +export interface StatListItem { + stat: Array +} + +export interface StatItem { + name: string + count: string + source: string + severity: string +} diff --git a/host/ide/src/trace/component/metrics/TraceTaskStrategy.ts b/host/ide/src/trace/component/metrics/TraceTaskStrategy.ts new file mode 100644 index 0000000000000000000000000000000000000000..c6eb95802bb0d3c5901ec8329a9a08c0f0f80877 --- /dev/null +++ b/host/ide/src/trace/component/metrics/TraceTaskStrategy.ts @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {info} from "../../../log/Log.js"; + +export const initTraceTaskStrategy = (metricData: Array): ProcessListItem => { + info("Trace Task Strategy data length is:", metricData.length) + let statListItems = [] + for (let sqlIndex = 0; sqlIndex < metricData.length; sqlIndex++) { + let pidList = metricData[sqlIndex].pid; + let processNameList = metricData[sqlIndex].process_name; + let threadNameList = metricData[sqlIndex].thread_name; + let threadNames = []; + let newArr = ''; + if (threadNameList != null) { + threadNames = threadNameList.split(','); + newArr = threadNames.reduce((prev: any, item: any) => prev.includes(item) ? prev : prev.concat(item), []); + } + + let statListItem = { + pid: pidList, + processName: processNameList, + threadName: newArr + } + statListItems?.push(statListItem) + } + return { + process: statListItems + } +} + +export interface ProcessListItem { + process: Array +} + +export interface ProcessItem { + pid: string + processName: string + threadName: string +} diff --git a/host/ide/src/trace/component/setting/SpAllocations.ts b/host/ide/src/trace/component/setting/SpAllocations.ts index 9763ea000f6fc7338230c6f67e5828a0a02edfb1..0860bad1bdd045f267ab7d025a0c7e226747da60 100644 --- a/host/ide/src/trace/component/setting/SpAllocations.ts +++ b/host/ide/src/trace/component/setting/SpAllocations.ts @@ -14,177 +14,296 @@ */ import {BaseElement, element} from "../../../base-ui/BaseElement.js"; +import {log} from "../../../log/Log.js"; +import {HdcDeviceManager} from "../../../hdc/HdcDeviceManager.js"; +import {LitAllocationSelect} from "../../../base-ui/select/LitAllocationSelect.js"; +import "../../../base-ui/select/LitAllocationSelect.js"; +import {SpApplication} from "../../SpApplication.js"; +import {LitSearch} from "../trace/search/Search.js"; +import {SpRecordTrace} from "../SpRecordTrace.js"; +import {Cmd} from "../../../command/Cmd.js"; +import {CmdConstant} from "../../../command/CmdConstant.js"; +import LitSwitch from "../../../base-ui/switch/lit-switch.js"; @element('sp-allocations') export class SpAllocations extends BaseElement { - private processId: HTMLInputElement | null | undefined; + private processId: LitAllocationSelect | null | undefined; private unwindEL: HTMLInputElement | null | undefined; private shareMemory: HTMLInputElement | null | undefined; private shareMemoryUnit: HTMLSelectElement | null | undefined; private filterMemory: HTMLInputElement | null | undefined; private filterMemoryUnit: HTMLSelectElement | null | undefined; + private fpUnWind: LitSwitch | null | undefined; get appProcess(): string { - return this.processId!.value; + return this.processId!.value || ""; } get unwind(): number { + log("unwind value is :" + this.unwindEL!.value) return Number(this.unwindEL!.value); } get shared(): number { let value = this.shareMemory?.value || ""; + log("shareMemory value is :" + value) if (value != "") { - let unit = this.shareMemoryUnit?.value || ""; - return this.convertToValue(value, unit); + let unit = Number(this.shareMemory?.value) || 16384; + return unit; } - return 8192; + return 16384; } get filter(): number { let value = this.filterMemory?.value || ""; + log("filter value is :" + value) if (value != "") { return Number(value); } - return 0; + return 4096; + } + + get fp_unwind(): boolean { + let value = this.fpUnWind?.checked + if (value != undefined) { + return value; + } + return true } initElements(): void { - this.processId = this.shadowRoot?.getElementById("pid") as HTMLInputElement + this.processId = this.shadowRoot?.getElementById("pid") as LitAllocationSelect + let input = this.processId.shadowRoot?.querySelector('.multipleSelect') as HTMLDivElement + let sp = document.querySelector("sp-application") as SpApplication; + let litSearch = sp?.shadowRoot?.querySelector('#lit-search') as LitSearch; + let processData: Array = [] + input.addEventListener('mousedown', ev => { + if (SpRecordTrace.serialNumber == '') { + this.processId!.processData = [] + } + }) + input.addEventListener('valuable', ev => { + this.dispatchEvent(new CustomEvent('addProbe', {})); + }) + input.addEventListener('inputClick', () => { + processData = [] + if (SpRecordTrace.serialNumber != '') { + if (SpRecordTrace.isVscode) { + let cmd = Cmd.formatString(CmdConstant.CMD_GET_PROCESS_DEVICES, [SpRecordTrace.serialNumber]) + Cmd.execHdcCmd(cmd, (res: string) => { + let lineValues: string[] = res.replace(/\r\n/g, "\r").replace(/\n/g, "\r").split(/\r/); + for (let lineVal of lineValues) { + if (lineVal.indexOf("__progname") != -1 || lineVal.indexOf("PID CMD") != -1) { + continue; + } + let process: string[] = lineVal.trim().split(" "); + if (process.length == 2) { + let processId = process[0] + let processName = process[1] + processData.push(processName + "(" + processId + ")") + } + } + this.processId!.processData = processData + this.processId!.initData() + }) + } else { + HdcDeviceManager.connect(SpRecordTrace.serialNumber).then(rr => { + if (sp.search) { + sp.search = false; + litSearch.clear(); + } + if (rr) { + HdcDeviceManager.shellResultAsString(CmdConstant.CMD_GET_PROCESS, false).then(res => { + if (res) { + let lineValues: string[] = res.replace(/\r\n/g, "\r").replace(/\n/g, "\r").split(/\r/); + for (let lineVal of lineValues) { + if (lineVal.indexOf("__progname") != -1 || lineVal.indexOf("PID CMD") != -1) { + continue; + } + let process: string[] = lineVal.trim().split(" "); + if (process.length == 2) { + let processId = process[0] + let processName = process[1] + processData.push(processName + "(" + processId + ")") + } + } + } + this.processId!.processData = processData + this.processId!.initData() + }) + } else { + sp.search = true; + litSearch.clear(); + litSearch.setPercent("please kill other hdc-server! ", -1); + } + }) + } + } + }) this.unwindEL = this.shadowRoot?.getElementById("unwind") as HTMLInputElement this.shareMemory = this.shadowRoot?.getElementById("shareMemory") as HTMLInputElement this.shareMemoryUnit = this.shadowRoot?.getElementById("shareMemoryUnit") as HTMLSelectElement this.filterMemory = this.shadowRoot?.getElementById("filterSized") as HTMLInputElement this.filterMemoryUnit = this.shadowRoot?.getElementById("filterSizedUnit") as HTMLSelectElement + this.fpUnWind = this.shadowRoot?.getElementById("use_fp_unwind") as LitSwitch } initHtml(): string { return ` - -
-
- Allocations -
-
- ProcessId or ProcessName : - -
-
- Max unwind level : - -
-
- Shared Memory Size (Must be a multiple of 4 KB) : -
- - -
-
-
- Filter Memory Size : -
- - -
-
-
`; + .font-style{ + font-family: Helvetica-Bold; + font-size: 1em; + color: var(--dark-color1,#000000); + line-height: 28px; + font-weight: 700; + } + .inner-font-style { + font-family: Helvetica,serif; + font-size: 1em; + color: var(--dark-color1,#000000); + text-align: left; + line-height: 20px; + font-weight: 400; + } + input { + width: 72%; + height: 25px; + border:0; + outline:none; + border-radius: 16px; + text-indent:2% + } + input::-webkit-input-placeholder{ + color:var(--bark-prompt,#999999); + } + .select { + height: 30px; + border:0; + border-radius: 3px; + outline:none; + border: 1px solid var(--dark-border,#B3B3B3); + width: 60px; + background-color:var(--dark-background5, #FFFFFF) + font-family: Helvetica; + font-size: 14px; + color:var(--dark-color,#212121) + text-align: center; + line-height: 16px; + font-weight: 400; + border-radius: 16px; + } + .application{ + display: flex; + flex-direction: column; + grid-gap: 15px; + margin-top: 40px; + } + .switchstyle{ + margin-top: 40px; + display: flex; + } + #fp-unwind { + display:flex; + width:25%; + margin-top: 3px; + } + .inputstyle{ + background: var(--dark-background5,#FFFFFF); + border: 1px solid var(--dark-background5,#999999); + font-family: Helvetica; + font-size: 14px; + color: var(--dark-color1,#212121); + text-align: left; + line-height: 16px; + font-weight: 400; + } + .inputstyle::-webkit-input-placeholder { + background: var(--dark-background5,#FFFFFF); + } + #one_mb{ + background-color:var(--dark-background5, #FFFFFF) + } + #one_kb{ + background-color:var(--dark-background5, #FFFFFF) + } + #two_mb{ + background-color:var(--dark-background5, #FFFFFF) + } + #two_kb{ + background-color:var(--dark-background5, #FFFFFF) + } + .processSelect { + border-radius: 15px; + width: 84%; + } + .value-range { + opacity: 0.6; + font-family: Helvetica; + font-size: 1em; + color: var(--dark-color,#000000); + text-align: left; + line-height: 20px; + font-weight: 400; + } + + +
+
+ Native Memory +
+
+ ProcessId or ProcessName + Record process + + +
+
+ Max unwind level + Max Unwind Level Rang is 0 - 512, default 10 + +
+
+ Shared Memory Size (One page equals 4 KB) + Shared Memory Size Range is 0 - 131072 page, default 16384 page +
+ + Page +
+
+
+ Filter Memory Size + Filter size Range is 0 - 65535 byte, default 4096 byte +
+ + Byte +
+
+
+ Use Fp Unwind : + +
+
+ `; } private convertToValue(input: string, unit: string): number { @@ -201,7 +320,7 @@ input::-webkit-input-placeholder{ } let number = value / 4096; if (number > 0 && number < 1) { - return 8192; + return 16384; } return parseInt(String(number)); } diff --git a/host/ide/src/trace/component/setting/SpFileSystem.ts b/host/ide/src/trace/component/setting/SpFileSystem.ts new file mode 100644 index 0000000000000000000000000000000000000000..fbc546e6f5c791c8a2fd33f0b26731cfd13f3385 --- /dev/null +++ b/host/ide/src/trace/component/setting/SpFileSystem.ts @@ -0,0 +1,469 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../base-ui/BaseElement.js"; +import {LitSelectV} from "../../../base-ui/select/LitSelectV.js"; +import LitSwitch from "../../../base-ui/switch/lit-switch.js"; +import "../../../base-ui/select/LitSelectV.js"; +import "../../../base-ui/select/LitSelect.js"; + +import "../../../base-ui/switch/lit-switch.js"; +import {LitSelect} from "../../../base-ui/select/LitSelect.js"; +import {SpRecordTrace} from "../SpRecordTrace.js"; +import {Cmd} from "../../../command/Cmd.js"; +import {CmdConstant} from "../../../command/CmdConstant.js"; +import {HdcDeviceManager} from "../../../hdc/HdcDeviceManager.js"; + +@element("sp-file-system") +export class SpFileSystem extends BaseElement { + private processInput: LitSelectV | undefined | null; + private maximum: HTMLInputElement | undefined | null; + private selectProcess: HTMLInputElement | undefined | null; + + private configList: Array = []; + private list: Array = []; + + private eventList: Array = [ + "open", + "close", + "read", + "write" + ]; + + set startRecord(start: boolean) { + if (start) { + this.unDisable(); + this.setAttribute("startRecord", ""); + this.selectProcess!.removeAttribute("readonly"); + } else { + if (!this.startFileSystem && !this.startVirtualMemory && !this.startIo) { + this.removeAttribute("startRecord") + this.disable(); + this.selectProcess!.setAttribute("readonly", "readonly") + } + } + } + + get startRecord(): boolean { + return this.hasAttribute("startRecord"); + } + + set startFileSystem(start: boolean) { + if (start) { + this.setAttribute("startSamp", ""); + } else { + this.removeAttribute("startSamp") + } + this.startRecord = start; + } + + get startFileSystem(): boolean { + return this.hasAttribute("startSamp"); + } + + set startVirtualMemory(start: boolean) { + if (start) { + this.setAttribute("virtual", ""); + } else { + this.removeAttribute("virtual") + } + this.startRecord = start; + } + + get startVirtualMemory(): boolean { + return this.hasAttribute("virtual"); + } + + set startIo(start: boolean) { + if (start) { + this.setAttribute("io", ""); + } else { + this.removeAttribute("io") + } + this.startRecord = start; + } + + get startIo(): boolean { + return this.hasAttribute("io"); + } + + getSystemConfig(): SystemConfig | undefined { + let configVal = this.shadowRoot?.querySelectorAll(".config"); + let systemConfig: SystemConfig = { + process: "", + unWindLevel: 0 + }; + configVal!.forEach(value => { + switch (value.title) { + case "Process": + let processSelect = value as LitSelectV; + if (processSelect.all) { + systemConfig.process = "ALL" + break + } + if (processSelect.value.length > 0) { + let result = processSelect.value.match(/\((.+?)\)/g) + if (result) { + systemConfig.process = result.toString().replaceAll("(", "").replaceAll(")", "") + } else { + systemConfig.process = processSelect.value; + } + } + break; + case "Max Unwind Level": + let maxUnwindLevel = value as HTMLInputElement + if (maxUnwindLevel.value != "") { + systemConfig.unWindLevel = Number(maxUnwindLevel.value); + } + } + }); + return systemConfig; + } + + initElements(): void { + this.initConfigList(); + let configList = this.shadowRoot?.querySelector(".configList"); + this.configList.forEach(config => { + let div = document.createElement("div"); + if (config.hidden) { + div.className = "config-div hidden"; + } else { + div.className = "config-div"; + } + let headDiv = document.createElement("div"); + div.appendChild(headDiv); + let title = document.createElement("span"); + title.className = "title"; + title.textContent = config.title; + headDiv.appendChild(title); + let des = document.createElement("span"); + des.textContent = config.des; + des.className = "des"; + headDiv.appendChild(des); + switch (config.type) { + case "select-multiple": + let html = ''; + let placeholder = config.selectArray[0]; + if (config.title == "Process") { + } else if (config.title == "SystemCall Event") { + placeholder = "ALL-Event" + } + html += `` + config.selectArray.forEach((value: string) => { + html += `${value}` + }); + html += ``; + div.innerHTML = div.innerHTML + html; + break; + case "input": + let input = document.createElement("input"); + input.className = "input config"; + input.textContent = config.value; + input.value = config.value; + input.title = config.title; + if (config.title == "Record Time") { + input.oninput = (ev) => { + input.value = input.value.replace(/\D/g, '') + }; + } + div.appendChild(input); + break; + case "select": + let html1 = ''; + html1 += `` + config.selectArray.forEach((value: string) => { + html1 += `${value}` + }) + html1 += `` + div.innerHTML = div.innerHTML + html1; + break; + case "switch": + let switch1 = document.createElement("lit-switch") as LitSwitch; + switch1.className = "config"; + switch1.title = config.title; + if (config.value) { + switch1.checked = true; + } else { + switch1.checked = false; + } + if (config.title == "Start FileSystem Record") { + switch1.addEventListener("change", (event: any) => { + let detail = event.detail; + if (detail.checked) { + this.startFileSystem = true; + } else { + this.startFileSystem = false; + } + }) + } + if (config.title == "Start Page Fault Record") { + switch1.addEventListener("change", (event: any) => { + let detail = event.detail; + if (detail.checked) { + this.startVirtualMemory = true; + } else { + this.startVirtualMemory = false; + } + }) + } + if (config.title == "Start BIO Latency Record") { + switch1.addEventListener("change", (event: any) => { + let detail = event.detail; + if (detail.checked) { + this.startIo = true; + } else { + this.startIo = false; + } + }) + } + headDiv.appendChild(switch1); + break; + default: + break; + } + configList!.appendChild(div); + }); + this.processInput = this.shadowRoot?.querySelector("lit-select-v[title='Process']"); + this.maximum = this.shadowRoot?.querySelector("input[title='Max Unwind Level']"); + this.maximum?.addEventListener('keyup', (eve:Event) => { + this.maximum!.value = this.maximum!.value.replace(/\D/g,'') + if (this.maximum!.value != '') { + let mun = parseInt(this.maximum!.value) + if (mun > 64 || mun < 0) { + this.maximum!.value = '10' + } + } + }) + this.selectProcess = this.processInput!.shadowRoot?.querySelector("input") as HTMLInputElement; + let processData: Array = [] + this.selectProcess!.addEventListener('mousedown', ev => { + if (SpRecordTrace.serialNumber == '') { + this.processInput!.dataSource([], '') + } + }) + + this.selectProcess!.addEventListener('mouseup', () => { + if (SpRecordTrace.serialNumber == '') { + this.processInput?.dataSource([], 'ALL-Process') + } else { + if (SpRecordTrace.isVscode) { + let cmd = Cmd.formatString(CmdConstant.CMD_GET_PROCESS_DEVICES, [SpRecordTrace.serialNumber]) + Cmd.execHdcCmd(cmd, (res: string) => { + processData = [] + let lineValues: string[] = res.replace(/\r\n/g, "\r").replace(/\n/g, "\r").split(/\r/); + for (let lineVal of lineValues) { + if (lineVal.indexOf("__progname") != -1 || lineVal.indexOf("PID CMD") != -1) { + continue; + } + let process: string[] = lineVal.trim().split(" "); + if (process.length == 2) { + let processId = process[0] + let processName = process[1] + processData.push(processName + "(" + processId + ")") + } + } + if (processData.length > 0 && this.startRecord) { + this.processInput!.setAttribute("readonly", "readonly") + } + this.processInput?.dataSource(processData, 'ALL-Process') + }) + } else { + HdcDeviceManager.connect(SpRecordTrace.serialNumber).then(conn => { + if (conn) { + HdcDeviceManager.shellResultAsString(CmdConstant.CMD_GET_PROCESS, false).then(res => { + processData = [] + if (res) { + let lineValues: string[] = res.replace(/\r\n/g, "\r").replace(/\n/g, "\r").split(/\r/); + for (let lineVal of lineValues) { + if (lineVal.indexOf("__progname") != -1 || lineVal.indexOf("PID CMD") != -1) { + continue; + } + let process: string[] = lineVal.trim().split(" "); + if (process.length == 2) { + let processId = process[0] + let processName = process[1] + processData.push(processName + "(" + processId + ")") + } + } + } + if (processData.length > 0 && this.startRecord) { + this.selectProcess!.setAttribute("readonly", "readonly") + } + this.processInput?.dataSource(processData, 'ALL-Process') + }) + } + }) + } + } + }); + this.disable(); + } + + private unDisable() { + let configVal = this.shadowRoot?.querySelectorAll(".config"); + configVal!.forEach(configVal1 => { + configVal1.removeAttribute("disabled") + }) + } + + private disable() { + let configVal = this.shadowRoot?.querySelectorAll(".config"); + configVal!.forEach(configVal1 => { + if (configVal1.title == "Start FileSystem Record" || configVal1.title == "Start Page Fault Record" || configVal1.title == "Start BIO Latency Record") { + } else { + configVal1.setAttribute("disabled", '') + } + }) + } + + initConfigList(): void { + this.configList = [ + { + title: "Start FileSystem Record", + des: "", + hidden: false, + type: "switch", + value: false + }, + { + title: "Start Page Fault Record", + des: "", + hidden: false, + type: "switch", + value: false + }, + { + title: "Start BIO Latency Record", + des: "", + hidden: false, + type: "switch", + value: false + }, + { + title: "Process", + des: "Record process", + hidden: false, + type: "select-multiple", + selectArray: [ + "" + ] + }, + { + title: "Max Unwind Level", + des: "", + hidden: false, + type: "input", + value: "10" + } + ] + } + + initHtml(): string { + return ` + +
+
+
+
+ `; + } +} + +export interface SystemConfig { + process: string; + unWindLevel: number +} diff --git a/host/ide/src/trace/component/setting/SpHisysEvent.ts b/host/ide/src/trace/component/setting/SpHisysEvent.ts new file mode 100644 index 0000000000000000000000000000000000000000..6a53b67b3f7f4ca26a6ef508fab37fb24e6c2b3d --- /dev/null +++ b/host/ide/src/trace/component/setting/SpHisysEvent.ts @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../base-ui/BaseElement.js"; +import LitSwitch from "../../../base-ui/switch/lit-switch.js"; +import "../../../base-ui/select/LitAllocationSelect.js"; + +import "../../../base-ui/switch/lit-switch.js"; +import {LitAllocationSelect} from "../../../base-ui/select/LitAllocationSelect.js"; +import {SpRecordTrace} from "../SpRecordTrace.js"; +import {Cmd} from "../../../command/Cmd.js"; +import {CmdConstant} from "../../../command/CmdConstant.js"; +import {HdcDeviceManager} from "../../../hdc/HdcDeviceManager.js"; + +@element("sp-hisys-event") +export class SpHisysEvent extends BaseElement { + private processInput: LitAllocationSelect | undefined | null; + private selectProcess: HTMLInputElement | undefined | null; + private configList: Array = []; + + set startSamp(start: boolean) { + if (start) { + this.setAttribute("startSamp", ""); + this.selectProcess!.removeAttribute("readonly"); + } else { + this.removeAttribute("startSamp") + this.selectProcess!.setAttribute("readonly", "readonly") + } + } + + get process(): string { + if (this.processInput!.value.length > 0) { + return this.processInput!.value; + } + return "" + } + + get startSamp(): boolean { + return this.hasAttribute("startSamp"); + } + + initElements(): void { + this.initConfigList(); + let configList = this.shadowRoot?.querySelector(".configList"); + this.configList.forEach(config => { + let div = document.createElement("div"); + if (config.hidden) { + div.className = "config-div hidden"; + } else { + div.className = "config-div"; + } + let headDiv = document.createElement("div"); + div.appendChild(headDiv); + let title = document.createElement("span"); + title.className = "title"; + title.textContent = config.title; + headDiv.appendChild(title); + let des = document.createElement("span"); + des.textContent = config.des; + des.className = "des"; + headDiv.appendChild(des); + switch (config.type) { + case "select": + let html1 = ''; + html1 += `` + html1 += `` + div.innerHTML = div.innerHTML + html1; + break; + case "switch": + let switch1 = document.createElement("lit-switch") as LitSwitch; + switch1.className = "config"; + switch1.title = config.title; + if (config.value) { + switch1.checked = true; + } else { + switch1.checked = false; + } + if (config.title == "Start Hisystem Event Tracker Record") { + switch1.addEventListener("change", (event: any) => { + let detail = event.detail; + if (detail.checked) { + this.startSamp = true; + this.unDisable(); + } else { + this.startSamp = false; + this.disable(); + } + }) + } + headDiv.appendChild(switch1); + break; + default: + break; + } + configList!.appendChild(div); + }); + this.processInput = this.shadowRoot?.querySelector("lit-allocation-select[title='AppName']"); + let inputDiv = this.processInput?.shadowRoot?.querySelector('.multipleSelect') as HTMLDivElement + this.selectProcess = this.processInput!.shadowRoot?.querySelector("input") as HTMLInputElement; + let processData: Array = [] + inputDiv!.addEventListener('mousedown', ev => { + if (SpRecordTrace.serialNumber == '') { + this.processInput!.processData = [] + this.processInput!.initData() + } + }) + inputDiv!.addEventListener('mouseup', () => { + if (SpRecordTrace.serialNumber == '') { + this.processInput!.processData = [] + this.processInput!.initData() + } else { + if (SpRecordTrace.isVscode) { + let cmd = Cmd.formatString(CmdConstant.CMD_GET_APP_NMAE_DEVICES, [SpRecordTrace.serialNumber]) + Cmd.execHdcCmd(cmd, (res: string) => { + processData = [] + let lineValues: string[] = res.replace(/\r\n/g, "\r").replace(/\n/g, "\r").split(/\r/); + for (let lineVal of lineValues) { + if (lineVal.indexOf("__progname") != -1 || lineVal.indexOf("CMD") != -1) { + continue; + } + let process = lineVal.trim(); + if (process != "") { + processData.push(process) + } + } + if (processData.length > 0 && this.startSamp) { + this.processInput!.setAttribute("readonly", "readonly") + } + this.processInput!.processData = processData + this.processInput!.initData() + }) + } else { + HdcDeviceManager.connect(SpRecordTrace.serialNumber).then(conn => { + if (conn) { + HdcDeviceManager.shellResultAsString(CmdConstant.CMD_GET_APP_NMAE, false).then(res => { + processData = [] + if (res) { + let lineValues: string[] = res.replace(/\r\n/g, "\r").replace(/\n/g, "\r").split(/\r/); + for (let lineVal of lineValues) { + if (lineVal.indexOf("__progname") != -1 || lineVal.indexOf("CMD") != -1) { + continue; + } + let process = lineVal.trim(); + if (process != "") { + processData.push(process) + } + } + } + if (processData.length > 0 && this.startSamp) { + this.selectProcess!.setAttribute("readonly", "readonly") + } + this.processInput!.processData = processData + this.processInput!.initData() + }) + } + }) + } + } + }); + this.disable(); + } + + private unDisable() { + let configVal = this.shadowRoot?.querySelectorAll(".config"); + configVal!.forEach(configVal1 => { + configVal1.removeAttribute("disabled") + }) + } + + private disable() { + let configVal = this.shadowRoot?.querySelectorAll(".config"); + configVal!.forEach(configVal1 => { + if (configVal1.title != "Start Hisystem Event Tracker Record") { + configVal1.setAttribute("disabled", '') + } + }) + } + + initConfigList(): void { + this.configList = [ + { + title: "Start Hisystem Event Tracker Record", + des: "", + hidden: false, + type: "switch", + value: false + }, + { + title: "AppName", + des: "Record AppName", + hidden: false, + type: "select", + selectArray: [ + '' + ] + } + ] + } + + initHtml(): string { + return ` + +
+
+
+
+ `; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/setting/SpProbesConfig.ts b/host/ide/src/trace/component/setting/SpProbesConfig.ts index a2af05c5580c7c489e9612bb8f5f68039e030214..4decd4fdd563796963d9ad3e65267acd075a8b68 100644 --- a/host/ide/src/trace/component/setting/SpProbesConfig.ts +++ b/host/ide/src/trace/component/setting/SpProbesConfig.ts @@ -17,16 +17,19 @@ import {BaseElement, element} from "../../../base-ui/BaseElement.js"; import {checkDesBean, SpCheckDesBox} from "./SpCheckDesBox.js"; import {LitCheckBox} from "../../../base-ui/checkbox/LitCheckBox.js"; import {LitRadioGroup} from "../../../base-ui/radiobox/LitRadioGroup.js"; +import {info, log} from "../../../log/Log.js"; @element('probes-config') export class SpProbesConfig extends BaseElement { private traceConfigList: Array | undefined private memoryConfigList: Array | undefined + private abilityConfigList: Array | undefined private hitraceConfigList: Array | undefined; private hitrace: SpCheckDesBox | undefined private _traceConfig: HTMLElement | undefined; private _memoryConfig: HTMLElement | undefined | null; + private _abilityConfig: HTMLElement | undefined | null; get traceConfig() { let selectedTrace = this._traceConfig?.querySelectorAll(`check-des-box[checked]`) || []; @@ -37,6 +40,7 @@ export class SpProbesConfig extends BaseElement { if (this.hitrace && this.hitrace.checked) { values.push(this.hitrace.value) } + info("traceConfig is :", values) return values; } @@ -46,9 +50,15 @@ export class SpProbesConfig extends BaseElement { for (const litCheckBoxElement of selectedMemory) { values.push(litCheckBoxElement.value) } + log("memoryConfig size is :" + values.length) return values } + get recordAbility() { + let selectedMemory = this._abilityConfig?.querySelectorAll(`check-des-box[checked]`) as NodeListOf + return selectedMemory.length > 0 + } + get traceEvents() { let values = [] if (this.hitrace && this.hitrace.checked) { @@ -58,6 +68,7 @@ export class SpProbesConfig extends BaseElement { values.push(litCheckBoxElement.value) } } + log("traceEvents size is :" + values.length) return values; } @@ -73,35 +84,26 @@ export class SpProbesConfig extends BaseElement { initElements(): void { this.traceConfigList = [ - {value: 'Scheduling details', isSelect: false, des: "enables high-detailed tracking of scheduling events"} - , { - value: "Board voltages & frequency", isSelect: false, - des: "Tracks voltage and frequency changes from board sensors" - } - , { - value: "CPU Frequency and idle states", isSelect: false, + {value: 'Scheduling details', isSelect: true, des: "enables high-detailed tracking of scheduling events"}, + { + value: "CPU Frequency and idle states", isSelect: true, des: "Records cpu frequency and idle state change viaftrace" - } - , { - value: "High frequency memory", isSelect: false, - des: "Allows to track short memory splikes and transitories through ftrace's mm_event." + - " rss_stat and ion events. " + - "Available only on recent Kernel version >= 4.19" - } - , { + }, + { value: "Advanced ftrace config", isSelect: false, - des: "Enable individual events and tune the kernel-tracng(ftrace) module." + des: "Enable individual events and tune the kernel-tracing(ftrace) module." + "The events enabled here are in addition to those from" + " enabled by other probes." - } - , {value: "Syscalls", isSelect: false, des: "Tracks the enter and exit of all syscalls"} - , {value: "FPS", isSelect: false, des: "Tracks the FPS"}] + }] this._traceConfig = this.shadowRoot?.querySelector(".trace-config") as HTMLElement this.traceConfigList.forEach(configBean => { let checkDesBox = new SpCheckDesBox(); checkDesBox.value = configBean.value; checkDesBox.checked = configBean.isSelect; checkDesBox.des = configBean.des; + checkDesBox.addEventListener("onchange", (ev: any) => { + this.dispatchEvent(new CustomEvent('addProbe', {})); + }) this._traceConfig?.appendChild(checkDesBox) }) this.memoryConfigList = [ @@ -119,18 +121,53 @@ export class SpProbesConfig extends BaseElement { checkDesBox.value = configBean.value; checkDesBox.checked = configBean.isSelect; checkDesBox.des = configBean.des; + checkDesBox.addEventListener("onchange", (ev: any) => { + this.dispatchEvent(new CustomEvent('addProbe', {})); + }) this._memoryConfig?.appendChild(checkDesBox) }) - this.hitraceConfigList = ["ability", "ace", "app", "ark", "binder", "disk", "distributeddatamgr" - , "dsoftbus", "freq", "graphic", "i2c", "idle", "irq", "mdfs", "memory", "memreclaim", "misc", "mmc", - "msdp", "multimodalinput", "notification", "ohos", "pagecache", "regulators", "rpc", "sched", "sensors", "sync" - , "window", "workq", "zaudio", "zcamera", "zimage", "zmedia"] + this.abilityConfigList = [ + { + value: "AbilityMonitor", + isSelect: false, + des: "Tracks the AbilityMonitor" + } + ] + this._abilityConfig = this.shadowRoot?.querySelector(".ability-config") + this.abilityConfigList.forEach(configBean => { + let checkDesBox = new SpCheckDesBox(); + checkDesBox.value = configBean.value; + checkDesBox.checked = configBean.isSelect; + checkDesBox.des = configBean.des; + checkDesBox.addEventListener("onchange", (ev: any) => { + this.dispatchEvent(new CustomEvent('addProbe', {})); + }) + this._abilityConfig?.appendChild(checkDesBox) + }) + + this.hitraceConfigList = [ + {value: 'ability', isSelect: true}, {value: 'accesscontrol', isSelect: false}, {value: 'accessibility', isSelect: false},{value: 'account', isSelect: false}, + {value: 'ace', isSelect: true}, {value: 'app', isSelect: true},{value: 'ark', isSelect: true},{value: 'binder', isSelect: true}, + {value: 'daudio', isSelect: false},{value: 'dcamera', isSelect: false},{value: 'devicemanager', isSelect: false}, {value: 'deviceprofile', isSelect: false}, + {value: 'dhfwk', isSelect: false},{value: 'dinput', isSelect: false},{value: 'disk', isSelect: true},{value: 'dlpcre', isSelect: false}, + {value: 'dsched', isSelect: false}, {value: 'dscreen', isSelect: false},{value: 'dslm', isSelect: false},{value: 'dsoftbus', isSelect: false}, + {value: 'filemanagement', isSelect: false},{value: 'freq', isSelect: true},{value: 'graphic', isSelect: true}, {value: 'gresource', isSelect: false}, + {value: 'huks', isSelect: false},{value: 'i2c', isSelect: false}, {value: 'idle', isSelect: true},{value: 'irq', isSelect: true}, + {value: 'load', isSelect: false}, {value: 'mdfs', isSelect: false},{value: 'memreclaim', isSelect: true},{value: 'misc', isSelect: false}, + {value: 'mmc', isSelect: true},{value: 'msdp', isSelect: false},{value: 'multimodalinput', isSelect: true},{value: 'net', isSelect: false}, + {value: 'notification', isSelect: false},{value: 'nweb', isSelect: false},{value: 'ohos', isSelect: true},{value: 'pagecache', isSelect: true}, + {value: 'power', isSelect: false},{value: 'regulators', isSelect: false},{value: 'rpc', isSelect: true},{value: 'samgr', isSelect: false}, + {value: 'sched', isSelect: true},{value: 'sensors', isSelect: false},{value: 'sync', isSelect: true},{value: 'ufs', isSelect: false}, + {value: 'useriam', isSelect: false},{value: 'window', isSelect: true},{value: 'workq', isSelect: true},{value: 'zaudio', isSelect: true}, + {value: 'zcamera', isSelect: true},{value: 'zimage', isSelect: true},{value: 'zmedia', isSelect: true} + ] this.hitrace = this.shadowRoot?.getElementById("hitrace") as SpCheckDesBox let parent = this.shadowRoot?.querySelector('.user-events') as Element - this.hitraceConfigList?.forEach(value => { + this.hitraceConfigList?.forEach((hitraceConfig:any) => { let litCheckBox = new LitCheckBox(); litCheckBox.setAttribute("name", "userEvents") - litCheckBox.value = value; + litCheckBox.value = hitraceConfig.value; + litCheckBox.checked = hitraceConfig.isSelect; litCheckBox.addEventListener("change", (ev: any) => { let detail = ev.detail; if (this.hitrace?.checked == false) { @@ -148,6 +185,7 @@ export class SpProbesConfig extends BaseElement { this.hitrace.checked = hasChecked } } + this.dispatchEvent(new CustomEvent('addProbe', {})); }) parent.append(litCheckBox) }) @@ -155,96 +193,115 @@ export class SpProbesConfig extends BaseElement { initHtml(): string { return ` - -
-
Record mode
-
-
-
-
- -
- -
-
-
-
-
- Memory Config + .span-col-2{ + grid-column: span 2 / auto; + } + + .log-config{ + display: grid; + grid-template-columns: repeat(2, 1fr); + border-style: solid none none none; + border-color: #D5D5D5; + padding-top: 15px; + gap: 10px; + } + + #hitrace-cat{ + display: grid; + grid-template-columns: 1fr 1fr; + } + .user-events{ + display: grid; + grid-template-columns: repeat(4, 1fr); + grid-template-rows: repeat(2, 1fr); + gap: 10px; + margin-left: 15px;; + } + +
+
Record mode
+
+
+
+
+ + +
+ +
+
+
+
+
+ Memory Config +
+
+
+
+ Ability Config +
+
-
-
`; + `; } //当 custom element首次被插入文档DOM时,被调用。 @@ -256,6 +313,7 @@ export class SpProbesConfig extends BaseElement { siblingNode.forEach(node => { node.checked = detail.checked }) + this.dispatchEvent(new CustomEvent('addProbe', {})); }) } -} \ No newline at end of file +} diff --git a/host/ide/src/trace/component/setting/SpRecordPerf.ts b/host/ide/src/trace/component/setting/SpRecordPerf.ts new file mode 100644 index 0000000000000000000000000000000000000000..b6cdcf118ae9a4dd3ecc40727b9d9f399981e9f6 --- /dev/null +++ b/host/ide/src/trace/component/setting/SpRecordPerf.ts @@ -0,0 +1,861 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../base-ui/BaseElement.js"; +import {LitSelectV} from "../../../base-ui/select/LitSelectV.js"; +import {LitSelect} from "../../../base-ui/select/LitSelect.js"; +import {LitSlider} from "../../../base-ui/slider/LitSlider.js"; +import LitSwitch from "../../../base-ui/switch/lit-switch.js"; +import "../../../base-ui/select/LitSelectV.js"; +import "../../../base-ui/select/LitSelect.js"; + +import "../../../base-ui/switch/lit-switch.js"; +import {info, log} from "../../../log/Log.js"; +import {HdcDeviceManager} from "../../../hdc/HdcDeviceManager.js"; +import {SpRecordTrace} from "../SpRecordTrace.js"; +import {SpApplication} from "../../SpApplication.js"; +import {LitSearch} from "../trace/search/Search.js"; +import {Cmd} from "../../../command/Cmd.js"; +import {CmdConstant} from "../../../command/CmdConstant.js"; + +@element("sp-record-perf") +export class SpRecordPerf extends BaseElement { + private addOptionButton: HTMLButtonElement | undefined | null; + private processSelect: LitSelectV | undefined | null; + private cpuSelect: LitSelectV | undefined | null; + private eventSelect: LitSelectV | undefined | null; + + private frequencySetInput: HTMLInputElement | undefined | null; + private processInput: HTMLInputElement | undefined | null; + private offCPUSwitch: LitSwitch | undefined | null; + private callSelect: LitSelect | undefined | null; + private configList: Array = []; + + get show(): boolean { + return this.hasAttribute("show"); + } + + set show(show: boolean) { + if (show) { + this.setAttribute("show", ""); + } else { + this.removeAttribute("show") + } + } + + set startSamp(start: boolean) { + if (start) { + this.setAttribute("startSamp", ""); + this.processInput!.removeAttribute("readonly"); + } else { + this.removeAttribute("startSamp") + this.processInput!.setAttribute("readonly", 'readonly'); + } + } + + get startSamp(): boolean { + return this.hasAttribute("startSamp"); + } + + getPerfConfig(): PerfConfig | undefined { + let configVal = this.shadowRoot?.querySelectorAll(".config"); + let perfConfig: PerfConfig = { + process: "ALL", + cpu: "select ALL", + eventList: "NONE", + cpuPercent: 100, + frequency: 1000, + period: 1, + isOffCpu: true, + noInherit: false, + callStack: "dwarf", + branch: "none", + mmap: 256, + clockType: "monotonic" + } + configVal!.forEach(value => { + switch (value.title) { + case "Process": + let processSelect = value as LitSelectV; + if (processSelect.all) { + perfConfig.process = "ALL" + break + } + if (processSelect.value.length > 0) { + let result = processSelect.value.match(/\((.+?)\)/g) + if (result) { + perfConfig.process = result.toString().replaceAll("(", "").replaceAll(")", "") + } else { + perfConfig.process = processSelect.value; + } + } + break; + case "CPU": + let selectV = value as LitSelectV; + if (selectV.value.length > 0) { + perfConfig.cpu = selectV.value + } + break; + case "Event List": + let selectList = value as LitSelectV; + if (selectList.value.length > 0) { + perfConfig.eventList = selectList.value.replace(/\s/g, ","); + } + break; + case "CPU Percent": + let selectSlider = value as LitSlider; + let parEle = value.parentElement; + if (parEle!.hasAttribute("percent")) { + let percent = parEle!.getAttribute("percent"); + perfConfig.cpuPercent = Number(percent); + } + break; + case "Frequency": + let input = value as HTMLInputElement; + if (input.value != "") { + perfConfig.frequency = Number(input.value); + } + break; + case "Period": + let periodInput = value as HTMLInputElement; + if (periodInput.value != "") { + perfConfig.period = Number(periodInput.value); + } + break; + case "Off CPU": + let cpuImage = value as LitSwitch; + perfConfig.isOffCpu = cpuImage.checked; + break; + case "No Inherit": + let InheritImage = value as LitSwitch; + perfConfig.noInherit = InheritImage.checked; + break; + case "Call Stack": + let callStack = value as LitSelect; + if (callStack.value != "") { + perfConfig.callStack = callStack.value; + } + break; + case "Branch": + let branch = value as LitSelect; + if (branch.value != "") { + perfConfig.branch = branch.value; + } + break; + case "Mmap Pages": + let pages = value as LitSlider; + let parent = value.parentElement; + if (parent!.hasAttribute("percent")) { + let pagesPercent = parent!.getAttribute("percent"); + perfConfig.mmap = Math.pow(2, Number(pagesPercent)); + } + break; + case "Clock Type": + let clock = value as LitSelect; + if (clock.value != "") { + perfConfig.clockType = clock.value; + } + break; + } + }) + info("perfConfig is : ", perfConfig) + return perfConfig; + } + + initElements(): void { + let that = this + this.initConfigList(); + let configList = this.shadowRoot?.querySelector(".configList"); + this.addOptionButton = this.shadowRoot?.querySelector("#addOptions"); + this.configList.forEach(config => { + let div = document.createElement("div") + if (config.hidden) { + div.className = "config-div hidden"; + } else { + div.className = "config-div"; + } + let headDiv = document.createElement("div") + div.appendChild(headDiv); + let title = document.createElement("span") + title.className = "title" + title.textContent = config.title + headDiv.appendChild(title) + let des = document.createElement("span") + des.textContent = config.des + des.className = "des" + headDiv.appendChild(des); + switch (config.type) { + case "select-multiple": + let html = ''; + let placeholder = config.selectArray[0] + if (config.title == "Event List") { + placeholder = "NONE" + } + html += `` + config.selectArray.forEach((value: string) => { + html += `${value}` + }) + html += `` + div.innerHTML = div.innerHTML + html; + break; + case "lit-slider": + let silder = `
+ +
` + div.innerHTML = div.innerHTML + silder; + let litSlider = div.querySelector(".silderclass"); + litSlider!.percent = config.litSliderStyle.defaultValue + let sliderBody = div.querySelector(".sliderBody"); + let bufferInput = div?.querySelector('.sliderInput') as HTMLInputElement; + litSlider!.addEventListener('input', evt => { + bufferInput.value = sliderBody!.getAttribute("percent") + config.litSliderStyle.resultUnit; + }) + litSlider!.sliderStyle = config.litSliderStyle; + break; + case "Mmap-lit-slider": + let defaultValue = Math.pow(2, config.litSliderStyle.defaultValue); + let mapsilder = `
+ +
` + div.innerHTML = div.innerHTML + mapsilder; + let maplitSlider = div.querySelector(".silderclass"); + maplitSlider!.percent = config.litSliderStyle.defaultValue + let mapsliderBody = div.querySelector(".sliderBody"); + let mapbufferInput = div?.querySelector('.sliderInput') as HTMLInputElement; + maplitSlider!.addEventListener('input', evt => { + let percnet = mapsliderBody!.getAttribute("percent"); + if (percnet != null) { + mapbufferInput.value = Math.pow(2, Number(percnet)) + config.litSliderStyle.resultUnit; + } + }) + maplitSlider!.sliderStyle = config.litSliderStyle; + break; + case "input": + let input = document.createElement("input"); + input.className = "input config"; + input.textContent = config.value; + input.value = config.value; + input.title = config.title; + input.oninput = (ev) => { + input.value = input.value.replace(/\D/g, '') + } + div.appendChild(input); + break; + case "select": + let html1 = ''; + html1 += `` + config.selectArray.forEach((value: string) => { + html1 += `${value}` + }) + html1 += `` + div.innerHTML = div.innerHTML + html1; + break; + case "switch": + let switch1 = document.createElement("lit-switch") as LitSwitch; + switch1.className = "config" + switch1.title = config.title; + if (config.value) { + switch1.checked = true; + } else { + switch1.checked = false; + } + if (config.title == "Start Hiperf Sampling") { + switch1.addEventListener("change", (event: any) => { + let detail = event.detail; + if (detail.checked) { + this.startSamp = true; + this.unDisable(); + this.dispatchEvent(new CustomEvent('addProbe', {})); + } else { + this.startSamp = false; + this.addOptionButton!.style.display = "unset"; + this.disable(); + this.show = false; + } + }) + } + headDiv.appendChild(switch1); + break; + default: + break; + } + configList!.appendChild(div); + }) + let sp = document.querySelector("sp-application") as SpApplication; + let litSearch = sp?.shadowRoot?.querySelector('#lit-search') as LitSearch; + this.processSelect = this.shadowRoot?.querySelector("lit-select-v[title='Process']"); + this.processInput = this.processSelect?.shadowRoot?.querySelector('input'); + let querySelector = this.processSelect!.shadowRoot?.querySelector("input") as HTMLInputElement; + let processData: Array = [] + querySelector.addEventListener('mousedown', ev => { + if (SpRecordTrace.serialNumber == '') { + this.processSelect!.dataSource([], 'ALL-Process') + } + }) + querySelector!.addEventListener('mouseup', () => { + if (SpRecordTrace.serialNumber == '') { + this.processSelect?.dataSource([], 'ALL-Process') + } else { + if (sp.search) { + sp.search = false; + litSearch.clear(); + } + if (SpRecordTrace.isVscode) { + let cmd = Cmd.formatString(CmdConstant.CMD_GET_PROCESS_DEVICES, [SpRecordTrace.serialNumber]) + Cmd.execHdcCmd(cmd, (res: string) => { + processData = [] + let lineValues: string[] = res.replace(/\r\n/g, "\r").replace(/\n/g, "\r").split(/\r/); + for (let lineVal of lineValues) { + if (lineVal.indexOf("__progname") != -1 || lineVal.indexOf("PID CMD") != -1) { + continue; + } + let process: string[] = lineVal.trim().split(" "); + if (process.length == 2) { + let processId = process[0] + let processName = process[1] + processData.push(processName + "(" + processId + ")") + } + } + if(processData.length > 0 && this.startSamp){ + this.processInput!.setAttribute("readonly", "readonly") + } + this.processSelect?.dataSource(processData, 'ALL-Process') + }) + } else { + HdcDeviceManager.connect(SpRecordTrace.serialNumber).then(conn => { + if (conn) { + HdcDeviceManager.shellResultAsString(CmdConstant.CMD_GET_PROCESS, false).then(res => { + processData = [] + if (res) { + let lineValues: string[] = res.replace(/\r\n/g, "\r").replace(/\n/g, "\r").split(/\r/); + for (let lineVal of lineValues) { + if (lineVal.indexOf("__progname") != -1 || lineVal.indexOf("PID CMD") != -1) { + continue; + } + let process: string[] = lineVal.trim().split(" "); + if (process.length == 2) { + let processId = process[0] + let processName = process[1] + processData.push(processName + "(" + processId + ")") + } + } + } + if(processData.length > 0 && this.startSamp){ + this.processInput!.setAttribute("readonly", "readonly") + } + this.processSelect?.dataSource(processData, 'ALL-Process') + }) + } else { + sp.search = true; + litSearch.clear(); + litSearch.setPercent("please kill other hdc-server !", -1); + } + }) + } + } + }) + + this.cpuSelect = this.shadowRoot?.querySelector("lit-select-v[title='CPU']"); + let inputCpu = this.cpuSelect!.shadowRoot?.querySelector("input") as HTMLInputElement; + let cpuData: Array = [] + inputCpu.addEventListener('mousedown', ev => { + if (SpRecordTrace.serialNumber == '') { + this.cpuSelect!.dataSource([], 'ALL-CPU') + } + }) + inputCpu!.addEventListener("mouseup", () => { + if (SpRecordTrace.serialNumber == '') { + this.cpuSelect?.dataSource([], '') + } else { + if (sp.search) { + sp.search = false; + litSearch.clear(); + } + if (SpRecordTrace.isVscode) { + let cmd = Cmd.formatString(CmdConstant.CMD_GET_CPU_COUNT_DEVICES, [SpRecordTrace.serialNumber]) + Cmd.execHdcCmd(cmd, (res: string) => { + cpuData = [] + let cpuCount = res!.trim(); + let cpus = Number(cpuCount); + for (let index = 0; index < cpus; index++) { + cpuData.push(String(index)) + } + this.cpuSelect?.dataSource(cpuData, 'ALL-CPU'); + }) + } else { + HdcDeviceManager.connect(SpRecordTrace.serialNumber).then(conn => { + cpuData = [] + if (conn) { + HdcDeviceManager.shellResultAsString(CmdConstant.CMD_GET_CPU_COUNT, false).then(res => { + let cpuCount = res!.trim(); + let cpus = Number(cpuCount); + for (let index = 0; index < cpus; index++) { + cpuData.push(String(index)) + } + this.cpuSelect?.dataSource(cpuData, 'ALL-CPU'); + }) + } else { + sp.search = true; + litSearch.clear(); + litSearch.setPercent("please kill other hdc-server !", -1); + } + }); + } + } + }) + this.eventSelect = this.shadowRoot?.querySelector("lit-select-v[title='Event List']"); + let inputEvent = this.eventSelect!.shadowRoot?.querySelector("input") as HTMLInputElement; + let eventData: Array = []; + inputEvent.addEventListener('mousedown', ev => { + if (SpRecordTrace.serialNumber == '') { + this.eventSelect!.dataSource([], '') + } + }) + inputEvent!.addEventListener("click", () => { + if (SpRecordTrace.serialNumber == '') { + this.eventSelect?.dataSource(["hw-cpu-cycles", + "hw-instructions", + "hw-cache-references", + "hw-cache-misses", + "hw-branch-instructions", + "hw-branch-misses", + "hw-bus-cycles", + "hw-stalled-cycles-backend", + "hw-stalled-cycles-frontend", + "sw-cpu-clock", + "sw-task-clock", + "sw-page-faults", + "sw-context-switches", + "sw-cpu-migrations", + "sw-page-faults-min", + "sw-page-faults-maj", + "sw-alignment-faults", + "sw-emulation-faults", + "sw-dummy", + "sw-bpf-output"], ''); + } else { + if (sp.search) { + sp.search = false; + litSearch.clear(); + } + if (SpRecordTrace.isVscode) { + let cmd = Cmd.formatString(CmdConstant.CMD_GET_HIPERF_EVENTS_DEVICES, [SpRecordTrace.serialNumber]); + Cmd.execHdcCmd(cmd, (res: string) => { + let eventMap = that.parseEvent(res); + let eventList = that.getSoftHardWareEvents(eventMap); + if (eventList) { + for (let eventListElement of eventList) { + eventData.push(eventListElement.trim()) + } + } + this.eventSelect!.dataSource(eventData, ''); + }); + } else { + HdcDeviceManager.connect(SpRecordTrace.serialNumber).then(conn => { + eventData = []; + if (conn) { + HdcDeviceManager.shellResultAsString(CmdConstant.CMD_GET_HIPERF_EVENTS, false).then(res => { + if (res) { + let eventMap = that.parseEvent(res); + let eventList = that.getSoftHardWareEvents(eventMap); + if (eventList) { + for (let eventListElement of eventList) { + eventData.push(eventListElement.trim()) + } + } + this.eventSelect!.dataSource(eventData, ''); + } + }) + } else { + sp.search = true; + litSearch.clear(); + litSearch.setPercent("please kill other hdc-server !", -1); + } + }); + } + } + }) + + this.frequencySetInput = this.shadowRoot?.querySelector("input[title='Frequency']"); + this.offCPUSwitch = this.shadowRoot?.querySelector("lit-switch[title='Off CPU']"); + this.callSelect = this.shadowRoot?.querySelector("lit-select[title='Call Stack']"); + this.addOptionButton!.addEventListener("click", (event) => { + if (!this.startSamp) { + return; + } + this.addOptionButton!.style.display = "none"; + this.show = true; + }); + this.disable(); + } + + getSoftHardWareEvents(eventListResult: Map) { + let shEvents = []; + let hardwareEvents = eventListResult.get("hardware"); + if (hardwareEvents) { + for (let hardwareEvent of hardwareEvents) { + shEvents.push(hardwareEvent); + } + } + let softwareEvents = eventListResult.get("software"); + if (softwareEvents) { + for (let softwareEvent of softwareEvents) { + shEvents.push(softwareEvent); + } + } + return shEvents; + } + + parseEvent(eventListResult: string): Map> { + let eventMap: Map> = new Map>(); + let events: Array = []; + let type: string = ""; + let lineValues: string[] = eventListResult.replace(/\r\n/g, "\r").replace(/\n/g, "\r").split(/\r/); + for (let line of lineValues) { + if (line.startsWith("Supported")) { + let startSign: string = "for"; + type = line.substring(line.indexOf(startSign) + startSign.length, line.lastIndexOf(":")).trim(); + events = new Array(); + eventMap.set(type, events); + } else if (line.indexOf("not support") != -1 || line.trim().length == 0 || line.indexOf("Text file busy") != -1) { + // do not need deal with it + } else { + let event: string = line.split(" ")[0]; + let ventMap = eventMap.get(type); + if (ventMap != null) { + ventMap.push(event); + } + } + } + return eventMap; + } + + + private unDisable() { + if (this.processSelect) { + this.processSelect.removeAttribute("disabled"); + } + if (this.frequencySetInput) { + this.frequencySetInput!.disabled = false; + } + if (this.offCPUSwitch) { + this.offCPUSwitch!.disabled = false; + } + if (this.callSelect) { + this.callSelect!.removeAttribute("disabled"); + } + if (this.addOptionButton) { + this.addOptionButton.disabled = false; + } + } + + private disable() { + if (this.processSelect) { + this.processSelect.setAttribute("disabled", ''); + } + if (this.frequencySetInput) { + this.frequencySetInput!.disabled = true; + } + if (this.offCPUSwitch) { + this.offCPUSwitch!.disabled = true; + } + if (this.callSelect) { + this.callSelect!.setAttribute("disabled", ''); + } + if (this.addOptionButton) { + this.addOptionButton.disabled = true; + } + } + + initConfigList(): void { + this.configList = [ + { + title: "Start Hiperf Sampling", + des: "", + hidden: false, + type: "switch", + value: false + }, + { + title: "Process", + des: "Record process", + hidden: false, + type: "select-multiple", + selectArray: [ + "" + ] + }, + { + title: "CPU", + des: "Record assign cpu num such as 0,1,2", + hidden: true, + type: "select-multiple", + selectArray: [ + "" + ] + }, { + title: "Event List", + des: "Event type Default is cpu cycles", + hidden: true, + type: "select-multiple", + selectArray: [ + "" + ] + }, { + title: "CPU Percent", + des: "Set the max percent of cpu time used for recording", + hidden: true, + type: "lit-slider", + litSliderStyle: { + minRange: 0, + maxRange: 100, + defaultValue: '100', + resultUnit: "%", + stepSize: 1, + lineColor: "var(--dark-color3,#a88888)", + buttonColor: "#a88888" + } + }, + { + title: "Frequency", + des: "Set event sampling frequency", + hidden: false, + type: "input", + value: "1000" + }, + { + title: "Period", + des: "Set event sampling period for trace point events2", + hidden: true, + type: "input", + value: "1" + }, + { + title: "Off CPU", + des: "Trace when threads are scheduled off cpu", + hidden: false, + type: "switch", + value: true + }, + { + title: "No Inherit", + des: "Don't trace child processes", + hidden: true, + type: "switch", + value: false + }, + { + title: "Call Stack", + des: "Setup and enable call stack recording", + hidden: false, + type: "select", + selectArray: ["dwarf", "fp", "none"] + }, + { + title: "Branch", + des: "Taken branch stack sampling", + hidden: true, + type: "select", + selectArray: ["none", "any", "any_call", "any_ret", "ind_call", "call", "user", "kernel"] + }, + { + title: "Mmap Pages", + des: "Used to receiving record data from kernel", + hidden: true, + type: "Mmap-lit-slider", + litSliderStyle: { + minRange: 1, + maxRange: 10, + defaultValue: "8", + resultUnit: "MB", + stepSize: 1, + lineColor: "var(--dark-color3,#46B1E3)", + buttonColor: "#999999" + } + }, + { + title: "Clock Type", + des: "Set the clock id to use for the various time fields in the perf_event_type records", + hidden: true, + type: "select", + selectArray: ["monotonic","realtime", "monotonic_raw", "boottime", "perf"] + }, + ] + } + + initHtml(): string { + return ` + +
+
+
+ +
+ `; + } +} + +export interface PerfConfig { + process: string; + cpu: string; + eventList: string; + cpuPercent: number; + frequency: number; + period: number; + isOffCpu: boolean; + noInherit: boolean; + callStack: string; + branch: string; + mmap: number; + clockType: string; +} diff --git a/host/ide/src/trace/component/setting/SpRecordSetting.ts b/host/ide/src/trace/component/setting/SpRecordSetting.ts index 9db5328af629b8ba41a39402b9bedbaf4b7d7436..4d83df30420a136db36fd8ad8e345a3db1231875 100644 --- a/host/ide/src/trace/component/setting/SpRecordSetting.ts +++ b/host/ide/src/trace/component/setting/SpRecordSetting.ts @@ -18,12 +18,19 @@ import "../../../base-ui/radiobox/LitRadioBox.js"; import {LitRadioBox} from "../../../base-ui/radiobox/LitRadioBox.js"; import "../../../base-ui/slider/LitSlider.js"; import {LitSlider} from "../../../base-ui/slider/LitSlider.js"; +import "../../../base-ui/popover/LitPopover.js" +import {info} from "../../../log/Log.js"; @element('record-setting') export class SpRecordSetting extends BaseElement { private memoryBufferSlider: LitSlider | undefined; private maxDurationSliders: LitSlider | undefined; private radioBox: LitRadioBox | undefined + private bufferNumber: HTMLElement | undefined + private durationNumber: HTMLElement | undefined + private outputPath: HTMLInputElement | undefined + private lastMemoryValue: string | undefined; + private lastDurationValue: string | undefined; get recordMod(): boolean { if (this.radioBox) { @@ -32,92 +39,415 @@ export class SpRecordSetting extends BaseElement { return false; } + get output(): string { + if (this.outputPath && this.outputPath.value != '') { + return "/data/local/tmp/" + this.outputPath.value + } + return "/data/local/tmp/hiprofiler_data.htrace"; + } + get bufferSize(): number { - let bufferSize = this.shadowRoot?.querySelector(".buffer-size") as HTMLElement - return Number(bufferSize.getAttribute("percent")); + if (this.bufferNumber?.hasAttribute('percent')) { + info("bufferSize is : ", this.bufferNumber!.getAttribute("percent")) + return Number(this.bufferNumber!.getAttribute("percent")); + } + return 64 } get maxDur(): number { - let bufferSize = this.shadowRoot?.querySelector(".max-duration") as HTMLElement - return Number(bufferSize.getAttribute("percent")); + if (this.durationNumber?.hasAttribute('percent')) { + info("maxDur is : ", this.durationNumber!.getAttribute("percent")) + return Number(this.durationNumber!.getAttribute("percent")); + } + return 30 + } + + resetValue(): void{ + let bufferInput = this.shadowRoot?.querySelector('.memory_buffer_result') as HTMLInputElement; + let parentElement = this.memoryBufferSlider!.parentNode as Element; + if (bufferInput.style.color != 'var(--dark-color1,#000000)' && this.lastMemoryValue) { + bufferInput.value = this.lastMemoryValue + ''; + this.memoryBufferSlider!.percent = this.lastMemoryValue + ''; + this.memoryBufferSlider!.sliderStyle = { + minRange: 4, + maxRange: 512, + defaultValue: this.lastMemoryValue + '', + resultUnit: "MB", + stepSize: 2, + lineColor: "var(--dark-color3,#46B1E3)", + buttonColor: "#999999" + }; + parentElement.setAttribute('percent', this.lastMemoryValue + ''); + this.lastMemoryValue = this.lastMemoryValue + '' + bufferInput.style.color = 'var(--dark-color1,#000000)'; + } + + let durationInput = this.shadowRoot?.querySelector('.max_duration_result') as HTMLInputElement; + let durationEl = this.maxDurationSliders!.parentNode as Element; + if (durationInput.style.color != 'var(--dark-color1,#000000)' && this.lastDurationValue) { + durationInput.style.color = 'var(--dark-color1,#000000)'; + let durationList = this.lastDurationValue.split(":"); + let resultDuration = Number(durationList[0]) * 3600 + Number(durationList[1]) * 60 + Number(durationList[2]); + + durationInput.value = this.lastDurationValue + this.maxDurationSliders!.sliderStyle = { + minRange: 10, + maxRange: 3600, + defaultValue: this.lastDurationValue!, + resultUnit: "h:m:s", + stepSize: 1, + lineColor: "var(--dark-color4,#61CFBE)", + buttonColor: "#999999" + } + durationEl.setAttribute('percent', resultDuration.toString()); + } } initElements(): void { + this.bufferNumber = this.shadowRoot?.querySelector(".buffer-size") as HTMLElement + this.durationNumber = this.shadowRoot?.querySelector(".max-duration") as HTMLElement + let bu = this.shadowRoot?.querySelector('.record') as HTMLDivElement + this.shadowRoot?.querySelectorAll('.MenuButton').forEach(button => { + + button!.addEventListener('mouseenter', e => { + button.style.backgroundColor = '#EFEFEF' + }) + + button!.addEventListener('mouseout', e => { + button.style.backgroundColor = '#E4E3E9' + }) + }) + this.radioBox = this.shadowRoot?.querySelector("#litradio") as LitRadioBox + this.outputPath = this.shadowRoot?.querySelector('#trace_path') as HTMLInputElement; + + this.initLitSlider() + } + + initLitSlider() { this.memoryBufferSlider = this.shadowRoot?.querySelector('#memory-buffer') as LitSlider; - let sliderSize1 = this.memoryBufferSlider.sliderSize; + this.memoryBufferSlider.sliderStyle = { + minRange: 4, + maxRange: 512, + defaultValue: "64", + resultUnit: "MB", + stepSize: 2, + lineColor: "var(--dark-color3,#46B1E3)", + buttonColor: "#999999" + }; + this.lastMemoryValue = '64' + let parentElement = this.memoryBufferSlider!.parentNode as Element; + let bufferInput = this.shadowRoot?.querySelector('.memory_buffer_result') as HTMLInputElement; + bufferInput.value = this.memoryBufferSlider.sliderStyle.defaultValue; + this.memoryBufferSlider.addEventListener('input', evt => { + bufferInput.value = this.bufferSize.toString(); + }) + parentElement.setAttribute('percent', '64'); + bufferInput.style.color = 'var(--dark-color1,#000000)'; + bufferInput.addEventListener('input', ev => { + if (this.bufferNumber!.hasAttribute('percent')) { + this.bufferNumber!.removeAttribute('percent'); + } + bufferInput.style.color = 'var(--dark-color1,#000000)'; + bufferInput.parentElement!.style.backgroundColor = "var(--dark-background5,#F2F2F2)"; + bufferInput.style.backgroundColor = "var(--dark-background5,#F2F2F2)"; + if (bufferInput.value.trim() == '') { + bufferInput.style.color = 'red'; + parentElement.setAttribute('percent', '64'); + return + } + let memorySize = Number(bufferInput.value); + if (!memorySize || memorySize < this.memoryBufferSlider!.sliderStyle.minRange || + memorySize > this.memoryBufferSlider!.sliderStyle.maxRange) { + bufferInput.style.color = 'red'; + parentElement.setAttribute('percent', '64'); + } else { + this.memoryBufferSlider!.percent = bufferInput.value; + let htmlInputElement = this.memoryBufferSlider!.shadowRoot?.querySelector("#slider") as HTMLInputElement; + htmlInputElement.value = bufferInput.value; + this.memoryBufferSlider!.sliderStyle = { + minRange: 4, + maxRange: 512, + defaultValue: bufferInput.value, + resultUnit: "MB", + stepSize: 2, + lineColor: "var(--dark-color3,#46B1E3)", + buttonColor: "#999999" + }; + parentElement.setAttribute('percent', bufferInput.value); + this.lastMemoryValue = bufferInput.value + } + }) + + let memoryBufferInput = this.memoryBufferSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; + + memoryBufferInput.addEventListener('input', ev => { + bufferInput.style.color = 'var(--dark-color1,#000000)'; + bufferInput.parentElement!.style.backgroundColor = "var(--dark-background5,#F2F2F2)"; + bufferInput.style.backgroundColor = "var(--dark-background5,#F2F2F2)"; + }) + this.maxDurationSliders = this.shadowRoot?.querySelector('#max-duration') as LitSlider; - let sliderSize2 = this.maxDurationSliders.sliderSize; + this.maxDurationSliders.sliderStyle = { + minRange: 10, + maxRange: 3600, + defaultValue: '00:00:30', + resultUnit: "h:m:s", + stepSize: 1, + lineColor: "var(--dark-color4,#61CFBE)", + buttonColor: "#999999" + } + this.lastDurationValue = '00:00:30' + let durationParentElement = this.maxDurationSliders!.parentNode as Element; + let durationInput = this.shadowRoot?.querySelector('.max_duration_result') as HTMLInputElement; + durationInput.value = this.maxDurationSliders.sliderStyle.defaultValue; + this.maxDurationSliders.addEventListener('input', evt => { + durationInput.value = this.maxDurationSliders!.formatSeconds(this.maxDur.toString()); + }) + + durationInput.style.color = 'var(--dark-color1,#000000)'; + durationInput.addEventListener('input', ev => { + if (this.durationNumber!.hasAttribute('percent')) { + this.durationNumber!.removeAttribute('percent'); + } + durationInput.style.color = 'var(--dark-color1,#000000)'; + durationInput.parentElement!.style.backgroundColor = "var(--dark-background5,#F2F2F2)"; + durationInput.style.backgroundColor = "var(--dark-background5,#F2F2F2)"; + let regExpMatchArray = durationInput.value.trim(); + if (regExpMatchArray == '') { + durationInput.style.color = 'red'; + durationParentElement.setAttribute('percent', '30'); + return + } + let regExpMatch = durationInput.value.trim().match(`^\\d{1,2}\\:\\d{1,2}\\:\\d{1,2}$`); + if (regExpMatch) { + let durationList = regExpMatchArray.split(":"); + let resultDuration = Number(durationList[0]) * 3600 + Number(durationList[1]) * 60 + Number(durationList[2]); + if (Number(durationList[0]) > 60 || Number(durationList[1]) > 60 || Number(durationList[2]) > 60 || + resultDuration > this.maxDurationSliders!.sliderStyle.maxRange || + resultDuration < this.maxDurationSliders!.sliderStyle.minRange) { + durationInput.style.color = 'red'; + durationParentElement.setAttribute('percent', '30'); + } else { + durationInput.style.color = 'var(--dark-color1,#000000)'; + durationInput.parentElement!.style.backgroundColor = "var(--dark-background5,#F2F2F2)"; + durationInput.style.backgroundColor = "var(--dark-background5,#F2F2F2)"; + let htmlInputElement = this.maxDurationSliders!.shadowRoot?.querySelector("#slider") as HTMLInputElement; + htmlInputElement.value = resultDuration + ''; + this.maxDurationSliders!.sliderStyle = { + minRange: 10, + maxRange: 3600, + defaultValue: Number(durationList[0]) + ':' + Number(durationList[1]) + ':' + Number(durationList[2]), + resultUnit: "h:m:s", + stepSize: 1, + lineColor: "var(--dark-color4,#61CFBE)", + buttonColor: "#999999" + } + durationParentElement.setAttribute('percent', resultDuration.toString()); + this.lastDurationValue = regExpMatchArray + } + } else { + durationInput.style.color = 'red'; + durationParentElement.setAttribute('percent', '30'); + } + }) + + let maxDurationInput = this.maxDurationSliders!.shadowRoot?.querySelector('#slider') as HTMLInputElement; + maxDurationInput.addEventListener('input', ev => { + durationInput.style.color = 'var(--dark-color1,#000000)'; + durationInput.parentElement!.style.backgroundColor = "var(--dark-background5,#F2F2F2)" + durationInput.style.backgroundColor = "var(--dark-background5,#F2F2F2)" + }) } initHtml(): string { return ` - -
-
- Record mode - Stop when full -
-
- In-memory buffer size - -
-
- Max duration - -
-
`; + +
+
+ Record mode + Stop when full +
+
+ output file path +
+ /data/local/tmp/ + +
+
+
+
+ In-memory buffer size + (max memory buffer size is 512 MB) +
+ + +
+ + MB +
+
+
+
+ Max duration + (max duration value is 01:00:00) +
+ + +
+ + h:m:s +
+ +
+
+ `; } -} +} \ No newline at end of file diff --git a/host/ide/src/trace/component/setting/SpSdkConfig.ts b/host/ide/src/trace/component/setting/SpSdkConfig.ts new file mode 100644 index 0000000000000000000000000000000000000000..4a086d5c6fcb3cf1c02a2ebf0413ef21def358be --- /dev/null +++ b/host/ide/src/trace/component/setting/SpSdkConfig.ts @@ -0,0 +1,489 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../base-ui/BaseElement.js"; +import "../../../base-ui/select/LitSelectV.js"; +import "../../../base-ui/select/LitSelect.js"; + +import "../../../base-ui/switch/lit-switch.js"; +import LitSwitch from "../../../base-ui/switch/lit-switch.js"; +import {LitSelectV} from "../../../base-ui/select/LitSelectV.js"; +import {LitAllocationSelect} from "../../../base-ui/select/LitAllocationSelect.js"; +import {SpRecordTrace} from "../SpRecordTrace.js"; + +@element("sp-sdk-config") +export class SpSdkConfig extends BaseElement { + private worker: Worker | undefined; + private configList: any; + private customConfig: HTMLDivElement | undefined | null; + private selectConfig: LitAllocationSelect | undefined | null; + private list: Array | undefined + private pluginName:string = ""; + private sampleInterval: number = 5000; + + static get observedAttributes() { + return ["configName","value","type"] + } + + get show(): boolean { + return this.hasAttribute("show"); + } + + set show(show: boolean) { + if (show) { + this.setAttribute("show", ""); + } else { + this.removeAttribute("show") + } + } + + set startSamp(start: boolean) { + if (start) { + this.setAttribute("startSamp", ""); + } else { + this.removeAttribute("startSamp") + } + } + + get startSamp(): boolean { + return this.hasAttribute("startSamp"); + } + + set configName(configName:string) { + if (configName != '') { + this.setAttribute("configName",configName ); + } else { + this.removeAttribute("configName") + } + } + + get configName():string{ + return this.getAttribute('configName') || '' + } + + get type():string{ + return this.getAttribute('type') || '' + } + + set type(type:string) { + if (type != '') { + this.setAttribute("type",type ); + } else { + this.removeAttribute("type") + } + } + + private wasmMap: Map = new Map(); + private wasmList: Array = [] + + private changGpu(gpuName: string) { + let config = this.wasmMap.get(gpuName); + this.pluginName = config?.pluginName; + this.sampleInterval = config?.sampleInterval; + let pam = { + action: "open", + componentId: config.componentId, + wasmJsName: config.wasmJsName, + WasmName: config.wasmName, + } + this.worker!.postMessage(pam) + this.worker!.onmessage = (event: MessageEvent) => { + let results = event.data.results; + this.configList = results.settingConfig; + this.initConfig() + } + } + + getPlugName(): string{ + return this.pluginName + } + + getSampleInterval(): number{ + return this.sampleInterval + } + + getGpuConfig(): any { + let configVal = this.shadowRoot?.querySelectorAll(".config"); + let gpuConfig:any = {} + for (let i = 0;i("sp-application"); + let wasmJsonUrl = `https://${window.location.host.split(':')[0]}:${window.location.port}/application/wasm.json` + if (spApplication!.hasAttribute("vs")) { + wasmJsonUrl = `http://${window.location.host.split(':')[0]}:${window.location.port}/wasm.json` + } + fetch(wasmJsonUrl).then(res => { + if (res.ok) { + res.text().then(text => { + this.wasmMap = new Map(); + this.wasmList = []; + let wasmJson = JSON.parse(text) + let wasmFiles = wasmJson.WasmFiles + wasmFiles.forEach((wasmFile: any) => { + this.wasmMap.set(wasmFile.disPlayName, wasmFile) + this.wasmList.push(wasmFile.disPlayName); + }) + + } + ) + } + } + ).catch(err => {}); + if (this.worker == null) { + this.worker = new Worker("trace/database/ConfigWorker.js"); + } + } catch (e) { + + } + this.customConfig = this.shadowRoot?.querySelector(".configList"); + let switchButton = this.shadowRoot?.querySelector(".config_switch") as LitSwitch; + switchButton.addEventListener("change", (event: any) => { + let detail = event.detail; + if (detail.checked) { + this.startSamp = true; + this.isAbleShowConfig(false); + } else { + this.startSamp = false; + this.isAbleShowConfig(true); + } + }) + this.selectConfig = this.shadowRoot?.querySelector('lit-allocation-select'); + let inputDiv = this.selectConfig?.shadowRoot?.querySelector('.multipleSelect') as HTMLDivElement + let input = this.selectConfig?.shadowRoot?.querySelector('#singleInput') + if (input) { + input.readOnly = true + inputDiv.addEventListener('inputClick', () => { + this.selectConfig!.processData = this.wasmList + this.selectConfig!.initData() + }) + inputDiv.addEventListener('valuable', ev => { + this.changGpu(input!.value); + }) + } + this.list = [] + this.list.push(this.selectConfig!) + this.isAbleShowConfig(true); + } + + initConfig() { + this.customConfig!.innerHTML = '' + this.list = [] + this.list.push(this.selectConfig!) + let switch1 = document.createElement("lit-switch") as LitSwitch; + for (let key in this.configList.configuration) { + let html = ''; + let div = document.createElement("div") + div.className = "config-div"; + let headDiv = document.createElement("div") + div.appendChild(headDiv); + let title = document.createElement("span") + title.className = "title"; + title.textContent = key; + headDiv.appendChild(title); + let des = document.createElement("span") + des.textContent = this.configList.configuration[key].description; + des.className = "des" + headDiv.appendChild(des); + switch (this.configList.configuration[key].type) { + case "string": + if (this.configList.configuration[key].enum) { + let placeholder = '' + if(this.configList.configuration[key].default){ + placeholder = this.configList.configuration[key].default + } + html += `` + div.innerHTML = div.innerHTML + html; + } else { + let inputElement = document.createElement("input"); + inputElement.className = "input config"; + if(this.configList.configuration[key].default){ + inputElement.value = this.configList.configuration[key].default; + } + inputElement.setAttribute("configName",key) + inputElement.setAttribute("type",this.configList.configuration[key].type) + div.appendChild(inputElement); + this.list.push(inputElement) + } + break; + case "number": + let numberInput = document.createElement("input"); + numberInput.className = "input config"; + if(this.configList.configuration[key].default){ + numberInput.value = this.configList.configuration[key].default; + } + numberInput.setAttribute("configName",key) + numberInput.setAttribute("type", "num") + numberInput.oninput = (ev) => { + let inputValue = this.checkFloatInput(numberInput.value) + numberInput.value = inputValue + } + div.appendChild(numberInput); + this.list.push(numberInput); + break; + case "integer": + let input = document.createElement("input"); + input.className = "input config"; + if(this.configList.configuration[key].default){ + input.value = this.configList.configuration[key].default; + } + input.setAttribute("configName",key) + input.setAttribute("type",this.configList.configuration[key].type) + input.oninput = (ev) => { + let inputValue = this.checkIntegerInput(input.value) + input.value = inputValue + title.setAttribute("value", input.value) + } + div.appendChild(input); + this.list.push(input); + break; + case "boolean": + switch1.className = "switch1 config"; + switch1.setAttribute("configName",key) + switch1.setAttribute("type",this.configList.configuration[key].type) + if (this.configList.configuration[key].default == 'true') { + switch1.setAttribute('checked', ''); + switch1.setAttribute("value","true") + } else { + switch1.removeAttribute('checked'); + switch1.setAttribute("value","false") + } + headDiv.appendChild(switch1); + this.list.push(switch1) + break; + } + this.customConfig!.appendChild(div); + if (this.configList.configuration[key].enum) { + let select = this.shadowRoot!.querySelector(`#${key}`); + select!.setAttribute("type","enum") + select!.setAttribute("value",this.configList.configuration[key].default) + select!.dataSource(this.configList.configuration[key].enum, ''); + this.list.push(select!) + select!.addEventListener("click", (event: any) => { + select!.setAttribute("value",select!.value) + }) + } + } + switch1.addEventListener("change", (event: any) => { + if(switch1.hasAttribute("checked")){ + switch1.setAttribute("value","true") + } else { + switch1.setAttribute("value","false") + } + }) + } + + checkIntegerInput(value: string): string { + let inputValue = value.replace(/[^\-\d]|\-{2,}/g, "") + .replace(/(\d)\-|-(0+)|^0+(\d)/g, "$1") + .replace(/(-?\d{15})\d*/, '$1'); + return inputValue + } + + checkFloatInput(value: string): string { + let inputValue = value.replace(/[^\d.]/g, "") + .replace(/^\.|^0+(\d)/g, '') + .replace(/(\.\d+)\.|(-)\.|(\d+|\.)-/g, '$1') + .replace(/(-?\d{9})\d*/, '$1'); + return inputValue.replace(/\.{2,}|-(0){2,}|(-)0+(\d+)/g, '.') + } + + isAbleShowConfig(isAbleShow: boolean) { + if(this.list!){ + if (isAbleShow) { + this.list!.forEach(item => { + item.setAttribute("disabled", ''); + }) + } else { + this.list!.forEach(item => { + item.removeAttribute("disabled"); + }) + } + } + } + + initConfigList(): void { + this.configList = + { + "name": "", + "configuration": { + "ss": { + "type": "string", + "default": "strsadsa", + "description": "xxxx", + }, + "aa": { + "type": "string", + "default": "11", + "enum": [ + "consistent", + "11", + "delegated" + ] + }, + "cc": { + "type": "number", + "description": "number1111", + }, + "ee": { + "type": "integer", + "default": "12", + "description": "integer1222", + }, + "ff": { + "type": "boolean", + "description": "switchhh", + } + } + } + } + + initHtml(): string { + return ` + +
+
+
+ Start Custom Config + +
+
+
+ +
+
+
+
+ `; + } +} diff --git a/host/ide/src/trace/component/setting/SpTraceCommand.ts b/host/ide/src/trace/component/setting/SpTraceCommand.ts index b3f2a542c08dd2e18081e2c665c6020ad30fef09..a5524c88913ba5f5cef00d636ff57bacaa3368ba 100644 --- a/host/ide/src/trace/component/setting/SpTraceCommand.ts +++ b/host/ide/src/trace/component/setting/SpTraceCommand.ts @@ -14,6 +14,7 @@ */ import {BaseElement, element} from "../../../base-ui/BaseElement.js"; +import {info} from "../../../log/Log.js"; @element('trace-command') export class SpTraceCommand extends BaseElement { @@ -21,11 +22,24 @@ export class SpTraceCommand extends BaseElement { private copyEl: HTMLElement | undefined | null; private codeCopyText: HTMLInputElement | undefined; + set show(show: boolean) { + if (show) { + this.setAttribute("show", '') + } else { + this.removeAttribute("show") + } + } + + get show() { + return this.hasAttribute("show") + } + get hdcCommon(): string { return this.codeHl!.textContent + ""; } set hdcCommon(value: string) { + info("hdc Common is:", value) this.codeHl!.textContent = value; } @@ -56,91 +70,115 @@ export class SpTraceCommand extends BaseElement { initHtml(): string { return ` - -
- - -
`; + +
+ + + +
+ `; } -} +} \ No newline at end of file diff --git a/host/ide/src/trace/component/setting/SpVmTracker.ts b/host/ide/src/trace/component/setting/SpVmTracker.ts new file mode 100644 index 0000000000000000000000000000000000000000..e3c9ecf765f80eb9c0009c7c975359e925d926a1 --- /dev/null +++ b/host/ide/src/trace/component/setting/SpVmTracker.ts @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../base-ui/BaseElement.js"; +import LitSwitch from "../../../base-ui/switch/lit-switch.js"; +import "../../../base-ui/select/LitAllocationSelect.js"; + +import "../../../base-ui/switch/lit-switch.js"; +import {LitAllocationSelect} from "../../../base-ui/select/LitAllocationSelect.js"; +import {SpRecordTrace} from "../SpRecordTrace.js"; +import {Cmd} from "../../../command/Cmd.js"; +import {CmdConstant} from "../../../command/CmdConstant.js"; +import {HdcDeviceManager} from "../../../hdc/HdcDeviceManager.js"; + +@element("sp-vm-tracker") +export class SpVmTracker extends BaseElement { + private processInput: LitAllocationSelect | undefined | null; + private selectProcess: HTMLInputElement | undefined | null; + private configList: Array = []; + + set startSamp(start: boolean) { + if (start) { + this.setAttribute("startSamp", ""); + this.selectProcess!.removeAttribute("readonly"); + } else { + this.removeAttribute("startSamp") + this.selectProcess!.setAttribute("readonly", "readonly") + } + } + + get process():string{ + if (this.processInput!.value.length > 0) { + let result = this.processInput!.value.match(/\((.+?)\)/g) + if (result) { + return result.toString().replace("(", "").replace(")", "") + } else { + return this.processInput!.value; + } + } + return "" + } + + get startSamp(): boolean { + return this.hasAttribute("startSamp"); + } + + initElements(): void { + this.initConfigList(); + let configList = this.shadowRoot?.querySelector(".configList"); + this.configList.forEach(config => { + let div = document.createElement("div"); + if (config.hidden) { + div.className = "config-div hidden"; + } else { + div.className = "config-div"; + } + let headDiv = document.createElement("div"); + div.appendChild(headDiv); + let title = document.createElement("span"); + title.className = "title"; + title.textContent = config.title; + headDiv.appendChild(title); + let des = document.createElement("span"); + des.textContent = config.des; + des.className = "des"; + headDiv.appendChild(des); + switch (config.type) { + case "select": + let html1 = ''; + html1 += `` + html1 += `` + div.innerHTML = div.innerHTML + html1; + break; + case "switch": + let switch1 = document.createElement("lit-switch") as LitSwitch; + switch1.className = "config"; + switch1.title = config.title; + if (config.value) { + switch1.checked = true; + } else { + switch1.checked = false; + } + if (config.title == "Start VM Tracker Record") { + switch1.addEventListener("change", (event: any) => { + let detail = event.detail; + if (detail.checked) { + this.startSamp = true; + this.unDisable(); + } else { + this.startSamp = false; + this.disable(); + } + }) + } + headDiv.appendChild(switch1); + break; + default: + break; + } + configList!.appendChild(div); + }); + this.processInput = this.shadowRoot?.querySelector("lit-allocation-select[title='Process']"); + let inputDiv = this.processInput?.shadowRoot?.querySelector('.multipleSelect') as HTMLDivElement + this.selectProcess = this.processInput!.shadowRoot?.querySelector("input") as HTMLInputElement; + let processData: Array = [] + inputDiv!.addEventListener('mousedown', ev => { + if (SpRecordTrace.serialNumber == '') { + this.processInput!.processData = [] + this.processInput!.initData() + } + }) + inputDiv!.addEventListener('mouseup', () => { + if (SpRecordTrace.serialNumber == '') { + this.processInput!.processData = [] + this.processInput!.initData() + } else { + if (SpRecordTrace.isVscode) { + let cmd = Cmd.formatString(CmdConstant.CMD_GET_PROCESS_DEVICES, [SpRecordTrace.serialNumber]) + Cmd.execHdcCmd(cmd, (res: string) => { + processData = [] + let lineValues: string[] = res.replace(/\r\n/g, "\r").replace(/\n/g, "\r").split(/\r/); + for (let lineVal of lineValues) { + if (lineVal.indexOf("__progname") != -1 || lineVal.indexOf("PID CMD") != -1) { + continue; + } + let process: string[] = lineVal.trim().split(" "); + if (process.length == 2) { + let processId = process[0] + let processName = process[1] + processData.push(processName + "(" + processId + ")") + } + } + if (processData.length > 0 && this.startSamp) { + this.processInput!.setAttribute("readonly", "readonly") + } + this.processInput!.processData = processData + this.processInput!.initData() + }) + } else { + HdcDeviceManager.connect(SpRecordTrace.serialNumber).then(conn => { + if (conn) { + HdcDeviceManager.shellResultAsString(CmdConstant.CMD_GET_PROCESS, false).then(res => { + processData = [] + if (res) { + let lineValues: string[] = res.replace(/\r\n/g, "\r").replace(/\n/g, "\r").split(/\r/); + for (let lineVal of lineValues) { + if (lineVal.indexOf("__progname") != -1 || lineVal.indexOf("PID CMD") != -1) { + continue; + } + let process: string[] = lineVal.trim().split(" "); + if (process.length == 2) { + let processId = process[0] + let processName = process[1] + processData.push(processName + "(" + processId + ")") + } + } + } + if (processData.length > 0 && this.startSamp) { + this.selectProcess!.setAttribute("readonly", "readonly") + } + this.processInput!.processData = processData + this.processInput!.initData() + }) + } + }) + } + } + }); + this.disable(); + } + + private unDisable() { + let configVal = this.shadowRoot?.querySelectorAll(".config"); + configVal!.forEach(configVal1 => { + configVal1.removeAttribute("disabled") + }) + } + + private disable() { + let configVal = this.shadowRoot?.querySelectorAll(".config"); + configVal!.forEach(configVal1 => { + if (configVal1.title != "Start VM Tracker Record") { + configVal1.setAttribute("disabled", '') + } + }) + } + + initConfigList(): void { + this.configList = [ + { + title: "Start VM Tracker Record", + des: "", + hidden: false, + type: "switch", + value: false + }, + { + title: "Process", + des: "Record process", + hidden: false, + type: "select", + selectArray: [ + '' + ] + } + ] + } + + initHtml(): string { + return ` + +
+
+
+
+ `; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/setting/bean/ProfilerServiceTypes.ts b/host/ide/src/trace/component/setting/bean/ProfilerServiceTypes.ts index 88464f8e900e24126542ee29ea9d5abaa83ed58c..28b6716eebdd3b656b4c17d2d87a61a971993552 100644 --- a/host/ide/src/trace/component/setting/bean/ProfilerServiceTypes.ts +++ b/host/ide/src/trace/component/setting/bean/ProfilerServiceTypes.ts @@ -81,10 +81,14 @@ export interface CreateSessionRequest { export interface ProfilerPluginConfig { pluginName: string; - sampleInterval: number; + sampleInterval?: number; configData: T; } +export interface FileSystemConfig { + cmdLine: string; + outfileName: string; +} export interface MemoryConfig { /** set true to report process list */ @@ -108,6 +112,8 @@ export interface MemoryConfig { reportAppMemByMemoryService: boolean; /** set required pid list */ pid: number[]; + /** set true to report smaps meminfo from /proc/${pid}/smaps */ + reportSmapsMemInfo?: boolean; } @@ -675,6 +681,7 @@ export enum SysMeminfoType { MEMINFO_VMALLOC_CHUNK = "PMEM_VMALLOC_CHUNK", MEMINFO_CMA_TOTAL = "PMEM_CMA_TOTAL", MEMINFO_CMA_FREE = "PMEM_CMA_FREE", + MEMINFO_KERNEL_RECLAIMABLE = "PMEM_KERNEL_RECLAIMABLE", UNRECOGNIZED = "UNRECOGNIZED", } @@ -782,6 +789,9 @@ export function sysMeminfoTypeFromJSON(object: any): SysMeminfoType { case 33: case "MEMINFO_CMA_FREE": return SysMeminfoType.MEMINFO_CMA_FREE; + case 34: + case "MEMINFO_KERNEL_RECLAIMABLE": + return SysMeminfoType.MEMINFO_KERNEL_RECLAIMABLE; case -1: case "UNRECOGNIZED": default: @@ -841,10 +851,53 @@ export interface NativeHookConfig { fileName: string, filterSize: number, smbPages: number, - maxStackDepth: number - processName: string + maxStackDepth: number, + processName: string, + mallocFreeMatchingInterval: number, + mallocFreeMatchingCnt: number, + stringCompressed: boolean + fpUnwind: boolean + blocked: boolean } export interface FpsConfig { reportFps: boolean; } + +export interface ProcessConfig { + report_process_tree: boolean; + report_cpu: boolean; + report_diskio: boolean; + report_pss: boolean; +} + +export interface CpuConfig { + pid: number; + reportProcessInfo: boolean; +} + +enum IoReportType { + UNSPECIFIED = "UNSPECIFIED", + IO_REPORT = "IO_REPORT", + IO_REPORT_EX = "IO_REPORT_EX" +} + +export interface DiskioConfig { + reportIoStats: string; +} + +export interface NetworkConfig { + testFile: string; +} + + +export interface HiperfPluginConfig { + isRoot: boolean; + outfileName: string; + recordArgs: string; +} + +export interface HiSystemEventConfig { + msg:string; + processName:string +} \ No newline at end of file diff --git a/host/ide/src/trace/component/setting/utils/PluginConvertUtils.ts b/host/ide/src/trace/component/setting/utils/PluginConvertUtils.ts index 895520db8b4c4564b71681162f2ee8662e7bf0c9..b4271aa15365e8767e94a56a3e2611013c9433c4 100644 --- a/host/ide/src/trace/component/setting/utils/PluginConvertUtils.ts +++ b/host/ide/src/trace/component/setting/utils/PluginConvertUtils.ts @@ -18,11 +18,13 @@ export class PluginConvertUtils { private static leftBrace: string = "{" private static rightBrace: string = "}" - public static createHdcCmd(requestString: string, time: number) { + public static createHdcCmd(requestString: string, outputPath: string, time: number) { return "hiprofiler_cmd \\" + this.crlf + " -c - \\" + this.crlf - + " -o /data/local/tmp/hiprofiler_data.htrace \\" + this.crlf + + " -o " + outputPath + " \\" + this.crlf + " -t " + time + " \\" + this.crlf + + " -s \\" + this.crlf + + " -k \\" + this.crlf + "<, indentation: number, needColon: boolean, spacesNumber: number): string { + private static handleArray(key: string, arr: Array, indentation: number, + needColon: boolean, spacesNumber: number): string { let text = ""; arr.forEach(arrValue => { switch (typeof arrValue) { case "bigint": - text = text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) + ": " + arrValue.toString() + this.crlf + text = text + + ' '.repeat(spacesNumber).repeat(indentation + 1) + + this.humpToSnake(key) + + ": " + + arrValue.toString() + + this.crlf break case "boolean": - text = text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) + ": " + arrValue.toString() + this.crlf + text = text + + ' '.repeat(spacesNumber).repeat(indentation + 1) + + this.humpToSnake(key) + + ": " + + arrValue.toString() + + this.crlf break case "number": - text = text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) + ": " + arrValue.toString() + this.crlf + text = text + + ' '.repeat(spacesNumber).repeat(indentation + 1) + + this.humpToSnake(key) + + ": " + + arrValue.toString() + + this.crlf break case "string": if (arrValue == '') { break } if (arrValue.startsWith("VMEMINFO") || arrValue.startsWith("PMEM")) { - text = text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) + ": " + arrValue.toString() + this.crlf + text = text + + ' '.repeat(spacesNumber).repeat(indentation + 1) + + this.humpToSnake(key) + + ": " + + arrValue.toString() + + this.crlf } else { - text = text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) + ": \"" + arrValue.toString() + "\"" + this.crlf + text = text + + ' '.repeat(spacesNumber).repeat(indentation + 1) + + this.humpToSnake(key) + + ": \"" + + arrValue.toString() + + "\"" + + this.crlf } break case "object": default: if (needColon) { - text = text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) + ": " + this.handleObj(arrValue, indentation + 1, needColon, spacesNumber) + "" + this.crlf + text = text + + ' '.repeat(spacesNumber).repeat(indentation + 1) + + this.humpToSnake(key) + + ": " + + this.handleObj(arrValue, indentation + 1, needColon, spacesNumber) + + "" + + this.crlf } else { - text = text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) + this.handleObj(arrValue, indentation + 1, needColon, spacesNumber) + "" + this.crlf + text = text + + ' '.repeat(spacesNumber).repeat(indentation + 1) + + this.humpToSnake(key) + + this.handleObj(arrValue, indentation + 1, needColon, spacesNumber) + + "" + + this.crlf } } }) @@ -127,6 +207,5 @@ export class PluginConvertUtils { private static humpToSnake(humpString: string): string { return humpString.replace(/[A-Z]/g, (value) => '_' + value.toLowerCase()); } - } diff --git a/host/ide/src/trace/component/trace/TimerShaftElement.ts b/host/ide/src/trace/component/trace/TimerShaftElement.ts index 04bb21e77cd9f1cafd4770788cc0d76c0fd90062..30b1fc5b669342c16aac869d8e830f39dcc2080c 100644 --- a/host/ide/src/trace/component/trace/TimerShaftElement.ts +++ b/host/ide/src/trace/component/trace/TimerShaftElement.ts @@ -20,6 +20,8 @@ import {RangeRuler, TimeRange} from "./timer-shaft/RangeRuler.js"; import {SportRuler} from "./timer-shaft/SportRuler.js"; import {procedurePool} from "../../database/Procedure.js"; import {Flag} from "./timer-shaft/Flag.js"; +import {info} from "../../../log/Log.js"; +import {LitIcon} from "../../../base-ui/icon/LitIcon"; //随机生成十六位进制颜色 export function randomRgbColor() { @@ -76,6 +78,7 @@ export class TimerShaftElement extends BaseElement { public timeTotalEL: HTMLSpanElement | null | undefined public timeOffsetEL: HTMLSpanElement | null | undefined public loadComplete: boolean = false + public collecBtn:HTMLElement | null | undefined rangeChangeHandler: ((timeRange: TimeRange) => void) | undefined = undefined flagChangeHandler: ((hoverFlag: Flag | undefined | null, selectFlag: Flag | undefined | null) => void) | undefined = undefined flagClickHandler: ((flag: Flag | undefined | null) => void) | undefined = undefined @@ -103,6 +106,7 @@ export class TimerShaftElement extends BaseElement { } set cpuUsage(value: Array<{ cpu: number, ro: number, rate: number }>) { + info("set cpuUsage values :", value); this._cpuUsage = value; if (this.rangeRuler) { this.rangeRuler.cpuUsage = this._cpuUsage; @@ -114,6 +118,7 @@ export class TimerShaftElement extends BaseElement { } set totalNS(value: number) { + info("set totalNS values :", value); this._totalNS = value; if (this.timeRuler) this.timeRuler.totalNS = value; if (this.rangeRuler) this.rangeRuler.range.totalNS = value; @@ -149,6 +154,7 @@ export class TimerShaftElement extends BaseElement { this.rangeRuler.cpuUsage = [] this.sportRuler!.flagList.length = 0 this.sportRuler!.isRangeSelect = false + this.setSlicesMark(); } this.removeTriangle("inverted"); this.totalNS = 10_000_000_000; @@ -160,6 +166,7 @@ export class TimerShaftElement extends BaseElement { this.totalEL = this.shadowRoot?.querySelector('.total') this.timeTotalEL = this.shadowRoot?.querySelector('.time-total') this.timeOffsetEL = this.shadowRoot?.querySelector('.time-offset') + this.collecBtn = this.shadowRoot?.querySelector('.time-collect') procedurePool.timelineChange = (a: any) => { this.rangeChangeHandler?.(a); } @@ -192,11 +199,18 @@ export class TimerShaftElement extends BaseElement { } if (!this.rangeRuler) { this.rangeRuler = new RangeRuler(this, new Rect(0, 25, width, 75), { + slicesTime: { + startTime: null, + endTime: null, + color: null, + }, + scale: 0, startX: 0, endX: this.canvas?.clientWidth || 0, startNS: 0, endNS: this.totalNS, totalNS: this.totalNS, + refresh: true, xs: [], xsTxt: [] }, (a) => { @@ -217,6 +231,7 @@ export class TimerShaftElement extends BaseElement { } setRangeNS(startNS: number, endNS: number) { + info("set startNS values :" + startNS + "endNS values : " + endNS); this.rangeRuler?.setRangeNS(startNS, endNS); } @@ -225,14 +240,7 @@ export class TimerShaftElement extends BaseElement { } updateWidth(width: number) { - if (this.isOffScreen) { - this.frame.width = width - (this.totalEL?.clientWidth || 0); - this.frame.height = this.shadowRoot!.host.clientHeight || 0; - this.canvasWidth = Math.round((this.frame.width) * this.dpr); - this.canvasHeight = Math.round((this.frame.height) * this.dpr); - this.render(); - return; - } + this.dpr = window.devicePixelRatio || 1; this.canvas!.width = width - (this.totalEL?.clientWidth || 0); this.canvas!.height = this.shadowRoot!.host.clientHeight || 0; let oldWidth = this.canvas!.width; @@ -251,173 +259,48 @@ export class TimerShaftElement extends BaseElement { } documentOnMouseDown = (ev: MouseEvent) => { - if (this.isOffScreen) { - procedurePool.submitWithName(`timeline`, `timeline`, { - offscreen: this.must ? this.offscreen : undefined,//是否离屏 - dpr: this.dpr,//屏幕dpr值 - hoverX: this.hoverX, - hoverY: this.hoverY, - canvasWidth: this.canvasWidth, - canvasHeight: this.canvasHeight, - offsetLeft: this.canvas?.offsetLeft || 0, - offsetTop: this.canvas?.offsetTop || 0, - mouseDown: {offsetX: ev.offsetX, offsetY: ev.offsetY}, - mouseUp: null, - mouseMove: null, - mouseOut: null, - keyPressCode: null, - keyUpCode: null, - lineColor: "#dadada", - startNS: this.startNS, - endNS: this.endNS, - totalNS: this.totalNS, - frame: this.frame, - }, this.must ? this.offscreen : undefined, (res: any) => { - this.must = false; - }) - } else { - this.rangeRuler?.mouseDown(ev); - } + if ((window as any).isSheetMove) return; + this.rangeRuler?.mouseDown(ev); } documentOnMouseUp = (ev: MouseEvent) => { - if (this.isOffScreen) { - procedurePool.submitWithName(`timeline`, `timeline`, { - offscreen: this.must ? this.offscreen : undefined,//是否离屏 - dpr: this.dpr,//屏幕dpr值 - hoverX: this.hoverX, - hoverY: this.hoverY, - canvasWidth: this.canvasWidth, - canvasHeight: this.canvasHeight, - offsetLeft: this.canvas?.offsetLeft || 0, - offsetTop: this.canvas?.offsetTop || 0, - mouseUp: {offsetX: ev.offsetX, offsetY: ev.offsetY}, - mouseMove: null, - mouseOut: null, - keyPressCode: null, - keyUpCode: null, - lineColor: "#dadada", - startNS: this.startNS, - endNS: this.endNS, - totalNS: this.totalNS, - frame: this.frame, - }, this.must ? this.offscreen : undefined, (res: any) => { - this.must = false; - }) - } else { - this.rangeRuler?.mouseUp(ev); - this._sportRuler?.mouseUp(ev); - } + if ((window as any).isSheetMove) return; + this.rangeRuler?.mouseUp(ev); + this.sportRuler?.mouseUp(ev); } documentOnMouseMove = (ev: MouseEvent) => { - if (this.isOffScreen) { - procedurePool.submitWithName(`timeline`, `timeline`, { - offscreen: this.must ? this.offscreen : undefined,//是否离屏 - dpr: this.dpr,//屏幕dpr值 - hoverX: this.hoverX, - hoverY: this.hoverY, - canvasWidth: this.canvasWidth, - canvasHeight: this.canvasHeight, - offsetLeft: this.canvas?.offsetLeft || 0, - offsetTop: this.canvas?.offsetTop || 0, - mouseMove: {offsetX: ev.offsetX, offsetY: ev.offsetY}, - mouseOut: null, - keyPressCode: null, - keyUpCode: null, - lineColor: "#dadada", - startNS: this.startNS, - endNS: this.endNS, - totalNS: this.totalNS, - frame: this.frame, - }, this.must ? this.offscreen : undefined, (res: any) => { - this.must = false; - }) - } else { - this.rangeRuler?.mouseMove(ev); - this._sportRuler?.mouseMove(ev); - } + this.rangeRuler?.mouseMove(ev); + this.sportRuler?.mouseMove(ev); } documentOnMouseOut = (ev: MouseEvent) => { - if (this.isOffScreen) { - procedurePool.submitWithName(`timeline`, `timeline`, { - offscreen: this.must ? this.offscreen : undefined,//是否离屏 - dpr: this.dpr,//屏幕dpr值 - hoverX: this.hoverX, - hoverY: this.hoverY, - canvasWidth: this.canvasWidth, - canvasHeight: this.canvasHeight, - offsetLeft: this.canvas?.offsetLeft || 0, - offsetTop: this.canvas?.offsetTop || 0, - mouseOut: {offsetX: ev.offsetX, offsetY: ev.offsetY}, - keyPressCode: null, - keyUpCode: null, - lineColor: "#dadada", - startNS: this.startNS, - endNS: this.endNS, - totalNS: this.totalNS, - frame: this.frame, - }, this.must ? this.offscreen : undefined, (res: any) => { - this.must = false; - }) - } else { - this.rangeRuler?.mouseOut(ev); - } + this.rangeRuler?.mouseOut(ev); } documentOnKeyPress = (ev: KeyboardEvent) => { - if (this.isOffScreen) { - procedurePool.submitWithName(`timeline`, `timeline`, { - offscreen: this.must ? this.offscreen : undefined,//是否离屏 - dpr: this.dpr,//屏幕dpr值 - hoverX: this.hoverX, - hoverY: this.hoverY, - canvasWidth: this.canvasWidth, - canvasHeight: this.canvasHeight, - keyPressCode: {key: ev.key}, - keyUpCode: null, - lineColor: "#dadada", - startNS: this.startNS, - endNS: this.endNS, - totalNS: this.totalNS, - frame: this.frame, - }, this.must ? this.offscreen : undefined, (res: any) => { - this.must = false; - }) - } else { - this.rangeRuler?.keyPress(ev); - } + if ((window as any).isSheetMove) return; + if ((window as any).flagInputFocus) return; + this.rangeRuler?.keyPress(ev); } documentOnKeyUp = (ev: KeyboardEvent) => { - if (this.isOffScreen) { - procedurePool.submitWithName(`timeline`, `timeline`, { - offscreen: this.must ? this.offscreen : undefined,//是否离屏 - dpr: this.dpr,//屏幕dpr值 - hoverX: this.hoverX, - hoverY: this.hoverY, - canvasWidth: this.canvasWidth, - canvasHeight: this.canvasHeight, - keyPressCode: null, - keyUpCode: {key: ev.key}, - lineColor: "#dadada", - startNS: this.startNS, - endNS: this.endNS, - totalNS: this.totalNS, - frame: this.frame, - }, this.must ? this.offscreen : undefined, (res: any) => { - this.must = false; - }) - } else { - this.rangeRuler?.keyUp(ev); - } + if ((window as any).isSheetMove) return; + if ((window as any).flagInputFocus) return; + this.rangeRuler?.keyUp(ev); } disconnectedCallback() { } + firstRender = true; + + lineColor(){ + return window.getComputedStyle(this.canvas!, null).getPropertyValue("color"); + } + render() { + this.dpr = window.devicePixelRatio||1; if (this.ctx) { this.ctx.fillStyle = 'transparent'; this.ctx?.fillRect(0, 0, this.canvas?.width || 0, this.canvas?.height || 0) @@ -449,73 +332,110 @@ export class TimerShaftElement extends BaseElement { this._sportRuler?.modifyFlagList(flag); } + cancelPressFrame() { + this.rangeRuler?.cancelPressFrame(); + } + + cancelUpFrame() { + this.rangeRuler?.cancelUpFrame(); + } + + drawTriangle(time: number, type: string) { - this._sportRuler?.drawTriangle(time, type); + return this._sportRuler?.drawTriangle(time, type); } - removeTriangle(type:string){ + removeTriangle(type: string) { this._sportRuler?.removeTriangle(type) } + setSlicesMark(startTime: null | number = null, endTime: null | number = null) { + this._sportRuler?.setSlicesMark(startTime, endTime) + } + + displayCollect(showCollect: boolean){ + if(showCollect){ + this.collecBtn!.style.visibility = 'visible' + }else { + this.collecBtn!.style.visibility = 'hidden' + } + } + initHtml(): string { return ` - -
-
-
-
- 10 - 0 + +
+
+
+
+ 10 + 0 +
+ +
+ +
+
+
-
- -
`; } } diff --git a/host/ide/src/trace/component/trace/base/ColorUtils.ts b/host/ide/src/trace/component/trace/base/ColorUtils.ts index e5798ef2ee798b9c6dc93218fc0947fb819f46ff..2c66f574d1dc62b3c1cbfcb7d5cf0de05069da8d 100644 --- a/host/ide/src/trace/component/trace/base/ColorUtils.ts +++ b/host/ide/src/trace/component/trace/base/ColorUtils.ts @@ -13,40 +13,44 @@ * limitations under the License. */ -import {CpuStruct} from "../../../bean/CpuStruct.js"; + +import {CpuStruct} from "../../../database/ui-worker/ProcedureWorkerCPU.js"; export class ColorUtils { public static GREY_COLOR: string = "#f0f0f0" public static MD_PALETTE: Array = [ - "#3391ff", - "#0076ff", - "#66adff", - "#2db3aa", - "#008078", - "#73e6de", - "#535da6", - "#38428c", - "#7a84cc", - "#ff9201", - "#ff7500", - "#ffab40", - "#2db4e2", - "#0094c6", - "#7cdeff", - "#ffd44a", - "#fbbf00", - "#ffe593", + "#9785D3", + "#A27F7E", + "#00bdd6", + "#94B5F4", + "#B282F6", + "#E97978", + "#7AD7E6", + "#A1C38A", + "#DB8E86", + "#42B7A4", + "#AACEA0", + "#E69553", + "#7EC6BB", + "#C6D9F2", ]; public static FUNC_COLOR: Array = [ - "#3391ff", - "#2db4e2", - "#2db3aa", - "#ffd44a", - "#535da6", - "#008078", - "#ff9201", - "#38428c"]; + "#9785D3", + "#A27F7E", + "#00bdd6", + "#94B5F4", + "#B282F6", + "#E97978", + "#7AD7E6", + "#A1C38A", + "#DB8E86", + "#42B7A4", + "#AACEA0", + "#E69553", + "#7EC6BB", + "#C6D9F2", + ]; public static hash(str: string, max: number): number { let colorA: number = 0x811c9dc5; @@ -76,6 +80,7 @@ export class ColorUtils { } public static formatNumberComma(str: number): string { + if(!str) return ""; let l = str.toString().split("").reverse(); let t: string = ""; for (let i = 0; i < l.length; i++) { @@ -83,4 +88,18 @@ export class ColorUtils { } return t.split("").reverse().join("") } -} + + public static hashFunc(str: string, depth: number, max: number): number { + let colorA: number = 0x811c9dc5; + let colorB: number = 0xfffffff; + let colorC: number = 16777619; + let colorD: number = 0xffffffff; + let hash: number = colorA & colorB; + let st = str.replace(/[0-9]+/g, ""); + for (let index: number = 0; index < st.length; index++) { + hash ^= st.charCodeAt(index); + hash = (hash * colorC) & colorD; + } + return (Math.abs(hash) + depth) % max; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/base/Extension.ts b/host/ide/src/trace/component/trace/base/Extension.ts new file mode 100644 index 0000000000000000000000000000000000000000..cba2aec9731955d309e5362d61a27a0e6573f4ed --- /dev/null +++ b/host/ide/src/trace/component/trace/base/Extension.ts @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare global { + interface Number { + n2x(): number; + } + + interface Array { + isEmpty(): boolean; + + isNotEmpty(): boolean; + } + + interface HTMLElement { + containPoint(ev: MouseEvent, cut?: { left?: number, right?: number, top?: number, bottom?: number }): boolean; + } +} + +Number.prototype.n2x = function (): number { + return Number(this); +} + +Array.prototype.isEmpty = function (): boolean { + return this == null || this == undefined || this.length == 0; +} +Array.prototype.isNotEmpty = function (): boolean { + return this != null && this != undefined && this.length > 0; +} + +HTMLElement.prototype.containPoint = function (ev, cut) { + let rect = this.getBoundingClientRect(); + return ev.pageX >= (rect.left + (cut?.left ?? 0)) + && ev.pageX <= (rect.right - (cut?.right ?? 0)) + && ev.pageY >= (rect.top + (cut?.top ?? 0)) + && ev.pageY <= (rect.bottom - (cut?.bottom ?? 0)); +} + +export {}; \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/base/RangeSelect.ts b/host/ide/src/trace/component/trace/base/RangeSelect.ts index 3e2e8f5b3f9d8f1dab7d6e4a42f97a39f43cdb03..8e3d4c41379141bf9b1a89fe0e883dd87a20feb3 100644 --- a/host/ide/src/trace/component/trace/base/RangeSelect.ts +++ b/host/ide/src/trace/component/trace/base/RangeSelect.ts @@ -16,9 +16,14 @@ import {RangeSelectStruct, TraceRow} from "./TraceRow.js"; import {Rect} from "../timer-shaft/Rect.js"; import {ns2x, TimerShaftElement} from "../TimerShaftElement.js"; +import {info} from "../../../../log/Log.js"; +import "./Extension.js" +import {SpSystemTrace} from "../../SpSystemTrace.js"; export class RangeSelect { - rowsEL: HTMLDivElement | undefined | null; + private rowsEL: HTMLDivElement | undefined | null; + private rowsPaneEL: HTMLDivElement | undefined | null; + private favoriteRowsEL: HTMLDivElement | undefined | null; isMouseDown: boolean = false; public rangeTraceRow: Array> | undefined public selectHandler: ((ds: Array>, refreshCheckBox: boolean) => void) | undefined; @@ -33,28 +38,25 @@ export class RangeSelect { private isHover: boolean = false; private movingMark: string = ""; private mark: { startMark: number, endMark: number } = {startMark: 0, endMark: 0} - private spacerEL: HTMLDivElement; - - constructor(timerShaftEL: TimerShaftElement | null | undefined) { - this.timerShaftEL = timerShaftEL; + private readonly spacerEL: HTMLDivElement; + private trace: SpSystemTrace | null | undefined; + drag = false; + constructor(trace: SpSystemTrace | null | undefined) { + this.trace = trace; + this.timerShaftEL = trace?.timerShaftEL; this.timerShaftDragEL = this.timerShaftEL?.shadowRoot?.querySelector(".total > div:nth-child(1)"); - this.spacerEL = this.timerShaftEL?.nextElementSibling! as HTMLDivElement; + this.spacerEL = trace?.spacerEL!; + this.rowsEL = trace?.rowsEL; + this.rowsPaneEL = trace?.rowsPaneEL; + this.favoriteRowsEL = trace?.favoriteRowsEL } isInRowsEl(ev: MouseEvent): boolean { - return (ev.offsetY > this.timerShaftDragEL!.clientHeight! && - ev.offsetY < this.rowsEL!.offsetTop + this.rowsEL!.offsetHeight && - ev.offsetX > this.rowsEL!.offsetLeft! && - ev.offsetX < this.rowsEL!.offsetLeft + this.rowsEL!.offsetWidth - ) + return this.rowsPaneEL!.containPoint(ev, {left: 248}); } isInSpacerEL(ev: MouseEvent): boolean { - return (ev.offsetY > this.spacerEL.offsetTop && - ev.offsetY < this.spacerEL.offsetTop + this.spacerEL.offsetHeight && - ev.offsetX > this.spacerEL.offsetLeft! && - ev.offsetX < this.spacerEL.offsetLeft + this.spacerEL.offsetWidth - ) + return this.spacerEL.containPoint(ev, {left: 248}); } mouseDown(ev: MouseEvent) { @@ -65,26 +67,27 @@ export class RangeSelect { if (this.isInRowsEl(ev)) { this.rangeTraceRow = []; this.isMouseDown = true; - this.startX = ev.offsetX - this.rowsEL!.offsetLeft!; + TraceRow.rangeSelectObject = undefined; + this.startX = ev.pageX - this.rowsEL!.getBoundingClientRect().left - 248; if (this.isInSpacerEL(ev)) { this.startY = 0; - this.startY2 = ev.offsetY + 48; + this.startY2 = ev.pageY - this.spacerEL.getBoundingClientRect().top - this.rowsPaneEL!.scrollTop; } else { - this.startY = ev.offsetY - this.rowsEL!.offsetTop!; - this.startY2 = this.spacerEL.offsetTop + this.spacerEL.offsetHeight! + 48; + this.startY = ev.pageY - this.rowsEL!.getBoundingClientRect().top + this.spacerEL.getBoundingClientRect().height; + this.startY2 = ev.pageY - this.spacerEL!.getBoundingClientRect().top - this.rowsPaneEL!.scrollTop; } } } mouseUp(ev: MouseEvent) { - if (this.isInRowsEl(ev) && this.isDrag()) { - this.endX = ev.offsetX - this.rowsEL!.offsetLeft!; + if (this.drag) { + this.endX = ev.pageX - this.rowsEL!.getBoundingClientRect().left - 248; if (this.isInSpacerEL(ev)) { - this.endY = ev.offsetY - this.rowsEL!.clientTop! + this.rowsEL!.offsetTop!; - this.endY2 = ev.offsetY + 48; + this.endY = 0; + this.endY2 = ev.pageY - this.spacerEL!.getBoundingClientRect().top - this.rowsPaneEL!.scrollTop; } else { - this.endY = ev.offsetY - this.rowsEL!.clientTop! + this.rowsEL!.offsetTop!; - this.endY2 = this.spacerEL.offsetTop + this.spacerEL.offsetHeight! + 48; + this.endY = ev.pageY - this.rowsEL!.getBoundingClientRect().top + this.spacerEL.getBoundingClientRect().height; + this.endY2 = ev.pageY - this.spacerEL!.getBoundingClientRect().top - this.rowsPaneEL!.scrollTop; } if (this.selectHandler) { this.selectHandler(this.rangeTraceRow || [], !this.isHover); @@ -94,50 +97,71 @@ export class RangeSelect { } isDrag(): boolean { - return this.startX != this.endX && (this.startY != this.endY || this.startY2 != this.endY2) + return this.startX != this.endX } isTouchMark(ev: MouseEvent): boolean { - let notTimeHeight: boolean = ev.offsetY > (this.timerShaftDragEL!.clientHeight || 0) + let notTimeHeight: boolean = this.rowsPaneEL!.containPoint(ev, {left: 248, top: -45}); if (!notTimeHeight) { - this.isHover = false; return false } - if ((this.rangeTraceRow ? this.rangeTraceRow.length == 0 : false) && !this.isMouseDown) { + if ((this.rangeTraceRow?.isEmpty() ?? false) && !this.isMouseDown) { this.isHover = false; } - return notTimeHeight && (this.rangeTraceRow ? this.rangeTraceRow.length > 0 : false) && !this.isMouseDown + return notTimeHeight && (this.rangeTraceRow?.isNotEmpty() ?? false) && !this.isMouseDown + } + + mouseOut(ev: MouseEvent){ + if (this.drag) { + this.endX = this.rowsEL!.getBoundingClientRect().right - this.rowsEL!.getBoundingClientRect().left - 248; + if (this.isInSpacerEL(ev)) { + this.endY = 0; + this.endY2 = ev.pageY - this.spacerEL!.getBoundingClientRect().top - this.rowsPaneEL!.scrollTop; + } else { + this.endY = ev.pageY - this.rowsEL!.getBoundingClientRect().top + this.spacerEL.getBoundingClientRect().height; + this.endY2 = ev.pageY - this.spacerEL!.getBoundingClientRect().top - this.rowsPaneEL!.scrollTop; + } + if (this.selectHandler && this.isMouseDown) { + this.selectHandler(this.rangeTraceRow || [], !this.isHover); + } + } + document.getSelection()?.removeAllRanges() + this.isMouseDown = false; } mouseMove(rows: Array>, ev: MouseEvent) { - if (this.isTouchMark(ev)) { - let markA = ns2x(TraceRow.rangeSelectObject!.startNS!, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS!, {width: this.timerShaftEL?.canvas?.clientWidth || 0} as Rect); - let markB = ns2x(TraceRow.rangeSelectObject!.endNS!, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS!, {width: this.timerShaftEL?.canvas?.clientWidth || 0} as Rect); - this.mark = {startMark: markA, endMark: markB}; - let mouseX = ev.offsetX - (this.timerShaftEL?.totalEL?.clientWidth || 0) - if ((mouseX > markA - 5 && mouseX < markA + 5)) { + if (this.isTouchMark(ev) && TraceRow.rangeSelectObject) { + info("isTouchMark"); + let x1 = (TraceRow.rangeSelectObject!.startNS! - TraceRow.range!.startNS) * (this.timerShaftEL?.canvas?.clientWidth || 0) / (TraceRow.range!.endNS - TraceRow.range!.startNS) + let x2 = (TraceRow.rangeSelectObject!.endNS! - TraceRow.range!.startNS) * (this.timerShaftEL?.canvas?.clientWidth || 0) / (TraceRow.range!.endNS - TraceRow.range!.startNS) + this.mark = {startMark: x1, endMark: x2}; + let mouseX = ev.pageX - this.rowsPaneEL!.getBoundingClientRect().left - 248; + if ((mouseX > x1 - 5 && mouseX < x1 + 5)) { this.isHover = true; document.body.style.cursor = "ew-resize" - this.movingMark = markA < markB ? "markA" : "markB" - } else if (mouseX > markB - 5 && mouseX < markB + 5) { + this.movingMark = x1 < x2 ? "markA" : "markB" + } else if (mouseX > x2 - 5 && mouseX < x2 + 5) { this.isHover = true; document.body.style.cursor = "ew-resize" - this.movingMark = markB < markA ? "markA" : "markB" + this.movingMark = x2 < x1 ? "markA" : "markB" } else { this.isHover = false; } } - if (this.isHover && this.isMouseDown) { + if ((this.isHover && this.isMouseDown)) { let rangeSelect: RangeSelectStruct | undefined; this.rangeTraceRow = rows.filter(it => { if (it.rangeSelect) { if (!rangeSelect) { rangeSelect = new RangeSelectStruct(); - let mouseX = ev.offsetX - this.rowsEL!.offsetLeft! - (it.canvasContainer?.offsetLeft || 248) + let mouseX = ev.pageX - this.rowsEL!.getBoundingClientRect().left - 248; + mouseX = mouseX<0 ? 0 : mouseX; let markA = this.movingMark == "markA" ? mouseX : this.mark.startMark; let markB = this.movingMark == "markB" ? mouseX : this.mark.endMark; let startX = markA < markB ? markA : markB let endX = markB < markA ? markA : markB + rangeSelect.startX = startX; + rangeSelect.endX = endX; rangeSelect.startNS = Math.floor((TraceRow.range!.endNS - TraceRow.range!.startNS) * startX / it.frame.width + TraceRow.range!.startNS!); rangeSelect.endNS = Math.floor((TraceRow.range!.endNS - TraceRow.range!.startNS) * endX / it.frame.width + TraceRow.range!.startNS!); if (rangeSelect.startNS <= TraceRow.range!.startNS) { @@ -146,6 +170,8 @@ export class RangeSelect { if (rangeSelect.endNS >= TraceRow.range!.endNS) { rangeSelect.endNS = TraceRow.range!.endNS } + if (startX < 0) {rangeSelect.startNS = TraceRow.rangeSelectObject!.startNS!} + if (endX > it.frame.width) {rangeSelect.endNS = TraceRow.rangeSelectObject!.endNS!} } TraceRow.rangeSelectObject = rangeSelect; return true @@ -156,38 +182,53 @@ export class RangeSelect { return; } if (!this.isMouseDown) { - this.timerShaftEL!.sportRuler!.isRangeSelect = (this.rangeTraceRow?.length || 0) > 0; + this.timerShaftEL!.sportRuler!.isRangeSelect = this.rangeTraceRow?.isNotEmpty() ?? false; this.timerShaftEL!.sportRuler!.draw(); return; } - this.endX = ev.offsetX - this.rowsEL!.offsetLeft!; + // this.endX = ev.offsetX - this.rowsEL!.offsetLeft!; + this.endX = ev.pageX - this.rowsEL!.getBoundingClientRect().left - 248; if (this.isInSpacerEL(ev)) { this.endY = 0; - this.endY2 = ev.offsetY + 48; + // this.endY2 = ev.offsetY + 48; + this.endY2 = ev.pageY - this.spacerEL!.getBoundingClientRect().top - this.rowsPaneEL!.scrollTop; } else { - this.endY = ev.offsetY - this.rowsEL!.offsetTop!; - this.endY2 = this.spacerEL.offsetTop + this.spacerEL.offsetHeight! + 48; + // this.endY = ev.offsetY - this.rowsEL!.offsetTop!; + this.endY = ev.pageY - this.rowsEL!.getBoundingClientRect().top + this.spacerEL.getBoundingClientRect().height; + // this.endY2 = this.spacerEL.offsetTop + this.spacerEL.offsetHeight! + 48; + this.endY2 = ev.pageY - this.spacerEL!.getBoundingClientRect().top - this.rowsPaneEL!.scrollTop; } - let scrollTop = this.rowsEL?.scrollTop || 0 + let scrollTop = this.rowsPaneEL?.scrollTop || 0 let xMin = this.startX < this.endX ? this.startX : this.endX; let xMax = this.startX > this.endX ? this.startX : this.endX; let yMin = this.startY < this.endY ? this.startY : this.endY; let yMax = this.startY > this.endY ? this.startY : this.endY; let rangeSelect: RangeSelectStruct | undefined; + let spacerRect = this.favoriteRowsEL!.getBoundingClientRect(); + let rowsRect = this.rowsPaneEL!.getBoundingClientRect(); this.rangeTraceRow = rows.filter(it => { let rt: Rect; - let canvasOffsetLeft = (it.canvasContainer?.offsetLeft || 0); - let canvasOffsetTop = (it.canvasContainer?.offsetTop || 0); + let bound:DOMRect|any + let itRect: Rect; if (it.collect) { - rt = new Rect(xMin - canvasOffsetLeft, Math.min(this.startY2, this.endY2) - it.offsetTop, xMax - xMin, Math.abs(this.startY2 - this.endY2)); + bound = it.getBoundingClientRect(); + itRect = Rect.getIntersect(bound,spacerRect) + rt = new Rect(xMin, Math.min(this.startY2, this.endY2), xMax - xMin, Math.abs(this.startY2 - this.endY2)); } else { - rt = new Rect(xMin - canvasOffsetLeft, yMin - canvasOffsetTop + scrollTop + this.rowsEL!.offsetTop, xMax - xMin, yMax - yMin); + bound = it.getBoundingClientRect(); + itRect = Rect.getIntersect(bound,new Rect(rowsRect.x,rowsRect.y + spacerRect.height,rowsRect.width,rowsRect.height - spacerRect.height)) + rt = new Rect(xMin, yMin - scrollTop, xMax - xMin, yMax - yMin); } - if (Rect.intersect(it.frame, rt)) { + itRect.x -= 248; + itRect.y -= 195; + if (Rect.intersect(itRect, rt)) { if (!rangeSelect) { + it.setTipLeft(0, null); rangeSelect = new RangeSelectStruct(); let startX = Math.floor(rt.x <= 0 ? 0 : rt.x); let endX = Math.floor((rt.x + rt.width) > it.frame.width ? it.frame.width : (rt.x + rt.width)); + rangeSelect.startX = startX; + rangeSelect.endX = endX; rangeSelect.startNS = Math.floor((TraceRow.range!.endNS - TraceRow.range!.startNS) * startX / it.frame.width + TraceRow.range!.startNS!); rangeSelect.endNS = Math.floor((TraceRow.range!.endNS - TraceRow.range!.startNS) * endX / it.frame.width + TraceRow.range!.startNS!); } @@ -199,7 +240,7 @@ export class RangeSelect { return false; } }) - this.timerShaftEL!.sportRuler!.isRangeSelect = (this.rangeTraceRow?.length || 0) > 0; + this.timerShaftEL!.sportRuler!.isRangeSelect = this.rangeTraceRow?.length > 0; this.timerShaftEL!.sportRuler!.draw(); } } diff --git a/host/ide/src/trace/component/trace/base/TraceRow.ts b/host/ide/src/trace/component/trace/base/TraceRow.ts index dc54efbbd5b7119d649fb579d795c6ba0b3ecf8b..c3e0691e98621f58a0118d8e01cb348fe92a7da9 100644 --- a/host/ide/src/trace/component/trace/base/TraceRow.ts +++ b/host/ide/src/trace/component/trace/base/TraceRow.ts @@ -25,6 +25,9 @@ import {LitCheckBox} from "../../../../base-ui/checkbox/LitCheckBox.js"; import {LitIcon} from "../../../../base-ui/icon/LitIcon"; import "../../../../base-ui/popover/LitPopoverV.js" import {LitPopover} from "../../../../base-ui/popover/LitPopoverV.js"; +import {info} from "../../../../log/Log.js"; +import {ColorUtils} from "./ColorUtils.js"; +import {drawSelectionRange} from "../../../database/ui-worker/ProcedureWorkerCommon.js"; export class RangeSelectStruct { startX: number | undefined @@ -33,17 +36,47 @@ export class RangeSelectStruct { endNS: number | undefined } +let collectList: Array = []; +let rowDragElement: EventTarget | undefined | null; +let dragDirection: string = ""; + @element('trace-row') export class TraceRow extends HTMLElement { - static ROW_TYPE_CPU = "cpu" + static ROW_TYPE_CPU = "cpu-data" + static ROW_TYPE_CPU_STATE = "cpu-state" static ROW_TYPE_CPU_FREQ = "cpu-freq" + static ROW_TYPE_CPU_FREQ_LIMIT = "cpu-limit-freq" static ROW_TYPE_FPS = "fps" static ROW_TYPE_NATIVE_MEMORY = "native-memory" + static ROW_TYPE_HIPERF = "hiperf" + static ROW_TYPE_HIPERF_CPU = "hiperf-cpu" + static ROW_TYPE_HIPERF_PROCESS = "hiperf-process" + static ROW_TYPE_HIPERF_THREAD = "hiperf-thread" + static ROW_TYPE_HIPERF_REPORT = "hiperf-report" + static ROW_TYPE_HIPERF_EVENT = "hiperf-event" static ROW_TYPE_PROCESS = "process" static ROW_TYPE_THREAD = "thread" static ROW_TYPE_MEM = "mem" + static ROW_TYPE_VIRTUAL_MEMORY_GROUP = "virtual-memory-group" + static ROW_TYPE_VIRTUAL_MEMORY = "virtual-memory-cell" + static ROW_TYPE_FILE_SYSTEM_GROUP = "file-system-group" + static ROW_TYPE_FILE_SYSTEM = "file-system-cell" static ROW_TYPE_HEAP = "heap" static ROW_TYPE_FUNC = "func" + static ROW_TYPE_MONITOR = "ability-monitor" + static ROW_TYPE_CPU_ABILITY = "cpu-ability" + static ROW_TYPE_MEMORY_ABILITY = "memory-ability" + static ROW_TYPE_DISK_ABILITY = "disk-ability" + static ROW_TYPE_NETWORK_ABILITY = "network-ability" + static ROW_TYPE_SDK = "sdk" + static ROW_TYPE_SDK_COUNTER = "sdk-counter" + static ROW_TYPE_SDK_SLICE = "sdk-slice" + static ROW_TYPE_ENERGY = "energy" + static ROW_TYPE_ANOMALY_ENERGY = "anomaly-energy" + static ROW_TYPE_SYSTEM_ENERGY = "system-energy" + static ROW_TYPE_POWER_ENERGY = "power-energy" + static ROW_TYPE_STATE_ENERGY = "state-energy" + static ROW_TYPE_SMAPS = "smaps" static range: TimeRange | undefined | null; static rangeSelectObject: RangeSelectStruct | undefined public obj: TraceRowObject | undefined | null; @@ -55,15 +88,16 @@ export class TraceRow extends HTMLElement { public isTransferCanvas = false; onComplete: Function | undefined; isComplete: boolean = false; - public dataList: undefined | Array; - public describeEl: Element | null | undefined; + public dataList: Array = []; + public dataList2: Array = []; + public dataListCache: Array = []; + public describeEl: HTMLElement | null | undefined; public canvas: Array = []; public canvasContainer: HTMLDivElement | null | undefined; public tipEL: HTMLDivElement | null | undefined; public checkBoxEL: LitCheckBox | null | undefined; public collectEL: LitIcon | null | undefined; - public onDrawHandler: ((ctx: CanvasRenderingContext2D) => void) | undefined | null - public onThreadHandler: ((useCache: boolean) => void) | undefined | null + public onThreadHandler: ((useCache: boolean, buf: ArrayBuffer | undefined | null) => void) | undefined | null public onDrawTypeChangeHandler: ((type: number) => void) | undefined | null public supplier: (() => Promise>) | undefined | null public favoriteChangeHandler: ((fav: TraceRow) => void) | undefined | null @@ -74,27 +108,60 @@ export class TraceRow extends HTMLElement { canvasWidth = 0 canvasHeight = 0 public _frame: Rect | undefined; + public isLoading: boolean = false + public readonly args: any; private rootEL: HTMLDivElement | null | undefined; private nameEL: HTMLLabelElement | null | undefined; - public isLoading: boolean = false private _rangeSelect: boolean = false; - public readonly args: any; private _drawType: number = 0 + private folderIconEL: LitIcon | null | undefined; + online: boolean = false; + static isUserInteraction: boolean; + asyncFuncName: string | undefined | null; + asyncFuncNamePID: number | undefined | null; + translateY: number = 0;//single canvas offsetY; + focusHandler?: (ev: MouseEvent) => void | undefined; - constructor(args: { canvasNumber: number, alpha: boolean, contextId: string, isOffScreen: boolean }) { + constructor(args: { canvasNumber: number, alpha: boolean, contextId: string, isOffScreen: boolean, skeleton?: boolean } = { + canvasNumber: 1, alpha: false, contextId: "2d", isOffScreen: true, skeleton: false + }) { super(); this.args = args; this.attachShadow({mode: 'open'}).innerHTML = this.initHtml(); this.initElements(); } + static skeleton(): TraceRow { + let tr = new TraceRow({ + alpha: false, canvasNumber: 0, contextId: "", isOffScreen: false, skeleton: true + }); + tr.isTransferCanvas = true; + return tr; + } + static get observedAttributes() { return ["folder", "name", "expansion", "children", "height", "row-type", "row-id", "row-parent-id", "sleeping", "check-type", - "collect-type" + "collect-type", + "disabled-check", + "row-discard", ]; } + get rowDiscard(): boolean { + return this.hasAttribute("row-discard"); + } + + set rowDiscard(value: boolean) { + if (value) { + this.setAttribute("row-discard", "") + this.style.display = "none"; + } else { + this.removeAttribute("row-discard") + this.style.display = "block"; + } + } + get collect() { return this.hasAttribute("collect-type") } @@ -124,7 +191,6 @@ export class TraceRow extends HTMLElement { this.setAttribute("sleeping", "") } else { this.removeAttribute("sleeping") - this.draw(); } } @@ -194,6 +260,9 @@ export class TraceRow extends HTMLElement { if (!it.collect) { it.rowHidden = !this.expansion; } + if (it.folder && !value && it.expansion) { + it.expansion = value; + } }) this.dispatchEvent(new CustomEvent("expansion-change", { detail: { @@ -211,17 +280,13 @@ export class TraceRow extends HTMLElement { } } - get frame(): Rect { - let cHeight = 0; - this.canvas.forEach(it => { - cHeight += (it?.clientHeight || 40); - }) + get frame(): Rect | any { if (this._frame) { this._frame.width = (this.parentElement?.clientWidth || 0) - 248 - SpSystemTrace.scrollViewWidth; - this._frame.height = cHeight; + this._frame.height = this.clientHeight ; return this._frame; } else { - this._frame = new Rect(0, 0, (this.parentElement?.clientWidth || 0) - 248 - SpSystemTrace.scrollViewWidth, cHeight); + this._frame = new Rect(0, 0, (this.parentElement?.clientWidth || 0) - 248 - SpSystemTrace.scrollViewWidth, this.clientHeight || 40); return this._frame; } } @@ -230,12 +295,34 @@ export class TraceRow extends HTMLElement { this._frame = f; } + get disabledCheck(): boolean { + return this.hasAttribute("disabled-check"); + } + + set disabledCheck(value: boolean) { + if (value) { + this.setAttribute("disabled-check", '') + this.checkBoxEL!.style.display = "none"; + } else { + this.removeAttribute('disabled-check') + this.checkBoxEL!.style.display = "flex"; + } + } + get checkType(): string { return this.getAttribute("check-type") || ""; } set checkType(value: string) { + if (!value || value.length == 0) { + this.removeAttribute("check-type"); + return; + } this.setAttribute("check-type", value); + if (this.hasAttribute("disabled-check")) { + this.checkBoxEL!.style.display = "none"; + return; + } switch (value) { case "-1": this.checkBoxEL!.style.display = "none"; @@ -286,20 +373,27 @@ export class TraceRow extends HTMLElement { } } + set folderPaddingLeft(value: number) { + this.folderIconEL!.style.marginLeft = value + "px"; + } + initElements(): void { this.rootEL = this.shadowRoot?.querySelector('.root') this.checkBoxEL = this.shadowRoot?.querySelector('.lit-check-box') this.collectEL = this.shadowRoot?.querySelector('.collect') this.describeEl = this.shadowRoot?.querySelector('.describe') + this.folderIconEL = this.shadowRoot?.querySelector('.icon') this.nameEL = this.shadowRoot?.querySelector('.name') this.canvasContainer = this.shadowRoot?.querySelector('.panel-container') this.tipEL = this.shadowRoot?.querySelector('.tip') let canvasNumber = this.args["canvasNumber"]; - for (let i = 0; i < canvasNumber; i++) { - let canvas = document.createElement('canvas'); - canvas.className = "panel"; - this.canvas.push(canvas); - this.canvasContainer!.appendChild(canvas); + if (!this.args["skeleton"]) { + for (let i = 0; i < canvasNumber; i++) { + let canvas = document.createElement('canvas'); + canvas.className = "panel"; + this.canvas.push(canvas); + this.canvasContainer!.appendChild(canvas); + } } this.describeEl?.addEventListener('click', () => { if (this.folder) { @@ -309,21 +403,27 @@ export class TraceRow extends HTMLElement { } initCanvas(list: Array): void { - let timerShaftCanvas = this.parentElement!.parentElement!.querySelector("timer-shaft-element")!.shadowRoot!.querySelector("canvas"); - let tempHeight:number = 0; - if(this.rowType==TraceRow.ROW_TYPE_FUNC ){ + let timerShaftEL = document!.querySelector("body > sp-application")!.shadowRoot!.querySelector("#sp-system-trace")!.shadowRoot!.querySelector("div > timer-shaft-element"); + let timerShaftCanvas = timerShaftEL!.shadowRoot!.querySelector("canvas"); + let tempHeight: number = 0; + if (this.rowType == TraceRow.ROW_TYPE_FUNC) { tempHeight = 20; - }else if(this.rowType==TraceRow.ROW_TYPE_THREAD ){ + } else if (this.rowType == TraceRow.ROW_TYPE_THREAD) { tempHeight = 30; - }else{ + } else if (this.rowType == TraceRow.ROW_TYPE_SYSTEM_ENERGY) { + tempHeight = 80; + } else if (this.rowType == TraceRow.ROW_TYPE_POWER_ENERGY) { + tempHeight = 200; + } else if (this.rowType == TraceRow.ROW_TYPE_ANOMALY_ENERGY) { + tempHeight = 55; + } else { tempHeight = 40; } + this.dpr = window.devicePixelRatio || 1; list.forEach((canvas, i) => { - // let oldWidth = (this.shadowRoot!.host.clientWidth || 0) - (this.describeEl?.clientWidth || 248) - SpSystemTrace.scrollViewWidth; this.rootEL!.style.height = `${this.getAttribute("height") || '40'}px` canvas.style.width = timerShaftCanvas!.style.width; canvas.style.height = tempHeight + 'px'; - // canvas.style.backgroundColor = `${randomRgbColor()}` this.canvasWidth = timerShaftCanvas!.width; this.canvasHeight = Math.ceil(tempHeight * this.dpr); canvas.width = this.canvasWidth; @@ -334,15 +434,26 @@ export class TraceRow extends HTMLElement { } updateWidth(width: number) { - let dpr = window.devicePixelRatio || 1; - let tempHeight = 40; - let tempTop = 0; + this.dpr = window.devicePixelRatio || 1; + let tempHeight: number = 0; + if (this.rowType == TraceRow.ROW_TYPE_FUNC) { + tempHeight = 20; + } else if (this.rowType == TraceRow.ROW_TYPE_THREAD) { + tempHeight = 30; + } else if (this.rowType == TraceRow.ROW_TYPE_SYSTEM_ENERGY) { + tempHeight = 90; + } else if (this.rowType == TraceRow.ROW_TYPE_POWER_ENERGY) { + tempHeight = 200; + } else if (this.rowType == TraceRow.ROW_TYPE_ANOMALY_ENERGY) { + tempHeight = 55; + } else { + tempHeight = 40; + } if (this.canvas.length > 1) { tempHeight = 20; - tempTop = 10; } this.canvas.forEach(it => { - this.canvasWidth = Math.ceil((width - (this.describeEl?.clientWidth || 248)) * dpr); + this.canvasWidth = Math.ceil((width - (this.describeEl?.clientWidth || 248)) * this.dpr); this.canvasHeight = Math.ceil(tempHeight * this.dpr); it!.style.width = (width - (this.describeEl?.clientWidth || 248)) + 'px'; if (this.args.isOffScreen) { @@ -351,9 +462,29 @@ export class TraceRow extends HTMLElement { }) } + drawLine(item: HTMLDivElement, direction: string/*string[top|bottom]*/) { + if (!item) return; + switch (direction) { + case "top": + item.classList.remove("line-bottom"); + item.classList.add("line-top"); + break; + case "bottom": + item.classList.remove("line-top"); + item.classList.add("line-bottom"); + break; + case "": + item.classList.remove("line-top"); + item.classList.remove("line-bottom"); + break; + } + } + connectedCallback() { this.checkBoxEL!.onchange = (ev: any) => { + info("checkBoxEL onchange "); if (!ev.target.checked) { + info("checkBoxEL target not checked"); this.rangeSelect = false; this.checkType = "0" this.draw(); @@ -364,19 +495,43 @@ export class TraceRow extends HTMLElement { } this.setCheckBox(ev.target.checked); } - this.collectEL!.onclick = (e) => { - this.collect = !this.collect; + this.describeEl!.ondragstart = (ev: DragEvent) => this.rowDragstart(ev); + this.describeEl!.ondragleave = (ev: any) => { + this.drawLine(ev.currentTarget, ''); + return undefined; + } + this.describeEl!.ondragend = (ev: any) => { + rowDragElement = null; + ev.target.classList.remove("drag") + this.drawLine(ev.currentTarget, ''); + return undefined; + } + this.describeEl!.ondragover = (ev: any) => { + if (!this.collect) return; + if (rowDragElement === this) return; + let rect = ev.currentTarget.getBoundingClientRect(); + if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) {//上面 + dragDirection = 'top'; + this.drawLine(ev.currentTarget, 'top'); + } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) {//下面 + dragDirection = 'bottom'; + this.drawLine(ev.currentTarget, 'bottom'); + } + return undefined; + } + this.describeEl!.ondrop = (ev: any) => { + if (!this.collect) return; + this.drawLine(ev.currentTarget, ''); let spacer = this.parentElement!.previousElementSibling! as HTMLDivElement; - if (this.collect) { - spacer.style.height = `${spacer.offsetHeight + this.offsetHeight!}px`; - } else { - spacer.style.height = `${spacer.offsetHeight - this.offsetHeight!}px`; - let parent = this.parentElement!.querySelector>(`trace-row[row-id='${this.rowParentId}']`); - if (parent) { - this.rowHidden = !parent.expansion; - } + let startDragNode = collectList.findIndex((it) => it === rowDragElement); + let endDragNode = collectList.findIndex((it) => it === this); + if (startDragNode === -1 || endDragNode === -1) return; + if (startDragNode < endDragNode && dragDirection === "top") { + endDragNode--; + } else if (startDragNode > endDragNode && dragDirection === "bottom") { + endDragNode++; } - let collectList = this.parentElement!.querySelectorAll>(`trace-row[collect-type]`); + collectList.splice(endDragNode, 0, ...collectList.splice(startDragNode, 1)) collectList.forEach((it, i) => { if (i == 0) { it.style.top = `${spacer.offsetTop + 48}px`; @@ -384,13 +539,28 @@ export class TraceRow extends HTMLElement { it.style.top = `${collectList[i - 1].offsetTop + collectList[i - 1].offsetHeight}px`; } }) + } + this.collectEL!.onclick = (e) => { + this.collect = !this.collect; + if (this.collect) { + this.describeEl!.draggable = false; + } else { + this.describeEl!.draggable = false; + } + document.dispatchEvent(new CustomEvent("collect",{ + detail:{ + type:e.type, + row:this + } + })) this.favoriteChangeHandler?.(this) } - this.initCanvas(this.canvas); - let _this = this; + if (!this.args["skeleton"]) { + this.initCanvas(this.canvas); + } let radioList = this.shadowRoot!.querySelectorAll("input[type=radio][name=status]") let popover = this.shadowRoot!.querySelector(".popover") - this.shadowRoot!.querySelector("#first-radio")!.onclick = (e) => { + this.shadowRoot?.querySelector("#first-radio")?.addEventListener("click", (e) => { // @ts-ignore radioList[0]!.checked = true; // @ts-ignore @@ -398,8 +568,8 @@ export class TraceRow extends HTMLElement { setTimeout(() => { this.onDrawTypeChangeHandler?.(0); }, 300); - } - this.shadowRoot!.querySelector("#second-radio")!.onclick = (e) => { + }) + this.shadowRoot?.querySelector("#second-radio")?.addEventListener('click', (e) => { // @ts-ignore radioList[1]!.checked = true; // @ts-ignore @@ -407,7 +577,12 @@ export class TraceRow extends HTMLElement { setTimeout(() => { this.onDrawTypeChangeHandler?.(1); }, 300); - } + }) + } + + rowDragstart(ev: any) { + rowDragElement = this; + ev.target.classList.add("drag") } setCheckBox(isCheck: boolean) { @@ -422,24 +597,27 @@ export class TraceRow extends HTMLElement { this.selectChangeHandler?.([...this.parentElement!.querySelectorAll>("trace-row[check-type='2']")]) return; } - let checkList = this.parentElement?.querySelectorAll>(`trace-row[row-parent-id='${this.folder ? this.rowId : this.rowParentId}'][check-type="2"]`) - let unselectedList = this.parentElement?.querySelectorAll>(`trace-row[row-parent-id='${this.folder ? this.rowId : this.rowParentId}'][check-type="0"]`) + let checkList = this.parentElement!.parentElement!.querySelectorAll>(`trace-row[row-parent-id='${this.folder ? this.rowId : this.rowParentId}'][check-type="2"]`) + let unselectedList = this.parentElement!.parentElement!.querySelectorAll>(`trace-row[row-parent-id='${this.folder ? this.rowId : this.rowParentId}'][check-type="0"]`) let parentRow = this.parentElement?.querySelector>(`trace-row[row-id='${this.folder ? this.rowId : this.rowParentId}'][folder]`) let parentCheck: LitCheckBox | null | undefined = parentRow?.shadowRoot?.querySelector(".lit-check-box") - - if (unselectedList!.length == 0) { - parentRow!.setAttribute("check-type", "2") - parentCheck!.checked = true - parentCheck!.indeterminate = false; + if (unselectedList?.length == 0) { + parentRow?.setAttribute("check-type", "2") + if(parentCheck){ + parentCheck!.checked = true + parentCheck!.indeterminate = false; + } checkList?.forEach((it) => { it.checkType = "2"; it.rangeSelect = true; it.draw() }) } else { - parentRow!.setAttribute("check-type", "1") - parentCheck!.checked = false - parentCheck!.indeterminate = true; + parentRow?.setAttribute("check-type", "1") + if(parentCheck){ + parentCheck!.checked = false + parentCheck!.indeterminate = true; + } checkList?.forEach((it) => { it.checkType = "2"; it.rangeSelect = true; @@ -452,17 +630,19 @@ export class TraceRow extends HTMLElement { }) } - if (checkList!.length == 0) { - parentRow!.setAttribute("check-type", "0") - parentCheck!.checked = false - parentCheck!.indeterminate = false; + if (checkList?.length == 0) { + parentRow?.setAttribute("check-type", "0") + if(parentCheck) { + parentCheck!.checked = false + parentCheck!.indeterminate = false; + } unselectedList?.forEach((it) => { it.checkType = "0"; it.rangeSelect = false; it.draw() }) } - this.selectChangeHandler?.([...this.parentElement!.querySelectorAll>("trace-row[check-type='2']")]) + this.selectChangeHandler?.([...this.parentElement!.parentElement!.querySelectorAll>("trace-row[check-type='2']")]) } onMouseHover(x: number, y: number, tip: boolean = true): T | undefined | null { @@ -479,7 +659,7 @@ export class TraceRow extends HTMLElement { } if (this.tipEL) { this.tipEL.style.display = 'flex'; - if (x + this.tipEL.clientWidth > (this.canvas[0]!.clientWidth || 0)) { + if (x + this.tipEL.clientWidth > (this.canvasContainer!.clientWidth || 0)) { this.tipEL.style.transform = `translateX(${x - this.tipEL.clientWidth - 1}px)`; } else { this.tipEL.style.transform = `translateX(${x}px)`; @@ -494,9 +674,19 @@ export class TraceRow extends HTMLElement { } draw(useCache: boolean = false) { + this.dpr = window.devicePixelRatio || 1; if (this.sleeping) { return; } + if (this.online) { + if (!useCache && !TraceRow.isUserInteraction) { + this.supplier?.().then(res => { + this.onThreadHandler?.(useCache, res as any); + }); + } + this.onThreadHandler?.(useCache, null); + return; + } if (!this.isComplete) { if (this.supplier && !this.isLoading) { this.isLoading = true; @@ -520,12 +710,27 @@ export class TraceRow extends HTMLElement { } } } else { - if (this.onThreadHandler && this.dataList) { - this.onThreadHandler!(useCache) + if (!this.hasAttribute("row-hidden")) { + if (this.onThreadHandler && this.dataList) { + this.onThreadHandler!(useCache, null); + } } } } + canvasSave(ctx: CanvasRenderingContext2D) { + ctx.save(); + ctx.translate(0, this.translateY); + const clipRect = new Path2D(); + clipRect.rect(0, 0, this.frame.width, this.frame.height); + ctx.clip(clipRect); + } + + canvasRestore(ctx: CanvasRenderingContext2D) { + drawSelectionRange(ctx, this); + ctx.restore(); + } + clearCanvas(ctx: CanvasRenderingContext2D) { if (ctx) { this.canvas.forEach(it => { @@ -567,6 +772,48 @@ export class TraceRow extends HTMLElement { return ((startTime || 0) + (duration || 0) > (TraceRow.range?.startNS || 0) && (startTime || 0) < (TraceRow.range?.endNS || 0)); } + buildArgs(obj: any) { + let result: any = { + list: this.must ? this.dataList : undefined, + offscreen: !this.isTransferCanvas ? this.offscreen[0] : undefined,//是否离屏 + dpr: this.dpr,//屏幕dpr值 + xs: TraceRow.range?.xs,//线条坐标信息 + isHover: this.isHover, + hoverX: this.hoverX, + hoverY: this.hoverY, + canvasWidth: this.canvasWidth, + canvasHeight: this.canvasHeight, + isRangeSelect: this.rangeSelect, + rangeSelectObject: TraceRow.rangeSelectObject, + lineColor: this.getLineColor(), + chartColor: ColorUtils.MD_PALETTE[0], + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + totalNS: TraceRow.range?.totalNS || 0, + slicesTime: TraceRow.range?.slicesTime, + range: TraceRow.range, + frame: this.frame, + flagMoveInfo: null, + flagSelectedInfo: null, + wakeupBean: null + }; + Reflect.ownKeys(obj).forEach(it => { + result[it] = obj[it]; + }) + return result; + } + + getTransferArray() { + let tsf = []; + if (!this.isTransferCanvas) { + tsf.push(this.offscreen[0]); + } + if (this.must && this.dataList instanceof ArrayBuffer) { + tsf.push(this.dataList); + } + return tsf; + } + attributeChangedCallback(name: string, oldValue: string, newValue: string) { switch (name) { case "name": @@ -591,233 +838,265 @@ export class TraceRow extends HTMLElement { } } + focusContain(e: MouseEvent): boolean { + let _y = (e.currentTarget as HTMLElement).getBoundingClientRect().y; + let myRect = this.getBoundingClientRect(); + let x = e.offsetX; + let y = e.offsetY + _y; + if (x >= myRect.x && x <= myRect.x + myRect.width && y >= myRect.y && y <= myRect.y + myRect.height) { + this.hoverX = x - this.describeEl!.clientWidth; + this.hoverY = y - myRect.y; + this.isHover = true; + return true; + } else { + this.isHover = false; + if (this.tipEL) { + this.tipEL.style.display = 'none'; + } + return false; + } + } + initHtml(): string { return ` - -
-
- - - - -
-
Current Bytes
-
Native Memory Density
+ +
+
+ + + + +
+
+ Current Bytes
+
+ Native Memory Density
+
+ +
+ +
+
+ +
+
- - - -
-
-
- P:process [1573]
- T:Thread [675]
-
-
`; } - } diff --git a/host/ide/src/trace/component/trace/base/TraceRowRecyclerView.ts b/host/ide/src/trace/component/trace/base/TraceRowRecyclerView.ts index f5ce8484b72dfae6b9e4a74d0b4d23296bef5dfb..3e5977903ef6b0bc7897c83832a435eb2a77bb4b 100644 --- a/host/ide/src/trace/component/trace/base/TraceRowRecyclerView.ts +++ b/host/ide/src/trace/component/trace/base/TraceRowRecyclerView.ts @@ -15,6 +15,7 @@ import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; import {TraceRowObject} from "./TraceRowObject.js"; import {TraceRow} from "./TraceRow.js"; +import {log} from "../../../../log/Log.js"; @element("trace-row-recycler-view") export class TraceRowRecyclerView extends BaseElement { @@ -33,6 +34,7 @@ export class TraceRowRecyclerView extends BaseElement { } set dataSource(value: Array>) { + log("dataSource TraceRowObject size :" + value.length); this._dataSource = value; this.measureHeight(); this.initUI(); @@ -118,7 +120,7 @@ export class TraceRowRecyclerView extends BaseElement { } if (!this.recycler) this.visibleRowsCount = this.dataSource.length; for (let i = 0; i <= this.visibleRowsCount; i++) { - let el = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + let el = new TraceRow({canvasNumber: 1, alpha: true, contextId: '2d', isOffScreen: true}); el.className = "recycler-cell" this.container?.appendChild(el); el.addEventListener('expansion-change', (ev: any) => { @@ -149,42 +151,42 @@ export class TraceRowRecyclerView extends BaseElement { initHtml(): string { return ` - -
-
-
+ +
+
+
-`; + `; } } diff --git a/host/ide/src/trace/component/trace/base/TraceSheet.ts b/host/ide/src/trace/component/trace/base/TraceSheet.ts index 0ede469f0d6d9fe0302cb43c0f8a077e1887145e..71dbf65550139450bbfb4056696a90f5da93a8f7 100644 --- a/host/ide/src/trace/component/trace/base/TraceSheet.ts +++ b/host/ide/src/trace/component/trace/base/TraceSheet.ts @@ -15,186 +15,146 @@ import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; import {LitTabs} from "../../../../base-ui/tabs/lit-tabs.js"; -import "../../../../base-ui/tabs/lit-tabpane.js"; -import {CpuStruct} from "../../../bean/CpuStruct.js"; -import "../../../../base-ui/table/lit-table.js"; import {LitTabpane} from "../../../../base-ui/tabs/lit-tabpane.js"; -import "../sheet/TabPaneCpu.js"; -import "../sheet/TabPaneThreadStates.js" -import "../sheet/TabPaneSlices.js" -import "../sheet/TabPaneCounter.js" -import "../sheet/TabPaneCpuByProcess.js" -import "../sheet/TabPaneCpuByThread.js" -import "../sheet/TabPaneFps.js" -import "../sheet/TabPaneSPT.js" -import "../sheet/TabPanePTS.js" -import "../sheet/TabPaneContextSwitch.js" -import "../sheet/TabPaneThreadSwitch.js" -import "../sheet/TabPaneCpuUsage.js"; -import "../sheet/TabPaneBoxChild.js"; -import "../sheet/TabPaneHeap.js"; -import "../sheet/TabPaneNMStatstics.js"; -import "../sheet/TabPaneNMCallInfo.js"; -import "../sheet/TabPaneNMemory.js"; -import "../sheet/TabPaneNMSampleList.js"; import {BoxJumpParam, SelectionParam} from "../../../bean/BoxSelection.js"; -import {TabPaneThreadStates} from "../sheet/TabPaneThreadStates.js"; -import {TabPaneCpuByProcess} from "../sheet/TabPaneCpuByProcess.js"; -import {TabPaneCpuByThread} from "../sheet/TabPaneCpuByThread.js"; -import {TabPaneSlices} from "../sheet/TabPaneSlices.js"; -import {TabPaneSPT} from "../sheet/TabPaneSPT.js"; -import {TabPanePTS} from "../sheet/TabPanePTS.js"; -import {TabPaneContextSwitch} from "../sheet/TabPaneContextSwitch.js"; -import {TabPaneThreadSwitch} from "../sheet/TabPaneThreadSwitch.js"; -import {TabPaneBoxChild} from "../sheet/TabPaneBoxChild.js"; -import {TabPaneCounter} from "../sheet/TabPaneCounter.js"; -import "../sheet/TabPaneCurrentSelection.js"; import {TabPaneCurrentSelection} from "../sheet/TabPaneCurrentSelection.js"; -import {FuncStruct} from "../../../bean/FuncStruct.js"; -import {ProcessMemStruct} from "../../../bean/ProcessMemStruct.js"; -import {ThreadStruct} from "../../../bean/ThreadStruct.js"; -import {TabPaneFps} from "../sheet/TabPaneFps.js"; -import {TabPaneCpuUsage} from "../sheet/TabPaneCpuUsage.js"; -import "../timer-shaft/TabPaneFlag.js"; import {TabPaneFlag} from "../timer-shaft/TabPaneFlag.js"; import {Flag} from "../timer-shaft/Flag.js"; -import {TabPaneHeap} from "../sheet/TabPaneHeap.js"; -import {TabPaneNMStatstics} from "../sheet/TabPaneNMStatstics.js"; -import {TabPaneNMCallInfo} from "../sheet/TabPaneNMCallInfo.js"; -import {TabPaneNMemory} from "../sheet/TabPaneNMemory.js"; -import {TabPaneNMSampleList} from "../sheet/TabPaneNMSampleList.js"; import {WakeupBean} from "../../../bean/WakeupBean.js"; import {LitIcon} from "../../../../base-ui/icon/LitIcon.js"; +import {tabConfig} from "./TraceSheetConfig.js"; +import {TabPaneBoxChild} from "../sheet/cpu/TabPaneBoxChild.js"; +import {SpFreqChart} from "../../chart/SpFreqChart.js"; +import { CpuStruct } from "../../../database/ui-worker/ProcedureWorkerCPU.js"; +import { CpuFreqStruct } from "../../../database/ui-worker/ProcedureWorkerFreq.js"; +import {CpuFreqLimitsStruct} from "../../../database/ui-worker/ProcedureWorkerCpuFreqLimits.js"; +import { ThreadStruct } from "../../../database/ui-worker/ProcedureWorkerThread.js"; +import { FuncStruct } from "../../../database/ui-worker/ProcedureWorkerFunc.js"; +import { ProcessMemStruct } from "../../../database/ui-worker/ProcedureWorkerMem.js"; +import {CpuStateStruct} from "../../../database/ui-worker/ProcedureWorkerCpuState.js"; + @element("trace-sheet") export class TraceSheet extends BaseElement { private litTabs: LitTabs | undefined | null private nav: HTMLDivElement | undefined | null - private tabCurrentSelection: LitTabpane | undefined | null - private tabBoxCpuThread: LitTabpane | undefined | null - private tabBoxCpuProcess: LitTabpane | undefined | null - private tabBoxThreadStates: LitTabpane | undefined | null - private tabBoxSlices: LitTabpane | undefined | null - private tabBoxCounters: LitTabpane | undefined | null - private tabBoxFps: LitTabpane | undefined | null - private tabBoxSPT: LitTabpane | undefined | null - private tabBoxPTS: LitTabpane | undefined | null - private tabBoxContextSwitch: LitTabpane | undefined | null - private tabBoxThreadSwitch: LitTabpane | undefined | null - private tabBoxCpuUsage: LitTabpane | undefined | null - private tabBoxChild: LitTabpane | undefined | null - private tabBoxFlag: TabPaneFlag | undefined | null - private tabBoxHeap: LitTabpane | undefined | null - private tabBoxNMStatistics: LitTabpane | undefined | null - private tabBoxNMCallInfo: LitTabpane | undefined | null - private tabBoxNMemory: LitTabpane | undefined | null - private tabBoxNMSample: LitTabpane | undefined | null - private tabSPT: TabPaneSPT | undefined | null - private tabPTS: TabPanePTS | undefined | null - private tabCs: TabPaneContextSwitch | undefined | null - private tabTs: TabPaneThreadSwitch | undefined | null - private tabChild: TabPaneBoxChild | undefined | null - private tabNativeStatistics: TabPaneNMStatstics | undefined | null - private tabNativeMemory: TabPaneNMemory | undefined | null - private tabNativeCallInfo: TabPaneNMCallInfo | undefined | null - private tabNativeSample: TabPaneNMSampleList | undefined | null - private currentKey: string = "1"; private selection: SelectionParam | undefined | null; + private currentPaneID: string = "current-selection"; static get observedAttributes() { return ['mode']; } - initElements(): void { - this.litTabs = this.shadowRoot?.querySelector("#tabs"); - this.tabCurrentSelection = this.shadowRoot?.querySelector("#current-selection"); - this.tabBoxCpuThread = this.shadowRoot?.querySelector("#box-cpu-thread"); - this.tabBoxCpuProcess = this.shadowRoot?.querySelector("#box-cpu-process"); - this.tabBoxThreadStates = this.shadowRoot?.querySelector("#box-thread-states"); - this.tabBoxSlices = this.shadowRoot?.querySelector("#box-slices"); - this.tabBoxCounters = this.shadowRoot?.querySelector("#box-counters"); - this.tabBoxFps = this.shadowRoot?.querySelector("#box-fps"); - this.tabBoxSPT = this.shadowRoot?.querySelector("#box-spt"); - this.tabBoxPTS = this.shadowRoot?.querySelector("#box-pts"); - this.tabBoxContextSwitch = this.shadowRoot?.querySelector("#box-cs"); - this.tabBoxThreadSwitch = this.shadowRoot?.querySelector("#box-ts"); - this.tabBoxCpuUsage = this.shadowRoot?.querySelector("#box-cpu-usage"); - this.tabBoxChild = this.shadowRoot?.querySelector("#box-cpu-child"); - this.tabBoxFlag = this.shadowRoot?.querySelector("#box-flag"); - this.tabBoxHeap = this.shadowRoot?.querySelector("#box-heap"); + buildTabs(litTabs: LitTabs | undefined | null) { + Reflect.ownKeys(tabConfig).forEach((key, index) => { + let pane = new LitTabpane(); + pane.id = key.toString(); + pane.className = "tabHeight"; + pane.tab = tabConfig[key].title; + pane.hidden = true; + pane.key = `${tabConfig[key].key || index}`; + let cls = tabConfig[key].type; + let node = new cls(); + pane.append(node) + litTabs!.append(pane); + }) + } - this.tabBoxNMStatistics = this.shadowRoot?.querySelector("#box-native-statstics"); - this.tabBoxNMCallInfo = this.shadowRoot?.querySelector("#box-native-callinfo"); - this.tabBoxNMemory = this.shadowRoot?.querySelector("#box-native-memory"); - this.tabBoxNMSample = this.shadowRoot?.querySelector("#box-native-sample"); + displayTab(...names: string[]): T { + this.setAttribute("mode", "max") + this.shadowRoot?.querySelectorAll("#tabs lit-tabpane").forEach(it => it.hidden = !names.some(k => k === it.id)) + let litTabpane = this.shadowRoot?.querySelector(`#tabs lit-tabpane[id='${names[0]}']`); + this.shadowRoot?.querySelector("#tabs")?.activePane(litTabpane!.key) + return litTabpane!.children.item(0) as unknown as T; + } - this.tabSPT = this.shadowRoot!.querySelector('#tab-spt'); - this.tabPTS = this.shadowRoot!.querySelector('#tab-pts'); - this.tabCs = this.shadowRoot!.querySelector('#tab-cs'); - this.tabTs = this.shadowRoot!.querySelector('#tab-ts'); - this.tabChild = this.shadowRoot!.querySelector('#tab-box-child'); + getComponentByID(id: string): T { + return (this.getPaneByID(id)!.children.item(0) as unknown as T); + } - this.tabNativeStatistics = this.shadowRoot!.querySelector('#tab-box-native-stats'); - this.tabNativeCallInfo = this.shadowRoot!.querySelector('#tab-box-native-callinfo'); - this.tabNativeMemory = this.shadowRoot!.querySelector('#tab-box-native-memory'); - this.tabNativeSample = this.shadowRoot!.querySelector('#tab-box-native-sample'); + getPaneByID(id: string): LitTabpane { + return this.shadowRoot!.querySelector(`#${id}`)!; + } + initElements(): void { + this.litTabs = this.shadowRoot?.querySelector("#tabs"); + this.buildTabs(this.litTabs); let minBtn = this.shadowRoot?.querySelector("#min-btn"); - minBtn?.addEventListener('click', (e) => { - }) - this.litTabs!.onTabClick = (e: any) => { - this.loadTabPaneData(e.detail.key) - } - this.litTabs!.addEventListener("close-handler", (e) => { - this.recoveryBoxSelection(); - this.tabBoxChild!.hidden = true; - this.litTabs?.activeByKey(this.currentKey); - }) - this.tabSPT!.addEventListener("row-click", (e) => { - this.jumpBoxChild("11", e) - }) - this.tabPTS!.addEventListener("row-click", (e) => { - this.jumpBoxChild("12", e) - }) - this.tabCs!.addEventListener("row-click", (e) => { - this.jumpBoxChild("13", e) - }) - this.tabTs!.addEventListener("row-click", (e) => { - this.jumpBoxChild("14", e) + minBtn?.addEventListener('click', () => { + }); + this.litTabs!.onTabClick = (e: any) => this.loadTabPaneData(e.detail.key) + this.litTabs!.addEventListener("close-handler", () => { + Reflect.ownKeys(tabConfig).reverse().forEach(id => { + let element = tabConfig[id]; + let pane = this.shadowRoot!.querySelector(`#${id as string}`); + if (element.require) { + pane!.hidden = !element.require(this.selection); + } else { + pane!.hidden = true; + } + }) + this.litTabs?.activeByKey(`${this.getPaneByID(this.currentPaneID).key}`); }) - this.tabNativeStatistics!.addEventListener("row-click",(e)=>{ - // @ts-ignore + this.getComponentByID("box-spt")!.addEventListener("row-click", this.rowClickHandler.bind(this)); + this.getComponentByID("box-pts")!.addEventListener("row-click", this.rowClickHandler.bind(this)); + this.getComponentByID("box-cs")!.addEventListener("row-click", this.rowClickHandler.bind(this)); + this.getComponentByID("box-ts")!.addEventListener("row-click", this.rowClickHandler.bind(this)); + this.getComponentByID("box-native-statstics")!.addEventListener("row-click", (e: any) => { this.selection!.statisticsSelectData = e.detail - this.tabNativeMemory?.fromStastics(this.selection) - this.litTabs?.activeByKey("18"); - }) + let pane = this.getPaneByID("box-native-memory"); + this.litTabs?.activeByKey(pane.key); + (pane.children.item(0) as any)!.fromStastics(this.selection) + }); + this.getComponentByID("box-virtual-memory-statistics")!.addEventListener("row-click", (e: any) => { + this.selection!.fileSystemVMData = {path:e.detail.path} + let pane = this.getPaneByID("box-vm-events"); + this.litTabs?.activeByKey(pane.key); + if (e.detail.path) { + (pane.children.item(0) as any)!.fromStastics(this.selection) + } + }); + this.getComponentByID("box-io-tier-statistics")!.addEventListener("row-click", (e: any) => { + this.selection!.fileSystemIoData = {path:e.detail.path} + let pane = this.getPaneByID("box-io-events"); + this.litTabs?.activeByKey(pane.key); + if (e.detail.path) { + (pane.children.item(0) as any)!.fromStastics(this.selection) + } + }); + this.getComponentByID("box-file-system-statistics")!.addEventListener("row-click", (e: any) => { + this.selection!.fileSystemFsData = e.detail.data + let pane = this.getPaneByID("box-file-system-event"); + this.litTabs?.activeByKey(pane.key); + if (e.detail.data) { + (pane.children.item(0) as any)!.fromStastics(this.selection) + } + }); } connectedCallback() { - this.nav = this.shadowRoot?.querySelector("#tabs")?.shadowRoot?.querySelector('#nav') + this.nav = this.shadowRoot?.querySelector("#tabs")?.shadowRoot?.querySelector('.tab-nav-container') let tabs: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('#tabs') let navRoot: HTMLDivElement | null | undefined = this.shadowRoot?.querySelector("#tabs")?.shadowRoot?.querySelector('.nav-root') - let search: HTMLDivElement | undefined | null = document.querySelector("body > sp-application")?.shadowRoot?.querySelector("div > div.search-container") let timerShaft: HTMLDivElement | undefined | null = this.parentElement?.querySelector(".timer-shaft") + let spacer: HTMLDivElement | undefined | null = this.parentElement?.querySelector(".spacer") + let rowsPaneEL: HTMLDivElement | undefined | null = this.parentElement?.querySelector(".rows-pane") let borderTop: number = 1; - let initialHeight = { - tabs: `calc(30vh + 39px)`, - node: "30vh" - } + let initialHeight = {tabs: `calc(30vh + 39px)`, node: "30vh"}; this.nav!.onmousedown = (event) => { + (window as any).isSheetMove = true; let litTabpane: NodeListOf | undefined | null = this.shadowRoot?.querySelectorAll("#tabs > lit-tabpane") let preY = event.pageY; - let preHeight = tabs!.offsetHeight; - document.onmousemove = function (event) { - let moveY: number; - - moveY = preHeight - (event.pageY - preY) - litTabpane!.forEach((node: HTMLDivElement, b) => { - if (navRoot!.offsetHeight <= moveY && (search!.offsetHeight + timerShaft!.offsetHeight + borderTop) <= (window.innerHeight - moveY)) { + let moveY: number = preHeight - (event.pageY - preY) + litTabpane!.forEach((node: HTMLDivElement) => { + if(spacer!.offsetHeight > rowsPaneEL!.offsetHeight){ + tabs!.style.height = moveY + "px" + node!.style.height = (moveY - navRoot!.offsetHeight) + "px" + tabsPackUp!.name = "down" + }else if (navRoot!.offsetHeight <= moveY && (search!.offsetHeight + timerShaft!.offsetHeight + borderTop + spacer!.offsetHeight) <= (window.innerHeight - moveY)) { tabs!.style.height = moveY + "px" node!.style.height = (moveY - navRoot!.offsetHeight) + "px" tabsPackUp!.name = "down" @@ -202,16 +162,16 @@ export class TraceSheet extends BaseElement { tabs!.style.height = navRoot!.offsetHeight + "px" node!.style.height = "0px" tabsPackUp!.name = "up" - } else if ((search!.offsetHeight + timerShaft!.offsetHeight + borderTop) >= (window.innerHeight - moveY)) { - tabs!.style.height = (window.innerHeight - search!.offsetHeight - timerShaft!.offsetHeight - borderTop) + "px" - node!.style.height = (window.innerHeight - search!.offsetHeight - timerShaft!.offsetHeight - navRoot!.offsetHeight - borderTop) + "px" + } else if ((search!.offsetHeight + timerShaft!.offsetHeight + borderTop + spacer!.offsetHeight) >= (window.innerHeight - moveY)) { + tabs!.style.height = (window.innerHeight - search!.offsetHeight - timerShaft!.offsetHeight - borderTop - spacer!.offsetHeight) + "px" + node!.style.height = (window.innerHeight - search!.offsetHeight - timerShaft!.offsetHeight - navRoot!.offsetHeight - borderTop - spacer!.offsetHeight) + "px" tabsPackUp!.name = "down" } }) - } - document.onmouseup = function (event) { - litTabpane!.forEach((node: HTMLDivElement, b) => { + document.onmouseup = function () { + (window as any).isSheetMove = false; + litTabpane!.forEach((node: HTMLDivElement) => { if (node!.style.height !== "0px" && tabs!.style.height != "") { initialHeight.node = node!.style.height; initialHeight.tabs = tabs!.style.height; @@ -223,197 +183,91 @@ export class TraceSheet extends BaseElement { } let tabsOpenUp: LitIcon | undefined | null = this.shadowRoot?.querySelector("#tabs > div > lit-icon:nth-child(1)") let tabsPackUp: LitIcon | undefined | null = this.shadowRoot?.querySelector("#tabs > div > lit-icon:nth-child(2)") - tabsOpenUp!.onclick = (e) => { + tabsOpenUp!.onclick = () => { tabs!.style.height = (window.innerHeight - search!.offsetHeight - timerShaft!.offsetHeight - borderTop) + "px" let litTabpane: NodeListOf | undefined | null = this.shadowRoot?.querySelectorAll("#tabs > lit-tabpane") - litTabpane!.forEach((node: HTMLDivElement, b) => { + litTabpane!.forEach((node: HTMLDivElement) => { node!.style.height = (window.innerHeight - search!.offsetHeight - timerShaft!.offsetHeight - navRoot!.offsetHeight - borderTop) + "px" initialHeight.node = node!.style.height; }) initialHeight.tabs = tabs!.style.height; tabsPackUp!.name = "down" } - tabsPackUp!.onclick = (e) => { + tabsPackUp!.onclick = () => { let litTabpane: NodeListOf | undefined | null = this.shadowRoot?.querySelectorAll("#tabs > lit-tabpane") if (tabsPackUp!.name == "down") { tabs!.style.height = navRoot!.offsetHeight + "px" - litTabpane!.forEach((node: HTMLDivElement, b) => { - node!.style.height = "0px" - }) - tabsPackUp!.name = "up" + litTabpane!.forEach((node: HTMLDivElement) => node!.style.height = "0px") + tabsPackUp!.name = "up"; + (window as any).isPackUpTable = true; } else { tabsPackUp!.name = "down" tabs!.style.height = initialHeight.tabs; - litTabpane!.forEach((node: HTMLDivElement, b) => { - node!.style.height = initialHeight.node; - }) + litTabpane!.forEach((node: HTMLDivElement) => node!.style.height = initialHeight.node) } } } initHtml(): string { return ` - -
- -
- - -
- - - - - - - - - - - - - - - - - - - - -
-
`; + +
+ +
+ + + + +
+
+
`; } - clear() { - this.shadowRoot?.querySelectorAll("lit-tabpane").forEach(it => this.litTabs?.removeChild(it)) - } - - displayThreadData(data: ThreadStruct, scrollCallback: ((e: ThreadStruct) => void) | undefined) { - this.setAttribute("mode", "max") - this.tabCurrentSelection!.hidden = false; - this.hideBoxTab(); - this.litTabs?.activeByKey("1") - let tabCpu = this.shadowRoot!.querySelector('#tabpane-cpu'); - tabCpu!.setThreadData(data, scrollCallback); - } - - displayMemData(data: ProcessMemStruct) { - this.setAttribute("mode", "max") - this.tabCurrentSelection!.hidden = false; - this.hideBoxTab(); - this.litTabs?.activeByKey("1") - let tabCpu = this.shadowRoot!.querySelector('#tabpane-cpu'); - tabCpu!.setMemData(data) - } + displayThreadData = (data: ThreadStruct, scrollCallback: ((e: ThreadStruct) => void) | undefined, scrollWakeUp: (d: any) => void | undefined) => + this.displayTab("current-selection").setThreadData(data, scrollCallback, scrollWakeUp) + displayMemData = (data: ProcessMemStruct) => + this.displayTab("current-selection").setMemData(data); + displayFuncData = (data: FuncStruct, scrollCallback: Function) => + this.displayTab("current-selection").setFunctionData(data, scrollCallback); + displayCpuData = (data: CpuStruct, callback: ((data: WakeupBean | null) => void) | undefined = undefined, scrollCallback?: (data: CpuStruct) => void) => + this.displayTab("current-selection").setCpuData(data, callback, scrollCallback); + displayFlagData = (flagObj: Flag) => this.displayTab("box-flag").setFlagObj(flagObj); + displayFreqData = () => this.displayTab("box-freq").data = CpuFreqStruct.selectCpuFreqStruct; + displayCpuStateData = () => this.displayTab("cpu-state-click").data = CpuStateStruct.selectStateStruct; + displayFreqLimitData = () => this.displayTab("box-freq-limit").data = CpuFreqLimitsStruct.selectCpuFreqLimitsStruct; - displayFuncData(data: FuncStruct) { - this.setAttribute("mode", "max") - this.tabCurrentSelection!.hidden = false; - this.hideBoxTab(); - this.litTabs?.activeByKey("1") - let tabCpu = this.shadowRoot!.querySelector('#tabpane-cpu'); - tabCpu!.setFunctionData(data) - } - - displayCpuData(data: CpuStruct, - callback: ((data: WakeupBean | null) => void) | undefined = undefined, - scrollCallback?: (data: CpuStruct) => void) { - this.setAttribute("mode", "max") - this.tabCurrentSelection!.hidden = false; - this.hideBoxTab(); - this.litTabs?.activeByKey("1") - let tabCpu = this.shadowRoot!.querySelector('#tabpane-cpu'); - tabCpu!.setCpuData(data, callback, scrollCallback) - } - - displayFlagData(flagObj: Flag) { - this.setAttribute("mode", "max") - this.tabCurrentSelection!.hidden = true; - this.hideBoxTab(); - this.tabBoxFlag!.hidden = false; - this.litTabs?.activeByKey("10") - let tabFlag = this.shadowRoot!.querySelector('#tab-flag'); - tabFlag!.setFlagObj(flagObj) - } - - boxSelection(selection: SelectionParam):boolean { - this.tabBoxChild!.hidden = true; + rangeSelect(selection: SelectionParam): boolean { this.selection = selection; - if (selection.hasFps || selection.cpus.length > 0 || selection.threadIds.length > 0 - || selection.funTids.length > 0 || selection.trackIds.length > 0 || selection.heapIds.length > 0 - || selection.nativeMemory.length > 0) { + Reflect.ownKeys(tabConfig).reverse().forEach(id => { + let element = tabConfig[id]; + if (element.require) { + if (element.require(selection)) { + let pane = this.shadowRoot!.querySelector(`#${id as string}`); + pane!.hidden = false; + } else { + this.shadowRoot!.querySelector(`#${id as string}`)!.hidden = true; + } + } else { + this.shadowRoot!.querySelector(`#${id as string}`)!.hidden = true; + } + }) + let firstPane = this.shadowRoot!.querySelector(`lit-tabpane[hidden='false']`); + if (firstPane) { + this.litTabs?.activeByKey(firstPane.key) + this.loadTabPaneData(firstPane.key) this.setAttribute("mode", "max") - this.tabCurrentSelection!.hidden = true; - this.tabBoxFlag!.hidden = true; - this.tabBoxCpuThread!.hidden = selection.cpus.length == 0; - this.tabBoxCpuProcess!.hidden = selection.cpus.length == 0; - this.tabBoxCpuUsage!.hidden = selection.cpus.length == 0; - this.tabBoxSPT!.hidden = selection.cpus.length == 0; - this.tabBoxPTS!.hidden = selection.cpus.length == 0; - this.tabBoxContextSwitch!.hidden = selection.cpus.length == 0; - this.tabBoxThreadSwitch!.hidden = selection.cpus.length == 0; - this.tabBoxThreadStates!.hidden = selection.threadIds.length == 0; - this.tabBoxSlices!.hidden = selection.funTids.length == 0; - this.tabBoxCounters!.hidden = selection.trackIds.length == 0; - this.tabBoxFps!.hidden = !selection.hasFps; - this.tabBoxHeap!.hidden = selection.heapIds.length == 0; - this.tabBoxNMStatistics!.hidden = selection.nativeMemory.length == 0 - this.tabBoxNMCallInfo!.hidden = selection.nativeMemory.length == 0 - this.tabBoxNMemory!.hidden = selection.nativeMemory.length == 0 - this.tabBoxNMSample!.hidden = selection.nativeMemory.length == 0 - this.setBoxActiveKey(selection); return true; } else { this.setAttribute("mode", "hidden") @@ -421,166 +275,28 @@ export class TraceSheet extends BaseElement { } } - recoveryBoxSelection() { - this.tabCurrentSelection!.hidden = true; - this.tabBoxCpuThread!.hidden = !(this.selection!.cpus.length > 0); - this.tabBoxCpuProcess!.hidden = !(this.selection!.cpus.length > 0); - this.tabBoxCpuUsage!.hidden = !(this.selection!.cpus.length > 0); - this.tabBoxSPT!.hidden = !(this.selection!.cpus.length > 0); - this.tabBoxPTS!.hidden = !(this.selection!.cpus.length > 0); - this.tabBoxContextSwitch!.hidden = !(this.selection!.cpus.length > 0); - this.tabBoxThreadSwitch!.hidden = !(this.selection!.cpus.length > 0); - this.tabBoxThreadStates!.hidden = !(this.selection!.threadIds.length > 0); - this.tabBoxSlices!.hidden = !(this.selection!.funTids.length > 0); - this.tabBoxCounters!.hidden = !(this.selection!.trackIds.length > 0) - this.tabBoxHeap!.hidden = !(this.selection!.heapIds.length > 0) - this.tabBoxFps!.hidden = !this.selection?.hasFps; - this.tabBoxNMStatistics!.hidden = !(this.selection!.nativeMemory.length > 0) - this.tabBoxNMCallInfo!.hidden = !(this.selection!.nativeMemory.length > 0) - this.tabBoxNMemory!.hidden = !(this.selection!.nativeMemory.length > 0) - this.tabBoxNMSample!.hidden = !(this.selection!.nativeMemory.length > 0) - } - - setBoxActiveKey(val: SelectionParam) { - if (val.cpus.length > 0) { - this.litTabs?.activeByKey("2") - this.loadTabPaneData("2") - } else if (val.threadIds.length > 0) { - this.litTabs?.activeByKey("4") - this.loadTabPaneData("4") - } else if (val.funTids.length > 0) { - this.litTabs?.activeByKey("5") - this.loadTabPaneData("5") - } else if (val.trackIds.length > 0) { - this.litTabs?.activeByKey("6") - this.loadTabPaneData("6") - } else if (val.hasFps) { - this.litTabs?.activeByKey("7") - this.loadTabPaneData("7") - } else if (val.heapIds.length > 0) { - this.litTabs?.activeByKey("9") - this.loadTabPaneData("9") - } else if(val.nativeMemory.length > 0) { - this.litTabs?.activeByKey("16") - this.loadTabPaneData("16") - }else{ - this.litTabs?.activeByKey("1") - this.loadTabPaneData("1") - } - } - loadTabPaneData(key: string) { - if (key == "2") { - let tabCpuThread = this.shadowRoot!.querySelector('#tab-cpu-thread'); - tabCpuThread!.data = this.selection; - } else if (key == "3") { - let tabCpuProcess = this.shadowRoot!.querySelector('#tab-cpu-process'); - tabCpuProcess!.data = this.selection; - } else if (key == "4") { - let tabThreadStates = this.shadowRoot!.querySelector('#tab-thread-states'); - tabThreadStates!.data = this.selection; - } else if (key == "5") { - let tabSlices = this.shadowRoot!.querySelector('#tab-slices'); - tabSlices!.data = this.selection; - } else if (key == "6") { - let tabCounters = this.shadowRoot!.querySelector('#tab-counters'); - tabCounters!.data = this.selection; - } else if (key == "7") { - let tabFps = this.shadowRoot!.querySelector('#tab-fps'); - tabFps!.data = this.selection; - } else if (key == "8") { - let tabCpuUsage = this.shadowRoot!.querySelector('#tab-cpu-usage'); - tabCpuUsage!.data = this.selection; - } else if (key == "9") { - let tabHeap = this.shadowRoot!.querySelector('#tab-heap'); - tabHeap!.data = this.selection; - } else if (key == "10") { - - } else if (key == "11") { - this.tabSPT!.data = this.selection; - } else if (key == "12") { - this.tabPTS!.data = this.selection; - } else if (key == "13") { - this.tabCs!.data = this.selection; - } else if (key == "14") { - this.tabTs!.data = this.selection; - } else if (key == "16") { - this.tabNativeStatistics!.data = this.selection; - } else if (key == "17") { - this.tabNativeCallInfo!.data = this.selection; - } else if (key == "18") { - this.tabNativeMemory!.data = this.selection; - } else if (key == "19") { - this.tabNativeSample!.data = this.selection; - } - } - - hideBoxTab() { - this.tabBoxCpuThread!.hidden = true; - this.tabBoxCpuProcess!.hidden = true; - this.tabBoxThreadStates!.hidden = true; - this.tabBoxSlices!.hidden = true; - this.tabBoxCounters!.hidden = true; - this.tabBoxFps!.hidden = true; - this.tabBoxSPT!.hidden = true; - this.tabBoxPTS!.hidden = true; - this.tabBoxContextSwitch!.hidden = true; - this.tabBoxThreadSwitch!.hidden = true; - this.tabBoxCpuUsage!.hidden = true; - this.tabBoxFlag!.hidden = true; - this.tabBoxHeap!.hidden = true; - this.tabBoxChild!.hidden = true; - this.tabBoxNMStatistics!.hidden = true; - this.tabBoxNMCallInfo!.hidden = true; - this.tabBoxNMemory!.hidden = true; - this.tabBoxNMSample!.hidden = true; - } - - hideOtherBoxTab(key: string) { - this.tabBoxCpuThread!.hidden = true; - this.tabBoxCpuProcess!.hidden = true; - this.tabBoxThreadStates!.hidden = true; - this.tabBoxSlices!.hidden = true; - this.tabBoxCounters!.hidden = true; - this.tabBoxFps!.hidden = true; - this.tabBoxCpuUsage!.hidden = true; - this.tabBoxHeap!.hidden = true; - this.tabBoxNMStatistics!.hidden = true; - this.tabBoxNMCallInfo!.hidden = true; - this.tabBoxNMemory!.hidden = true; - this.tabBoxNMSample!.hidden = true; - if (key == "11") { - this.tabBoxPTS!.hidden = true; - this.tabBoxContextSwitch!.hidden = true; - this.tabBoxThreadSwitch!.hidden = true; - } else if (key == "12") { - this.tabBoxSPT!.hidden = true; - this.tabBoxContextSwitch!.hidden = true; - this.tabBoxThreadSwitch!.hidden = true; - } else if (key == "13") { - this.tabBoxSPT!.hidden = true; - this.tabBoxPTS!.hidden = true; - this.tabBoxThreadSwitch!.hidden = true; - } else if (key == "14") { - this.tabBoxSPT!.hidden = true; - this.tabBoxPTS!.hidden = true; - this.tabBoxContextSwitch!.hidden = true; + let component: any = this.shadowRoot?.querySelector(`#tabs lit-tabpane[key='${key}']`)?.children.item(0); + if (component) { + component.data = this.selection; } - this.tabBoxChild!.hidden = false - this.currentKey = key - this.litTabs?.activeByKey("15") } - jumpBoxChild(key: string, e: any) { - this.hideOtherBoxTab(key) - this.tabBoxChild!.tab = e.detail.title + rowClickHandler(e: any) { + this.currentPaneID = e.target.parentElement.id + this.shadowRoot!.querySelectorAll(`lit-tabpane`) + .forEach(it => it.id != this.currentPaneID ? (it.hidden = true) : (it.hidden = false)); + let pane = this.getPaneByID("box-cpu-child"); + pane.closeable = true; + pane.hidden = false; + this.litTabs!.activeByKey(pane.key) + pane.tab = e.detail.title let param = new BoxJumpParam(); param.leftNs = this.selection!.leftNs; param.rightNs = this.selection!.rightNs; param.state = e.detail.state; param.threadId = e.detail.threadId; param.processId = e.detail.processId; - this.tabChild!.data = param; + (pane.children.item(0) as TabPaneBoxChild).data = param; } - } diff --git a/host/ide/src/trace/component/trace/base/TraceSheetConfig.ts b/host/ide/src/trace/component/trace/base/TraceSheetConfig.ts new file mode 100644 index 0000000000000000000000000000000000000000..6c07bf923efbb9e522a4c0a931c840dadc535133 --- /dev/null +++ b/host/ide/src/trace/component/trace/base/TraceSheetConfig.ts @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {TabPaneCurrentSelection} from "../sheet/TabPaneCurrentSelection.js"; +import {TabPaneFreq} from "../sheet/freq/TabPaneFreq.js"; +import {TabPaneCpuByThread} from "../sheet/cpu/TabPaneCpuByThread.js"; +import {SelectionParam} from "../../../bean/BoxSelection.js"; +import {TabPaneCpuByProcess} from "../sheet/cpu/TabPaneCpuByProcess.js"; +import {TabPaneCpuUsage} from "../sheet/cpu/TabPaneCpuUsage.js"; +import {TabPaneSPT} from "../sheet/cpu/TabPaneSPT.js"; +import {TabPaneContextSwitch} from "../sheet/cpu/TabPaneContextSwitch.js"; +import {TabPanePTS} from "../sheet/cpu/TabPanePTS.js"; +import {TabPaneThreadSwitch} from "../sheet/cpu/TabPaneThreadSwitch.js"; +import {TabPaneSlices} from "../sheet/process/TabPaneSlices.js"; +import {TabPaneCounter} from "../sheet/process/TabPaneCounter.js"; +import {TabPaneFps} from "../sheet/fps/TabPaneFps.js"; +import {TabPaneFlag} from "../timer-shaft/TabPaneFlag.js"; +import {TabPaneBoxChild} from "../sheet/cpu/TabPaneBoxChild.js"; +import {TabPaneNMStatstics} from "../sheet/native-memory/TabPaneNMStatstics.js"; +import {TabPaneNMCallInfo} from "../sheet/native-memory/TabPaneNMCallInfo.js"; +import {TabPaneNMemory} from "../sheet/native-memory/TabPaneNMemory.js"; +import {TabPaneNMSampleList} from "../sheet/native-memory/TabPaneNMSampleList.js"; +import {TabpanePerfProfile} from "../sheet/hiperf/TabPerfProfile.js"; +import {TabPanePerfSample} from "../sheet/hiperf/TabPerfSampleList.js"; +import {TabPaneLiveProcesses} from "../sheet/ability/TabPaneLiveProcesses.js"; +import {TabPaneHistoryProcesses} from "../sheet/ability/TabPaneHistoryProcesses.js"; +import {TabPaneCpuAbility} from "../sheet/ability/TabPaneCpuAbility.js"; +import {TabPaneMemoryAbility} from "../sheet/ability/TabPaneMemoryAbility.js"; +import {TabPaneDiskAbility} from "../sheet/ability/TabPaneDiskAbility.js"; +import {TabPaneNetworkAbility} from "../sheet/ability/TabPaneNetworkAbility.js"; +import {TabPaneFileStatistics} from "../sheet/file-system/TabPaneFilesystemStatistics.js"; +import {TabpaneFilesystemCalltree} from "../sheet/file-system/TabPaneFileSystemCalltree.js"; +import {TabPaneFileSystemEvents} from "../sheet/file-system/TabPaneFileSystemEvents.js"; +import {TabPaneFileSystemDescHistory} from "../sheet/file-system/TabPaneFileSystemDescHistory.js"; +import {TabPaneFileSystemDescTimeSlice} from "../sheet/file-system/TabPaneFileSystemDescTimeSlice.js"; +import {TabPaneSdkSlice} from "../sheet/sdk/TabPaneSdkSlice.js"; +import {TabPaneSdkCounter} from "../sheet/sdk/TabPaneSdkCounter.js"; +import {TabPaneCounterSample} from "../sheet/cpu/TabPaneCounterSample.js"; +import {TabPaneThreadStates} from "../sheet/process/TabPaneThreadStates.js"; +import {TabPaneFrequencySample} from "../sheet/cpu/TabPaneFrequencySample.js"; +import {TabPaneEnergyAnomaly} from "../sheet/energy/TabPaneEnergyAnomaly.js"; +import {TabPaneSystemDetails} from "../sheet/energy/TabPaneSystemDetails.js"; +import {TabPanePowerDetails} from "../sheet/energy/TabPanePowerDetails.js"; +import {TabPanePowerBattery} from "../sheet/energy/TabPanePowerBattery.js"; +import {TabPaneCpuStateClick} from "../sheet/cpu/TabPaneCpuStateClick.js"; +import {TabPaneVirtualMemoryStatistics} from "../sheet/file-system/TabPaneVirtualMemoryStatistics.js"; +import {TabPaneIOTierStatistics} from "../sheet/file-system/TabPaneIOTierStatistics.js"; +import {TabPaneIOCallTree, TabPaneVMCallTree} from "../sheet/file-system/TabPaneIOCallTree.js"; +import {TabPaneIoCompletionTimes} from "../sheet/file-system/TabPaneIoCompletionTimes.js"; +import {TabPaneVirtualMemoryEvents} from "../sheet/file-system/TabPaneVMEvents.js"; +import {TabPaneSmapsStatistics} from "../sheet/smaps/TabPaneSmapsStatistics.js"; +import {TabPaneSmapsRecord} from "../sheet/smaps/TabPaneSmapsRecord.js"; +import {TabPaneFreqLimit} from "../sheet/freq/TabPaneFreqLimit.js"; +import {TabPaneCpuFreqLimits} from "../sheet/freq/TabPaneCpuFreqLimits.js"; +import {TabpaneNMCalltree} from "../sheet/native-memory/TabPaneNMCallTree.js"; + +export let tabConfig: any = { + "current-selection": { + title: "Current Selection", type: TabPaneCurrentSelection, + }, //cpu data click + "cpu-state-click":{ + title: "Cpu State", type: TabPaneCpuStateClick, + }, + "box-freq": { + title: "Frequency", type: TabPaneFreq, + },//freq data click + "box-freq-limit":{ + title: "Frequency Limits", type: TabPaneFreqLimit, + }, + "box-cpu-freq-limit":{ + title: "Cpu Frequency Limits", type: TabPaneCpuFreqLimits, + require: (param: SelectionParam) => param.cpuFreqLimitDatas.length > 0, + }, + "box-cpu-thread": { + title: "CPU by thread", type: TabPaneCpuByThread, + require: (param: SelectionParam) => param.cpus.length > 0, + }, //range select + "box-cpu-process": { + title: "CPU by process", type: TabPaneCpuByProcess, + require: (param: SelectionParam) => param.cpus.length > 0, + }, + "box-cpu-usage": { + title: "CPU Usage", type: TabPaneCpuUsage, + require: (param: SelectionParam) => param.cpus.length > 0, + }, + "box-spt": { + title: "States List", type: TabPaneSPT, + require: (param: SelectionParam) => param.cpus.length > 0, + }, + "box-cs": { + title: "Switches List", type: TabPaneContextSwitch, + require: (param: SelectionParam) => param.cpus.length > 0, + }, + "box-pts": { + title: "Thread States", type: TabPanePTS, + require: (param: SelectionParam) => param.cpus.length > 0, + }, + "box-ts": { + title: "Thread Switches", type: TabPaneThreadSwitch, + require: (param: SelectionParam) => param.cpus.length > 0, + },//end range select + "box-slices": { + title: "Slices", type: TabPaneSlices, + require: (param: SelectionParam) => param.funTids.length > 0 || param.funAsync.length > 0, + }, + "box-counters": { + title: "Counters", type: TabPaneCounter, + require: (param: SelectionParam) => (param.processTrackIds.length > 0 || param.virtualTrackIds.length > 0), + }, + "box-fps": { + title: "FPS", type: TabPaneFps, + require: (param: SelectionParam) => param.hasFps, + }, + "box-flag": { + title: "Current Selection", type: TabPaneFlag, + }, + "box-cpu-child": { + title: "", type: TabPaneBoxChild, + }, + "box-native-statstics": { + title: "Statistics", type: TabPaneNMStatstics, + require: (param: SelectionParam) => param.nativeMemory.length > 0, + }, + "box-native-calltree": { + title: "Call Info", type: TabpaneNMCalltree, + require: (param: SelectionParam) => param.nativeMemory.length > 0, + }, + // "box-native-callinfo": { + // title: "Call Info", type: TabPaneNMCallInfo, + // require: (param: SelectionParam) => param.nativeMemory.length > 0, + // }, + "box-native-memory": { + title: "Native Memory", type: TabPaneNMemory, + require: (param: SelectionParam) => param.nativeMemory.length > 0, + }, + "box-native-sample": { + title: "Snapshot List", type: TabPaneNMSampleList, + require: (param: SelectionParam) => param.nativeMemory.length > 0, + }, + "box-perf-profile": { + title: "Perf Profile", type: TabpanePerfProfile, + require: (param: SelectionParam) => param.perfSampleIds.length > 0, + }, + "box-perf-sample": { + title: "Sample List", type: TabPanePerfSample, + require: (param: SelectionParam) => param.perfSampleIds.length > 0, + }, + "box-live-processes-child": { + title: "Live Processes", type: TabPaneLiveProcesses, + require: (param: SelectionParam) => param.cpuAbilityIds.length > 0 || param.memoryAbilityIds.length > 0 && param.diskAbilityIds.length > 0 || param.networkAbilityIds.length > 0, + }, + "box-history-processes-child": { + title: "Processes History", type: TabPaneHistoryProcesses, + require: (param: SelectionParam) => param.cpuAbilityIds.length > 0 || param.memoryAbilityIds.length > 0 || param.diskAbilityIds.length > 0 || param.networkAbilityIds.length > 0, + }, + "box-system-cpu-child": { + title: "System CPU Summary", type: TabPaneCpuAbility, + require: (param: SelectionParam) => param.cpuAbilityIds.length > 0, + }, + "box-system-memory-child": { + title: "System Memory Summary", type: TabPaneMemoryAbility, + require: (param: SelectionParam) => param.memoryAbilityIds.length > 0, + }, + "box-system-diskIo-child": { + title: "System Disk Summary", type: TabPaneDiskAbility, + require: (param: SelectionParam) => param.diskAbilityIds.length > 0, + }, + "box-system-network-child": { + title: "System Network Summary", type: TabPaneNetworkAbility, + require: (param: SelectionParam) => param.networkAbilityIds.length > 0, + }, + "box-sdk-slice-child": { + title: "Sdk Slice", type: TabPaneSdkSlice, + require: (param: SelectionParam) => param.sdkSliceIds.length > 0, + }, + "box-system-counter-child": { + title: "SDK Counter", type: TabPaneSdkCounter, + require: (param: SelectionParam) => param.sdkCounterIds.length > 0, + }, + "box-counter-sample": { + title: "Cpu State", type: TabPaneCounterSample, + require: (param: SelectionParam) => param.cpuStateFilterIds.length > 0, + }, + "box-thread-states": { + title: "Thread States", type: TabPaneThreadStates, + require: (param: SelectionParam) => param.threadIds.length > 0, + }, + "box-frequency-sample": { + title: "Cpu Frequency", type: TabPaneFrequencySample, + require: (param: SelectionParam) => param.cpuFreqFilterIds.length > 0, + }, + "box-anomaly-details": { + title: "Anomaly details", type: TabPaneEnergyAnomaly, + require: (param: SelectionParam) => param.anomalyEnergy.length > 0, + }, + "box-system-details": { + title: "System Details", type: TabPaneSystemDetails, + require: (param: SelectionParam) => param.systemEnergy.length > 0, + }, + "box-power-battery": { + title: "Power Battery", type: TabPanePowerBattery, + require: (param: SelectionParam) => param.powerEnergy.length > 0, + }, + "box-power-details": { + title: "Power Details", type: TabPanePowerDetails, + require: (param: SelectionParam) => param.powerEnergy.length > 0, + }, + "box-file-system-statistics": { + title: "Filesystem statistics", type: TabPaneFileStatistics, + require: (param: SelectionParam) => param.fileSystemType.length > 0, + }, + "box-file-system-calltree": { + title: "Filesystem Calltree", type: TabpaneFilesystemCalltree, + require: (param: SelectionParam) => param.fileSystemType.length > 0||param.fsCount > 0, + }, + "box-file-system-event": { + title: "Filesystem Events", type: TabPaneFileSystemEvents, + require: (param: SelectionParam) => param.fileSystemType.length > 0, + }, + "box-file-system-desc-history": { + title: "File Descriptor History", type: TabPaneFileSystemDescHistory, + require: (param: SelectionParam) => param.fileSystemType.length > 0, + }, + "box-file-system-desc-time-slice": { + title: "File Descriptor Time Slice", type: TabPaneFileSystemDescTimeSlice, + require: (param: SelectionParam) => param.fileSystemType.length > 0, + }, + "box-virtual-memory-statistics": { + title: "Page Fault Statistics", type: TabPaneVirtualMemoryStatistics, + require: (param: SelectionParam) => param.fileSysVirtualMemory, + }, + "box-vm-calltree": { + title: "Page Fault CallTree", type: TabPaneVMCallTree, + require: (param: SelectionParam) => param.fileSysVirtualMemory||param.vmCount > 0, + }, + "box-vm-events": { + title: "Page Fault Events", type: TabPaneVirtualMemoryEvents, + require: (param: SelectionParam) => param.fileSysVirtualMemory, + }, + "box-io-tier-statistics": { + title: "Disk I/O Tier Statistics", type: TabPaneIOTierStatistics, + require: (param: SelectionParam) => param.diskIOLatency, + }, + "box-io-calltree": { + title: "Disk I/O Latency Calltree", type: TabPaneIOCallTree, + require: (param: SelectionParam) => param.diskIOLatency||param.diskIOipids.length > 0, + }, + "box-io-events": { + title: "Trace Completion Times", type: TabPaneIoCompletionTimes, + require: (param: SelectionParam) => param.diskIOLatency, + }, + "box-smaps-statistics": { + title: "VM Tracker Statistics", type: TabPaneSmapsStatistics, + require: (param: SelectionParam) => param.smapsType.length > 0, + }, + "box-smaps-record": { + title: "VM Tracker Record List", type: TabPaneSmapsRecord, + require: (param: SelectionParam) => param.smapsType.length > 0, + }, +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/base/Utils.ts b/host/ide/src/trace/component/trace/base/Utils.ts index cb7e6dad238611e49ff712b5c3dc88695d98dd94..744f08561af496e0920866854bf9dc3d0e24b550 100644 --- a/host/ide/src/trace/component/trace/base/Utils.ts +++ b/host/ide/src/trace/component/trace/base/Utils.ts @@ -106,6 +106,32 @@ export class Utils { return res } + public static getProbablyTime(ns: number): string { + let currentNs = ns + let hour1 = 3600_000_000_000 + let minute1 = 60_000_000_000 + let second1 = 1_000_000_000; + let millisecond1 = 1_000_000; + let microsecond1 = 1_000; + let res = ""; + if (currentNs >= hour1) { + res += (currentNs / hour1).toFixed(2) + "h "; + }else if (currentNs >= minute1) { + res += (currentNs / minute1).toFixed(2) + "m "; + }else if (currentNs >= second1) { + res += (currentNs / second1).toFixed(2) + "s "; + }else if (currentNs >= millisecond1) { + res += (currentNs / millisecond1).toFixed(2) + "ms "; + }else if (currentNs >= microsecond1) { + res += (currentNs / microsecond1).toFixed(2) + "μs "; + }else if (currentNs > 0) { + res += currentNs + "ns "; + }else if (res == "") { + res = ns + ""; + } + return res + } + public static getTimeStringHMS(ns: number): string { let currentNs = ns let hour1 = 3600_000_000_000 @@ -148,23 +174,191 @@ export class Utils { return "-" + this.getByteWithUnit(Math.abs(bytes)) } let currentBytes = bytes - let kb1 = 1024 - let mb1 = 1048576 - let gb1 = 1073741824; // 1 gb + let kb1 = 1 << 10; + let mb1 = 1 << 10 << 10; + let gb1 = 1 << 10 << 10 << 10; // 1 gb let res = "" if (currentBytes > gb1) { res += (currentBytes / gb1).toFixed(2) + " Gb"; } else if (currentBytes > mb1) { res += (currentBytes / mb1).toFixed(2) + " Mb"; } else if (currentBytes > kb1) { - res += (currentBytes / kb1).toFixed(2) + " kb"; + res += (currentBytes / kb1).toFixed(2) + " Kb"; + } else { + res += Math.round(currentBytes) + " byte"; + } + return res + } + + public static groupByMap(array: Array, key: string) { + let result = new Map(); + array.forEach(item => { + let value = item[key]; + if (!result.has(value)) { + result.set(value, []) + } + result.get(value).push(item); + }) + return result; + } + + public static groupBy(array: Array, key: string) { + return array.reduce((pre, current, index, arr) => { + (pre[current[key]] = pre[current[key]] || []).push(current); + return pre; + }, {}); + } + + public static timeMsFormat2p(ns: number) { + let currentNs = ns + let hour1 = 3600_000 + let minute1 = 60_000 + let second1 = 1_000; // 1 second + let res = "" + if (currentNs >= hour1) { + res += Math.floor(currentNs / hour1).toFixed(2) + "h" + return res + } + if (currentNs >= minute1) { + res += Math.floor(currentNs / minute1).toFixed(2) + "min" + return res + } + if (currentNs >= second1) { + res += Math.floor(currentNs / second1).toFixed(2) + "s" + return res + } + if (currentNs > 0) { + res += currentNs.toFixed(2) + "ms"; + return res + } + if (res == "") { + res = "0s"; + } + return res + } + + public static uuid(): string { + // @ts-ignore + return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)); + } + + public static getBinaryByteWithUnit(bytes: number): string { + if (bytes == 0) { + return "0Bytes" + } + let currentBytes = bytes + let kib1 = 1024 + let mib1 = 1024 * 1024 + let gib1 = 1024 * 1024 * 1024; + let res = "" + if (currentBytes >= gib1) { + res += (currentBytes / gib1).toFixed(2) + "Gib"; + } else if (currentBytes >= mib1) { + res += (currentBytes / mib1).toFixed(2) + "Mib"; + } else if (currentBytes >= kib1) { + res += (currentBytes / kib1).toFixed(2) + "kib"; } else { - res += currentBytes + " byte"; + res += currentBytes.toFixed(2) + "Bytes"; } return res } + public static getTimeStampHMS(ns: number): string { + let currentNs = ns + let hour1 = 3600_000_000_000 + let minute1 = 60_000_000_000 + let second1 = 1_000_000_000; // 1 second + let millisecond1 = 1_000_000; // 1 millisecond + let microsecond1 = 1_000; // 1 microsecond + let res = ""; + if (currentNs >= hour1) { + res += this.getCompletionTime(Math.floor(currentNs / hour1), 2) + ":"; + currentNs = currentNs - Math.floor(currentNs / hour1) * hour1 + } + if (currentNs >= minute1) { + res += this.getCompletionTime(Math.floor(currentNs / minute1), 2) + ":"; + currentNs = currentNs - Math.floor(ns / minute1) * minute1 + } + if (currentNs >= second1) { + res += this.getCompletionTime(Math.floor(currentNs / second1), 2) + ":"; + currentNs = currentNs - Math.floor(currentNs / second1) * second1 + } else { + res += '00:' + } + if (currentNs >= millisecond1) { + res += this.getCompletionTime(Math.floor(currentNs / millisecond1), 3) + "."; + currentNs = currentNs - Math.floor(currentNs / millisecond1) * millisecond1 + } else { + res += "000." + } + if (currentNs >= microsecond1) { + res += this.getCompletionTime(Math.floor(currentNs / microsecond1), 3) + "."; + currentNs = currentNs - Math.floor(currentNs / microsecond1) * microsecond1 + } else { + res += "000" + } + if (currentNs > 0) { + res += this.getCompletionTime(currentNs, 3); + } + if (res == "") { + res = ns + ""; + } + return res + } + + public static getDurString(ns: number): string { + let currentNs = ns + let second1 = 1000000000; + let millisecond1 = 1000000; + let res = ""; + if (currentNs >= second1) { + let cu = currentNs / second1 + res += cu.toFixed(3) + " s " + return res; + } + if (currentNs >= millisecond1) { + res += Math.floor(currentNs / millisecond1) + " ms "; + return res; + } + if (res == "") { + res = ns + ""; + } + return res + } + + private static getCompletionTime(time: number, maxLength: number): string { + if (maxLength == 2) { + if (time.toString().length == 2) { + return '' + time; + } else { + return '0' + time; + } + } else if (maxLength == 3) { + if (time.toString().length == 3) { + return time.toString(); + } else if (time.toString().length == 2) { + return '0' + time; + } else { + return '00' + time; + } + } else { + return '0' + } + } + public getStatusMap(): Map { return Utils.statusMap; } + + public static removeDuplicates(array1:any[],array2:any[],key:string){ + let obj:any = {}; + return array1.concat(array2).reduce(function (total, item) { + if (!obj[`${item[key]}-${item["pid"]}`]) { + obj[`${item[key]}-${item["pid"]}`] = true + total.push(item) + } + return total; + }, []); + } + } diff --git a/host/ide/src/trace/component/trace/search/Search.ts b/host/ide/src/trace/component/trace/search/Search.ts index 23ff8f918a5925be94ed571142ac4d903073f40c..f5e0f3faea639e51d1141b401028d85b034b17c2 100644 --- a/host/ide/src/trace/component/trace/search/Search.ts +++ b/host/ide/src/trace/component/trace/search/Search.ts @@ -40,7 +40,11 @@ export class LitSearch extends BaseElement { set index(value: number) { this._index = value; - this.indexEL!.textContent = `${value+1}`; + this.indexEL!.textContent = `${value + 1}`; + } + + get searchValue(){ + return this.search?.value } get total(): number { @@ -54,9 +58,22 @@ export class LitSearch extends BaseElement { this.totalEL!.textContent = value.toString(); } + get isLoading(): boolean{ + return this.hasAttribute('isLoading') + } + + set isLoading(va){ + if (va) { + this.setAttribute('isLoading',''); + } else { + this.removeAttribute('isLoading') + } + } + setPercent(name: string = "", value: number) { let searchHide = this.shadowRoot!.querySelector(".root") let searchIcon = this.shadowRoot!.querySelector("#search-icon") + this.isLoading = false if (value > 0 && value <= 100) { searchHide!.style.display = "flex" searchHide!.style.backgroundColor = "var(--dark-background5,#e3e3e3)" @@ -64,6 +81,7 @@ export class LitSearch extends BaseElement { this.search!.setAttribute('placeholder', `${name}${value}%`); this.search!.setAttribute('readonly', ""); this.search!.className = "readonly" + this.isLoading = true } else if (value > 100) { searchHide!.style.display = "flex" searchHide!.style.backgroundColor = "var(--dark-background5,#fff)" @@ -89,9 +107,10 @@ export class LitSearch extends BaseElement { this.list = []; } - blur(){ + blur() { this.search?.blur(); } + initElements(): void { this.search = this.shadowRoot!.querySelector("input"); this.totalEL = this.shadowRoot!.querySelector("#total"); @@ -110,24 +129,31 @@ export class LitSearch extends BaseElement { } })); }); + this.search!.addEventListener('change', (event) => { + this.index = -1; + }); + this.search!.addEventListener("keyup", (e: KeyboardEvent) => { if (e.code == "Enter") { if (e.shiftKey) { this.dispatchEvent(new CustomEvent("previous-data", { detail: { value: this.search!.value - } + }, + composed:false })); } else { this.dispatchEvent(new CustomEvent("next-data", { detail: { value: this.search!.value - } + }, + composed:false })); } } else { this.valueChangeHandler?.(this.search!.value); } + e.stopPropagation(); }); this.shadowRoot?.querySelector("#arrow-left")?.addEventListener("click", (e) => { this.dispatchEvent(new CustomEvent("previous-data", { @@ -147,70 +173,73 @@ export class LitSearch extends BaseElement { initHtml(): string { return ` - - + + `; } - } diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneContextSwitch.ts b/host/ide/src/trace/component/trace/sheet/TabPaneContextSwitch.ts deleted file mode 100644 index 0098d18d90f375868153e0469ce679acee218153..0000000000000000000000000000000000000000 --- a/host/ide/src/trace/component/trace/sheet/TabPaneContextSwitch.ts +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (C) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import {SelectionParam} from "../../../bean/BoxSelection.js"; -import { - getTabStatesGroupByProcess, - getTabStatesGroupByProcessThread, - getTabStatesGroupByStatePidTid -} from "../../../database/SqlLite.js"; -import {StateProcessThread} from "../../../bean/StateProcessThread.js"; -import {Utils} from "../base/Utils.js"; -import {SpSystemTrace} from "../../SpSystemTrace.js"; - -@element('tabpane-context-switch') -export class TabPaneContextSwitch extends BaseElement { - private tbl: LitTable | null | undefined; - private range: HTMLLabelElement | null | undefined; - private loadDataInCache: boolean = true; - - set data(val: SelectionParam | any) { - // @ts-ignore - this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45)+"px" - this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" - if (this.loadDataInCache) { - this.queryDataInCacheData(val).then((arr) => { - this.tbl!.recycleDataSource = arr; - }); - } else { - this.queryDataByDB(val) - } - } - - initElements(): void { - this.tbl = this.shadowRoot?.querySelector('#tb-cs'); - this.range = this.shadowRoot?.querySelector('#time-range') - new ResizeObserver((entries) => { - if (this.parentElement?.clientHeight != 0) { - // @ts-ignore - this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45)+"px" - this.tbl?.reMeauseHeight() - } - }).observe(this.parentElement!) - } - - async queryDataInCacheData(val: SelectionParam | any): Promise> { - return new Promise>((resolve, reject) => { - let pMap: Map = new Map(); - let ptMap: Map = new Map(); - let ptsMap: Map = new Map(); - SpSystemTrace.SPT_DATA.map((d)=>{ - if(!(d.end_ts < val.leftNs || d.start_ts > val.rightNs)){ - if (pMap.has(d.processId + "")) { - let obj1 = pMap.get(d.processId + ""); - obj1!.count++; - obj1!.wallDuration += d.dur; - obj1!.avgDuration = (obj1!.wallDuration / obj1!.count).toFixed(2); - if (d.dur > obj1!.maxDuration) { - obj1!.maxDuration = d.dur; - } - if (d.dur < obj1!.minDuration) { - obj1!.minDuration = d.dur; - } - } else { - let obj1 = new StateProcessThread(); - obj1.id = "p" + d.processId; - obj1.title = (d.process == null || d.process == "" ? "Process" : d.process) + "(" + d.processId + ")"; - obj1.process = d.process; - obj1.processId = d.processId; - obj1.minDuration = d.dur; - obj1.maxDuration = d.dur; - obj1.count = 1; - obj1.avgDuration = d.dur + ""; - obj1.wallDuration = d.dur; - pMap.set(d.processId + "", obj1); - } - if (ptMap.has(d.processId + "_" + d.threadId)) { - let obj2 = ptMap.get(d.processId + "_" + d.threadId); - obj2!.count++; - obj2!.wallDuration += d.dur; - obj2!.avgDuration = (obj2!.wallDuration / obj2!.count).toFixed(2); - if (d.dur > obj2!.maxDuration) { - obj2!.maxDuration = d.dur; - } - if (d.dur < obj2!.minDuration) { - obj2!.minDuration = d.dur; - } - } else { - let obj2 = new StateProcessThread(); - obj2.id = "p" + d.processId + "_" + "t" + d.threadId; - obj2.pid = "p" + d.processId; - obj2.title = (d.thread == null || d.thread == "" ? "Thread" : d.thread) + "(" + d.threadId + ")" - obj2.processId = d.processId; - obj2.process = d.process; - obj2.thread = d.thread; - obj2.threadId = d.threadId; - obj2.minDuration = d.dur; - obj2.maxDuration = d.dur; - obj2.count = 1; - obj2.avgDuration = d.dur + ""; - obj2.wallDuration = d.dur; - ptMap.set(d.processId + "_" + d.threadId, obj2); - } - if (ptsMap.has(d.processId + "_" + d.threadId + "_" + d.state)) { - let obj3 = ptsMap.get(d.processId + "_" + d.threadId + "_" + d.state); - obj3!.count++; - obj3!.wallDuration += d.dur; - obj3!.avgDuration = (obj3!.wallDuration / obj3!.count).toFixed(2); - if (d.dur > obj3!.maxDuration) { - obj3!.maxDuration = d.dur; - } - if (d.dur < obj3!.minDuration) { - obj3!.minDuration = d.dur; - } - } else { - let obj3 = new StateProcessThread(); - obj3.id = "p" + d.processId + "_" + "t" + d.threadId + "_" + (d.state == "R+" ? "RP" : d.state) - obj3.pid = "p" + d.processId + "_" + "t" + d.threadId; - obj3.title = Utils.getEndState(d.state) - obj3.processId = d.processId; - obj3.process = d.process; - obj3.thread = d.thread; - obj3.threadId = d.threadId; - obj3.state = d.state; - obj3.minDuration = d.dur; - obj3.maxDuration = d.dur; - obj3.count = 1; - obj3.avgDuration = d.dur + ""; - obj3.wallDuration = d.dur; - ptsMap.set(d.processId + "_" + d.threadId + "_" + d.state, obj3); - } - } - }) - let arr: Array = []; - for (let key of pMap.keys()) { - let s = pMap.get(key); - s!.children = []; - for (let ks of ptMap.keys()) { - if (ks.startsWith(key + "_")) { - let sp = ptMap.get(ks) - sp!.children = []; - for (let kst of ptsMap.keys()) { - if (kst.startsWith(ks + "_")) { - let spt = ptsMap.get(kst) - sp!.children.push(spt!); - } - } - s!.children.push(sp!) - } - } - arr.push(s!) - } - resolve(arr); - }) - } - - queryDataByDB(val: SelectionParam | any) { - Promise.all([ - getTabStatesGroupByProcess(val.leftNs, val.rightNs), - getTabStatesGroupByProcessThread(val.leftNs, val.rightNs), - getTabStatesGroupByStatePidTid(val.leftNs, val.rightNs)]).then((values) => { - let processes = values[0]; - processes.map((spt) => { - spt.id = "p" + spt.processId - spt.title = (spt.process == null || spt.process == "" ? "Process" : spt.process) + "(" + spt.processId + ")" - }); - let threadMap = this.groupByProcessToMap(values[1]); - let stateMap = this.groupByProcessThreadToMap(values[2]); - for (let process of processes) { - let threads = threadMap.get(process.processId); - if (threads != undefined) { - threads!.map((spt) => { - spt.id = "p" + spt.processId + "_" + "t" + spt.threadId; - spt.pid = "p" + spt.processId; - spt.title = (spt.thread == null || spt.thread == "" ? "Thread" : spt.thread) + "(" + spt.threadId + ")" - }) - } - process.children = threads ?? []; - let map = stateMap.get(process.processId); - for (let thread of threads!) { - let states = map!.get(thread.threadId); - states!.map((spt) => { - spt.id = "p" + spt.processId + "_" + "t" + spt.threadId + "_" + (spt.state == "R+" ? "RP" : spt.state) - spt.pid = "p" + spt.processId + "_" + "t" + spt.threadId; - spt.title = Utils.getEndState(spt.state) - }) - thread.children = states ?? []; - } - } - this.tbl!.dataSource = processes; - }) - } - - groupByThreadToMap(arr: Array): Map> { - let map = new Map>(); - for (let spt of arr) { - if (map.has(spt.threadId)) { - map.get(spt.threadId)!.push(spt); - } else { - let list: Array = []; - list.push(spt); - map.set(spt.threadId, list); - } - } - return map; - } - - groupByProcessToMap(arr: Array): Map> { - let map = new Map>(); - for (let spt of arr) { - if (map.has(spt.processId)) { - map.get(spt.processId)!.push(spt); - } else { - let list: Array = []; - list.push(spt); - map.set(spt.processId, list); - } - } - return map; - } - - groupByProcessThreadToMap(arr: Array): Map>> { - let map = new Map>>(); - let processMap = this.groupByProcessToMap(arr); - for (let key of processMap.keys()) { - let threadMap = this.groupByThreadToMap(processMap.get(key)!) - map.set(key, threadMap); - } - return map; - } - - initHtml(): string { - return ` - - - - - - - `; - } - -} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts b/host/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts index 6ffdaf1669a00a2177962e936eebcb94253ec909..79e4f99b3a88c4fd3c439d68472329037f7176c6 100644 --- a/host/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts +++ b/host/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts @@ -14,20 +14,23 @@ */ import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {CpuStruct} from "../../../bean/CpuStruct.js"; import {LitTable} from "../../../../base-ui/table/lit-table.js"; import "../../../../base-ui/table/lit-table-column.js"; import { - queryBinderArgsByArgset, - queryWakeUpThread_WakeThread, - queryWakeUpThread_WakeTime + queryBinderArgsByArgset, queryBinderByArgsId, queryBinderBySliceId, + queryThreadWakeUp, + queryThreadWakeUpFrom, + queryWakeUpFromThread_WakeThread, + queryWakeUpFromThread_WakeTime, } from "../../../database/SqlLite.js"; import {WakeupBean} from "../../../bean/WakeupBean.js"; -import {ThreadStruct} from "../../../bean/ThreadStruct.js"; -import {ProcessMemStruct} from "../../../bean/ProcessMemStruct.js"; -import {FuncStruct} from "../../../bean/FuncStruct.js"; import {SpApplication} from "../../../SpApplication.js"; +import {TraceRow} from "../base/TraceRow.js"; +import { CpuStruct } from "../../../database/ui-worker/ProcedureWorkerCPU.js"; +import { ThreadStruct } from "../../../database/ui-worker/ProcedureWorkerThread.js"; +import { FuncStruct } from "../../../database/ui-worker/ProcedureWorkerFunc.js"; +import { ProcessMemStruct } from "../../../database/ui-worker/ProcedureWorkerMem.js"; const STATUS_MAP: any = { D: "Uninterruptible Sleep", @@ -100,12 +103,8 @@ export class TabPaneCurrentSelection extends BaseElement { leftTitle.innerText = "Slice Details" } let list: any[] = [] - let process = data.processName - let processId = data.processId - if (process == null || process == "") { - process = data.name - processId = data.tid - } + let process = this.transferString( data.processName || "Process"); + let processId = data.processId || data.tid; let state = "" if (data.end_state) { state = STATUS_MAP[data.end_state] @@ -116,18 +115,29 @@ export class TabPaneCurrentSelection extends BaseElement { } list.push({name: 'Process', value: `${process || 'Process'} [${processId}]`}) - list.push({ - name: 'Thread', value: `
-
${data.name || 'Process'} [${data.tid}]
+ let name = this.transferString(data.name ?? ""); + if(data.processId){ + list.push({ + name: 'Thread', value: `
+
${name || 'Process'} [${data.tid}]
` - }) + }) + }else { + list.push({ + name: 'Thread', value: `
+
${name || 'Process'} [${data.tid}]
+
` + }) + } + list.push({name: 'CmdLine', value: `${data.processCmdLine}`}) - list.push({name: 'StartTime', value: getTimeString(data.startTime || 0)}) + list.push({name: 'StartTime(Relative)', value: getTimeString(data.startTime || 0)}) + list.push({name: 'StartTime(Absolute)', value: ((data.startTime||0) + (window as any).recordStartNS)/1000000000}) list.push({name: 'Duration', value: getTimeString(data.dur || 0)}) list.push({name: 'Prio', value: data.priority || 0}) list.push({name: 'End State', value: state}) - this.queryWakeUpData(data).then((bean) => { + this.queryCPUWakeUpFromData(data).then((bean) => { if (callback) { callback(bean) } @@ -163,7 +173,7 @@ export class TabPaneCurrentSelection extends BaseElement { }) } - setFunctionData(data: FuncStruct) {//方法信息 + setFunctionData(data: FuncStruct,scrollCallback:Function) {//方法信息 this.initCanvas() let leftTitle: HTMLElement | null | undefined = this?.shadowRoot?.querySelector("#leftTitle"); let rightTitle: HTMLElement | null | undefined = this?.shadowRoot?.querySelector("#rightTitle"); @@ -174,24 +184,99 @@ export class TabPaneCurrentSelection extends BaseElement { leftTitle.innerText = "Slice Details" } let list: any[] = [] - list.push({name: 'Name', value: data.funName}) - // list.push({name: 'Category', value:data.category}) 暂无参数 - list.push({name: 'StartTime', value: getTimeString(data.startTs || 0)}) - list.push({name: 'Duration', value: getTimeString(data.dur || 0)}) - if (FuncStruct.isBinder(data)) { - if (data.argsetid != undefined) { + let name = this.transferString(data.funName ?? ""); + let isBinder = FuncStruct.isBinder(data); + let isAsyncBinder = isBinder&&FuncStruct.isBinderAsync(data); + if (data.argsetid != undefined&&data.argsetid != null) { + if(isAsyncBinder){ + Promise.all([queryBinderByArgsId(data.argsetid!,data.startTs!,!data.funName!.endsWith("rcv")),queryBinderArgsByArgset(data.argsetid)]).then((result)=>{ + let asyncBinderRes = result[0] + let argsBinderRes = result[1] + let asyncBinderStract:any; + if(asyncBinderRes.length > 0){ + asyncBinderRes[0].type = TraceRow.ROW_TYPE_FUNC + asyncBinderStract = asyncBinderRes[0] + } + if(argsBinderRes.length > 0){ + argsBinderRes.forEach((item) => { + list.push({name: item.keyName, value: item.strValue}) + }) + } + if(asyncBinderStract != undefined){ + list.unshift({ + name: 'Name', value: `
+
${name || 'binder'}
+ +
` + }) + }else { + list.unshift({name: 'Name', value:name}) + } + list.push({name: 'StartTime', value: getTimeString(data.startTs || 0)}) + list.push({name: 'Duration', value: getTimeString(data.dur || 0)}) + list.push({name: 'depth', value: data.depth}) + list.push({name: 'arg_set_id', value: data.argsetid}) + this.tbl!.dataSource = list; + let funcClick = this.tbl?.shadowRoot?.querySelector("#function-jump") + funcClick?.addEventListener("click", () => { + scrollCallback(asyncBinderStract) + }) + }) + } else if(isBinder){ queryBinderArgsByArgset(data.argsetid).then((argset) => { + let binderSliceId = -1; argset.forEach((item) => { + if(item.keyName == 'destination slice id'){ + binderSliceId = Number(item.strValue) + list.unshift({ + name: 'Name', value: `
+
${name || 'binder'}
+ +
` + }) + } list.push({name: item.keyName, value: item.strValue}) }) - + if(binderSliceId == -1) { + list.unshift({name: 'Name', value:name}) + } + list.push({name: 'StartTime', value: getTimeString(data.startTs || 0)}) + list.push({name: 'Duration', value: getTimeString(data.dur || 0)}) + list.push({name: 'depth', value: data.depth}) + list.push({name: 'arg_set_id', value: data.argsetid}) + this.tbl!.dataSource = list; + let funcClick = this.tbl?.shadowRoot?.querySelector("#function-jump") + funcClick?.addEventListener("click", () => { + if (!Number.isNaN(binderSliceId)&&binderSliceId!=-1) { + queryBinderBySliceId(binderSliceId).then((result:any[])=>{ + if(result.length > 0){ + result[0].type = TraceRow.ROW_TYPE_FUNC + scrollCallback(result[0]) + } + }) + } + }) }); + } else { + queryBinderArgsByArgset(data.argsetid).then((argset) => { + list.push({name: 'Name', value:name}) + argset.forEach((item) => { + list.push({name: item.keyName, value: item.strValue}) + }) + list.push({name: 'StartTime', value: getTimeString(data.startTs || 0)}) + list.push({name: 'Duration', value: getTimeString(data.dur || 0)}) + list.push({name: 'depth', value: data.depth}) + list.push({name: 'arg_set_id', value: data.argsetid}) + this.tbl!.dataSource = list; + }) } + }else { + list.push({name: 'Name', value:name}) + list.push({name: 'StartTime', value: getTimeString(data.startTs || 0)}) + list.push({name: 'Duration', value: getTimeString(data.dur || 0)}) list.push({name: 'depth', value: data.depth}) - list.push({name: 'arg_set_id', value: data.argsetid}) + this.tbl!.dataSource = list; } - this.tbl!.dataSource = list - } setMemData(data: ProcessMemStruct) {//时钟信息 @@ -209,7 +294,7 @@ export class TabPaneCurrentSelection extends BaseElement { } - setThreadData(data: ThreadStruct, scrollCallback: ((d: any) => void) | undefined) {//线程信息 + setThreadData(data: ThreadStruct, scrollCallback: ((d: any) => void) | undefined,scrollWakeUp:(d:any) => void | undefined) {//线程信息 this.initCanvas() let leftTitle: HTMLElement | null | undefined = this?.shadowRoot?.querySelector("#leftTitle"); let rightTitle: HTMLElement | null | undefined = this?.shadowRoot?.querySelector("#rightTitle"); @@ -217,7 +302,7 @@ export class TabPaneCurrentSelection extends BaseElement { rightTitle.style.visibility = "hidden" } if (leftTitle) { - leftTitle.innerText = "Counter Details" + leftTitle.innerText = "Thread State" } let list: any[] = [] list.push({name: 'StartTime', value: getTimeString(data.startTime || 0)}) @@ -247,22 +332,75 @@ export class TabPaneCurrentSelection extends BaseElement { if (processName == null || processName == "" || processName.toLowerCase() == "null") { processName = data.name; } - list.push({name: 'Process', value: processName + " [" + data.pid + "] "}) - this.tbl!.dataSource = list - this.tbl?.shadowRoot?.querySelector("#state-click")?.addEventListener("click", () => { - //线程点击 - if (scrollCallback) { - scrollCallback(data) + list.push({name: 'Process', value: this.transferString(processName ?? "") + " [" + data.pid + "] "}) + let cpu = new CpuStruct(); + cpu.id = data.id; + cpu.startTime = data.startTime; + Promise.all([this.queryThreadWakeUpFromData(data.id!,data.startTime!,data.dur!),this.queryThreadWakeUpData(data.id!,data.startTime!,data.dur!)]).then((result)=>{ + let fromBean = result[0] + let wakeUps = result[1]; + if(fromBean != null && fromBean != undefined && fromBean.pid != 0 && fromBean.tid != 0){ + list.push({ + name: 'wakeup from tid', value: `
+
${fromBean.tid}
+ +
` + }) + } + if(wakeUps != null){ + wakeUps.map((e) => { + list.push({ + name: 'wakeup tid', value: `
+
${e.tid}
+ +
` + }) + }) + } + this.tbl!.dataSource = list + this.tbl?.shadowRoot?.querySelector("#state-click")?.addEventListener("click", () => { + //线程点击 + if (scrollCallback) { + scrollCallback(data) + } + }) + this.tbl?.shadowRoot?.querySelector("#wakeup-from")?.addEventListener("click", (e) => { + //点击跳转,唤醒和被唤醒的 线程 + if(fromBean && scrollWakeUp){ + scrollWakeUp({ + processId: fromBean.pid, + tid: fromBean.tid, + startTime: fromBean.ts, + }) + } + }) + if(wakeUps){ + wakeUps.map((up) => { + this.tbl?.shadowRoot?.querySelector(`#wakeup-${up.tid}`)?.addEventListener("click", (e) => { + //点击跳转,唤醒和被唤醒的 线程 + if(up && scrollWakeUp != undefined){ + scrollWakeUp({ + tid: up.tid, + startTime: up.ts, + processId:up.pid, + }) + } + }) + }) } }) } - async queryWakeUpData(data: CpuStruct) { + /** + * 查询出 线程被唤醒的 线程信息 + * @param data + */ + async queryCPUWakeUpFromData(data: CpuStruct) { let wb: WakeupBean | null = null if (data.id == undefined || data.startTime == undefined) { return null } - let wakeupTimes = await queryWakeUpThread_WakeTime(data.id, data.startTime)// 3,4835380000 + let wakeupTimes = await queryWakeUpFromThread_WakeTime(data.id, data.startTime) if (wakeupTimes != undefined && wakeupTimes.length > 0) { let wakeupTime = wakeupTimes[0] if (wakeupTime.wakeTs != undefined && wakeupTime.preRow != undefined && wakeupTime.wakeTs < wakeupTime.preRow) { @@ -271,7 +409,7 @@ export class TabPaneCurrentSelection extends BaseElement { if (wakeupTime.wakeTs == undefined) { return null } - let wakeupBeans = await queryWakeUpThread_WakeThread(wakeupTime.wakeTs) + let wakeupBeans = await queryWakeUpFromThread_WakeThread(wakeupTime.wakeTs) if (wakeupBeans != undefined && wakeupBeans.length > 0) { wb = wakeupBeans[0] if (wb != null) { @@ -292,6 +430,32 @@ export class TabPaneCurrentSelection extends BaseElement { return wb } + /** + * 查询出 线程唤醒了哪些线程信息 + * @param data + */ + async queryThreadWakeUpFromData(itid: number, startTime: number,dur:number) : Promise { + let wakeUps = await queryThreadWakeUpFrom(itid, startTime,dur) + if (wakeUps != undefined && wakeUps.length > 0) { + return wakeUps[0]; + } + } + /** + * 查询出 线程唤醒了哪些线程信息 + * @param data + */ + async queryThreadWakeUpData(itid: number, startTime: number,dur:number) : Promise> { + let list :Array = []; + if (itid == undefined || startTime == undefined) { + return list + } + let wakeUps = await queryThreadWakeUp(itid, startTime,dur)// 3,4835380000 + if (wakeUps != undefined && wakeUps.length > 0) { + list.push(...wakeUps) + } + return list + } + initCanvas(): HTMLCanvasElement | null { let canvas = this.shadowRoot!.querySelector("#rightDraw") let width = getComputedStyle(this.tbl!).getPropertyValue("width") @@ -342,7 +506,7 @@ export class TabPaneCurrentSelection extends BaseElement { let strList = [] strList.push("wakeup @ " + getTimeString(wakeupBean?.wakeupTime || 0) + " on CPU " + wakeupBean?.cpu + " by") strList.push("P:" + wakeupBean?.process + " [ " + wakeupBean?.pid + " ]") - strList.push("F:" + wakeupBean?.thread + " [ " + wakeupBean?.tid + " ]") + strList.push("T:" + wakeupBean?.thread + " [ " + wakeupBean?.tid + " ]") strList.forEach((str, index) => { if (context != null) { context.fillText(str, 40, 40 + 16 * index) @@ -374,6 +538,22 @@ export class TabPaneCurrentSelection extends BaseElement { } } + transferString(str:string): string{ + let s = "" + if(str.length == 0){ + return ""; + } + s = str.replace(/&/g,"&") + s = s.replace(//g,">") + // s = s.replace(/ /g," ") + s = s.replace(/\'/g,"'") + s = s.replace(/\"/g,"&#quat;") + // s = s.replace(/(/g,"&") + // s = s.replace(/)/g,"&") + return s + } + initElements(): void { this.tbl = this.shadowRoot?.querySelector('#selectionTbl'); this.tbl?.addEventListener("column-click", (ev: any) => { @@ -446,5 +626,4 @@ export class TabPaneCurrentSelection extends BaseElement {
`; } - } diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneFilter.ts b/host/ide/src/trace/component/trace/sheet/TabPaneFilter.ts index 4ce88d324c97cdd4f4759eb2f36505c50010bb9f..682742fcc176dc920311820e853653deb9036ca9 100644 --- a/host/ide/src/trace/component/trace/sheet/TabPaneFilter.ts +++ b/host/ide/src/trace/component/trace/sheet/TabPaneFilter.ts @@ -18,347 +18,791 @@ import "../../../../base-ui/select/LitSelect.js"; import "../../../../base-ui/select/LitSelectOption.js"; import '../../../../base-ui/icon/LitIcon.js' import {LitIcon} from "../../../../base-ui/icon/LitIcon.js"; +import "../../../../base-ui/popover/LitPopoverV.js" +import {LitCheckBox} from "../../../../base-ui/checkbox/LitCheckBox.js"; -export interface FilterData{ - inputValue:string, - firstSelect:string|null|undefined, - secondSelect:string|null|undefined, - mark:boolean|null|undefined, - icon:string|null, +export interface FilterData { + inputValue: string, + firstSelect: string | null | undefined, + secondSelect: string | null | undefined, + thirdSelect: string | null | undefined, + mark: boolean | null | undefined, + icon: string | null, + type: string, +} + +export interface MiningData { + type: string, + item: any | null | undefined, + remove?: Array | null | undefined, } @element('tab-pane-filter') export class TabPaneFilter extends BaseElement { - private filterInputEL: HTMLInputElement | null | undefined; - private firstSelectEL: HTMLSelectElement | null | undefined; - private secondSelectEL: HTMLSelectElement | null | undefined; - private markButtonEL: HTMLButtonElement | null | undefined; - private iconEL: LitIcon | null | undefined; - private getFilter: ((e:FilterData)=>void) | undefined; - - initElements(): void { - // this.firstSelectEL = this.shadowRoot?.querySelector("#first-select") - // this.secondSelectEL = this.shadowRoot?.querySelector("#second-select") - this.filterInputEL = this.shadowRoot?.querySelector("#filter-input") - this.markButtonEL = this.shadowRoot?.querySelector("#mark") - this.iconEL = this.shadowRoot?.querySelector("#icon") - - this.iconEL!.onclick=(e)=>{ - if (this.iconEL!.name == "statistics") { - this.iconEL!.name = "menu"; - this.iconEL!.size = 18; - if (this.getFilter) { - this.getFilter({ - inputValue:this.filterInputEL!.value, - firstSelect:this.firstSelectEL?.value, - secondSelect:this.secondSelectEL?.value, - mark:false, - icon:this.icon - }) - } - }else if (this.iconEL!.name == "menu") { - this.iconEL!.name = "statistics"; - this.iconEL!.size = 16; - if (this.getFilter) { - this.getFilter({ - inputValue:this.filterInputEL!.value, - firstSelect:this.firstSelectEL?.value, - secondSelect:this.secondSelectEL?.value, - mark:false, - icon:this.icon - }) - } - } - } - - this.markButtonEL!.onclick=(e)=>{ - if (this.getFilter) { - this.getFilter({ - inputValue:this.filterInputEL!.value, - firstSelect:this.firstSelectEL?.value, - secondSelect:this.secondSelectEL?.value, - mark:true, - icon:this.icon - }) - } - } - - this.filterInputEL?.addEventListener("keydown", (event:any) => { - if (event.keyCode == 13) { - this.iconEL!.name="menu" - if (this.getFilter) { - this.getFilter({ - inputValue:event.target.value, - firstSelect:this.firstSelectEL?.value, - secondSelect:this.secondSelectEL?.value, - mark:false, - icon:this.icon - }) - } - } - }); - - // this.firstSelectEL!.onchange = (e)=>{ - // if (this.getFilter) { - // this.getFilter({ - // inputValue:this.filterInputEL!.value, - // firstSelect:this.firstSelectEL?.value, - // secondSelect:this.secondSelectEL?.value, - // mark:false - // }) - // } - // } - // this.secondSelectEL!.onchange = (e)=>{ - // if (this.getFilter) { - // this.getFilter({ - // inputValue:this.filterInputEL!.value, - // firstSelect:this.firstSelectEL?.value, - // secondSelect:this.secondSelectEL?.value, - // mark:false - // }) - // } - // } - this.setSelectList() - } - - set firstSelect(value:string){ - this.firstSelectEL!.value = value; - } - - get firstSelect(){ - return this.firstSelectEL?.value||"" - } - - set secondSelect(value:string){ - this.secondSelectEL!.value = value; - } - - get secondSelect(){ - return this.secondSelectEL?.value||"" - } - - set filterValue(value:string){ - this.filterInputEL!.value = value; - } - get filterValue(){ - return this.filterInputEL!.value - } - - get inputPlaceholder(){ - return this.getAttribute("inputPlaceholder") || "Detail Filter"; - } - - get icon(){ - if (this.getAttribute("icon") != "false") { - if (this.iconEL!.name == "statistics") { - return "tree" - }else if (this.iconEL!.name == "menu") { - return "block" - }else { - return "" - } - } else { - return ""; - } - } - - set icon(value:string){ - if (value == "block") { - this.iconEL!.name = "menu"; - this.iconEL!.size = 18; - }else if (value == "tree") { - this.iconEL!.name = "statistics"; - this.iconEL!.size = 16; - } - } - - - getFilterData(getFilter:(v:FilterData)=>void){ - this.getFilter = getFilter - } - - setSelectList(firstList :Array|null|undefined = [ "All Allocations" ,"Created & Existing" ,"Created & Destroyed" ], - secondList :Array|null|undefined = ["All Heap & Anonymous VM", "All Heap", "All Anonymous VM"]){ - if (!firstList && !secondList) return; - let sLE = this.shadowRoot?.querySelector("#load") - let html = ``; - if (firstList) { - html += ` - Allocation Lifespan` - firstList!.forEach((a,b)=>{ - html+=`${a}` - }) - html+=`` - } - if (secondList) { - html+=` - Allocation Type` - secondList!.forEach((a,b)=>{ - html+=`${a}` - }) - html+=`` - } - if (!firstList) { - this.secondSelectEL!.outerHTML = html; - } else if (!secondList) { - this.firstSelectEL!.outerHTML = html; - }else { - sLE!.innerHTML=html; - } - - this.firstSelectEL = this.shadowRoot?.querySelector("#first-select") - this.secondSelectEL = this.shadowRoot?.querySelector("#second-select") - - this.firstSelectEL!.onchange = (e)=>{ - if (this.getFilter) { - this.getFilter({ - inputValue:this.filterInputEL!.value, - firstSelect:this.firstSelectEL?.value, - secondSelect:this.secondSelectEL?.value, - mark:false, - icon:this.icon - }) - } - } - this.secondSelectEL!.onchange = (e)=>{ - if (this.getFilter) { - this.getFilter({ - inputValue:this.filterInputEL!.value, - firstSelect:this.firstSelectEL?.value, - secondSelect:this.secondSelectEL?.value, - mark:false, - icon:this.icon - }) - } - } - - } - - initHtml(): string { - return ` - - -Input Filter - - -
- -
- - - - - - - - - - - - - Call Tree - Call Tree Constraints - Data Mining + + Input Filter + + +
+ +
+ +
+
Invert
+
Hide System so
+
+ Options +
+ +
+ + + +
+
Constraints:Only enabled with data and while stopped;
+
filters data to thresholds.
+
+ +
+
+ Sample Count Filter +
+ +
+
+ +
+
+
Reset
+
+
+ Symbol Filter +
+ +
+
+ +
+
+
Reset
+
+
+ Library Filter +
+
+ +
Statistics by Thread
+
`; - } + } } diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneHeap.ts b/host/ide/src/trace/component/trace/sheet/TabPaneHeap.ts deleted file mode 100644 index ae9da25baf3b17b0b9aec65a3cff110ecd1dd59f..0000000000000000000000000000000000000000 --- a/host/ide/src/trace/component/trace/sheet/TabPaneHeap.ts +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import "../../../../base-ui/table/lit-table-column.js"; -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import {SelectionParam} from "../../../bean/BoxSelection.js"; -import {queryHeapAllData, queryHeapAllTable, queryHeapTable, queryHeapTreeTable} from "../../../database/SqlLite.js"; -import {Utils} from "../base/Utils.js"; -import {HeapBean} from "../../../bean/HeapBean.js"; -import {HeapTreeDataBean} from "../../../bean/HeapTreeDataBean.js"; -import {SpSystemTrace} from "../../SpSystemTrace.js"; - -@element('tabpane-heap') -export class TabPaneHeap extends BaseElement { - private tbl: LitTable | null | undefined; - private range: HTMLLabelElement | null | undefined; - - initElements(): void { - this.tbl = this.shadowRoot?.querySelector('#tb-heap'); - this.range = this.shadowRoot?.querySelector('#time-range') - new ResizeObserver((entries) => { - if (this.parentElement?.clientHeight != 0) { - // @ts-ignore - this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20)+"px" - this.tbl?.reMeauseHeight() - } - }).observe(this.parentElement!) - } - - - - set data(val: SelectionParam|any) { - // @ts-ignore - this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20)+"px" - queryHeapAllData(val.leftNs,val.rightNs,val.heapIds).then((allHeap)=>{ - if(allHeap.length>0){ - let groups:any = {}; - let treeGroup:any = {} - let treeData:HeapBean[] = [] - allHeap.forEach((heapData)=>{ - groups[heapData.eventId] = heapData - }) - SpSystemTrace.HEAP_FRAME_DATA.map((frame)=>{ - if(groups[frame.eventId]){ - treeGroup[frame.eventId] = treeGroup[frame.eventId]||[] - frame.heapSize = groups[frame.eventId].heapSize - frame.startTs = groups[frame.eventId].startTs - frame.endTs = groups[frame.eventId].endTs - frame.eventType = groups[frame.eventId].eventType - treeGroup[frame.eventId].push(frame) - } - }) - Object.keys(treeGroup).forEach((key)=>{ - if (treeGroup[key].length > 0) { - if(treeData.length>0){ - this.merageTree(0,treeData,treeGroup[key],val) - }else { - let currentData = new HeapBean() - let firstData = treeGroup[key][0] - currentData.AllocationFunction = firstData.AllocationFunction - currentData.depth = firstData.depth - currentData.MoudleName = firstData.MoudleName - treeData.push(currentData) - this.merageTree(0,treeData,treeGroup[key],val) - } - } - }) - this.setTreeDataSize(treeData) - this.tbl!.recycleDataSource = treeData - }else { - this.tbl!.recycleDataSource = [] - } - - }) - } - - setTreeDataSize(list:HeapBean[]){ - list.forEach((item)=>{ - item.AllocationSize = Utils.getByteWithUnit(Number(item.AllocationSize)) - item.DeAllocationSize = Utils.getByteWithUnit(Number(item.DeAllocationSize)) - item.RemainingSize = Utils.getByteWithUnit(Number(item.RemainingSize)) - if(item.children.length>0){ - this.setTreeDataSize(item.children) - } - }) - } - - merageTree(depth: number,beanList:HeapBean[],list:HeapTreeDataBean[],selection: SelectionParam|any){ - if(beanList.length>0){ - if(depth < list.length){ - let treeData = list[depth] - let currentData = beanList.find((item)=>{ - return treeData.MoudleName == item.MoudleName && treeData.AllocationFunction == item.AllocationFunction - }) - if(currentData!=undefined){ - (currentData.Allocations as number) += selection.leftNstreeData.endTs?1:0; - (currentData.AllocationSize as number) += selection.leftNstreeData.endTs?treeData.heapSize:0; - ( currentData.Total as number) = (currentData.Allocations as number) - (currentData.Deallocations as number); - currentData.RemainingSize = (currentData.AllocationSize as number) - (currentData.DeAllocationSize as number) - }else { - currentData = new HeapBean() - currentData.AllocationFunction = treeData.AllocationFunction - currentData.depth = treeData.depth - currentData.MoudleName = (treeData.MoudleName as string); - (currentData.Allocations as number) += selection.leftNstreeData.endTs?1:0; - (currentData.AllocationSize as number) += selection.leftNstreeData.endTs?treeData.heapSize:0; - currentData.Total = (currentData.Allocations as number) - (currentData.Deallocations as number); - currentData.RemainingSize = (currentData.AllocationSize as number) - (currentData.DeAllocationSize as number); - beanList.push(currentData) - } - if(depth+1 -:host{ - display: flex; - flex-direction: column; - padding: 10px 10px; -} - - - - - - - - - - - - - - - - - - - - - `; - } - -} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneNMCallInfo.ts b/host/ide/src/trace/component/trace/sheet/TabPaneNMCallInfo.ts deleted file mode 100644 index 0ad18bf9d6c346e1443979afa0bc1de4b0a1340d..0000000000000000000000000000000000000000 --- a/host/ide/src/trace/component/trace/sheet/TabPaneNMCallInfo.ts +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (C) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import {SelectionParam} from "../../../bean/BoxSelection.js"; -import {queryNativeHookEventTid} from "../../../database/SqlLite.js"; -import {NativeHookCallInfo, NativeHookStatistics} from "../../../bean/NativeHook.js"; -import {SpSystemTrace} from "../../SpSystemTrace.js"; -import {Utils} from "../base/Utils.js"; -import "./TabPaneFilter.js" -import {FilterData, TabPaneFilter} from "./TabPaneFilter"; - -@element('tabpane-native-callinfo') -export class TabPaneNMCallInfo extends BaseElement { - private tbl: LitTable | null | undefined; - private tblData: LitTable | null | undefined; - private source: Array = [] - private queryResult: Array = [] - private native_type:Array = ["All Heap & Anonymous VM","All Heap","All Anonymous VM"]; - private filterAllocationType:string = "0" - private filterNativeType:string = "0" - private currentSelection:SelectionParam|undefined - set data(val: SelectionParam | any) { - if(val!=this.currentSelection){ - this.currentSelection = val - this.initFilterTypes() - } - let types:Array = [] - if(val.nativeMemory.indexOf(this.native_type[0]) != -1){ - types.push("'AllocEvent'"); - types.push("'MmapEvent'"); - }else{ - if(val.nativeMemory.indexOf(this.native_type[1]) != -1){ - types.push("'AllocEvent'"); - } - if(val.nativeMemory.indexOf(this.native_type[2]) != -1){ - types.push("'MmapEvent'"); - } - } - // @ts-ignore - this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20 - 31) + "px" - // @ts-ignore - this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) + "px" - // @ts-ignore - this.tblData?.recycleDataSource = []; - // @ts-ignore - this.tbl?.recycleDataSource = []; - queryNativeHookEventTid(val.leftNs,val.rightNs,types).then((result)=>{ - if(result.length > 0){ - this.queryResult = result - this.source = this.handleQueryResult(result); - }else{ - this.source = []; - } - this.filterQueryData() - }) - } - - handleQueryResult(result:Array):Array{ - let resultMap = new Map(); - result.map((r)=>{ - resultMap.set(r.eventId,r); - }) - let map = new Map(); - SpSystemTrace.HEAP_FRAME_DATA.map((frame) => { - let frameEventId = parseInt(frame.eventId); - if(frameEventId >= result[0].eventId && frameEventId <= result[result.length - 1].eventId){ - if(resultMap.has(frameEventId)){ - let hook = resultMap.get(frameEventId); - if(hook != undefined){ - let target = new NativeHookCallInfo(); - target.id = frame.eventId + "_" + frame.depth; - target.eventId = frameEventId; - target.depth = frame.depth; - target.count = 1; - target.heapSize = hook.heapSize; - target.threadId = hook.tid; - target.heapSizeStr = Utils.getByteWithUnit(target.heapSize); - let sym_arr = frame.AllocationFunction?.split("/"); - let lib_arr = frame.MoudleName?.split("/"); - target.symbol = sym_arr![sym_arr!.length - 1]; - target.library = lib_arr![lib_arr!.length - 1]; - target.title = `[ ${target.symbol} ] ${target.library}`; - target.type = (target.library.endsWith(".so.1") || target.library.endsWith(".dll") || target.library.endsWith(".so")) ? 0 : 1; - if(map.has(frame.eventId)){ - let src = map.get(frame.eventId); - this.listToTree(target,src!); - }else{ - map.set(frame.eventId,target); - } - } - } - } - if(frameEventId > result[result.length -1].eventId){ - return false; - } - }); - let groupMap = new Map>(); - for (let value of map.values()) { - let key = value.threadId+ "_" + value.symbol; - if(groupMap.has(key)){ - groupMap.get(key)!.push(value); - }else{ - let arr:Array = []; - arr.push(value); - groupMap.set(key,arr); - } - } - let data:Array = []; - for (let arr of groupMap.values()) { - if(arr.length > 1){ - for (let i = 1; i < arr.length; i++) { - if(arr[i].children.length > 0){ - this.mergeTree(arr[i].children[0],arr[0]); - }else{ - arr[0].heapSize += arr[i].heapSize; - arr[0].heapSizeStr = Utils.getByteWithUnit(arr[0].heapSize); - } - } - } - arr[0].count = arr.length; - data.push(arr[0]); - } - return this.groupByWithTid(data) - } - - groupByWithTid(data:Array):Array{ - let tidMap = new Map(); - for (let call of data) { - call.pid = "tid_"+call.threadId; - if(tidMap.has(call.threadId)){ - let tidCall = tidMap.get(call.threadId); - tidCall!.heapSize += call.heapSize; - tidCall!.heapSizeStr = Utils.getByteWithUnit(tidCall!.heapSize); - tidCall!.count += call.count; - tidCall!.children.push(call); - }else{ - let tidCall = new NativeHookCallInfo(); - tidCall.id = "tid_" + call.threadId; - tidCall.count = call.count; - tidCall.heapSize = call.heapSize; - tidCall.heapSizeStr = Utils.getByteWithUnit(call.heapSize); - tidCall.title = "Thread " + call.threadId; - tidCall.type = -1; - tidCall.children.push(call); - tidMap.set(call.threadId,tidCall); - } - } - return Array.from(tidMap.values()); - } - - listToTree(target:NativeHookCallInfo,src:NativeHookCallInfo){ - if(target.depth == src.depth + 1){ - target.pid = src.id; - src.children.push(target) - }else{ - if(src.children.length > 0){ - this.listToTree(target,src.children[0]); - } - } - } - - mergeTree(target:NativeHookCallInfo,src:NativeHookCallInfo){ - let len = src.children.length; - if(len == 0){ - target.pid = src.id; - src.heapSize += target.heapSize; - src.heapSizeStr = Utils.getByteWithUnit(src.heapSize); - src.children.push(target); - }else{ - let index = src.children.findIndex((hook) => hook.symbol == target.symbol && hook.depth == target.depth); - src.heapSize += target.heapSize; - src.heapSizeStr = Utils.getByteWithUnit(src.heapSize); - if(index != -1){ - let srcChild = src.children[index]; - srcChild.count += 1; - if(target.children.length > 0){ - this.mergeTree(target.children[0],srcChild) - }else{ - srcChild.heapSize += target.heapSize; - srcChild.heapSizeStr = Utils.getByteWithUnit(srcChild.heapSize) - } - }else{ - target.pid = src.id; - src.children.push(target) - } - } - } - - setRightTableData(hook:NativeHookCallInfo){ - let arr:Array = []; - let maxEventId = hook.eventId; - let maxHeap = 0; - function findMaxStack(hook:NativeHookCallInfo){ - if(hook.children.length == 0){ - if(hook.heapSize > maxHeap){ - maxHeap = hook.heapSize; - maxEventId = hook.eventId; - } - }else{ - hook.children.map((hookChild)=>{ - findMaxStack(hookChild); - }) - } - } - findMaxStack(hook); - SpSystemTrace.HEAP_FRAME_DATA.map((frame) => { - let eventId = parseInt(frame.eventId); - if(eventId == maxEventId){ - let target = new NativeHookCallInfo(); - target.eventId = eventId; - target.depth = frame.depth; - let sym_arr = frame.AllocationFunction?.split("/"); - let lib_arr = frame.MoudleName?.split("/"); - target.symbol = sym_arr![sym_arr!.length - 1]; - target.library = lib_arr![lib_arr!.length - 1]; - target.title = `[ ${target.symbol} ] ${target.library}`; - target.type = (target.library.endsWith(".so.1") || target.library.endsWith(".dll") || target.library.endsWith(".so")) ? 0 : 1; - arr.push(target); - } - if(eventId > maxEventId){ - return false; - } - }); - // @ts-ignore - this.tblData?.recycleDataSource = arr; - } - - initFilterTypes(){ - let filter = this.shadowRoot?.querySelector("#filter") - this.queryResult = [] - filter!.firstSelect = "0" - filter!.secondSelect = "0" - this.filterAllocationType = "0" - this.filterNativeType = "0" - } - - initElements(): void { - this.tbl = this.shadowRoot?.querySelector('#tb-native-callinfo'); - this.tblData = this.shadowRoot?.querySelector('#tb-native-data'); - this.tbl!.addEventListener("row-click", (e) => { - // @ts-ignore - let data = (e.detail as NativeHookCallInfo) - this.setRightTableData(data); - }) - new ResizeObserver((entries) => { - if (this.parentElement?.clientHeight != 0) { - // @ts-ignore - this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight)-10-31+"px"; - this.tbl?.reMeauseHeight() - // @ts-ignore - this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) -10+"px" - this.tblData?.reMeauseHeight() - } - }).observe(this.parentElement!); - this.shadowRoot?.querySelector("#filter")!.getFilterData((data:FilterData)=>{ - this.filterAllocationType = data.firstSelect||"0" - this.filterNativeType = data.secondSelect||"0" - this.filterQueryData() - }) - this.initFilterTypes() - } - - filterQueryData(){ - if (this.queryResult.length > 0&&this.currentSelection) { - let filter = this.queryResult.filter((item)=>{ - let filterAllocation = true - let filterNative = true - if(this.filterAllocationType=="1"){ - filterAllocation = item.startTs>=this.currentSelection!.leftNs&&item.startTs<=this.currentSelection!.rightNs&&item.endTs>this.currentSelection!.rightNs - }else if(this.filterAllocationType=="2"){ - filterAllocation = item.startTs>=this.currentSelection!.leftNs&&item.startTs<=this.currentSelection!.rightNs&&item.endTs<=this.currentSelection!.rightNs - } - if(this.filterNativeType=="1"){ - filterNative = item.eventType == "AllocEvent" - }else if(this.filterNativeType=="2"){ - filterNative = item.eventType == "MmapEvent" - } - return filterAllocation&&filterNative - }) - if(filter.length>0){ - this.source = this.handleQueryResult(filter); - this.tbl!.recycleDataSource = this.source; - }else { - this.source = [] - this.tbl!.recycleDataSource = []; - } - } - } - - initHtml(): string { - return ` - -
-
- - - - - - - - - -
-
- - - - - - -
-
- - `; - } -} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneNMStatstics.ts b/host/ide/src/trace/component/trace/sheet/TabPaneNMStatstics.ts deleted file mode 100644 index e022aaff55750b1ba630c1abf5646b0b58357e2f..0000000000000000000000000000000000000000 --- a/host/ide/src/trace/component/trace/sheet/TabPaneNMStatstics.ts +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (C) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import { SelectionParam} from "../../../bean/BoxSelection.js"; -import { - queryNativeHookStatistics, - queryNativeHookStatisticsMalloc, - queryNativeHookStatisticsSubType -} from "../../../database/SqlLite.js"; -import { - NativeHookMalloc, - NativeHookStatistics, - NativeHookStatisticsTableData, - NativeMemory -} from "../../../bean/NativeHook.js"; -import {Utils} from "../base/Utils.js"; -import {SpSystemTrace} from "../../SpSystemTrace.js"; -import "./TabProgressBar.js" - -@element('tabpane-native-statistics') -export class TabPaneNMStatstics extends BaseElement { - private tbl: LitTable | null | undefined; - private source: Array = [] - private native_type:Array = ["All Heap & Anonymous VM","All Heap","All Anonymous VM"]; - private allMax:number = 0; - - set data(val: SelectionParam | any) { - this.allMax = 0; - SpSystemTrace.EVENT_HEAP.map((heap)=>{ - this.allMax += heap.sumHeapSize; - }); - // @ts-ignore - this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20) + "px" - // @ts-ignore - this.tbl?.recycleDataSource = []; - Promise.all([queryNativeHookStatistics(val.leftNs,val.rightNs), - queryNativeHookStatisticsSubType(val.leftNs,val.rightNs), - queryNativeHookStatisticsMalloc(val.leftNs,val.rightNs) - ]).then((values)=>{ - let arr:Array = []; - let index1 = val.nativeMemory.indexOf(this.native_type[0]) - let index2 = val.nativeMemory.indexOf(this.native_type[1]) - let index3 = val.nativeMemory.indexOf(this.native_type[2]) - this.setMemoryTypeData(val,values[0],arr); - if(index1 != -1 || index3 != -1){ - this.setSubTypeTableData(values[1],arr); - } - if(index1 != -1 || index2 != -1){ - this.setMallocTableData(values[2],arr); - } - this.tbl!.recycleDataSource = arr; - }) - } - - setMallocTableData(result:Array,arr:Array){ - result.map((malloc)=>{ - let data = new NativeHookStatisticsTableData(); - data.memoryTap = "Malloc " + Utils.getByteWithUnit(malloc.heapSize); - data.existing = malloc.allocByte; - data.allocCount = malloc.allocCount; - data.freeCount = malloc.freeCount; - data.totalBytes = malloc.allocByte + malloc.freeByte; - data.totalCount = malloc.allocCount + malloc.freeCount; - data.max = malloc.heapSize; - data.existingString = Utils.getByteWithUnit(data.existing); - data.totalBytesString = Utils.getByteWithUnit(data.totalBytes); - data.maxStr = Utils.getByteWithUnit(malloc.heapSize); - data.existingValue = [data.existing,data.totalBytes,this.allMax]; - arr.push(data); - }) - } - - setSubTypeTableData(result:Array,arr:Array){ - result.map((sub)=>{ - let data = new NativeHookStatisticsTableData(); - data.memoryTap = sub.subType - data.existing = sub.allocByte - data.allocCount = sub.allocCount; - data.freeCount = sub.freeCount; - data.totalBytes = sub.allocByte + sub.freeByte; - data.totalCount = sub.allocCount + sub.freeCount; - data.max = sub.heapSize; - data.existingString = Utils.getByteWithUnit(data.existing); - data.totalBytesString = Utils.getByteWithUnit(data.totalBytes); - data.maxStr = Utils.getByteWithUnit(sub.heapSize); - data.existingValue = [data.existing,data.totalBytes,this.allMax]; - arr.push(data); - }) - } - - setMemoryTypeData(val:SelectionParam,result:Array,arr:Array){ - let all:NativeHookStatisticsTableData | null = null - let heap:NativeHookStatisticsTableData | null = null - let anonymous:NativeHookStatisticsTableData | null = null - if(val.nativeMemory.indexOf(this.native_type[0]) != -1){ - all = new NativeHookStatisticsTableData(); - all.memoryTap = this.native_type[0]; - } - if(val.nativeMemory.indexOf(this.native_type[1]) != -1){ - heap = new NativeHookStatisticsTableData(); - heap.memoryTap = this.native_type[1]; - } - if(val.nativeMemory.indexOf(this.native_type[2]) != -1){ - anonymous = new NativeHookStatisticsTableData(); - anonymous.memoryTap = this.native_type[2]; - } - for (let hook of result) { - if(all != null){ - if(hook.eventType == "AllocEvent" || hook.eventType == "MmapEvent"){ - all.existing += hook.sumHeapSize; - all.allocCount += hook.count; - all.totalBytes += hook.sumHeapSize; - all.totalCount += hook.count; - if(hook.max > all.max){ - all.max = hook.max; - all.maxStr = Utils.getByteWithUnit(all.max); - } - }else if(hook.eventType == "FreeEvent" || hook.eventType == "MunmapEvent"){ - all.totalBytes += hook.sumHeapSize; - all.freeCount += hook.count; - all.totalCount += hook.count; - } - } - if(heap != null){ - if(hook.eventType == "AllocEvent" ){ - heap.existing += hook.sumHeapSize; - heap.allocCount += hook.count; - heap.totalBytes += hook.sumHeapSize; - heap.totalCount += hook.count; - if(hook.max > heap.max){ - heap.max = hook.max; - heap.maxStr = Utils.getByteWithUnit(heap.max); - } - }else if(hook.eventType == "FreeEvent"){ - heap.totalBytes += hook.sumHeapSize; - heap.totalCount += hook.count; - heap.freeCount += hook.count; - } - } - if(anonymous != null){ - if(hook.eventType == "MmapEvent" ){ - anonymous.existing += hook.sumHeapSize; - anonymous.allocCount += hook.count; - anonymous.totalBytes += hook.sumHeapSize; - anonymous.totalCount += hook.count; - if(hook.max > anonymous.max){ - anonymous.max = hook.max; - anonymous.maxStr = Utils.getByteWithUnit(anonymous.max); - } - }else if(hook.eventType == "MunmapEvent"){ - anonymous.totalBytes += hook.sumHeapSize; - anonymous.freeCount += hook.count; - anonymous.totalCount += hook.count; - } - } - } - if(all != null){ - all.existingString = Utils.getByteWithUnit(all.existing) - all.totalBytesString = Utils.getByteWithUnit(all.totalBytes) - all.existingValue = [all.existing,all.totalBytes,this.allMax] - arr.push(all) - } - if(heap != null){ - heap.existingString = Utils.getByteWithUnit(heap.existing) - heap.totalBytesString = Utils.getByteWithUnit(heap.totalBytes) - heap.existingValue = [heap.existing,heap.totalBytes,this.allMax] - arr.push(heap) - } - if(anonymous != null){ - anonymous.existingString = Utils.getByteWithUnit(anonymous.existing) - anonymous.totalBytesString = Utils.getByteWithUnit(anonymous.totalBytes) - anonymous.existingValue = [anonymous.existing,anonymous.totalBytes,this.allMax] - arr.push(anonymous) - } - } - - initElements(): void { - this.tbl = this.shadowRoot?.querySelector('#tb-native-statstics'); - new ResizeObserver((entries) => { - if (this.parentElement?.clientHeight != 0) { - // @ts-ignore - this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20)+"px" - this.tbl?.reMeauseHeight() - } - }).observe(this.parentElement!) - } - - - initHtml(): string { - return ` - - - - - - - - - - - - - - `; - } -} diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneNMemory.ts b/host/ide/src/trace/component/trace/sheet/TabPaneNMemory.ts deleted file mode 100644 index 43fde1a8ed02f124de021d53177c3312b4c0266d..0000000000000000000000000000000000000000 --- a/host/ide/src/trace/component/trace/sheet/TabPaneNMemory.ts +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (C) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import {SelectionParam} from "../../../bean/BoxSelection.js"; -import {queryNativeHookEventId} from "../../../database/SqlLite.js"; -import {NativeHookCallInfo, NativeHookStatistics, NativeMemory} from "../../../bean/NativeHook.js"; -import {SpSystemTrace} from "../../SpSystemTrace.js"; -import {HeapTreeDataBean} from "../../../bean/HeapTreeDataBean.js"; -import {Utils} from "../base/Utils.js"; -import "./TabPaneFilter.js" -import {FilterData, TabPaneFilter} from "./TabPaneFilter"; -import {TabPaneNMSampleList} from "./TabPaneNMSampleList.js"; - -@element('tabpane-native-memory') -export class TabPaneNMemory extends BaseElement { - private defaultNativeTypes = ["All Heap & Anonymous VM","All Heap","All Anonymous VM"]; - private tbl: LitTable | null | undefined; - private tblData: LitTable | null | undefined; - private source: Array = [] - private native_type:Array = [...this.defaultNativeTypes]; - private statsticsSelection: Array = [] - private queryResult: Array = [] - private filterAllocationType:string = "0" - private filterNativeType:string = "0" - private currentSelection:SelectionParam|undefined - private rowSelectData:any = undefined; - set data(val: SelectionParam | any) { - if(val==this.currentSelection){ - return - } - this.currentSelection = val - this.initFilterTypes() - let types:Array = [] - if(val.nativeMemory.indexOf(this.defaultNativeTypes[0]) != -1){ - types.push("'AllocEvent'"); - types.push("'MmapEvent'"); - }else{ - if(val.nativeMemory.indexOf(this.defaultNativeTypes[1]) != -1){ - types.push("'AllocEvent'"); - } - if(val.nativeMemory.indexOf(this.defaultNativeTypes[2]) != -1){ - types.push("'MmapEvent'"); - } - } - TabPaneNMSampleList.serSelection(val) - // @ts-ignore - this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20 - 31) + "px" - // @ts-ignore - this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight -20)+"px" - // @ts-ignore - this.tblData?.recycleDataSource = []; - // @ts-ignore - this.tbl?.recycleDataSource = []; - queryNativeHookEventId(val.leftNs,val.rightNs,types).then((result)=>{ - if(result.length > 0){ - this.queryResult = result - this.source = this.handleQueryResult(result); - }else{ - this.source = []; - } - this.filterQueryData() - }) - } - - fromStastics(val: SelectionParam | any){ - let filter = this.shadowRoot?.querySelector("#filter") - let typeIndexOf = this.native_type.indexOf(val.statisticsSelectData.memoryTap); - if(this.statsticsSelection.indexOf(val.statisticsSelectData) == -1&&typeIndexOf == -1){ - this.statsticsSelection.push(val.statisticsSelectData) - this.native_type.push(val.statisticsSelectData.memoryTap) - typeIndexOf = this.native_type.length - 1 - } - if(this.currentSelection != val){ - //设置选项后刷新当前的数据 - this.data = val - //todo 设置filter当前的选项和选中项 - filter!.setSelectList(null,this.native_type) - filter!.secondSelect = typeIndexOf+"" - this.filterNativeType = typeIndexOf+"" - }else{ - this.tblData!.recycleDataSource = []; - this.rowSelectData = undefined - filter!.setSelectList(null,this.native_type) - filter!.secondSelect = typeIndexOf+"" - this.filterNativeType = typeIndexOf+"" - //直接将当前数据过滤即可 - this.filterQueryData() - } - } - - getTypeFromIndex(indexOf:number,item:NativeHookStatistics):boolean{ - if(indexOf == -1){ - return false; - } - if(indexOf < 3){ - if(indexOf == 0){ - return true - }else if(indexOf == 1){ - return item.eventType == "AllocEvent" - }else if(indexOf == 2){ - return item.eventType == "MmapEvent" - } - }else if(indexOf-3 < this.statsticsSelection.length){ - let selectionElement = this.statsticsSelection[indexOf - 3]; - if(selectionElement.memoryTap!=undefined&&selectionElement.max!=undefined){ - if (selectionElement.memoryTap.indexOf("Malloc") != -1) { - return item.eventType == "AllocEvent"&&item.heapSize == selectionElement.max - }else { - return item.subType == selectionElement.memoryTap&&item.heapSize == selectionElement.max - } - } - } - return false; - } - - handleQueryResult(result:Array):Array{ - let resultMap = new Map(); - result.map((r)=>{ - resultMap.set(r.eventId,r); - }) - let data :Array = []; - let frameArr: Array = []; - SpSystemTrace.HEAP_FRAME_DATA.map((frame) => { - let frameEventId = parseInt(frame.eventId); - if(frameEventId >= result[0].eventId && frameEventId <= result[result.length - 1].eventId){ - if(resultMap.has(frameEventId) && frame.depth == 0){ - frameArr.push(frame); - } - } - if(frameEventId > result[result.length -1].eventId){ - return false; - } - }); - - let frameMap = new Map(); - frameArr.map((frame)=>{ - frameMap.set(parseInt(frame.eventId),frame); - }) - for (let i = 0,len = result.length; i < len; i++) { - let hook = result[i]; - let memory = new NativeMemory(); - memory.index = i; - memory.eventId = hook.eventId; - memory.eventType = hook.eventType; - memory.subType = hook.subType; - memory.heapSize = hook.heapSize; - memory.heapSizeUnit = Utils.getByteWithUnit(hook.heapSize); - memory.addr = "0x"+hook.addr; - memory.startTs = hook.startTs; - memory.timestamp = Utils.getTimeString(hook.startTs); - (memory as any).isSelected = hook.isSelected; - let frame = frameMap.get(hook.eventId); - if(frame != null && frame != undefined){ - let sym_arr = frame.AllocationFunction?.split("/"); - let lib_arr = frame.MoudleName?.split("/"); - memory.symbol = sym_arr![sym_arr!.length - 1]; - memory.library = lib_arr![lib_arr!.length - 1]; - } - data.push(memory); - } - return data - } - - initFilterTypes(){ - let filter = this.shadowRoot?.querySelector("#filter") - this.queryResult = [] - filter!.setSelectList(null,this.defaultNativeTypes) - filter!.firstSelect = "0" - filter!.secondSelect = "0" - this.filterAllocationType = "0" - this.filterNativeType = "0" - this.rowSelectData = undefined - } - - initElements(): void { - this.tbl = this.shadowRoot?.querySelector('#tb-native-memory'); - this.tblData = this.shadowRoot?.querySelector('#tb-native-data'); - this.tbl!.addEventListener("row-click", (e) => { - // @ts-ignore - let data = (e.detail as NativeMemory); - this.rowSelectData = data - this.setRightTableData(data); - document.dispatchEvent(new CustomEvent('triangle-flag', {detail: {time:data.startTs,type:"triangle"}})); - }) - new ResizeObserver((entries) => { - if (this.parentElement?.clientHeight != 0) { - // @ts-ignore - this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight)-10-31+"px"; - this.tbl?.reMeauseHeight(); - // @ts-ignore - this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight)-10+"px" - this.tblData?.reMeauseHeight() - } - }).observe(this.parentElement!) - let filter = this.shadowRoot?.querySelector("#filter") - this.shadowRoot?.querySelector("#filter")!.getFilterData((data:FilterData)=>{ - if (data.mark) { - if(this.rowSelectData!=undefined){ - let filterTemp = this.queryResult.filter((tempItem)=>{ - return tempItem.eventId == this.rowSelectData.eventId - }) - if(filterTemp.length>0){ - filterTemp[0].isSelected = true - } - TabPaneNMSampleList.addSampleData(this.rowSelectData) - if(this.rowSelectData.selectedCallback){ - this.rowSelectData.isSelected = true - this.rowSelectData.selectedCallback() - } - document.dispatchEvent(new CustomEvent('triangle-flag', {detail: {time:this.rowSelectData.startTs,type:"square"}})); - } - }else { - this.filterAllocationType = data.firstSelect||"0" - this.filterNativeType = data.secondSelect||"0" - this.filterQueryData() - } - }) - filter!.firstSelect = "1" - } - - filterQueryData(){ - if (this.queryResult.length > 0&&this.currentSelection) { - let filter = this.queryResult.filter((item)=>{ - let filterAllocation = true - if(this.filterAllocationType=="1"){ - filterAllocation = item.startTs>=this.currentSelection!.leftNs&&item.startTs<=this.currentSelection!.rightNs&&item.endTs>this.currentSelection!.rightNs - }else if(this.filterAllocationType=="2"){ - filterAllocation = item.startTs>=this.currentSelection!.leftNs&&item.startTs<=this.currentSelection!.rightNs&&item.endTs<=this.currentSelection!.rightNs - } - let filterNative = this.getTypeFromIndex(parseInt(this.filterNativeType),item) - return filterAllocation&&filterNative - }) - if(filter.length>0){ - this.source = this.handleQueryResult(filter); - this.tbl!.recycleDataSource = this.source; - }else { - this.source = [] - this.tbl!.recycleDataSource = []; - } - } - } - - setRightTableData(hook:NativeMemory){ - let arr:Array = []; - let frameArr = SpSystemTrace.HEAP_FRAME_DATA.filter((frame) => parseInt(frame.eventId) == hook.eventId); - frameArr.map((frame)=>{ - let target = new NativeHookCallInfo(); - target.eventId = parseInt(frame.eventId); - target.depth = frame.depth; - let sym_arr = frame.AllocationFunction?.split("/"); - let lib_arr = frame.MoudleName?.split("/"); - target.symbol = sym_arr![sym_arr!.length - 1]; - target.library = lib_arr![lib_arr!.length - 1]; - target.title = `[ ${target.symbol} ] ${target.library}`; - target.type = (target.library.endsWith(".so.1") || target.library.endsWith(".dll") || target.library.endsWith(".so")) ? 0 : 1; - arr.push(target); - }) - // @ts-ignore - this.tblData?.recycleDataSource = arr; - } - - initHtml(): string { - return ` - -
-
- - - - - - - - - - -
-
- - - - - - -
-
- `; - } -} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPanePTS.ts b/host/ide/src/trace/component/trace/sheet/TabPanePTS.ts deleted file mode 100644 index 9b3bf4c8b4ac48cfd85f21891491d6dbf08c7111..0000000000000000000000000000000000000000 --- a/host/ide/src/trace/component/trace/sheet/TabPanePTS.ts +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (C) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import {SelectionParam} from "../../../bean/BoxSelection.js"; -import { - getTabStatesGroupByProcess, - getTabStatesGroupByProcessThread, - getTabStatesGroupByStatePidTid -} from "../../../database/SqlLite.js"; -import {StateProcessThread} from "../../../bean/StateProcessThread.js"; -import {Utils} from "../base/Utils.js"; -import {SpSystemTrace} from "../../SpSystemTrace.js"; - -@element('tabpane-pts') -export class TabPanePTS extends BaseElement { - private tbl: LitTable | null | undefined; - private range: HTMLLabelElement | null | undefined; - private loadDataInCache: boolean = true; - - set data(val: SelectionParam | any) { - // @ts-ignore - this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" - this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" - if (this.loadDataInCache) { - this.queryDataInCacheData(val).then((arr) => { - this.tbl!.recycleDataSource = arr; - }); - } else { - this.queryDataByDB(val) - } - } - - initElements(): void { - this.tbl = this.shadowRoot?.querySelector('#tb-states'); - this.range = this.shadowRoot?.querySelector('#time-range') - new ResizeObserver((entries) => { - if (this.parentElement?.clientHeight != 0) { - // @ts-ignore - this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45)+"px" - this.tbl?.reMeauseHeight() - } - }).observe(this.parentElement!) - } - - async queryDataInCacheData(val: SelectionParam | any): Promise> { - return new Promise>((resolve, reject) => { - let pMap: Map = new Map(); - let ptMap: Map = new Map(); - let ptsMap: Map = new Map(); - SpSystemTrace.SPT_DATA.map((d)=>{ - if(!(d.end_ts < val.leftNs || d.start_ts > val.rightNs)){ - if (pMap.has(d.processId + "")) { - let obj1 = pMap.get(d.processId + ""); - obj1!.count++; - obj1!.wallDuration += d.dur; - obj1!.avgDuration = (obj1!.wallDuration / obj1!.count).toFixed(2); - if (d.dur > obj1!.maxDuration) { - obj1!.maxDuration = d.dur; - } - if (d.dur < obj1!.minDuration) { - obj1!.minDuration = d.dur; - } - } else { - let obj1 = new StateProcessThread(); - obj1.id = "p" + d.processId; - obj1.title = (d.process == null || d.process == "" ? "Process" : d.process) + "(" + d.processId + ")"; - obj1.process = d.process; - obj1.processId = d.processId; - obj1.minDuration = d.dur; - obj1.maxDuration = d.dur; - obj1.count = 1; - obj1.avgDuration = d.dur + ""; - obj1.wallDuration = d.dur; - pMap.set(d.processId + "", obj1); - } - if (ptMap.has(d.processId + "_" + d.threadId)) { - let obj2 = ptMap.get(d.processId + "_" + d.threadId); - obj2!.count++; - obj2!.wallDuration += d.dur; - obj2!.avgDuration = (obj2!.wallDuration / obj2!.count).toFixed(2); - if (d.dur > obj2!.maxDuration) { - obj2!.maxDuration = d.dur; - } - if (d.dur < obj2!.minDuration) { - obj2!.minDuration = d.dur; - } - } else { - let obj2 = new StateProcessThread(); - obj2.id = "p" + d.processId + "_" + "t" + d.threadId; - obj2.pid = "p" + d.processId; - obj2.title = (d.thread == null || d.thread == "" ? "Thread" : d.thread) + "(" + d.threadId + ")" - obj2.processId = d.processId; - obj2.process = d.process; - obj2.thread = d.thread; - obj2.threadId = d.threadId; - obj2.minDuration = d.dur; - obj2.maxDuration = d.dur; - obj2.count = 1; - obj2.avgDuration = d.dur + ""; - obj2.wallDuration = d.dur; - ptMap.set(d.processId + "_" + d.threadId, obj2); - } - if (ptsMap.has(d.processId + "_" + d.threadId + "_" + d.state)) { - let obj3 = ptsMap.get(d.processId + "_" + d.threadId + "_" + d.state); - obj3!.count++; - obj3!.wallDuration += d.dur; - obj3!.avgDuration = (obj3!.wallDuration / obj3!.count).toFixed(2); - if (d.dur > obj3!.maxDuration) { - obj3!.maxDuration = d.dur; - } - if (d.dur < obj3!.minDuration) { - obj3!.minDuration = d.dur; - } - } else { - let obj3 = new StateProcessThread(); - obj3.id = "p" + d.processId + "_" + "t" + d.threadId + "_" + (d.state == "R+" ? "RP" : d.state) - obj3.pid = "p" + d.processId + "_" + "t" + d.threadId; - obj3.title = Utils.getEndState(d.state) - obj3.processId = d.processId; - obj3.process = d.process; - obj3.thread = d.thread; - obj3.threadId = d.threadId; - obj3.state = d.state; - obj3.minDuration = d.dur; - obj3.maxDuration = d.dur; - obj3.count = 1; - obj3.avgDuration = d.dur + ""; - obj3.wallDuration = d.dur; - ptsMap.set(d.processId + "_" + d.threadId + "_" + d.state, obj3); - } - } - }) - let arr: Array = []; - for (let key of pMap.keys()) { - let s = pMap.get(key); - s!.children = []; - for (let ks of ptMap.keys()) { - if (ks.startsWith(key + "_")) { - let sp = ptMap.get(ks) - sp!.children = []; - for (let kst of ptsMap.keys()) { - if (kst.startsWith(ks + "_")) { - let spt = ptsMap.get(kst) - sp!.children.push(spt!); - } - } - s!.children.push(sp!) - } - } - arr.push(s!) - } - resolve(arr); - }); - } - - queryDataByDB(val: SelectionParam | any) { - Promise.all([ - getTabStatesGroupByProcess(val.leftNs, val.rightNs), - getTabStatesGroupByProcessThread(val.leftNs, val.rightNs), - getTabStatesGroupByStatePidTid(val.leftNs, val.rightNs)]).then((values) => { - let processes = values[0]; - processes.map((spt) => { - spt.id = "p" + spt.processId - spt.title = (spt.process == null || spt.process == "" ? "Process" : spt.process) + "(" + spt.processId + ")" - }); - let threadMap = this.groupByProcessToMap(values[1]); - let stateMap = this.groupByProcessThreadToMap(values[2]); - for (let process of processes) { - let threads = threadMap.get(process.processId); - if (threads != undefined) { - threads!.map((spt) => { - spt.id = "p" + spt.processId + "_" + "t" + spt.threadId; - spt.pid = "p" + spt.processId; - spt.title = (spt.thread == null || spt.thread == "" ? "Thread" : spt.thread) + "(" + spt.threadId + ")" - }) - } - process.children = threads ?? []; - let map = stateMap.get(process.processId); - for (let thread of threads!) { - let states = map!.get(thread.threadId); - states!.map((spt) => { - spt.id = "p" + spt.processId + "_" + "t" + spt.threadId + "_" + (spt.state == "R+" ? "RP" : spt.state) - spt.pid = "p" + spt.processId + "_" + "t" + spt.threadId; - spt.title = Utils.getEndState(spt.state) - }) - thread.children = states ?? []; - } - } - this.tbl!.dataSource = processes; - }) - } - - groupByThreadToMap(arr: Array): Map> { - let map = new Map>(); - for (let spt of arr) { - if (map.has(spt.threadId)) { - map.get(spt.threadId)!.push(spt); - } else { - let list: Array = []; - list.push(spt); - map.set(spt.threadId, list); - } - } - return map; - } - - groupByProcessToMap(arr: Array): Map> { - let map = new Map>(); - for (let spt of arr) { - if (map.has(spt.processId)) { - map.get(spt.processId)!.push(spt); - } else { - let list: Array = []; - list.push(spt); - map.set(spt.processId, list); - } - } - return map; - } - - groupByProcessThreadToMap(arr: Array): Map>> { - let map = new Map>>(); - let processMap = this.groupByProcessToMap(arr); - for (let key of processMap.keys()) { - let threadMap = this.groupByThreadToMap(processMap.get(key)!) - map.set(key, threadMap); - } - return map; - } - - initHtml(): string { - return ` - - - - - - - - - - - - `; - } - -} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneSPT.ts b/host/ide/src/trace/component/trace/sheet/TabPaneSPT.ts deleted file mode 100644 index 2c068cdf95997c8cf1a15d7c4c73853633fc0509..0000000000000000000000000000000000000000 --- a/host/ide/src/trace/component/trace/sheet/TabPaneSPT.ts +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (C) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import {SelectionParam} from "../../../bean/BoxSelection.js"; -import { - getTabStatesGroupByState, - getTabStatesGroupByStatePid, - getTabStatesGroupByStatePidTid -} from "../../../database/SqlLite.js"; -import {StateProcessThread} from "../../../bean/StateProcessThread.js"; -import {Utils} from "../base/Utils.js"; -import {SpSystemTrace} from "../../SpSystemTrace.js"; - -@element('tabpane-spt') -export class TabPaneSPT extends BaseElement { - private tbl: LitTable | null | undefined; - private range: HTMLLabelElement | null | undefined; - private loadDataInCache: boolean = true; - - set data(val: SelectionParam | any) { - // @ts-ignore - this.tbl?.shadowRoot?.querySelector(".table").style.height = (this.parentElement!.clientHeight - 45)+"px" - this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" - if (this.loadDataInCache) { - this.queryDataByCacheData(val).then((result) => { - this.tbl!.recycleDataSource = result; - }); - } else { - this.queryDataByDB(val); - } - } - - initElements(): void { - this.tbl = this.shadowRoot?.querySelector('#tb-states'); - this.range = this.shadowRoot?.querySelector('#time-range') - new ResizeObserver((entries) => { - if (this.parentElement?.clientHeight != 0) { - // @ts-ignore - this.tbl?.shadowRoot?.querySelector(".table").style.height = (this.parentElement!.clientHeight - 45)+"px" - this.tbl?.reMeauseHeight() - } - }).observe(this.parentElement!) - } - - async queryDataByCacheData(val: SelectionParam | any): Promise> { - //1. 框选时间区间的数据过滤出来 - return new Promise>((resolve, reject) => { - let statesMap: Map = new Map(); - let spMap: Map = new Map(); - let sptMap: Map = new Map(); - // @ts-ignore - SpSystemTrace.SPT_DATA.map((d) => { - if(!(d.end_ts < val.leftNs || d.start_ts > val.rightNs)){ - if (statesMap.has(d.state)) { - let obj1 = statesMap.get(d.state); - obj1!.count++; - obj1!.wallDuration += d.dur; - obj1!.avgDuration = (obj1!.wallDuration / obj1!.count).toFixed(2); - if (d.dur > obj1!.maxDuration) { - obj1!.maxDuration = d.dur; - } - if (d.dur < obj1!.minDuration) { - obj1!.minDuration = d.dur; - } - } else { - let obj1 = new StateProcessThread(); - obj1.id = (d.state == "R+" ? "RP" : d.state) - obj1.title = Utils.getEndState(d.state); - obj1.state = d.state; - obj1.minDuration = d.dur; - obj1.maxDuration = d.dur; - obj1.count = 1; - obj1.avgDuration = d.dur + ""; - obj1.wallDuration = d.dur; - statesMap.set(d.state, obj1); - } - if (spMap.has(d.state + "_" + d.processId)) { - let obj2 = spMap.get(d.state + "_" + d.processId); - obj2!.count++; - obj2!.wallDuration += d.dur; - obj2!.avgDuration = (obj2!.wallDuration / obj2!.count).toFixed(2); - if (d.dur > obj2!.maxDuration) { - obj2!.maxDuration = d.dur; - } - if (d.dur < obj2!.minDuration) { - obj2!.minDuration = d.dur; - } - } else { - let obj2 = new StateProcessThread(); - obj2.id = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId; - obj2.pid = (d.state == "R+" ? "RP" : d.state); - obj2.title = (d.process == null || d.process == "" ? "Process" : d.process) + "(" + d.processId + ")" - obj2.processId = d.processId; - obj2.process = d.process; - obj2.state = d.state; - obj2.minDuration = d.dur; - obj2.maxDuration = d.dur; - obj2.count = 1; - obj2.avgDuration = d.dur + ""; - obj2.wallDuration = d.dur; - spMap.set(d.state + "_" + d.processId, obj2); - } - if (sptMap.has(d.state + "_" + d.processId + "_" + d.threadId)) { - let obj3 = sptMap.get(d.state + "_" + d.processId + "_" + d.threadId); - obj3!.count++; - obj3!.wallDuration += d.dur; - obj3!.avgDuration = (obj3!.wallDuration / obj3!.count).toFixed(2); - if (d.dur > obj3!.maxDuration) { - obj3!.maxDuration = d.dur; - } - if (d.dur < obj3!.minDuration) { - obj3!.minDuration = d.dur; - } - } else { - let obj3 = new StateProcessThread(); - obj3.id = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId + "_" + d.threadId - obj3.pid = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId - obj3.title = (d.thread == null || d.thread == "" ? "Thread" : d.thread) + "(" + d.threadId + ")" - obj3.processId = d.processId; - obj3.process = d.process; - obj3.thread = d.thread; - obj3.threadId = d.threadId; - obj3.state = d.state; - obj3.minDuration = d.dur; - obj3.maxDuration = d.dur; - obj3.count = 1; - obj3.avgDuration = d.dur + ""; - obj3.wallDuration = d.dur; - sptMap.set(d.state + "_" + d.processId + "_" + d.threadId, obj3); - } - } - }); - let arr: Array = []; - for (let key of statesMap.keys()) { - let s = statesMap.get(key); - s!.children = []; - for (let ks of spMap.keys()) { - if (ks.startsWith(key + "_")) { - let sp = spMap.get(ks) - sp!.children = []; - for (let kst of sptMap.keys()) { - if (kst.startsWith(ks + "_")) { - let spt = sptMap.get(kst) - sp!.children.push(spt!); - } - } - s!.children.push(sp!) - } - } - arr.push(s!) - } - resolve(arr); - }); - } - - queryDataByDB(val: SelectionParam | any) { - Promise.all([ - getTabStatesGroupByState(val.leftNs, val.rightNs), - getTabStatesGroupByStatePid(val.leftNs, val.rightNs), - getTabStatesGroupByStatePidTid(val.leftNs, val.rightNs)]).then((values) => { - let states = values[0]; - states.map((spt) => { - spt.id = (spt.state == "R+" ? "RP" : spt.state) - spt.title = Utils.getEndState(spt.state); - }); - let processMap = this.groupByStateToMap(values[1]); - let threadMap = this.groupByStateProcessToMap(values[2]); - for (let state of states) { - let processes = processMap.get(state.state); - processes!.map((spt) => { - spt.id = (spt.state == "R+" ? "RP" : spt.state) + "_" + spt.processId; - spt.pid = (spt.state == "R+" ? "RP" : spt.state); - spt.title = (spt.process == null || spt.process == "" ? "Process" : spt.process) + "(" + spt.processId + ")" - }) - state.children = processes ?? []; - let map = threadMap.get(state.state); - for (let process of processes!) { - let threads = map!.get(process.processId); - threads!.map((spt) => { - spt.id = (spt.state == "R+" ? "RP" : spt.state) + "_" + spt.processId + "_" + spt.threadId - spt.pid = (spt.state == "R+" ? "RP" : spt.state) + "_" + spt.processId - spt.title = (spt.thread == null || spt.thread == "" ? "Thread" : spt.thread) + "(" + spt.threadId + ")" - }) - process.children = threads ?? []; - } - } - this.tbl!.recycleDataSource = states; - }) - } - - groupByStateToMap(arr: Array): Map> { - let map = new Map>(); - for (let spt of arr) { - if (map.has(spt.state)) { - map.get(spt.state)!.push(spt); - } else { - let list: Array = []; - list.push(spt); - map.set(spt.state, list); - } - } - return map; - } - - groupByProcessToMap(arr: Array): Map> { - let map = new Map>(); - for (let spt of arr) { - if (map.has(spt.processId)) { - map.get(spt.processId)!.push(spt); - } else { - let list: Array = []; - list.push(spt); - map.set(spt.processId, list); - } - } - return map; - } - - groupByStateProcessToMap(arr: Array): Map>> { - let map = new Map>>(); - let stateMap = this.groupByStateToMap(arr); - for (let key of stateMap.keys()) { - let processMap = this.groupByProcessToMap(stateMap.get(key)!) - map.set(key, processMap); - } - return map; - } - - initHtml(): string { - return ` - - - - - - - - - - - - `; - } - -} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneThreadSwitch.ts b/host/ide/src/trace/component/trace/sheet/TabPaneThreadSwitch.ts deleted file mode 100644 index 9af0690e12a460a5c9c331fd940b6ac01e7c5360..0000000000000000000000000000000000000000 --- a/host/ide/src/trace/component/trace/sheet/TabPaneThreadSwitch.ts +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import {SelectionParam} from "../../../bean/BoxSelection.js"; -import { - getTabStatesGroupByState, - getTabStatesGroupByStatePid, - getTabStatesGroupByStatePidTid -} from "../../../database/SqlLite.js"; -import {StateProcessThread} from "../../../bean/StateProcessThread.js"; -import {Utils} from "../base/Utils.js"; -import {SpSystemTrace} from "../../SpSystemTrace.js"; - -@element('tabpane-thread-switch') -export class TabPaneThreadSwitch extends BaseElement { - private tbl: LitTable | null | undefined; - private range: HTMLLabelElement | null | undefined; - private loadDataInCache: boolean = true; - - set data(val: SelectionParam | any) { - //@ts-ignore - this.tbl?.shadowRoot?.querySelector(".table")?.style?.height = (this.parentElement!.clientHeight - 45)+"px"; - this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms"; - if (this.loadDataInCache) { - this.queryDataByCacheData(val).then((arr) => { - this.tbl!.recycleDataSource = arr; - }); - } else { - this.queryDataByDB(val); - } - } - - initElements(): void { - this.tbl = this.shadowRoot?.querySelector('#tb-ts'); - this.range = this.shadowRoot?.querySelector('#time-range'); - new ResizeObserver((entries) => { - if (this.parentElement?.clientHeight != 0) { - // @ts-ignore - this.tbl?.shadowRoot?.querySelector(".table").style.height = (this.parentElement!.clientHeight - 45)+"px" - this.tbl?.reMeauseHeight() - } - }).observe(this.parentElement!); - } - - async queryDataByCacheData(val: SelectionParam | any): Promise> { - //1. 框选时间区间的数据过滤出来 - return new Promise>(((resolve, reject) => { - let statesMap: Map = new Map(); - let spMap: Map = new Map(); - let sptMap: Map = new Map(); - SpSystemTrace.SPT_DATA.map((d) => { - if(!(d.end_ts < val.leftNs || d.start_ts > val.rightNs)){ - if (statesMap.has(d.state)) { - let obj1 = statesMap.get(d.state); - obj1!.count++; - obj1!.wallDuration += d.dur; - obj1!.avgDuration = (obj1!.wallDuration / obj1!.count).toFixed(2); - if (d.dur > obj1!.maxDuration) { - obj1!.maxDuration = d.dur; - } - if (d.dur < obj1!.minDuration) { - obj1!.minDuration = d.dur; - } - } else { - let obj1 = new StateProcessThread(); - obj1.id = (d.state == "R+" ? "RP" : d.state) - obj1.title = Utils.getEndState(d.state); - obj1.state = d.state; - obj1.minDuration = d.dur; - obj1.maxDuration = d.dur; - obj1.count = 1; - obj1.avgDuration = d.dur + ""; - obj1.wallDuration = d.dur; - statesMap.set(d.state, obj1); - } - if (spMap.has(d.state + "_" + d.processId)) { - let obj2 = spMap.get(d.state + "_" + d.processId); - obj2!.count++; - obj2!.wallDuration += d.dur; - obj2!.avgDuration = (obj2!.wallDuration / obj2!.count).toFixed(2); - if (d.dur > obj2!.maxDuration) { - obj2!.maxDuration = d.dur; - } - if (d.dur < obj2!.minDuration) { - obj2!.minDuration = d.dur; - } - } else { - let obj2 = new StateProcessThread(); - obj2.id = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId; - obj2.pid = (d.state == "R+" ? "RP" : d.state); - obj2.title = (d.process == null || d.process == "" ? "Process" : d.process) + "(" + d.processId + ")" - obj2.processId = d.processId; - obj2.process = d.process; - obj2.state = d.state; - obj2.minDuration = d.dur; - obj2.maxDuration = d.dur; - obj2.count = 1; - obj2.avgDuration = d.dur + ""; - obj2.wallDuration = d.dur; - spMap.set(d.state + "_" + d.processId, obj2); - } - if (sptMap.has(d.state + "_" + d.processId + "_" + d.threadId)) { - let obj3 = sptMap.get(d.state + "_" + d.processId + "_" + d.threadId); - obj3!.count++; - obj3!.wallDuration += d.dur; - obj3!.avgDuration = (obj3!.wallDuration / obj3!.count).toFixed(2); - if (d.dur > obj3!.maxDuration) { - obj3!.maxDuration = d.dur; - } - if (d.dur < obj3!.minDuration) { - obj3!.minDuration = d.dur; - } - } else { - let obj3 = new StateProcessThread(); - obj3.id = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId + "_" + d.threadId - obj3.pid = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId - obj3.title = (d.thread == null || d.thread == "" ? "Thread" : d.thread) + "(" + d.threadId + ")" - obj3.processId = d.processId; - obj3.process = d.process; - obj3.thread = d.thread; - obj3.threadId = d.threadId; - obj3.state = d.state; - obj3.minDuration = d.dur; - obj3.maxDuration = d.dur; - obj3.count = 1; - obj3.avgDuration = d.dur + ""; - obj3.wallDuration = d.dur; - sptMap.set(d.state + "_" + d.processId + "_" + d.threadId, obj3); - } - } - }) - let arr: Array = []; - for (let key of statesMap.keys()) { - let s = statesMap.get(key); - s!.children = []; - for (let ks of spMap.keys()) { - if (ks.startsWith(key + "_")) { - let sp = spMap.get(ks) - sp!.children = []; - for (let kst of sptMap.keys()) { - if (kst.startsWith(ks + "_")) { - let spt = sptMap.get(kst) - sp!.children.push(spt!); - } - } - s!.children.push(sp!) - } - } - arr.push(s!) - } - resolve(arr); - })); - } - - queryDataByDB(val: SelectionParam | any) { - Promise.all([ - getTabStatesGroupByState(val.leftNs, val.rightNs), - getTabStatesGroupByStatePid(val.leftNs, val.rightNs), - getTabStatesGroupByStatePidTid(val.leftNs, val.rightNs)]).then((values) => { - let states = values[0]; - states.map((spt) => { - spt.id = (spt.state == "R+" ? "RP" : spt.state) - spt.title = Utils.getEndState(spt.state); - }); - let processMap = this.groupByStateToMap(values[1]); - let threadMap = this.groupByStateProcessToMap(values[2]); - for (let state of states) { - let processes = processMap.get(state.state); - processes!.map((spt) => { - spt.id = (spt.state == "R+" ? "RP" : spt.state) + "_" + spt.processId; - spt.pid = (spt.state == "R+" ? "RP" : spt.state); - spt.title = (spt.process == null || spt.process == "" ? "Process" : spt.process) + "(" + spt.processId + ")" - }) - state.children = processes ?? []; - let map = threadMap.get(state.state); - for (let process of processes!) { - let threads = map!.get(process.processId); - threads!.map((spt) => { - spt.id = (spt.state == "R+" ? "RP" : spt.state) + "_" + spt.processId + "_" + spt.threadId - spt.pid = (spt.state == "R+" ? "RP" : spt.state) + "_" + spt.processId - spt.title = (spt.thread == null || spt.thread == "" ? "Thread" : spt.thread) + "(" + spt.threadId + ")" - }) - process.children = threads ?? []; - } - } - this.tbl!.recycleDataSource = states; - }) - } - - groupByStateToMap(arr: Array): Map> { - let map = new Map>(); - for (let spt of arr) { - if (map.has(spt.state)) { - map.get(spt.state)!.push(spt); - } else { - let list: Array = []; - list.push(spt); - map.set(spt.state, list); - } - } - return map; - } - - groupByProcessToMap(arr: Array): Map> { - let map = new Map>(); - for (let spt of arr) { - if (map.has(spt.processId)) { - map.get(spt.processId)!.push(spt); - } else { - let list: Array = []; - list.push(spt); - map.set(spt.processId, list); - } - } - return map; - } - - groupByStateProcessToMap(arr: Array): Map>> { - let map = new Map>>(); - let stateMap = this.groupByStateToMap(arr); - for (let key of stateMap.keys()) { - let processMap = this.groupByProcessToMap(stateMap.get(key)!) - map.set(key, processMap); - } - return map; - } - - initHtml(): string { - return ` - - - - - - - `; - } -} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabProgressBar.ts b/host/ide/src/trace/component/trace/sheet/TabProgressBar.ts index 74640f8beaf93160964e685a981084b507dbe700..2d55de7af035df4d9184021d9e20eedfc04bc5a8 100644 --- a/host/ide/src/trace/component/trace/sheet/TabProgressBar.ts +++ b/host/ide/src/trace/component/trace/sheet/TabProgressBar.ts @@ -19,38 +19,38 @@ import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; @element('tab-progress-bar') export class TabProgressBar extends BaseElement { - initElements(): void { - let data:Array = this.getAttribute("data")!.split(",") - let first: HTMLDivElement | undefined | null =this.shadowRoot?.querySelector("#first") - let second: HTMLDivElement | undefined | null =this.shadowRoot?.querySelector("#second") - if (data!.length > 0 && data && data![2]!="0") { - if (parseInt(data[0])< 0) { - first!.style.width = (Number((Math.abs(parseInt(data[0]))/parseInt(data[2]))*100)).toFixed(2) + "%" - first!.style.background = "#FC74FF" - }else { - first!.style.width = (Number((parseInt(data[0])/parseInt(data[2]))*100)).toFixed(2) + "%" - } - if (parseInt(data[1])< 0) { - second!.style.width = (Number((Math.abs(parseInt(data[1])) / parseInt(data[2])) * 100)).toFixed(2) + "%" - first!.style.background = "#CC34CF" - }else { - second!.style.width = (Number((parseInt(data[1]) / parseInt(data[2])) * 100)).toFixed(2) + "%" - } - } - - } - - - - initHtml(): string { - return ` - -
-
+ initElements(): void { + let data: Array = this.getAttribute("data")!.split(",") + let first: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector("#first") + let second: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector("#second") + if (data!.length > 0 && data && data![2] != "0") { + if (parseInt(data[0]) < 0) { + first!.style.width = (Number((Math.abs(parseInt(data[0])) / parseInt(data[2])) * 100)).toFixed(2) + "%" + first!.style.background = "#FC74FF" + } else { + first!.style.width = (Number((parseInt(data[0]) / parseInt(data[2])) * 100)).toFixed(2) + "%" + } + if (parseInt(data[1]) < 0) { + second!.style.width = (Number((Math.abs(parseInt(data[1])) / parseInt(data[2])) * 100)).toFixed(2) + "%" + first!.style.background = "#CC34CF" + } else { + second!.style.width = (Number((parseInt(data[1]) / parseInt(data[2])) * 100)).toFixed(2) + "%" + } + } + + } + + initHtml(): string { + return ` + +
+
+
+
`; - } + } } diff --git a/host/ide/src/trace/component/trace/sheet/ability/TabPaneCpuAbility.ts b/host/ide/src/trace/component/trace/sheet/ability/TabPaneCpuAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..afc87e5f6a56b6d4949971951db59b123687b06b --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/ability/TabPaneCpuAbility.ts @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabCpuAbilityData,} from "../../../../database/SqlLite.js"; +import {SystemCpuSummary} from "../../../../bean/AbilityMonitor.js"; +import {Utils} from "../../base/Utils.js"; +import {ColorUtils} from "../../base/ColorUtils.js"; +import "../../../SpFilter.js"; +import {log} from "../../../../../log/Log.js"; + +@element('tabpane-cpu-ability') +export class TabPaneCpuAbility extends BaseElement { + private tbl: LitTable | null | undefined; + private source: Array = []; + private queryResult: Array = [] + private float: HTMLDivElement | null | undefined; + private search: HTMLInputElement | undefined | null + + set data(val: SelectionParam | any) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.queryDataByDB(val) + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-cpu-ability'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail) + }); + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + filterData() { + if (this.queryResult.length > 0) { + let filter = this.queryResult.filter((item) => { + let array = this.toCpuAbilityArray(item) + let isInclude = array.filter(value => value.indexOf(this.search!.value) > -1); + return isInclude.length > 0 + }); + if (filter.length > 0) { + this.source = filter; + this.tbl!.recycleDataSource = this.source; + } else { + this.source = [] + this.tbl!.recycleDataSource = []; + } + } + } + + toCpuAbilityArray(systemCpuSummary: SystemCpuSummary): any[] { + let array: Array = [] + array.push(systemCpuSummary.startTimeStr) + array.push(systemCpuSummary.durationStr) + array.push(systemCpuSummary.totalLoadStr) + array.push(systemCpuSummary.userLoadStr) + array.push(systemCpuSummary.systemLoadStr) + array.push(systemCpuSummary.threadsStr) + return array + } + + queryDataByDB(val: SelectionParam | any) { + getTabCpuAbilityData(val.leftNs, val.rightNs).then(result => { + log("getTabCpuAbilityData size :" + result.length); + if (result.length != null && result.length > 0) { + for (const systemCpuSummary of result) { + if (systemCpuSummary.startTime == 0) { + systemCpuSummary.startTimeStr = '0:000.000.000'; + } else { + systemCpuSummary.startTimeStr = Utils.getTimeStampHMS(systemCpuSummary.startTime); + } + systemCpuSummary.durationStr = Utils.getDurString(systemCpuSummary.duration); + systemCpuSummary.totalLoadStr = (systemCpuSummary.totalLoad).toFixed(2) + "%" + systemCpuSummary.userLoadStr = (systemCpuSummary.userLoad).toFixed(2) + "%" + systemCpuSummary.systemLoadStr = (systemCpuSummary.systemLoad).toFixed(2) + "%" + systemCpuSummary.threadsStr = ColorUtils.formatNumberComma(systemCpuSummary.threads); + } + this.source = result + this.queryResult = result; + this.tbl!.recycleDataSource = this.source + } else { + this.source = [] + this.queryResult = [] + this.tbl!.recycleDataSource = [] + } + }) + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + + + `; + } + + sortByColumn(detail: any) { + // @ts-ignore + function compare(property, sort, type) { + return function (a: SystemCpuSummary, b: SystemCpuSummary) { + if (type === 'number') { + // @ts-ignore + return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); + } else if (type === 'durationStr') { + return sort === 2 ? b.duration - a.duration : a.duration - b.duration; + } else if (type === 'totalLoadStr') { + return sort === 2 ? b.totalLoad - a.totalLoad : a.totalLoad - b.totalLoad; + } else if (type === 'userLoadStr') { + return sort === 2 ? b.userLoad - a.userLoad : a.userLoad - b.userLoad; + } else if (type === 'systemLoadStr') { + return sort === 2 ? b.systemLoad - a.systemLoad : a.systemLoad - b.systemLoad; + } else { + // @ts-ignore + if (b[property] > a[property]) { + return sort === 2 ? 1 : -1; + } else { // @ts-ignore + if (b[property] == a[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + } + } + + if (detail.key === 'startTime') { + this.source.sort(compare(detail.key, detail.sort, 'string')) + } else if (detail.key === 'durationStr') { + this.source.sort(compare(detail.key, detail.sort, 'durationStr')) + } else if (detail.key === 'totalLoadStr') { + this.source.sort(compare(detail.key, detail.sort, 'totalLoadStr')) + } else if (detail.key === 'userLoadStr') { + this.source.sort(compare(detail.key, detail.sort, 'userLoadStr')) + } else if (detail.key === 'systemLoadStr') { + this.source.sort(compare(detail.key, detail.sort, 'systemLoadStr')) + } else { + this.source.sort(compare(detail.key, detail.sort, 'number')) + } + this.tbl!.recycleDataSource = this.source; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/ability/TabPaneDiskAbility.ts b/host/ide/src/trace/component/trace/sheet/ability/TabPaneDiskAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..945aab8eb77bcee7a28511848369a782b58cd4fe --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/ability/TabPaneDiskAbility.ts @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabDiskAbilityData} from "../../../../database/SqlLite.js"; +import {SystemDiskIOSummary} from "../../../../bean/AbilityMonitor.js"; +import {Utils} from "../../base/Utils.js"; +import {ColorUtils} from "../../base/ColorUtils.js"; +import "../../../SpFilter.js"; +import {log} from "../../../../../log/Log.js"; + +@element('tabpane-disk-ability') +export class TabPaneDiskAbility extends BaseElement { + private tbl: LitTable | null | undefined; + private source: Array = []; + private queryResult: Array = [] + private search: HTMLInputElement | undefined | null + + set data(val: SelectionParam | any) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.queryDataByDB(val) + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-disk-ability'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail) + }); + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl!.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl!.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + filterData() { + if (this.queryResult.length > 0) { + let filter = this.queryResult.filter((item) => { + let array = this.toDiskAbilityArray(item) + let isInclude = array.filter(value => value.indexOf(this.search!.value) > -1); + return isInclude.length > 0 + }); + if (filter.length > 0) { + this.source = filter; + this.tbl!.recycleDataSource = this.source; + } else { + this.source = [] + this.tbl!.recycleDataSource = []; + } + } + } + + toDiskAbilityArray(systemDiskIOSummary: SystemDiskIOSummary): any[] { + let array: Array = [] + array.push(systemDiskIOSummary.startTimeStr) + array.push(systemDiskIOSummary.durationStr) + array.push(systemDiskIOSummary.dataReadStr) + array.push(systemDiskIOSummary.dataReadSecStr) + array.push(systemDiskIOSummary.dataWriteStr) + array.push(systemDiskIOSummary.readsInStr) + array.push(systemDiskIOSummary.readsInSecStr) + array.push(systemDiskIOSummary.writeOutStr) + array.push(systemDiskIOSummary.writeOutSecStr) + return array + } + + queryDataByDB(val: SelectionParam | any) { + getTabDiskAbilityData(val.leftNs, val.rightNs).then((result) => { + log("getTabDiskAbilityData result size : " + result.length) + if (result.length != null && result.length > 0) { + for (const systemDiskIOSummary of result) { + if (systemDiskIOSummary.startTime <= 0) { + systemDiskIOSummary.startTimeStr = '0:000.000.000'; + } else { + systemDiskIOSummary.startTimeStr = Utils.getTimeStampHMS(systemDiskIOSummary.startTime); + } + systemDiskIOSummary.durationStr = Utils.getDurString(systemDiskIOSummary.duration); + systemDiskIOSummary.dataReadStr = systemDiskIOSummary.dataRead + "KB"; + systemDiskIOSummary.dataReadSecStr = systemDiskIOSummary.dataReadSec + "KB/S"; + systemDiskIOSummary.dataWriteStr = systemDiskIOSummary.dataWrite + "KB"; + systemDiskIOSummary.dataWriteSecStr = systemDiskIOSummary.dataWriteSec + "KB/S"; + systemDiskIOSummary.readsInStr = ColorUtils.formatNumberComma(systemDiskIOSummary.readsIn); + systemDiskIOSummary.readsInSecStr = systemDiskIOSummary.readsInSec.toString(); + systemDiskIOSummary.writeOutStr = ColorUtils.formatNumberComma(systemDiskIOSummary.writeOut); + systemDiskIOSummary.writeOutSecStr = systemDiskIOSummary.writeOutSec.toString(); + } + this.source = result; + this.queryResult = result; + this.tbl!.recycleDataSource = result; + } else { + this.source = []; + this.queryResult = [] + this.tbl!.recycleDataSource = [] + } + }) + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + + + + + + + + + + + `; + } + + sortByColumn(detail: any) { + // @ts-ignore + function compare(property, sort, type) { + return function (a: SystemDiskIOSummary, b: SystemDiskIOSummary) { + if (type === 'number') { + // @ts-ignore + return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); + } else if (type === 'durationStr') { + return sort === 2 ? b.duration - a.duration : a.duration - b.duration; + } else if (type === 'dataReadStr') { + return sort === 2 ? b.dataRead - a.dataRead : a.dataRead - b.dataRead; + } else if (type === 'dataReadSecStr') { + return sort === 2 ? b.dataReadSec - a.dataReadSec : a.dataReadSec - b.dataReadSec; + } else if (type === 'dataWriteStr') { + return sort === 2 ? b.dataWrite - a.dataWrite : a.dataWrite - b.dataWrite; + } else if (type === 'dataWriteSecStr') { + return sort === 2 ? b.dataWriteSec - a.dataWriteSec : a.dataWriteSec - b.dataWriteSec; + } else if (type === 'readsInStr') { + return sort === 2 ? b.readsIn - a.readsIn : a.readsIn - b.readsIn; + } else if (type === 'readsInSecStr') { + return sort === 2 ? b.readsInSec - a.readsInSec : a.readsInSec - b.readsInSec; + } else if (type === 'writeOutStr') { + return sort === 2 ? b.writeOut - a.writeOut : a.writeOut - b.writeOut; + } else if (type === 'writeOutSecStr') { + return sort === 2 ? b.writeOutSec - a.writeOutSec : a.writeOutSec - b.writeOutSec; + } else { + // @ts-ignore + if (b[property] > a[property]) { + return sort === 2 ? 1 : -1; + } else { // @ts-ignore + if (b[property] == a[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + } + } + + if (detail.key === 'startTime') { + this.source.sort(compare(detail.key, detail.sort, 'string')) + } else if (detail.key === 'durationStr') { + this.source.sort(compare(detail.key, detail.sort, 'durationStr')) + } else if (detail.key === 'dataReadStr') { + this.source.sort(compare(detail.key, detail.sort, 'dataReadStr')) + } else if (detail.key === 'dataReadSecStr') { + this.source.sort(compare(detail.key, detail.sort, 'dataReadSecStr')) + } else if (detail.key === 'dataWriteStr') { + this.source.sort(compare(detail.key, detail.sort, 'dataWriteStr')) + } else if (detail.key === 'dataWriteSecStr') { + this.source.sort(compare(detail.key, detail.sort, 'dataWriteSecStr')) + } else if (detail.key === 'readsInStr') { + this.source.sort(compare(detail.key, detail.sort, 'readsInStr')) + } else if (detail.key === 'readsInSecStr') { + this.source.sort(compare(detail.key, detail.sort, 'readsInSecStr')) + } else if (detail.key === 'writeOutStr') { + this.source.sort(compare(detail.key, detail.sort, 'writeOutStr')) + } else if (detail.key === 'writeOutSecStr') { + this.source.sort(compare(detail.key, detail.sort, 'writeOutSecStr')) + } else { + this.source.sort(compare(detail.key, detail.sort, 'number')) + } + this.tbl!.recycleDataSource = this.source; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/ability/TabPaneHistoryProcesses.ts b/host/ide/src/trace/component/trace/sheet/ability/TabPaneHistoryProcesses.ts new file mode 100644 index 0000000000000000000000000000000000000000..344fab1a148c30ee87d7742de1e77d3e2082c3ec --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/ability/TabPaneHistoryProcesses.ts @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabProcessHistoryData} from "../../../../database/SqlLite.js"; +import {Utils} from "../../base/Utils.js"; +import {ProcessHistory} from "../../../../bean/AbilityMonitor.js"; +import "../../../SpFilter.js"; +import {log} from "../../../../../log/Log.js"; + +@element('tabpane-history-processes') +export class TabPaneHistoryProcesses extends BaseElement { + private tbl: LitTable | null | undefined; + private source: Array = []; + private queryResult: Array = [] + private float: HTMLDivElement | null | undefined; + private search: HTMLInputElement | undefined | null + + set data(val: SelectionParam | any) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.queryDataByDB(val) + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-history-processes'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail) + }); + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + filterData() { + if (this.queryResult.length > 0) { + let filter = this.queryResult.filter((item) => { + let array = this.toProcessHistoryArray(item) + let isInclude = array.filter(value => value.indexOf(this.search!.value) > -1); + return isInclude.length > 0 + }); + if (filter.length > 0) { + this.source = filter; + this.tbl!.recycleDataSource = this.source; + } else { + this.source = [] + this.tbl!.recycleDataSource = []; + } + } + } + + toProcessHistoryArray(process: ProcessHistory): any[] { + let array: Array = [] + array.push(process.processId.toString()) + array.push(process.processName) + array.push(process.alive) + array.push(process.firstSeen) + array.push(process.lastSeen) + array.push(process.responsibleProcess) + array.push(process.userName) + array.push(process.cpuTime) + return array + } + + queryDataByDB(val: SelectionParam | any) { + getTabProcessHistoryData(val.leftNs, val.rightNs, val.processId, val.threadId).then(item => { + if (item.length != null && item.length > 0) { + log("getTabProcessHistoryData result size : " + item.length) + for (const processHistory of item) { + processHistory.alive = processHistory.alive == '0' ? 'No' : 'Yes' + if (Number(processHistory.firstSeen) <= 0) { + processHistory.firstSeen = '0:000.000.000'; + processHistory.firstSeenNumber = 0; + } else { + processHistory.firstSeenNumber = Number(processHistory.firstSeen); + processHistory.firstSeen = Utils.getTimeStampHMS(processHistory.firstSeenNumber) + } + processHistory.lastSeenNumber = Number(processHistory.lastSeen); + processHistory.lastSeen = Utils.getTimeStampHMS(Number(processHistory.lastSeenNumber)) + processHistory.processName = processHistory.processName + '(' + processHistory.processId + ')' + processHistory.cpuTimeNumber = Number(processHistory.cpuTime); + processHistory.cpuTime = this.timeFormat(processHistory.cpuTimeNumber) + } + this.source = item + this.queryResult = item; + this.tbl!.recycleDataSource = this.source; + } else { + this.source = [] + this.queryResult = [] + this.tbl!.recycleDataSource = []; + } + }) + } + + timeFormat(ms: number): string { + let currentMs = ms + let hours = 3600000 + let minute1 = 60000 + let second1 = 1000; + let res = ""; + if (currentMs >= hours) { + res += Math.floor(currentMs / hours) + " h "; + currentMs = currentMs - Math.floor(currentMs / hours) * hours + } + if (currentMs >= minute1) { + res += Math.floor(currentMs / minute1) + " min "; + currentMs = currentMs - Math.floor(currentMs / minute1) * minute1 + } + if (currentMs >= second1) { + res += Math.floor(currentMs / second1) + " s "; + currentMs = currentMs - Math.floor(currentMs / second1) * second1; + } + if (currentMs > 0) { + res += currentMs + " ms "; + } else { + res += "0 ms "; + } + return res + } + + initHtml(): string { + return ` + + + + + + + + + + + + `; + } + + sortByColumn(detail: any) { + // @ts-ignore + function compare(property, sort, type) { + return function (a: ProcessHistory, b: ProcessHistory) { + if (type === 'number') { + // @ts-ignore + return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); + } else if (type === 'cpuTime') { + return sort === 2 ? b.cpuTimeNumber - a.cpuTimeNumber : a.cpuTimeNumber - b.cpuTimeNumber; + } else if (type === 'lastSeen') { + return sort === 2 ? b.lastSeenNumber - a.lastSeenNumber : a.lastSeenNumber - b.lastSeenNumber; + } else if (type === 'firstSeen') { + return sort === 2 ? b.firstSeenNumber - a.firstSeenNumber : a.firstSeenNumber - b.firstSeenNumber; + } else if (type === 'alive') { + let aaaa = 0; + let bbbb = 0; + // @ts-ignore + if (b[property] == "Yes") { + bbbb = 1; + } + // @ts-ignore + if (a[property] == "Yes") { + aaaa = 1; + } + if (aaaa - bbbb == 0) { + return 0; + } + return aaaa - bbbb ? -1 : 1 + } else { + // @ts-ignore + if (b[property] > a[property]) { + return sort === 2 ? 1 : -1; + } else { // @ts-ignore + if (b[property] == a[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + } + } + + if (detail.key === 'startTime' || detail.key === 'processName' ) { + this.source.sort(compare(detail.key, detail.sort, 'string')) + } else if (detail.key == 'cpuTime') { + this.source.sort(compare(detail.key, detail.sort, 'cpuTime')) + } else if (detail.key === 'alive') { + this.source.sort(compare(detail.key, detail.sort, 'alive')) + } else { + this.source.sort(compare(detail.key, detail.sort, 'number')) + } + this.tbl!.recycleDataSource = this.source; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/ability/TabPaneLiveProcesses.ts b/host/ide/src/trace/component/trace/sheet/ability/TabPaneLiveProcesses.ts new file mode 100644 index 0000000000000000000000000000000000000000..dcb8a1349ba1a51398ad5cb79d11ce046f6705bc --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/ability/TabPaneLiveProcesses.ts @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabLiveProcessData} from "../../../../database/SqlLite.js"; +import {LiveProcess} from "../../../../bean/AbilityMonitor.js"; +import "../../../SpFilter.js"; +import {Utils} from "../../base/Utils.js"; +import {log} from "../../../../../log/Log.js"; + +@element('tabpane-live-processes') +export class TabPaneLiveProcesses extends BaseElement { + private tbl: LitTable | null | undefined; + private source: Array = []; + private queryResult: Array = [] + private float: HTMLDivElement | null | undefined; + private search: HTMLInputElement | undefined | null + + set data(val: SelectionParam | any) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.queryDataByDB(val) + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-live-processes'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail) + }); + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + filterData() { + if (this.queryResult.length > 0) { + let filter = this.queryResult.filter((item) => { + let array = this.toLiveProcessArray(item) + let isInclude = array.filter(value => value.indexOf(this.search!.value) > -1); + return isInclude.length > 0 + }); + if (filter.length > 0) { + this.source = filter; + this.tbl!.recycleDataSource = this.source; + } else { + this.source = [] + this.tbl!.recycleDataSource = []; + } + } + } + + toLiveProcessArray(liveProcess: LiveProcess): any[] { + let array: Array = [] + array.push(liveProcess.processId.toString()) + array.push(liveProcess.processName) + array.push(liveProcess.responsibleProcess) + array.push(liveProcess.userName) + array.push(liveProcess.threads.toString()) + array.push(liveProcess.cpu) + array.push(liveProcess.memory) + array.push(liveProcess.diskReads.toString()) + array.push(liveProcess.diskWrite.toString()) + return array + } + + queryDataByDB(val: SelectionParam | any) { + getTabLiveProcessData(val.leftNs, val.rightNs).then(item => { + if (item.length != null && item.length > 0) { + log("getTabLiveProcessData result size : " + item.length) + for (const liveProcess of item) { + liveProcess.processName = liveProcess.processName + '(' + liveProcess.processId + ')' + liveProcess.memoryNumber = Number(liveProcess.memory); + liveProcess.memory = Utils.getBinaryByteWithUnit(liveProcess.memoryNumber) + if (Number(liveProcess.cpu) > 0) { + liveProcess.cpu = Number(Number(liveProcess.cpu).toFixed(3)) + "%" + } else { + liveProcess.cpu = "0%"; + } + liveProcess.cpuTimeNumber = Number(liveProcess.cpuTime); + liveProcess.cpuTime = this.timeFormat(Number(liveProcess.cpuTime)) + } + this.source = item + this.queryResult = item; + this.tbl!.recycleDataSource = this.source; + } else { + this.source = [] + this.queryResult = [] + this.tbl!.recycleDataSource = []; + } + }) + } + + + timeFormat(ms: number): string { + let currentMs = ms + let hours = 3600000 + let minute1 = 60000 + let second1 = 1000; + let res = ""; + if (currentMs >= hours) { + res += Math.floor(currentMs / hours) + " h "; + currentMs = currentMs - Math.floor(currentMs / hours) * hours + } + if (currentMs >= minute1) { + res += Math.floor(currentMs / minute1) + " min "; + currentMs = currentMs - Math.floor(currentMs / minute1) * minute1 + } + if (currentMs >= second1) { + res += Math.floor(currentMs / second1) + " s "; + currentMs = currentMs - Math.floor(currentMs / second1) * second1; + } + if (currentMs > 0) { + res += currentMs + " ms "; + } else { + res += "0 ms "; + } + return res + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + `; + } + + sortByColumn(detail: any) { + // @ts-ignore + function compare(property, sort, type) { + return function (a: LiveProcess, b: LiveProcess) { + if (type === 'number') { + // @ts-ignore + return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); + } else if (type === 'cpuTime') { + return sort === 2 ? b.cpuTimeNumber - a.cpuTimeNumber : a.cpuTimeNumber - b.cpuTimeNumber; + } else if (type === 'memory') { + return sort === 2 ? b.memoryNumber - a.memoryNumber : a.memoryNumber - b.memoryNumber; + } else { + // @ts-ignore + if (b[property] > a[property]) { + return sort === 2 ? 1 : -1; + } else { // @ts-ignore + if (b[property] == a[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + } + } + + if (detail.key == 'startTime' || detail.key == 'processName') { + this.source.sort(compare(detail.key, detail.sort, 'string')) + } else if (detail.key == 'cpuTime') { + this.source.sort(compare(detail.key, detail.sort, 'cpuTime')) + } else if (detail.key == 'memory') { + this.source.sort(compare(detail.key, detail.sort, 'memory')) + } else { + this.source.sort(compare(detail.key, detail.sort, 'number')) + } + this.tbl!.recycleDataSource = this.source; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/ability/TabPaneMemoryAbility.ts b/host/ide/src/trace/component/trace/sheet/ability/TabPaneMemoryAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..6162aea6470dac38b5869a0923cfc0614ea3769c --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/ability/TabPaneMemoryAbility.ts @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabMemoryAbilityData, queryStartTime} from "../../../../database/SqlLite.js"; +import {SystemMemorySummary} from "../../../../bean/AbilityMonitor.js"; +import {Utils} from "../../base/Utils.js"; +import "../../../SpFilter.js"; +import {log} from "../../../../../log/Log.js"; + +@element('tabpane-memory-ability') +export class TabPaneMemoryAbility extends BaseElement { + private tbl: LitTable | null | undefined; + private source: Array = []; + private float: HTMLDivElement | null | undefined; + private queryResult: Array = [] + private search: HTMLInputElement | undefined | null + + set data(val: SelectionParam | any) { + // @ts-ignore + this.tbl?.shadowRoot?.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.queryDataByDB(val) + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-memory-ability'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail) + }); + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + filterData() { + if (this.queryResult.length > 0) { + let filter = this.queryResult.filter((item) => { + let array = this.toMemoryAbilityArray(item) + let isInclude = array.filter(value => value.indexOf(this.search!.value) > -1); + return isInclude.length > 0 + }); + if (filter.length > 0) { + this.source = filter; + this.tbl!.recycleDataSource = this.source; + } else { + this.source = [] + this.tbl!.recycleDataSource = []; + } + } + } + + toMemoryAbilityArray(systemMemorySummary: SystemMemorySummary): any[] { + let array: Array = [] + array.push(systemMemorySummary.startTimeStr) + array.push(systemMemorySummary.durationStr) + array.push(systemMemorySummary.memoryTotal) + array.push(systemMemorySummary.cached) + array.push(systemMemorySummary.swapTotal) + return array + } + + queryDataByDB(val: SelectionParam | any) { + queryStartTime().then(res => { + let startTime = res[0].start_ts; + getTabMemoryAbilityData(val.leftNs + startTime, val.rightNs + startTime).then(items => { + log("getTabMemoryAbilityData result size : " + items.length) + this.source = [] + this.queryResult = []; + if (items.length != null && items.length > 0) { + let lastTime = 0; + for (const item of items) { + let systemMemorySummary = new SystemMemorySummary() + if (item.startTime - startTime <= 0) { + systemMemorySummary.startTimeStr = '0:000.000.000'; + } else { + systemMemorySummary.startTimeStr = Utils.getTimeStampHMS(item.startTime - startTime); + } + if (lastTime !== 0) { + systemMemorySummary.durationNumber = item.startTime - lastTime; + systemMemorySummary.durationStr = Utils.getDurString(systemMemorySummary.durationNumber); + } else { + systemMemorySummary.durationNumber = 0; + systemMemorySummary.durationStr = '-'; + } + lastTime = item.startTime; + let memorys = item.value.split(","); + let names = item.name.split(","); + if (memorys.length != names.length) { + continue; + } + for (let i = 0; i < names.length; i++) { + switch (names[i]) { + case "sys.mem.total": + systemMemorySummary.memoryTotal = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.free": + systemMemorySummary.memFree = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.buffers": + systemMemorySummary.buffers = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.cached": + systemMemorySummary.cached = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.shmem": + systemMemorySummary.shmem = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.slab": + systemMemorySummary.slab = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.swap.total": + systemMemorySummary.swapTotal = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.swap.free": + systemMemorySummary.swapFree = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.mapped": + systemMemorySummary.mapped = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.vmalloc.used": + systemMemorySummary.vmallocUsed = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.page.tables": + systemMemorySummary.pageTables = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.kernel.stack": + systemMemorySummary.kernelStack = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.active": + systemMemorySummary.active = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.inactive": + systemMemorySummary.inactive = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.unevictable": + systemMemorySummary.unevictable = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.vmalloc.total": + systemMemorySummary.vmallocTotal = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.slab.unreclaimable": + systemMemorySummary.sUnreclaim = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.cma.total": + systemMemorySummary.cmaTotal = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.cma.free": + systemMemorySummary.cmaFree = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.kernel.reclaimable": + systemMemorySummary.kReclaimable = Utils.getBinaryByteWithUnit(Number(memorys[i])) + break; + case "sys.mem.zram": + systemMemorySummary.zram = Utils.getBinaryByteWithUnit(Number(memorys[i]) * 1000) + break; + } + } + this.source.push(systemMemorySummary); + } + this.tbl!.recycleDataSource = this.source; + } else { + this.source = [] + this.tbl!.recycleDataSource = []; + } + }) + }); + if (this.tbl) { + let th = this.tbl.shadowRoot?.querySelector(".th") + if(th){ + th.style.gridColumnGap = "5px"; + } + } + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + + + + + + + + + + + + + + `; + } + + sortByColumn(detail: any) { + // @ts-ignore + function compare(property, sort, type) { + return function (a: SystemMemorySummary, b: SystemMemorySummary) { + if (type === 'number') { + // @ts-ignore + return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); + } else if (type === 'durationStr') { + return sort === 2 ? b.durationNumber - a.durationNumber : a.durationNumber - b.durationNumber; + } else { + // @ts-ignore + if (b[property] > a[property]) { + return sort === 2 ? 1 : -1; + } else { // @ts-ignore + if (b[property] == a[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + } + } + + if (detail.key === 'startTime') { + this.source.sort(compare(detail.key, detail.sort, 'string')) + } else if (detail.key === 'durationStr') { + this.source.sort(compare(detail.key, detail.sort, 'durationStr')) + } else { + this.source.sort(compare(detail.key, detail.sort, 'number')) + } + this.tbl!.recycleDataSource = this.source; + } +} + + diff --git a/host/ide/src/trace/component/trace/sheet/ability/TabPaneNetworkAbility.ts b/host/ide/src/trace/component/trace/sheet/ability/TabPaneNetworkAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..b8eee66c3bb5775da57b075dc46412b5cfb66f7f --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/ability/TabPaneNetworkAbility.ts @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabNetworkAbilityData} from "../../../../database/SqlLite.js"; +import {SystemNetworkSummary} from "../../../../bean/AbilityMonitor.js"; +import {Utils} from "../../base/Utils.js"; +import "../../../SpFilter.js"; +import {ColorUtils} from "../../base/ColorUtils.js"; +import {log} from "../../../../../log/Log.js"; + +@element('tabpane-network-ability') +export class TabPaneNetworkAbility extends BaseElement { + private tbl: LitTable | null | undefined; + private source: Array = []; + private float: HTMLDivElement | null | undefined; + private queryResult: Array = [] + private search: HTMLInputElement | undefined | null + + set data(val: SelectionParam | any) { + // @ts-ignore + this.tbl?.shadowRoot?.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.queryDataByDB(val) + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-network-ability'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail) + }); + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + filterData() { + if (this.queryResult.length > 0) { + let filter = this.queryResult.filter((item) => { + let array = this.toNetWorkAbilityArray(item) + let isInclude = array.filter(value => value.indexOf(this.search!.value) > -1); + return isInclude.length > 0 + }); + if (filter.length > 0) { + this.source = filter; + this.tbl!.recycleDataSource = this.source; + } else { + this.source = [] + this.tbl!.recycleDataSource = []; + } + } + } + + toNetWorkAbilityArray(systemNetworkSummary: SystemNetworkSummary): any[] { + let array: Array = [] + array.push(systemNetworkSummary.startTimeStr) + array.push(systemNetworkSummary.durationStr) + array.push(systemNetworkSummary.dataReceivedStr) + array.push(systemNetworkSummary.dataReceivedSecStr) + array.push(systemNetworkSummary.dataSendSecStr) + array.push(systemNetworkSummary.dataSendStr) + array.push(systemNetworkSummary.packetsIn.toString()) + array.push(systemNetworkSummary.packetsOut.toString()) + array.push(systemNetworkSummary.packetsOutSec.toString()) + return array + } + + queryDataByDB(val: SelectionParam | any) { + getTabNetworkAbilityData(val.leftNs, val.rightNs).then(item => { + log("getTabNetworkAbilityData result size : " + item.length) + if (item.length != null && item.length > 0) { + for (const systemNetworkSummary of item) { + if (systemNetworkSummary.startTime == 0) { + systemNetworkSummary.startTimeStr = '0:000.000.000'; + } else { + systemNetworkSummary.startTimeStr = Utils.getTimeStampHMS(systemNetworkSummary.startTime); + } + systemNetworkSummary.durationStr = Utils.getDurString(systemNetworkSummary.duration); + systemNetworkSummary.dataReceivedStr = Utils.getBinaryByteWithUnit(systemNetworkSummary.dataReceived); + systemNetworkSummary.dataReceivedSecStr = Utils.getBinaryByteWithUnit(systemNetworkSummary.dataReceivedSec); + systemNetworkSummary.dataSendStr = Utils.getBinaryByteWithUnit(systemNetworkSummary.dataSend); + systemNetworkSummary.dataSendSecStr = Utils.getBinaryByteWithUnit(systemNetworkSummary.dataSendSec); + systemNetworkSummary.packetsInStr = ColorUtils.formatNumberComma(systemNetworkSummary.packetsIn); + systemNetworkSummary.packetsInSecStr = systemNetworkSummary.packetsInSec.toFixed(2); + systemNetworkSummary.packetsOutStr = ColorUtils.formatNumberComma(systemNetworkSummary.packetsOut); + systemNetworkSummary.packetsOutSecStr = systemNetworkSummary.packetsOutSec.toFixed(2); + } + this.source = item + this.queryResult = item; + this.tbl!.recycleDataSource = this.source; + } else { + this.source = [] + this.queryResult = [] + this.tbl!.recycleDataSource = []; + } + }) + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + `; + } + + sortByColumn(detail: any) { + // @ts-ignore + function compare(property, sort, type) { + return function (a: SystemNetworkSummary, b: SystemNetworkSummary) { + if (type === 'number') { + // @ts-ignore + return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); + } else if (type === 'durationStr') { + return sort === 2 ? b.duration - a.duration : a.duration - b.duration; + } else if (type === 'dataReceivedStr') { + return sort === 2 ? b.dataReceived - a.dataReceived : a.dataReceived - b.dataReceived; + } else if (type === 'dataReceivedSecStr') { + return sort === 2 ? b.dataReceivedSec - a.dataReceivedSec : a.dataReceivedSec - b.dataReceivedSec; + } else if (type === 'dataSendStr') { + return sort === 2 ? b.dataSend - a.dataSend : a.dataSend - b.dataSend; + } else if (type === 'dataSendSecStr') { + return sort === 2 ? b.dataSendSec - a.dataSendSec : a.dataSendSec - b.dataSendSec; + } else if (type === 'packetsInStr') { + return sort === 2 ? b.packetsIn - a.packetsIn : a.packetsIn - b.packetsIn; + } else if (type === 'packetsInSecStr') { + return sort === 2 ? b.packetsInSec - a.packetsInSec : a.packetsInSec - b.packetsInSec; + } else if (type === 'packetsOutStr') { + return sort === 2 ? b.packetsOut - a.packetsOut : a.packetsOut - b.packetsOut; + } else if (type === 'packetsOutSecStr') { + return sort === 2 ? b.packetsOutSec - a.packetsOutSec : a.packetsOutSec - b.packetsOutSec; + } else { + // @ts-ignore + if (b[property] > a[property]) { + return sort === 2 ? 1 : -1; + } else { // @ts-ignore + if (b[property] == a[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + } + } + + if (detail.key === 'startTime') { + this.source.sort(compare(detail.key, detail.sort, 'string')) + } else if (detail.key === 'durationStr') { + this.source.sort(compare(detail.key, detail.sort, 'durationStr')) + } else if (detail.key === 'dataReceivedStr') { + this.source.sort(compare(detail.key, detail.sort, 'dataReceivedStr')) + } else if (detail.key === 'dataReceivedSecStr') { + this.source.sort(compare(detail.key, detail.sort, 'dataReceivedSecStr')) + } else if (detail.key === 'dataSendStr') { + this.source.sort(compare(detail.key, detail.sort, 'dataSendStr')) + } else if (detail.key === 'dataSendSecStr') { + this.source.sort(compare(detail.key, detail.sort, 'dataSendSecStr')) + } else if (detail.key === 'packetsInStr') { + this.source.sort(compare(detail.key, detail.sort, 'packetsInStr')) + } else if (detail.key === 'packetsInSecStr') { + this.source.sort(compare(detail.key, detail.sort, 'packetsInSecStr')) + } else if (detail.key === 'packetsOutStr') { + this.source.sort(compare(detail.key, detail.sort, 'packetsOutStr')) + } else if (detail.key === 'packetsOutSecStr') { + this.source.sort(compare(detail.key, detail.sort, 'packetsOutSecStr')) + } else { + this.source.sort(compare(detail.key, detail.sort, 'number')) + } + this.tbl!.recycleDataSource = this.source; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneBoxChild.ts b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneBoxChild.ts similarity index 60% rename from host/ide/src/trace/component/trace/sheet/TabPaneBoxChild.ts rename to host/ide/src/trace/component/trace/sheet/cpu/TabPaneBoxChild.ts index c37351bf74ec91f3ef5d077f474657fda33ffda8..c4ae904894f0b8720ad718fa0c0b4ef56727b647 100644 --- a/host/ide/src/trace/component/trace/sheet/TabPaneBoxChild.ts +++ b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneBoxChild.ts @@ -13,33 +13,37 @@ * limitations under the License. */ -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import {BoxJumpParam, SelectionData} from "../../../bean/BoxSelection.js"; -import {getTabBoxChildData} from "../../../database/SqlLite.js"; -import {Utils} from "../base/Utils.js"; -import {SpSystemTrace} from "../../SpSystemTrace.js"; -import {SPTChild} from "../../../bean/StateProcessThread.js"; +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {BoxJumpParam, SelectionData} from "../../../../bean/BoxSelection.js"; +import {getTabBoxChildData} from "../../../../database/SqlLite.js"; +import {Utils} from "../../base/Utils.js"; +import {SpSystemTrace} from "../../../SpSystemTrace.js"; +import {SPTChild} from "../../../../bean/StateProcessThread.js"; +import {TraceRow} from "../../base/TraceRow.js"; @element('tabpane-box-child') export class TabPaneBoxChild extends BaseElement { private tbl: LitTable | null | undefined; private range: HTMLLabelElement | null | undefined; private source: Array = []; - private loadDataInCache: boolean = true; + private loadDataInCache: boolean = false; set data(val: BoxJumpParam) { // @ts-ignore - this.tbl?.shadowRoot?.querySelector(".table")?.style?.height = (this.parentElement!.clientHeight - 45)+"px"; + this.tbl?.shadowRoot?.querySelector(".table")?.style?.height = (this.parentElement!.clientHeight - 45) + "px"; this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" - if (this.loadDataInCache) { - this.getDataByCache(val).then((arr) => { - this.source = arr; - // @ts-ignore - this.tbl?.recycleDataSource = arr; - }) - } else { - this.getDataByDB(val) + if(val.state != null && val.state != undefined && val.processId && val.threadId){ + this.tbl!.recycleDataSource = []; + if (this.loadDataInCache) { + this.getDataByCache(val).then((arr) => { + this.source = arr; + // @ts-ignore + this.tbl?.recycleDataSource = arr; + }) + } else { + this.getDataByDB(val) + } } } @@ -50,13 +54,17 @@ export class TabPaneBoxChild extends BaseElement { // @ts-ignore this.sortByColumn(evt.detail) }); + } + + connectedCallback() { + super.connectedCallback(); new ResizeObserver((entries) => { if (this.parentElement?.clientHeight != 0) { // @ts-ignore - this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45)+"px" + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" this.tbl?.reMeauseHeight() } - }).observe(this.parentElement!) + }).observe(this.parentElement!); } getDataByDB(val: BoxJumpParam) { @@ -64,34 +72,37 @@ export class TabPaneBoxChild extends BaseElement { if (result.length != null && result.length > 0) { result.map((e) => { e.startTime = Utils.getTimeString(e.startNs) + e.absoluteTime = ((window as any).recordStartNS + e.startNs)/1000000000 e.state = Utils.getEndState(e.state)! e.prior = e.priority == undefined || e.priority == null ? "-" : e.priority + "" e.core = e.cpu == undefined || e.cpu == null ? "-" : "CPU" + e.cpu e.processName = (e.process == undefined || e.process == null ? "process" : e.process) + "(" + e.processId + ")" e.threadName = (e.thread == undefined || e.thread == null ? "thread" : e.thread) + "(" + e.threadId + ")" + e.note = "-" }) this.source = result; // @ts-ignore - this.tbl?.dataSource = result; + this.tbl?.recycleDataSource = result; } else { this.source = []; // @ts-ignore - this.tbl?.dataSource = [] + this.tbl?.recycleDataSource = [] } }) } getDataByCache(val: BoxJumpParam): Promise> { return new Promise>((resolve, reject) => { - let time = Date.now(); let arr: Array = []; SpSystemTrace.SPT_DATA.map((spt) => { let b1 = (val.state != undefined && val.state != '') ? spt.state == val.state : true let b2 = (val.processId != undefined && val.processId != -1) ? spt.processId == val.processId : true let b3 = (val.threadId != undefined && val.threadId != -1) ? spt.threadId == val.threadId : true - if(!(spt.end_ts < val.leftNs || spt.start_ts > val.rightNs) && b1 && b2 && b3){ + if (!(spt.end_ts < val.leftNs || spt.start_ts > val.rightNs) && b1 && b2 && b3) { let sptChild = new SPTChild(); sptChild.startTime = Utils.getTimeString(spt.start_ts) + sptChild.absoluteTime = ((window as any).recordStartNS + spt.start_ts)/1000000000 + sptChild.startNs = spt.start_ts sptChild.state = Utils.getEndState(spt.state)! sptChild.prior = spt.priority == undefined || spt.priority == null ? "-" : spt.priority + "" sptChild.core = spt.cpu == undefined || spt.cpu == null ? "-" : "CPU" + spt.cpu @@ -102,28 +113,36 @@ export class TabPaneBoxChild extends BaseElement { }) resolve(arr); }) - } initHtml(): string { return ` - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + `; } @@ -151,7 +170,7 @@ export class TabPaneBoxChild extends BaseElement { // @ts-ignore this.source.sort(compare(detail.key, detail.sort, 'string')) - this.tbl!.dataSource = this.source; + this.tbl!.recycleDataSource = this.source; } } \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/cpu/TabPaneContextSwitch.ts b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneContextSwitch.ts new file mode 100644 index 0000000000000000000000000000000000000000..959e65d69f1ab7e33b4b356b08e1a95652216a66 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneContextSwitch.ts @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import { + getStatesProcessThreadDataByRange + +} from "../../../../database/SqlLite.js"; +import {SPT, StateProcessThread} from "../../../../bean/StateProcessThread.js"; +import {Utils} from "../../base/Utils.js"; +import {SpSystemTrace} from "../../../SpSystemTrace.js"; + +@element('tabpane-context-switch') +export class TabPaneContextSwitch extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private loadDataInCache: boolean = true; + private selectionParam:SelectionParam | null | undefined; + + set data(val: SelectionParam | any) { + if(val == this.selectionParam){ + return; + } + this.selectionParam = val; + // @ts-ignore + this.tbl?.shadowRoot?.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" + if (this.loadDataInCache) { + this.getDataBySPT(val.leftNs,val.rightNs,SpSystemTrace.SPT_DATA) + } else { + this.queryDataByDB(val) + } + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-cs'); + this.range = this.shadowRoot?.querySelector('#time-range') + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!) + } + + getDataBySPT(leftNs:number,rightNs:number,source:Array){ + let pMap: Map = new Map(); + let ptMap: Map = new Map(); + let ptsMap: Map = new Map(); + source.map((d) => { + if (!(d.end_ts < leftNs || d.start_ts > rightNs)) { + if (pMap.has(d.processId + "")) { + let obj1 = pMap.get(d.processId + ""); + obj1!.count++; + obj1!.wallDuration += d.dur; + obj1!.avgDuration = (obj1!.wallDuration / obj1!.count).toFixed(2); + if (d.dur > obj1!.maxDuration) { + obj1!.maxDuration = d.dur; + } + if (d.dur < obj1!.minDuration) { + obj1!.minDuration = d.dur; + } + } else { + let obj1 = new StateProcessThread(); + obj1.id = "p" + d.processId; + obj1.title = (d.process == null || d.process == "" ? "Process" : d.process) + "(" + d.processId + ")"; + obj1.process = d.process; + obj1.processId = d.processId; + obj1.minDuration = d.dur; + obj1.maxDuration = d.dur; + obj1.count = 1; + obj1.avgDuration = d.dur + ""; + obj1.wallDuration = d.dur; + pMap.set(d.processId + "", obj1); + } + if (ptMap.has(d.processId + "_" + d.threadId)) { + let obj2 = ptMap.get(d.processId + "_" + d.threadId); + obj2!.count++; + obj2!.wallDuration += d.dur; + obj2!.avgDuration = (obj2!.wallDuration / obj2!.count).toFixed(2); + if (d.dur > obj2!.maxDuration) { + obj2!.maxDuration = d.dur; + } + if (d.dur < obj2!.minDuration) { + obj2!.minDuration = d.dur; + } + } else { + let obj2 = new StateProcessThread(); + obj2.id = "p" + d.processId + "_" + "t" + d.threadId; + obj2.pid = "p" + d.processId; + obj2.title = (d.thread == null || d.thread == "" ? "Thread" : d.thread) + "(" + d.threadId + ")" + obj2.processId = d.processId; + obj2.process = d.process; + obj2.thread = d.thread; + obj2.threadId = d.threadId; + obj2.minDuration = d.dur; + obj2.maxDuration = d.dur; + obj2.count = 1; + obj2.avgDuration = d.dur + ""; + obj2.wallDuration = d.dur; + ptMap.set(d.processId + "_" + d.threadId, obj2); + } + if (ptsMap.has(d.processId + "_" + d.threadId + "_" + d.state)) { + let obj3 = ptsMap.get(d.processId + "_" + d.threadId + "_" + d.state); + obj3!.count++; + obj3!.wallDuration += d.dur; + obj3!.avgDuration = (obj3!.wallDuration / obj3!.count).toFixed(2); + if (d.dur > obj3!.maxDuration) { + obj3!.maxDuration = d.dur; + } + if (d.dur < obj3!.minDuration) { + obj3!.minDuration = d.dur; + } + } else { + let obj3 = new StateProcessThread(); + obj3.id = "p" + d.processId + "_" + "t" + d.threadId + "_" + (d.state == "R+" ? "RP" : d.state) + obj3.pid = "p" + d.processId + "_" + "t" + d.threadId; + obj3.title = Utils.getEndState(d.state) + obj3.processId = d.processId; + obj3.process = d.process; + obj3.thread = d.thread; + obj3.threadId = d.threadId; + obj3.state = d.state; + obj3.minDuration = d.dur; + obj3.maxDuration = d.dur; + obj3.count = 1; + obj3.avgDuration = d.dur + ""; + obj3.wallDuration = d.dur; + ptsMap.set(d.processId + "_" + d.threadId + "_" + d.state, obj3); + } + } + }) + let arr: Array = []; + for (let key of pMap.keys()) { + let s = pMap.get(key); + s!.children = []; + for (let ks of ptMap.keys()) { + if (ks.startsWith(key + "_")) { + let sp = ptMap.get(ks) + sp!.children = []; + for (let kst of ptsMap.keys()) { + if (kst.startsWith(ks + "_")) { + let spt = ptsMap.get(kst) + sp!.children.push(spt!); + } + } + s!.children.push(sp!) + } + } + arr.push(s!) + } + this.tbl!.recycleDataSource = arr; + } + + queryDataByDB(val: SelectionParam | any) { + getStatesProcessThreadDataByRange(val.leftNs,val.rightNs).then(result => { + this.getDataBySPT(val.leftNs,val.rightNs,result); + }) + } + + initHtml(): string { + return ` + + + + + + + + + `; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/cpu/TabPaneCounterSample.ts b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneCounterSample.ts new file mode 100644 index 0000000000000000000000000000000000000000..db0f0d17eadc3e1f2b1b7ae7e8838ad0f977fb57 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneCounterSample.ts @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabPaneCounterSampleData,} from "../../../../database/SqlLite.js"; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {Utils} from "../../base/Utils.js"; + +@element('tabpane-counter-sample') +export class TabPaneCounterSample extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private loadDataInCache: boolean = true; + private selectionParam:SelectionParam | null | undefined; + private progressEL:LitProgressBar | null | undefined; + private loadingPage:any; + private loadingList:number[] = []; + private source:any[] = [] + private sortKey: string = "counter"; + private sortType: number = 0; + + set data(val: SelectionParam | any) { + if(val == this.selectionParam){ + return; + } + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + this.selectionParam = val; + // @ts-ignore + this.tbl!.shadowRoot?.querySelector(".table").style.height = (this.parentElement!.clientHeight - 25) + "px" + this.queryDataByDB(val) + } + + initElements(): void { + this.progressEL = this.shadowRoot!.querySelector('.progress') + this.loadingPage = this.shadowRoot!.querySelector('.loading'); + this.tbl = this.shadowRoot!.querySelector('#tb-states'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key + // @ts-ignore + this.sortType = evt.detail.sort + // @ts-ignore + this.sortTable(evt.detail.key,evt.detail.sort) + }) + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement!.clientHeight != 0) { + // @ts-ignore + this.tbl!.shadowRoot!.querySelector(".table").style.height = (this.parentElement!.clientHeight - 25) + "px" + this.tbl!.reMeauseHeight() + this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px" + } + }).observe(this.parentElement!); + } + + queryDataByDB(val: SelectionParam | any) { + this.loadingList.push(1) + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible"; + + getTabPaneCounterSampleData(val.leftNs + val.recordStartNs, val.rightNs + val.recordStartNs, val.cpuStateFilterIds).then((result) => { + this.loadingList.splice(0,1) + if(this.loadingList.length == 0) { + this.progressEL!.loading = false + this.loadingPage.style.visibility = "hidden" + } + let sampleMap = new Map() + val.cpuStateFilterIds.forEach((a:number)=>{ + this.getInitTime(result.filter((f) => f.filterId == a),sampleMap,val) + }) + let dataList:Array = []; + sampleMap.forEach(a=>{a.timeStr = Utils.getProbablyTime(a.time);dataList.push(a);}); + this.source = dataList; + this.sortTable(this.sortKey,this.sortType) + }) + } + + getInitTime(result:Array,sampleMap:Map,val:SelectionParam){ + let leftNs = val.leftNs + val.recordStartNs; + let rightNs = val.rightNs + val.recordStartNs; + if (result.length == 0) return; + let idx = result.findIndex((a)=> a.ts >= (leftNs)); + if (idx !== 0) { + result = result.slice(idx==-1?result.length-1:idx - 1, result.length); + } + if (result[0].ts < leftNs && idx !== 0) result[0].ts = leftNs; + result.forEach((item,idx)=>{ + if ((idx + 1) == result.length) { + item.time = (rightNs) - item.ts; + }else { + item.time = result[idx+1].ts - item.ts; + } + if (sampleMap.has(item.filterId+"-"+item.value)) { + let obj = sampleMap.get(item.filterId+"-"+item.value); + obj.time += item.time; + }else { + sampleMap.set(item.filterId+"-"+item.value,{ + ...item, + counter:"Cpu "+item.cpu, + }) + } + }); + } + + sortTable(key: string,type:number){ + if(type == 0){ + this.tbl!.recycleDataSource = this.source + }else{ + let arr = Array.from(this.source) + arr.sort((a,b):number=>{ + if(key == "timeStr"){ + if(type == 1){ + return a.time - b.time ; + }else{ + return b.time - a.time ; + } + }else if(key == "counter"){ + if (a.counter > b.counter) { + return type === 2 ? -1 : 1; + } else if (a.counter == b.counter) { + return 0; + } else { + return type === 2 ? 1 : -1; + } + }else if(key == "value"){ + if(type == 1){ + return a.value - b.value ; + }else{ + return b.value - a.value ; + } + }else{ + return 0; + } + }) + this.tbl!.recycleDataSource = arr; + } + } + + initHtml(): string { + return ` + + + + + + + + + + +
+ `; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneCpuByProcess.ts b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuByProcess.ts similarity index 61% rename from host/ide/src/trace/component/trace/sheet/TabPaneCpuByProcess.ts rename to host/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuByProcess.ts index 5537ba596159ba28b00eada557613f78b5e82969..a082c3ec7ecf6ce16088e8daea3a93c612006a05 100644 --- a/host/ide/src/trace/component/trace/sheet/TabPaneCpuByProcess.ts +++ b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuByProcess.ts @@ -13,10 +13,11 @@ * limitations under the License. */ -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import {SelectionData, SelectionParam} from "../../../bean/BoxSelection.js"; -import {getTabCpuByProcess} from "../../../database/SqlLite.js"; +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionData, SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabCpuByProcess} from "../../../../database/SqlLite.js"; +import {log} from "../../../../../log/Log.js"; @element('tabpane-cpu-process') export class TabPaneCpuByProcess extends BaseElement { @@ -26,8 +27,12 @@ export class TabPaneCpuByProcess extends BaseElement { set data(val: SelectionParam | any) { this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" + // @ts-ignore + this.tbl!.shadowRoot!.querySelector(".table")?.style?.height = (this.parentElement!.clientHeight - 45) + "px"; + this.tbl!.recycleDataSource = []; getTabCpuByProcess(val.cpus, val.leftNs, val.rightNs).then((result) => { if (result != null && result.length > 0) { + log("getTabCpuByProcess size :" + result.length); let sumWall = 0.0; let sumOcc = 0; for (let e of result) { @@ -43,10 +48,10 @@ export class TabPaneCpuByProcess extends BaseElement { count.occurrences = sumOcc; result.splice(0, 0, count) this.source = result - this.tbl!.dataSource = result + this.tbl!.recycleDataSource = result } else { this.source = []; - this.tbl!.dataSource = this.source + this.tbl!.recycleDataSource = this.source } }); } @@ -60,23 +65,39 @@ export class TabPaneCpuByProcess extends BaseElement { }); } + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!) + } + initHtml(): string { return ` - - - - - - - - - + + + + + + + + + + + + + + `; } @@ -110,7 +131,7 @@ export class TabPaneCpuByProcess extends BaseElement { } else { this.source.sort(compare(detail.key, detail.sort, 'string')) } - this.tbl!.dataSource = this.source; + this.tbl!.recycleDataSource = this.source; } } \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneCpuByThread.ts b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuByThread.ts similarity index 60% rename from host/ide/src/trace/component/trace/sheet/TabPaneCpuByThread.ts rename to host/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuByThread.ts index 69192ddcf5a4bfe3c422a1d3b242806ae7ed23e2..5dbe891368d4b6d10eeeafccd04e72489e4760e9 100644 --- a/host/ide/src/trace/component/trace/sheet/TabPaneCpuByThread.ts +++ b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuByThread.ts @@ -13,10 +13,11 @@ * limitations under the License. */ -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import {SelectionData, SelectionParam} from "../../../bean/BoxSelection.js"; -import {getTabCpuByThread} from "../../../database/SqlLite.js"; +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionData, SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabCpuByThread} from "../../../../database/SqlLite.js"; +import {log} from "../../../../../log/Log.js"; @element('tabpane-cpu-thread') export class TabPaneCpuByThread extends BaseElement { @@ -28,6 +29,7 @@ export class TabPaneCpuByThread extends BaseElement { this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" getTabCpuByThread(val.cpus, val.leftNs, val.rightNs).then((result) => { if (result != null && result.length > 0) { + log("getTabCpuByThread size :" + result.length); let sumWall = 0.0; let sumOcc = 0; for (let e of result) { @@ -44,10 +46,10 @@ export class TabPaneCpuByThread extends BaseElement { count.occurrences = sumOcc; result.splice(0, 0, count) this.source = result - this.tbl!.dataSource = result + this.tbl!.recycleDataSource = result } else { this.source = []; - this.tbl!.dataSource = this.source + this.tbl!.recycleDataSource = this.source } }) } @@ -59,28 +61,45 @@ export class TabPaneCpuByThread extends BaseElement { // @ts-ignore this.sortByColumn(evt.detail) }); + } + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!) } initHtml(): string { return ` - - - - - - - - - - - + + + + + + + + + + + + + + + + + + `; } @@ -114,7 +133,7 @@ export class TabPaneCpuByThread extends BaseElement { } else { this.source.sort(compare(detail.key, detail.sort, 'string')) } - this.tbl!.dataSource = this.source; + this.tbl!.recycleDataSource = this.source; } } \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuStateClick.ts b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuStateClick.ts new file mode 100644 index 0000000000000000000000000000000000000000..23feb49d554c12500546fd92de53106c65efac85 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuStateClick.ts @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {Utils} from "../../base/Utils.js"; + +@element('tabpane-cpu-state-click') +export class TabPaneCpuStateClick extends BaseElement { + private tbl: LitTable | null | undefined; + + set data(val:any) { + if(val){ + this.tbl!.dataSource = [{ + startNS:Utils.getTimeString(val.startTs), + absoluteTime:(val.startTs + (window as any).recordStartNS)/1000000000, + dur:Utils.getProbablyTime(val.dur), + state:val.value, + cpu:`Cpu ${val.cpu}` + }] + } + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-freq'); + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!) + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + `; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneCpuUsage.ts b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuUsage.ts similarity index 67% rename from host/ide/src/trace/component/trace/sheet/TabPaneCpuUsage.ts rename to host/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuUsage.ts index e66a633683079dc4fe57679590b0db39d30e8ca5..0b2d89b221f9d869800cd73032b9f4a572bd1e42 100644 --- a/host/ide/src/trace/component/trace/sheet/TabPaneCpuUsage.ts +++ b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuUsage.ts @@ -13,11 +13,11 @@ * limitations under the License. */ -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import {SelectionParam} from "../../../bean/BoxSelection.js"; -import {getTabCpuFreq, getTabCpuUsage} from "../../../database/SqlLite.js"; -import {CpuUsage, Freq} from "../../../bean/CpuUsage.js"; +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabCpuFreq, getTabCpuUsage} from "../../../../database/SqlLite.js"; +import {CpuUsage, Freq} from "../../../../bean/CpuUsage.js"; @element('tabpane-cpu-usage') export class TabPaneCpuUsage extends BaseElement { @@ -26,6 +26,8 @@ export class TabPaneCpuUsage extends BaseElement { private orderByOldList: any[] = []; set data(val: SelectionParam | any) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" Promise.all([getTabCpuUsage(val.cpus, val.leftNs, val.rightNs), getTabCpuFreq(val.cpus, val.leftNs, val.rightNs)]).then((result) => { let usages = result[0]; @@ -71,7 +73,7 @@ export class TabPaneCpuUsage extends BaseElement { } data.push(usage) } - this.tbl!.dataSource = data; + this.tbl!.recycleDataSource = data; this.orderByOldList = [...data] }) } @@ -83,17 +85,28 @@ export class TabPaneCpuUsage extends BaseElement { // @ts-ignore let orderType = event.detail; if (orderType.sort == 1) {//倒序 注意 sort会改变原数组,需要传入table上的数组 不能传入缓存排序数组 - this.sortTable(this.tbl!.dataSource, orderType.key, false) + this.sortTable(this.tbl!.recycleDataSource, orderType.key, false) } else if (orderType.sort == 2) {//正序 - this.sortTable(this.tbl!.dataSource, orderType.key, true) + this.sortTable(this.tbl!.recycleDataSource, orderType.key, true) } else {//默认排序 - this.tbl!.dataSource = [...this.orderByOldList]; + this.tbl!.recycleDataSource = [...this.orderByOldList]; } }) } + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!) + } + sortTable(arr: any[], key: string, sort: boolean) { - this.tbl!.dataSource = arr.sort((item1, item2) => { + this.tbl!.recycleDataSource = arr.sort((item1, item2) => { let value1 = Number(item1[key].toString().replace("%", "")); let value2 = Number(item2[key].toString().replace("%", "")); if (value1 > value2) { @@ -152,24 +165,32 @@ export class TabPaneCpuUsage extends BaseElement { initHtml(): string { return ` - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + `; } } \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts new file mode 100644 index 0000000000000000000000000000000000000000..77f0a98852b903a086afa968ac7fd630c84b6f86 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabPaneFrequencySampleData} from "../../../../database/SqlLite.js"; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {Utils} from "../../base/Utils.js"; +import {ColorUtils} from "../../base/ColorUtils.js"; + +@element('tabpane-frequency-sample') +export class TabPaneFrequencySample extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private loadDataInCache: boolean = true; + private selectionParam:SelectionParam | null | undefined; + private progressEL:LitProgressBar | null | undefined; + private loadingPage:any; + private loadingList:number[] = []; + private source:any[] = [] + private sortKey: string = "counter"; + private sortType: number = 0; + + set data(val: SelectionParam | any) { + if(val == this.selectionParam){ + return; + } + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + this.selectionParam = val; + // @ts-ignore + this.tbl!.shadowRoot?.querySelector(".table").style.height = (this.parentElement!.clientHeight - 25) + "px" + this.queryDataByDB(val) + } + + initElements(): void { + this.progressEL = this.shadowRoot!.querySelector('.progress') + this.loadingPage = this.shadowRoot!.querySelector('.loading'); + this.tbl = this.shadowRoot!.querySelector('#tb-states'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key + // @ts-ignore + this.sortType = evt.detail.sort + // @ts-ignore + this.sortTable(evt.detail.key,evt.detail.sort) + }) + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement!.clientHeight != 0) { + // @ts-ignore + this.tbl!.shadowRoot!.querySelector(".table").style.height = (this.parentElement!.clientHeight - 25) + "px" + this.tbl!.reMeauseHeight() + this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px" + } + }).observe(this.parentElement!); + } + + queryDataByDB(val: SelectionParam | any) { + this.loadingList.push(1) + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible"; + + getTabPaneFrequencySampleData(val.leftNs + val.recordStartNs, val.rightNs + val.recordStartNs, val.cpuFreqFilterIds).then((result) => { + this.loadingList.splice(0,1) + if(this.loadingList.length == 0) { + this.progressEL!.loading = false + this.loadingPage.style.visibility = "hidden" + } + let sampleMap = new Map() + val.cpuFreqFilterIds.forEach((a:number)=>{ + this.getInitTime(result.filter((f) => f.filterId == a),sampleMap,val) + }) + + let dataList:Array = []; + sampleMap.forEach(a=>{ + a.timeStr = Utils.getProbablyTime(a.time); + dataList.push(a); + }); + this.source = dataList; + this.sortTable(this.sortKey,this.sortType) + }) + } + + getInitTime(result:Array,sampleMap:Map,val:SelectionParam){ + let leftNs = val.leftNs + val.recordStartNs; + let rightNs = val.rightNs + val.recordStartNs; + if (result.length == 0) return; + let idx = result.findIndex((a)=> a.ts >= (leftNs)); + if (idx !== 0) { + result = result.slice(idx==-1?result.length-1:idx - 1, result.length); + } + if (result[0].ts < leftNs && idx !== 0) result[0].ts = leftNs; + result.forEach((item,idx)=>{ + if ((idx + 1) == result.length) { + item.time = (rightNs) - item.ts; + }else { + item.time = result[idx+1].ts - item.ts; + } + if (sampleMap.has(item.filterId+"-"+item.value)) { + let obj = sampleMap.get(item.filterId+"-"+item.value); + obj.time += item.time; + }else { + sampleMap.set(item.filterId+"-"+item.value,{ + ...item, + counter:"Cpu "+item.cpu, + valueStr:ColorUtils.formatNumberComma(item.value)+" kHz", + }) + } + }); + } + + sortTable(key: string,type:number){ + if(type == 0){ + this.tbl!.recycleDataSource = this.source + }else{ + let arr = Array.from(this.source) + arr.sort((a,b):number=>{ + if(key == "timeStr"){ + if(type == 1){ + return a.time - b.time ; + }else{ + return b.time - a.time ; + } + }else if(key == "counter"){ + if (a.counter > b.counter) { + return type === 2 ? -1 : 1; + } else if (a.counter == b.counter) { + return 0; + } else { + return type === 2 ? 1 : -1; + } + }else if(key == "valueStr"){ + if(type == 1){ + return a.value - b.value ; + }else{ + return b.value - a.value ; + } + }else{ + return 0; + } + }) + this.tbl!.recycleDataSource = arr; + } + } + + initHtml(): string { + return ` + + + + + + + + + + +
+ `; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/cpu/TabPanePTS.ts b/host/ide/src/trace/component/trace/sheet/cpu/TabPanePTS.ts new file mode 100644 index 0000000000000000000000000000000000000000..910efc680d7e5eb56d24afacb038ee99aa7bf076 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/cpu/TabPanePTS.ts @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import { + getStatesProcessThreadDataByRange, +} from "../../../../database/SqlLite.js"; +import {SPT, StateProcessThread} from "../../../../bean/StateProcessThread.js"; +import {Utils} from "../../base/Utils.js"; +import {SpSystemTrace} from "../../../SpSystemTrace.js"; + +@element('tabpane-pts') +export class TabPanePTS extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private loadDataInCache: boolean = true; + private selectionParam:SelectionParam | null | undefined; + + set data(val: SelectionParam | any) { + if(val == this.selectionParam){ + return; + } + this.selectionParam = val; + this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" + if (this.loadDataInCache) { + this.getDataBySPT(val.leftNs,val.rightNs,SpSystemTrace.SPT_DATA) + } else { + this.queryDataByDB(val) + } + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-states'); + this.range = this.shadowRoot?.querySelector('#time-range') + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!) + } + + queryDataByDB(val: SelectionParam | any) { + getStatesProcessThreadDataByRange(val.leftNs,val.rightNs).then(result => { + this.getDataBySPT(val.leftNs,val.rightNs,result); + }) + } + + getDataBySPT(leftNs:number,rightNs:number,source:Array){ + let pMap: Map = new Map(); + let ptMap: Map = new Map(); + let ptsMap: Map = new Map(); + source.map((d) => { + if (!(d.end_ts < leftNs || d.start_ts > rightNs)) { + if (pMap.has(d.processId + "")) { + let obj1 = pMap.get(d.processId + ""); + obj1!.count++; + obj1!.wallDuration += d.dur; + obj1!.avgDuration = (obj1!.wallDuration / obj1!.count).toFixed(2); + if (d.dur > obj1!.maxDuration) { + obj1!.maxDuration = d.dur; + } + if (d.dur < obj1!.minDuration) { + obj1!.minDuration = d.dur; + } + } else { + let obj1 = new StateProcessThread(); + obj1.id = "p" + d.processId; + obj1.title = (d.process == null || d.process == "" ? "Process" : d.process) + "(" + d.processId + ")"; + obj1.process = d.process; + obj1.processId = d.processId; + obj1.minDuration = d.dur; + obj1.maxDuration = d.dur; + obj1.count = 1; + obj1.avgDuration = d.dur + ""; + obj1.wallDuration = d.dur; + pMap.set(d.processId + "", obj1); + } + if (ptMap.has(d.processId + "_" + d.threadId)) { + let obj2 = ptMap.get(d.processId + "_" + d.threadId); + obj2!.count++; + obj2!.wallDuration += d.dur; + obj2!.avgDuration = (obj2!.wallDuration / obj2!.count).toFixed(2); + if (d.dur > obj2!.maxDuration) { + obj2!.maxDuration = d.dur; + } + if (d.dur < obj2!.minDuration) { + obj2!.minDuration = d.dur; + } + } else { + let obj2 = new StateProcessThread(); + obj2.id = "p" + d.processId + "_" + "t" + d.threadId; + obj2.pid = "p" + d.processId; + obj2.title = (d.thread == null || d.thread == "" ? "Thread" : d.thread) + "(" + d.threadId + ")" + obj2.processId = d.processId; + obj2.process = d.process; + obj2.thread = d.thread; + obj2.threadId = d.threadId; + obj2.minDuration = d.dur; + obj2.maxDuration = d.dur; + obj2.count = 1; + obj2.avgDuration = d.dur + ""; + obj2.wallDuration = d.dur; + ptMap.set(d.processId + "_" + d.threadId, obj2); + } + if (ptsMap.has(d.processId + "_" + d.threadId + "_" + d.state)) { + let obj3 = ptsMap.get(d.processId + "_" + d.threadId + "_" + d.state); + obj3!.count++; + obj3!.wallDuration += d.dur; + obj3!.avgDuration = (obj3!.wallDuration / obj3!.count).toFixed(2); + if (d.dur > obj3!.maxDuration) { + obj3!.maxDuration = d.dur; + } + if (d.dur < obj3!.minDuration) { + obj3!.minDuration = d.dur; + } + } else { + let obj3 = new StateProcessThread(); + obj3.id = "p" + d.processId + "_" + "t" + d.threadId + "_" + (d.state == "R+" ? "RP" : d.state) + obj3.pid = "p" + d.processId + "_" + "t" + d.threadId; + obj3.title = Utils.getEndState(d.state) + obj3.processId = d.processId; + obj3.process = d.process; + obj3.thread = d.thread; + obj3.threadId = d.threadId; + obj3.state = d.state; + obj3.minDuration = d.dur; + obj3.maxDuration = d.dur; + obj3.count = 1; + obj3.avgDuration = d.dur + ""; + obj3.wallDuration = d.dur; + ptsMap.set(d.processId + "_" + d.threadId + "_" + d.state, obj3); + } + } + }) + let arr: Array = []; + for (let key of pMap.keys()) { + let s = pMap.get(key); + s!.children = []; + for (let ks of ptMap.keys()) { + if (ks.startsWith(key + "_")) { + let sp = ptMap.get(ks) + sp!.children = []; + for (let kst of ptsMap.keys()) { + if (kst.startsWith(ks + "_")) { + let spt = ptsMap.get(kst) + sp!.children.push(spt!); + } + } + s!.children.push(sp!) + } + } + arr.push(s!) + } + this.tbl!.recycleDataSource = arr; + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + + + + `; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/cpu/TabPaneSPT.ts b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneSPT.ts new file mode 100644 index 0000000000000000000000000000000000000000..3fb17a35111ce64b6b18bd73fb97a77613c94829 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneSPT.ts @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import { + getStatesProcessThreadDataByRange, +} from "../../../../database/SqlLite.js"; +import {SPT, StateProcessThread} from "../../../../bean/StateProcessThread.js"; +import {Utils} from "../../base/Utils.js"; +import {SpSystemTrace} from "../../../SpSystemTrace.js"; + +@element('tabpane-spt') +export class TabPaneSPT extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private loadDataInCache: boolean = true; + private selectionParam:SelectionParam | null | undefined; + + set data(val: SelectionParam | any) { + if(val == this.selectionParam){ + return; + } + this.selectionParam = val; + // @ts-ignore + this.tbl?.shadowRoot?.querySelector(".table").style.height = (this.parentElement!.clientHeight - 45) + "px" + this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" + if (this.loadDataInCache) { + this.getDataBySPT(val.leftNs,val.rightNs,SpSystemTrace.SPT_DATA) + } else { + this.queryDataByDB(val) + } + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-states'); + this.range = this.shadowRoot?.querySelector('#time-range') + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot?.querySelector(".table").style.height = (this.parentElement!.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!) + } + + getDataBySPT(leftNs:number,rightNs:number,source:Array){ + let statesMap: Map = new Map(); + let spMap: Map = new Map(); + let sptMap: Map = new Map(); + source.map((d) => { + if (!(d.end_ts < leftNs || d.start_ts > rightNs)) { + if (statesMap.has(d.state)) { + let obj1 = statesMap.get(d.state); + obj1!.count++; + obj1!.wallDuration += d.dur; + obj1!.avgDuration = (obj1!.wallDuration / obj1!.count).toFixed(2); + if (d.dur > obj1!.maxDuration) { + obj1!.maxDuration = d.dur; + } + if (d.dur < obj1!.minDuration) { + obj1!.minDuration = d.dur; + } + } else { + let obj1 = new StateProcessThread(); + obj1.id = (d.state == "R+" ? "RP" : d.state) + obj1.title = Utils.getEndState(d.state); + obj1.state = d.state; + obj1.minDuration = d.dur; + obj1.maxDuration = d.dur; + obj1.count = 1; + obj1.avgDuration = d.dur + ""; + obj1.wallDuration = d.dur; + statesMap.set(d.state, obj1); + } + if (spMap.has(d.state + "_" + d.processId)) { + let obj2 = spMap.get(d.state + "_" + d.processId); + obj2!.count++; + obj2!.wallDuration += d.dur; + obj2!.avgDuration = (obj2!.wallDuration / obj2!.count).toFixed(2); + if (d.dur > obj2!.maxDuration) { + obj2!.maxDuration = d.dur; + } + if (d.dur < obj2!.minDuration) { + obj2!.minDuration = d.dur; + } + } else { + let obj2 = new StateProcessThread(); + obj2.id = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId; + obj2.pid = (d.state == "R+" ? "RP" : d.state); + obj2.title = (d.process == null || d.process == "" ? "Process" : d.process) + "(" + d.processId + ")" + obj2.processId = d.processId; + obj2.process = d.process; + obj2.state = d.state; + obj2.minDuration = d.dur; + obj2.maxDuration = d.dur; + obj2.count = 1; + obj2.avgDuration = d.dur + ""; + obj2.wallDuration = d.dur; + spMap.set(d.state + "_" + d.processId, obj2); + } + if (sptMap.has(d.state + "_" + d.processId + "_" + d.threadId)) { + let obj3 = sptMap.get(d.state + "_" + d.processId + "_" + d.threadId); + obj3!.count++; + obj3!.wallDuration += d.dur; + obj3!.avgDuration = (obj3!.wallDuration / obj3!.count).toFixed(2); + if (d.dur > obj3!.maxDuration) { + obj3!.maxDuration = d.dur; + } + if (d.dur < obj3!.minDuration) { + obj3!.minDuration = d.dur; + } + } else { + let obj3 = new StateProcessThread(); + obj3.id = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId + "_" + d.threadId + obj3.pid = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId + obj3.title = (d.thread == null || d.thread == "" ? "Thread" : d.thread) + "(" + d.threadId + ")" + obj3.processId = d.processId; + obj3.process = d.process; + obj3.thread = d.thread; + obj3.threadId = d.threadId; + obj3.state = d.state; + obj3.minDuration = d.dur; + obj3.maxDuration = d.dur; + obj3.count = 1; + obj3.avgDuration = d.dur + ""; + obj3.wallDuration = d.dur; + sptMap.set(d.state + "_" + d.processId + "_" + d.threadId, obj3); + } + } + }); + let arr: Array = []; + for (let key of statesMap.keys()) { + let s = statesMap.get(key); + s!.children = []; + for (let ks of spMap.keys()) { + if (ks.startsWith(key + "_")) { + let sp = spMap.get(ks) + sp!.children = []; + for (let kst of sptMap.keys()) { + if (kst.startsWith(ks + "_")) { + let spt = sptMap.get(kst) + sp!.children.push(spt!); + } + } + s!.children.push(sp!) + } + } + arr.push(s!) + } + this.tbl!.recycleDataSource = arr; + } + + queryDataByDB(val: SelectionParam | any) { + getStatesProcessThreadDataByRange(val.leftNs,val.rightNs).then(result => { + this.getDataBySPT(val.leftNs,val.rightNs,result); + }) + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + + + + `; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/cpu/TabPaneThreadSwitch.ts b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneThreadSwitch.ts new file mode 100644 index 0000000000000000000000000000000000000000..d758ea9d4d9605cc810549034bbeb941d5c06500 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/cpu/TabPaneThreadSwitch.ts @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import { + getStatesProcessThreadDataByRange +} from "../../../../database/SqlLite.js"; +import {SPT, StateProcessThread} from "../../../../bean/StateProcessThread.js"; +import {Utils} from "../../base/Utils.js"; +import {SpSystemTrace} from "../../../SpSystemTrace.js"; + +@element('tabpane-thread-switch') +export class TabPaneThreadSwitch extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private loadDataInCache: boolean = true; + private selectionParam:SelectionParam | null | undefined; + + set data(val: SelectionParam | any) { + if(val == this.selectionParam){ + return; + } + this.selectionParam = val; + //@ts-ignore + this.tbl?.shadowRoot?.querySelector(".table")?.style?.height = (this.parentElement!.clientHeight - 45) + "px"; + this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms"; + if (this.loadDataInCache) { + this.getDataBySPT(val.leftNs,val.rightNs,SpSystemTrace.SPT_DATA) + } else { + this.queryDataByDB(val) + } + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-ts'); + this.range = this.shadowRoot?.querySelector('#time-range'); + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot?.querySelector(".table").style.height = (this.parentElement!.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + getDataBySPT(leftNs:number,rightNs:number,source:Array){ + let statesMap: Map = new Map(); + let spMap: Map = new Map(); + let sptMap: Map = new Map(); + source.map((d) => { + if (!(d.end_ts < leftNs || d.start_ts > rightNs)) { + if (statesMap.has(d.state)) { + let obj1 = statesMap.get(d.state); + obj1!.count++; + obj1!.wallDuration += d.dur; + obj1!.avgDuration = (obj1!.wallDuration / obj1!.count).toFixed(2); + if (d.dur > obj1!.maxDuration) { + obj1!.maxDuration = d.dur; + } + if (d.dur < obj1!.minDuration) { + obj1!.minDuration = d.dur; + } + } else { + let obj1 = new StateProcessThread(); + obj1.id = (d.state == "R+" ? "RP" : d.state) + obj1.title = Utils.getEndState(d.state); + obj1.state = d.state; + obj1.minDuration = d.dur; + obj1.maxDuration = d.dur; + obj1.count = 1; + obj1.avgDuration = d.dur + ""; + obj1.wallDuration = d.dur; + statesMap.set(d.state, obj1); + } + if (spMap.has(d.state + "_" + d.processId)) { + let obj2 = spMap.get(d.state + "_" + d.processId); + obj2!.count++; + obj2!.wallDuration += d.dur; + obj2!.avgDuration = (obj2!.wallDuration / obj2!.count).toFixed(2); + if (d.dur > obj2!.maxDuration) { + obj2!.maxDuration = d.dur; + } + if (d.dur < obj2!.minDuration) { + obj2!.minDuration = d.dur; + } + } else { + let obj2 = new StateProcessThread(); + obj2.id = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId; + obj2.pid = (d.state == "R+" ? "RP" : d.state); + obj2.title = (d.process == null || d.process == "" ? "Process" : d.process) + "(" + d.processId + ")" + obj2.processId = d.processId; + obj2.process = d.process; + obj2.state = d.state; + obj2.minDuration = d.dur; + obj2.maxDuration = d.dur; + obj2.count = 1; + obj2.avgDuration = d.dur + ""; + obj2.wallDuration = d.dur; + spMap.set(d.state + "_" + d.processId, obj2); + } + if (sptMap.has(d.state + "_" + d.processId + "_" + d.threadId)) { + let obj3 = sptMap.get(d.state + "_" + d.processId + "_" + d.threadId); + obj3!.count++; + obj3!.wallDuration += d.dur; + obj3!.avgDuration = (obj3!.wallDuration / obj3!.count).toFixed(2); + if (d.dur > obj3!.maxDuration) { + obj3!.maxDuration = d.dur; + } + if (d.dur < obj3!.minDuration) { + obj3!.minDuration = d.dur; + } + } else { + let obj3 = new StateProcessThread(); + obj3.id = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId + "_" + d.threadId + obj3.pid = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId + obj3.title = (d.thread == null || d.thread == "" ? "Thread" : d.thread) + "(" + d.threadId + ")" + obj3.processId = d.processId; + obj3.process = d.process; + obj3.thread = d.thread; + obj3.threadId = d.threadId; + obj3.state = d.state; + obj3.minDuration = d.dur; + obj3.maxDuration = d.dur; + obj3.count = 1; + obj3.avgDuration = d.dur + ""; + obj3.wallDuration = d.dur; + sptMap.set(d.state + "_" + d.processId + "_" + d.threadId, obj3); + } + } + }) + let arr: Array = []; + for (let key of statesMap.keys()) { + let s = statesMap.get(key); + s!.children = []; + for (let ks of spMap.keys()) { + if (ks.startsWith(key + "_")) { + let sp = spMap.get(ks) + sp!.children = []; + for (let kst of sptMap.keys()) { + if (kst.startsWith(ks + "_")) { + let spt = sptMap.get(kst) + sp!.children.push(spt!); + } + } + s!.children.push(sp!) + } + } + arr.push(s!) + } + this.tbl!.recycleDataSource = arr; + } + + queryDataByDB(val: SelectionParam | any) { + getStatesProcessThreadDataByRange(val.leftNs,val.rightNs).then(result => { + this.getDataBySPT(val.leftNs,val.rightNs,result); + }) + } + + initHtml(): string { + return ` + + + + + + + + + `; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/energy/TabPaneEnergyAnomaly.ts b/host/ide/src/trace/component/trace/sheet/energy/TabPaneEnergyAnomaly.ts new file mode 100644 index 0000000000000000000000000000000000000000..968007533d3d836b613b17a3ff2bf4756238267a --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/energy/TabPaneEnergyAnomaly.ts @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {SpHiSysEventChart} from "../../../chart/SpHiSysEventChart.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; + +import { + queryAnomalyDetailedData +} from "../../../../database/SqlLite.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {EnergyAnomalyStruct} from "../../../../database/ui-worker/ProcedureWorkerEnergyAnomaly.js"; + +@element('tabpane-anomaly-details') +export class TabPaneEnergyAnomaly extends BaseElement { + private tbl: LitTable | null | undefined; + private tableObserver: MutationObserver | undefined + private static KEY_INDEX: number = 2; + private static VALUE_INDEX: number = 3; + set data(selection: SelectionParam) { + let div: HTMLElement | null | undefined = this?.shadowRoot?.querySelector("#anomaly-details"); + let htmlText = ""; + if(selection){ + this.queryAnomalyTableData(selection.leftNs, selection.rightNs).then((bean) => { + let filterAppMap = new Map(); + for(let index = 0;index < bean.length;index++){ + let findAppNameIndex = -1; + let values = Object.values(bean[index]); + if(values[TabPaneEnergyAnomaly.VALUE_INDEX]){ + let apps = values[TabPaneEnergyAnomaly.VALUE_INDEX].split(','); + for(let appIndex = 0;appIndex < apps.length;appIndex++){ + if(apps.indexOf(SpHiSysEventChart.app_name) != -1){ + findAppNameIndex = apps.indexOf(SpHiSysEventChart.app_name); + filterAppMap.set(values[0] + values[1], findAppNameIndex); + break; + } + } + if(values[TabPaneEnergyAnomaly.KEY_INDEX] == 'APPNAME'){ + //ts+eventName : appNameIndex + filterAppMap.set(values[0] + values[1], findAppNameIndex); + } + } + } + let set = new Set(); + for(let index = 0;index < bean.length;index++){ + let values = Object.values(bean[index]); + let findAppNameIndex = -1; + if(filterAppMap.get(values[0] + values[1]) == -1){ + continue + }else { + findAppNameIndex = filterAppMap.get(values[0] + values[1]); + } + if(!set.has(values[0])){ + set.add(values[0]); + htmlText += "
" + + ""+values[1]+""; + } + if(set.has(Object.values(bean[index])[0])){ + let appValues = values[TabPaneEnergyAnomaly.VALUE_INDEX].split(','); + htmlText += ""+values[TabPaneEnergyAnomaly.KEY_INDEX] + +""+ + (findAppNameIndex >= 0 ? appValues.length > 1 ? appValues[findAppNameIndex] : values[TabPaneEnergyAnomaly.VALUE_INDEX] : values[TabPaneEnergyAnomaly.VALUE_INDEX]) + + TabPaneEnergyAnomaly.getUnit(values[TabPaneEnergyAnomaly.KEY_INDEX]) + +""; + } + if(index + 1 < bean.length){ + let nextValues = Object.values(bean[index + 1]); + let appValues = nextValues[TabPaneEnergyAnomaly.VALUE_INDEX].split(','); + if(set.has(nextValues[0])){ + htmlText += "" + nextValues[TabPaneEnergyAnomaly.KEY_INDEX] + + "" + + (findAppNameIndex >= 0 ? appValues.length > 1 ? appValues[findAppNameIndex] : nextValues[TabPaneEnergyAnomaly.VALUE_INDEX] : nextValues[TabPaneEnergyAnomaly.VALUE_INDEX]) + + TabPaneEnergyAnomaly.getUnit(nextValues[TabPaneEnergyAnomaly.KEY_INDEX]) + +""; + } else { + htmlText += ""; + htmlText += "
"; + continue; + } + index++; + } + } + div!.innerHTML = htmlText; + }) + } + } + + static getUnit(value: any) { + if(value == "DURATION"){ + return " ms"; + } else if(value == "ENERGY" || value == "BGENERGY" || value == "BATTERY_GAS_GUAGE"){ + return " mAh"; + } else if(value == "BGUSAGE"){ + return " s"; + } + return ""; + } + + /** + * 查询出 异常详细信息 + * @param data + */ + async queryAnomalyTableData(startTime: number, endTime: number) : Promise> { + let anomalyTableData = await queryAnomalyDetailedData(startTime, endTime) + return anomalyTableData; + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#anomalyselectionTbl'); + this.tbl?.addEventListener("column-click", (ev: any) => { + }) + this.addTableObserver() + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl!.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl!.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + addTableObserver() { + let MutationObserver = window.MutationObserver + this.tableObserver = new MutationObserver((list) => { + if (this.tbl) { + let width = getComputedStyle(this.tbl).getPropertyValue("width") + let height = getComputedStyle(this.tbl).getPropertyValue("height") + } + }) + let selector = this.shadowRoot?.querySelector(".left-table"); + this.tableObserver?.observe(selector!, {attributes: true, attributeFilter: ['style'], attributeOldValue: true}) + } + + initHtml(): string { + return ` + +
+
+

+
+
+
+ + + + + + +
+
+
+ `; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/energy/TabPanePowerBattery.ts b/host/ide/src/trace/component/trace/sheet/energy/TabPanePowerBattery.ts new file mode 100644 index 0000000000000000000000000000000000000000..6fd9b628664672a7680375ad535356c16732326d --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/energy/TabPanePowerBattery.ts @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabPowerBatteryData} from "../../../../database/SqlLite.js"; +import {SpHiSysEventChart} from "../../../chart/SpHiSysEventChart.js"; +import "../../../../../base-ui/table/lit-table.js"; + +@element('tabpane-power-battery') +export class TabPanePowerBattery extends BaseElement { + private tbl: LitTable | null | undefined; + + set data(val: SelectionParam | any) { + this.queryDataByDB(val) + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl!.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl!.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-power-battery-energy'); + } + + queryDataByDB(val: SelectionParam | any) { + getTabPowerBatteryData(val.rightNs).then(result => { + let list: Array = [] + let powerData: any = { + "POWER_IDE_BATTERY": { + gas_gauge: [], + charge: [], + screen: [], + level: [], + current: [], + capacity: [], + appName: "", + uid: [], + } + } + result.forEach(item => { + let powerDatum: any = powerData[item.eventName]; + if (item.appKey.toLocaleLowerCase() === "appname") { + powerDatum['appName'] = SpHiSysEventChart.app_name + } else { + let eventData: Array = item.eventValue.split(","); + if (eventData.length > 0) { + let i = eventData.length - 1 >= 0 ? eventData.length - 1 : 0 + powerDatum[item.appKey.toLocaleLowerCase()] = eventData[i] + } else { + powerDatum[item.appKey.toLocaleLowerCase()] = eventData.toString() + } + } + }) + list.push({name: 'Gas Gauge', value: powerData["POWER_IDE_BATTERY"].gas_gauge + " mAh"}) + list.push({name: 'Charge', value: powerData["POWER_IDE_BATTERY"].charge}) + list.push({name: 'Screen', value: powerData["POWER_IDE_BATTERY"].screen}) + list.push({name: 'Level', value: powerData["POWER_IDE_BATTERY"].level + " %"}) + list.push({name: 'Current', value: powerData["POWER_IDE_BATTERY"].current+ " mA"} ) + list.push({name: 'Capacity', value: powerData["POWER_IDE_BATTERY"].capacity + " mAh"}) + list.push({name: 'APP Name', value: SpHiSysEventChart.app_name!}) + if (list.length > 0) { + this.tbl!.recycleDataSource = list + } else { + this.tbl!.recycleDataSource = [] + } + this.tbl?.shadowRoot?.querySelectorAll(".tr").forEach(tr => { + let td = tr.querySelectorAll(".td"); + this.setTableStyle(td[0], "0.9", "16px") + this.setTableStyle(td[1], "0.6", "20px") + + }) + }) + } + + setTableStyle(td: HTMLDivElement, opacity: string, lineHeight: string) { + td.style.fontWeight = "400" + td.style.fontSize = "14px" + td.style.opacity = opacity + td.style.lineHeight = lineHeight + } + + initHtml(): string { + return ` + +
+
+
+ + + + +
+
+
+ `; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/energy/TabPanePowerDetails.ts b/host/ide/src/trace/component/trace/sheet/energy/TabPanePowerDetails.ts new file mode 100644 index 0000000000000000000000000000000000000000..39301ffa80ea3010c1493f297f368e16bf08a845 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/energy/TabPanePowerDetails.ts @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabPowerDetailsData} from "../../../../database/SqlLite.js"; +import {log} from "../../../../../log/Log.js"; +import {PowerDetailsEnergy} from "../../../../bean/EnergyStruct.js"; +import {SpHiSysEventChart} from "../../../chart/SpHiSysEventChart.js"; + +@element('tabpane-power-details') +export class TabPanePowerDetails extends BaseElement { + private tbl: LitTable | null | undefined; + private source: Array = []; + private itemType: any + + set data(val: SelectionParam | any) { + this.queryDataByDB(val) + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl!.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl!.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-power-details-energy'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail) + }); + this.source = [] + this.itemType = { + "time_type": ["foreground_duration", "background_duration", "screen_on_duration", "screen_off_duration", + "foreground_count", "background_count", "screen_on_count", "screen_off_count", "duration", "energy", + "usage", "camera_id"], + "duration_type": ["background_time", "screen_on_time", "screen_off_time", "load", "uid", "usage", "charge", + "foreground_count", "background_count", "screen_on_count", "screen_off_count", "energy", "duration"], + "energy_type": ["background_time", "screen_on_time", "screen_off_time", "load", "charge", + "foreground_count", "background_count", "screen_on_count", "screen_off_count", "camera_id", "uid", + "foreground_duration", "foreground_energy", "background_duration", "background_energy", + "screen_on_duration", "screen_on_energy", "screen_off_duration", "screen_off_energy"], + "count_type": ["background_time", "screen_on_time", "screen_off_time", "load", "energy", "usage", + "foreground_duration", "background_duration", "screen_on_duration", "screen_off_duration", + "camera_id", "uid", "duration", "charge"] + } + } + + queryDataByDB(val: SelectionParam | any) { + getTabPowerDetailsData(val.leftNs - val.leftNs, val.rightNs).then(items => { + log("getTabPowerDetailsData size :" + items.length); + let detailsData: Array = [] + let set = new Set() + set.add("COUNT") + set.add("LOAD") + set.add("CHARGE") + set.add("CAMERA_ID") + + let powerData: any = { + "POWER_IDE_CPU": new PowerDetailsEnergy("CPU"), + "POWER_IDE_LOCATION": new PowerDetailsEnergy("LOCATION"), + "POWER_IDE_GPU": new PowerDetailsEnergy("GPU"), + "POWER_IDE_DISPLAY": new PowerDetailsEnergy("DISPLAY"), + "POWER_IDE_CAMERA": new PowerDetailsEnergy("CAMERA"), + "POWER_IDE_BLUETOOTH": new PowerDetailsEnergy("BLUETOOTH"), + "POWER_IDE_FLASHLIGHT": new PowerDetailsEnergy("FLASHLIGHT"), + "POWER_IDE_AUDIO": new PowerDetailsEnergy("AUDIO"), + "POWER_IDE_WIFISCAN": new PowerDetailsEnergy("WIFISCAN") + }; + let tsMax = 0 + let currentAppIndex = -1 + items.forEach(item => { + let powerDatum: any = powerData[item.eventName]; + if (item.appKey.toLocaleLowerCase() === "appname") { + powerDatum['appName'] = SpHiSysEventChart.app_name + currentAppIndex = item.eventValue.split(",").indexOf(SpHiSysEventChart.app_name!); + tsMax = 0 + } else if (currentAppIndex > -1) { + if (set.has(item.appKey)) { + if (item.startNS >= tsMax) { + powerDatum[item.appKey.toLocaleLowerCase()] = item.eventValue + tsMax = item.startNS + } + } else { + powerDatum[item.appKey.toLocaleLowerCase()] += parseInt(item.eventValue.split(",")[currentAppIndex]) + } + } + }) + + let totalEnergy = powerData["POWER_IDE_CPU"].getTotalEnergy(false) + + powerData["POWER_IDE_LOCATION"].getTotalEnergy(false) + + powerData["POWER_IDE_GPU"].getTotalEnergy(true) + + powerData["POWER_IDE_DISPLAY"].getTotalEnergy(true) + + powerData["POWER_IDE_CAMERA"].getTotalEnergy(false) + + powerData["POWER_IDE_BLUETOOTH"].getTotalEnergy(false) + + powerData["POWER_IDE_FLASHLIGHT"].getTotalEnergy(false) + + powerData["POWER_IDE_AUDIO"].getTotalEnergy(false) + + powerData["POWER_IDE_WIFISCAN"].getTotalEnergy(false) + + detailsData.push(this.setEnergyItems(powerData, totalEnergy, "POWER_IDE_CPU", false, "time_type")) + detailsData.push(this.setEnergyItems(powerData, totalEnergy, "POWER_IDE_LOCATION", false, "duration_type")) + detailsData.push(this.setEnergyItems(powerData, totalEnergy, "POWER_IDE_GPU", true, "energy_type")) + detailsData.push(this.setEnergyItems(powerData, totalEnergy, "POWER_IDE_DISPLAY", true, "energy_type")) + detailsData.push(this.setEnergyItems(powerData, totalEnergy, "POWER_IDE_CAMERA", false, "duration_type")) + detailsData.push(this.setEnergyItems(powerData, totalEnergy, "POWER_IDE_BLUETOOTH", false, "duration_type")) + detailsData.push(this.setEnergyItems(powerData, totalEnergy, "POWER_IDE_FLASHLIGHT", false, "duration_type")) + detailsData.push(this.setEnergyItems(powerData, totalEnergy, "POWER_IDE_AUDIO", false, "duration_type")) + detailsData.push(this.setEnergyItems(powerData, totalEnergy, "POWER_IDE_WIFISCAN", false, "count_type")) + + if (detailsData.length > 0) { + this.source = detailsData + this.tbl!.recycleDataSource = detailsData + } else { + this.source = [] + this.tbl!.recycleDataSource = [] + } + this.tbl?.shadowRoot?.querySelectorAll(".td").forEach(td => { + td.style.fontSize = "14px" + td.style.fontWeight = "400" + td.style.opacity = '0.9' + td.style.lineHeight = "16px" + }) + }) + let th = this.tbl?.shadowRoot?.querySelector(".th") + if (th) { + th!.style.gridColumnGap = "5px"; + } + } + + setEnergyItems(powerData: any, totalEnergy: number, energyName: string, isSimpleEnergy: boolean, type: any): any { + let ratio = powerData[energyName] + .getTotalEnergy(isSimpleEnergy) * 100 / totalEnergy + if (totalEnergy == 0) { + powerData[energyName].energyConsumptionRatio = "0.000 %" + } else { + powerData[energyName].energyConsumptionRatio = ratio.toFixed(3) + " %" + } + return this.getEnergyStyle(powerData, energyName, type) + } + + getEnergyStyle(powerData: any, energyName: string, type: any) { + this.itemType[type].forEach((item: any) => { + powerData[energyName][item] = "-" + }) + if (type === "energy_type") { + if (energyName == "POWER_IDE_GPU") { + powerData[energyName]["duration"] = "-" + } else { + powerData[energyName]["usage"] = "-" + } + } else if (type === "duration_type") { + if (energyName != "POWER_IDE_CAMERA") { + powerData[energyName]["camera_id"] = "-" + } + } + return powerData[energyName] + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `; + } + + sortByColumn(detail: any) { + // @ts-ignore + function compare(property, sort, type) { + return function (a: PowerDetailsEnergy, b: PowerDetailsEnergy) { + if (type === 'number') { + // @ts-ignore + return sort === 2 ? parseFloat(b[property] == "-" ? 0 : b[property]) - parseFloat(a[property] == "-" ? 0 : a[property]) : parseFloat(a[property] == "-" ? 0 : a[property]) - parseFloat(b[property] == "-" ? 0 : b[property]); + } else { + // @ts-ignore + if (b[property] > a[property]) { + return sort === 2 ? 1 : -1; + } else { // @ts-ignore + if (b[property] == a[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + } + } + + if (detail.key === 'appName') { + this.source.sort(compare(detail.key, detail.sort, 'string')) + } else { + this.source.sort(compare(detail.key, detail.sort, 'number')) + } + this.tbl!.recycleDataSource = this.source; + + this.tbl?.shadowRoot?.querySelectorAll(".td").forEach(td => { + td.style.fontSize = "14px" + td.style.fontWeight = "400" + td.style.opacity = '0.9' + td.style.lineHeight = "16px" + }) + } +} diff --git a/host/ide/src/trace/component/trace/sheet/energy/TabPaneSystemDetails.ts b/host/ide/src/trace/component/trace/sheet/energy/TabPaneSystemDetails.ts new file mode 100644 index 0000000000000000000000000000000000000000..0d163e01da82ac07751001c07026492c8681e317 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/energy/TabPaneSystemDetails.ts @@ -0,0 +1,363 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SystemDetailsEnergy} from "../../../../bean/EnergyStruct.js"; +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import { + querySysLocationDetailsData, querySysLockDetailsData, + querySystemWorkData +} from "../../../../database/SqlLite.js"; +import {SpHiSysEventChart} from "../../../chart/SpHiSysEventChart.js"; + +@element('tabpane-system-details') +export class TabPaneSystemDetails extends BaseElement { + private tbl: LitTable | null | undefined; + private detailsTbl: LitTable | null | undefined; + private eventSource: Array = []; + private detailsSource: Array = [] + private boxDetails: HTMLDivElement | null | undefined; + + set data(val: SelectionParam | any) { + this.queryDataByDB(val) + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl!.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl!.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + initElements(): void { + this.boxDetails = this.shadowRoot?.querySelector('.box-details'); + this.tbl = this.shadowRoot?.querySelector('#tb-system-data'); + this.detailsTbl = this.shadowRoot?.querySelector('#tb-system-details-data'); + + this.tbl!.addEventListener('row-click', (e) => { + this.detailsSource = [] + // @ts-ignore + let data = (e.detail.data as SystemDetailsEnergy) + this.convertData(data); + }) + + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail.key, evt.detail.sort) + }); + } + + convertData(data: SystemDetailsEnergy) { + if (data.eventName === "Event Name") { + this.detailsTbl!.recycleDataSource = [] + this.boxDetails!.style.width = "100%" + } else { + this.detailsSource.push({key: "EVENT_NAME : ", value: data.eventName}) + this.detailsSource.push({key: "PID : ", value: data.pid}) + this.detailsSource.push({key: "UID : ", value: data.uid}) + if (data.eventName === "GNSS_STATE") { + this.detailsSource.push({key: "STATE : ", value: data.state}) + } else if (data.eventName === "POWER_RUNNINGLOCK") { + this.detailsSource.push({key: "TYPE : ", value: data.type}) + this.detailsSource.push({key: "STATE : ", value: data.state}) + this.detailsSource.push({key: "LOG_LEVEL : ", value: data.log_level}) + this.detailsSource.push({key: "NAME : ", value: data.name}) + this.detailsSource.push({key: "MESSAGE : ", value: data.message}) + this.detailsSource.push({key: "TAG : ", value: data.tag}) + } else { + this.detailsSource.push({key: "TYPE : ", value: data.type}) + this.detailsSource.push({key: "WORK_ID : ", value: data.workId}) + this.detailsSource.push({key: "NAME : ", value: data.name}) + this.detailsSource.push({key: "INTERVAL : ", value: data.interval}) + } + this.detailsTbl!.recycleDataSource = this.detailsSource + this.boxDetails!.style.width = "65%" + } + this.detailsTbl!.shadowRoot?.querySelectorAll(".td").forEach(td => { + let item = td.getAttribute("title"); + td.style.fontSize = "14px" + td.style.fontWeight = "400" + if (item != null && item.indexOf(":") > -1) { + td.style.opacity = "0.9" + td.style.lineHeight = "16px" + } else { + td.style.opacity = "0.6" + td.style.lineHeight = "20px" + } + }) + } + + queryDataByDB(val: SelectionParam | any) { + Promise.all([querySystemWorkData(val.rightNs), querySysLockDetailsData(val.rightNs, "POWER_RUNNINGLOCK"), querySysLocationDetailsData(val.rightNs, "GNSS_STATE")]).then(result => { + let itemList: Array = [] + let systemWorkData = this.getSystemWorkData(result[0], val.leftNs, val.rightNs); + if (systemWorkData.length > 0) { + systemWorkData.forEach(item => { + itemList.push(item) + }) + } + let systemLockData = this.getSystemLockData(result[1], val.leftNs); + if (systemLockData.length > 0) { + systemLockData.forEach(item => { + itemList.push(item) + }) + } + let systemLocationData = this.getSystemLocationData(result[2], val.leftNs); + if (systemLocationData.length > 0) { + systemLocationData.forEach(item => { + itemList.push(item) + }) + } + itemList.sort((leftData: any, rightData: any) => { + return leftData.ts - rightData.ts + }) + this.eventSource = [] + this.eventSource.push({ + ts: "Time", + interval: 0, + level: 0, + name: "", + state: 0, + tag: "", + type: "", + uid: 0, + pid: 0, + workId: "", + message: "", + log_level: "", + eventName: "Event Name" + }) + + this.tbl!.recycleDataSource = this.eventSource.concat(itemList) + this.detailsTbl!.recycleDataSource = [] + this.boxDetails!.style.width = "100%" + this.tbl?.shadowRoot?.querySelectorAll(".td").forEach(td => { + td.style.fontSize = "14px" + if (td.getAttribute("title") === "Event Name" || td.getAttribute("title") === "Time") { + td.style.fontWeight = "700" + } else { + td.style.fontWeight = "400" + td.style.opacity = '0.9' + td.style.lineHeight = "16px" + } + }) + }) + } + + private getSystemWorkData(data: Array, leftNs: number, rightNs: number) { + let values = this.getConvertData(data) + let lifeCycleData: Array = [] + let watchIndex: Array = [] + for (let index = 0; index < values.length; index++) { + let filterData: any = values[index]; + if (filterData.name == SpHiSysEventChart.app_name) { + if (filterData.eventName.indexOf("WORK_ADD") > -1) { + watchIndex.push(filterData.workId) + let number = watchIndex.indexOf(filterData.workId) + lifeCycleData[number] = { + startData: {}, + endData: {}, + rangeData: [] + } + lifeCycleData[number].startData = filterData + let virtualEndData = JSON.parse(JSON.stringify(filterData)) + virtualEndData.ts = rightNs + virtualEndData.eventName = "WORK_REMOVE" + lifeCycleData[number].endData = virtualEndData + } else if (filterData.eventName.indexOf("WORK_REMOVE") > -1) { + let number = watchIndex.indexOf(filterData.workId); + if (number > -1) { + lifeCycleData[number].endData = filterData + watchIndex[number] = number + filterData.ts + } + } else { + let number = watchIndex.indexOf(filterData.workId); + if (number > -1) { + lifeCycleData[number].rangeData.push(filterData) + let virtualEndData = JSON.parse(JSON.stringify(filterData)) + virtualEndData.ts = rightNs + virtualEndData.eventName = "WORK_REMOVE" + lifeCycleData[number].endData = virtualEndData + } else { + if (filterData.eventName.indexOf("WORK_START") > -1) { + lifeCycleData.push({ + startData: {}, + endData: {}, + rangeData: [] + }) + watchIndex.push(filterData.workId) + number = watchIndex.indexOf(filterData.workId); + let virtualData = JSON.parse(JSON.stringify(filterData)) + if (filterData.ts > 0) { + virtualData.ts = 0 + } else { + virtualData.ts = filterData.ts - 1 + } + virtualData.eventName = "WORK_ADD" + lifeCycleData[number].startData = virtualData + lifeCycleData[number].rangeData.push(filterData) + let virtualEndData = JSON.parse(JSON.stringify(filterData)) + virtualEndData.ts = rightNs + virtualEndData.eventName = "WORK_REMOVE" + lifeCycleData[number].endData = virtualEndData + } + } + } + } + } + let resultData: Array = [] + lifeCycleData.forEach((life: any) => { + if (life.endData.ts >= leftNs) { + let midData = life.rangeData; + midData.forEach((rang: any, index: number) => { + if (rang.eventName.indexOf("WORK_STOP") > -1 && rang.ts >= leftNs) { + resultData.push(life.startData) + if (index - 1 >= 0 && midData[index - 1].eventName.indexOf("WORK_START") > -1) { + resultData.push(midData[index - 1]) + } + resultData.push(rang) + } + }) + } + }) + return resultData + } + + private getSystemLocationData(data: Array, leftNs: number) { + let values = this.getConvertData(data) + let fillMap: Map = new Map() + let leftMap: Map = new Map() + let watchIndex: Array = [] + for (let index = 0; index < values.length; index++) { + let filterData: any = values[index]; + if (filterData.state.indexOf("start") > -1) { + leftMap.set(filterData.pid, filterData) + watchIndex.push(filterData.pid) + } else { + let i = watchIndex.indexOf(filterData.pid); + if (i > -1) { + fillMap.set(leftMap.get(filterData.pid), filterData) + delete watchIndex[i] + leftMap.delete(filterData.pid) + } + } + } + + let locationData: Array = [] + fillMap.forEach((value, key) => { + if (value.ts >= leftNs) { + locationData.push(key) + locationData.push(value) + } + }) + leftMap.forEach((value, key) => { + locationData.push(value) + }) + return locationData + } + + private getSystemLockData(data: Array, leftNs: number) { + let values = this.getConvertData(data) + let watchIndex: Array = [] + let fillMap: Map = new Map() + let leftMap: Map = new Map() + for (let index = 0; index < values.length; index++) { + let filterData: any = values[index]; + if (filterData.tag.indexOf("ADD") > -1) { + leftMap.set(filterData.message, filterData) + watchIndex.push(filterData.message) + } else { + let i = watchIndex.indexOf(filterData.message); + if (i > -1) { + fillMap.set(leftMap.get(filterData.message), filterData) + delete watchIndex[i] + leftMap.delete(filterData.message) + } + } + } + let lockData: Array = [] + fillMap.forEach((value, key) => { + if (value.ts >= leftNs) { + lockData.push(key) + lockData.push(value) + } + }) + leftMap.forEach((value, key) => { + lockData.push(value) + }) + return lockData + } + + private getConvertData(data: Array) { + let it: any = {} + data.forEach((item: any) => { + if (it[item.ts + item.eventName] == undefined) { + it[item.ts + item.eventName] = {} + it[item.ts + item.eventName]["ts"] = item.ts + it[item.ts + item.eventName]["eventName"] = item.eventName + it[item.ts + item.eventName][item.appKey.toLocaleLowerCase()] = item.appValue + } else { + it[item.ts + item.eventName][item.appKey.toLocaleLowerCase()] = item.appValue + } + }) + return Object.values(it); + } + + initHtml(): string { + return ` + +
+
+ +
+ + + + + + +
+ + + + + + + +
+
+ +
+ `; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/file-system/TabPaneCallTree.ts b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneCallTree.ts new file mode 100644 index 0000000000000000000000000000000000000000..b8c4e222d6c273f319e1856fe1d951b2472fe6fb --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneCallTree.ts @@ -0,0 +1,629 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {FrameChart} from "../../../chart/FrameChart.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {ChartMode} from "../../../../bean/FrameChartStruct.js"; +import {FilterData, TabPaneFilter} from "../TabPaneFilter.js"; +import {procedurePool} from "../../../../database/Procedure.js"; +import {MerageBean} from "../../../../database/logic-worker/ProcedureLogicWorkerCommon.js"; + +@element('tabpane-calltree') +export class TabPaneCallTree extends BaseElement { + public queryFuncName:string = "" + public procedureAction:string = "" + private tbl: LitTable | null | undefined; + private tbr: LitTable | null | undefined; + private progressEL:LitProgressBar | null | undefined; + private rightSource: Array = []; + private filter: any + private dataSource: any[] = [] + private sortKey = "weight"; + private sortType = 0; + private currentSelectedData: any = undefined + private frameChart: FrameChart | null | undefined; + private isChartShow: boolean = false; + private systmeRuleName = "/system/" + private numRuleName = "/max/min/" + private needShowMenu = true; + private searchValue: string = "" + private loadingList:number[] = [] + private loadingPage:any; + private currentSelection:SelectionParam|undefined + private flameChartMode:ChartMode = ChartMode.Duration + + set data(val: SelectionParam | any) { + if(val == this.currentSelection){ + return; + } + this.searchValue = ""; + this.initModeAndAction() + this.currentSelection = val + this.tbl!.style.visibility = "visible"; + if (this.parentElement!.clientHeight > this.filter!.clientHeight) { + this.filter!.style.display = "flex"; + } else { + this.filter!.style.display = "none"; + } + this.filter!.initializeFilterTree(true, true, true) + this.filter!.filterValue = "" + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + this.getDataByWorker([{ + funcName: "setSearchValue", + funcArgs: [""] + }, { + funcName: "getCurrentDataFromDb", + funcArgs: [{queryFuncName:this.queryFuncName,...val}] + }], (results: any[]) => { + this.setLTableData(results) + this.tbr!.recycleDataSource = [] + this.frameChart!.mode = this.flameChartMode; + this.frameChart!.data = this.dataSource; + this.frameChart?.updateCanvas(true, this.clientWidth); + this.frameChart?.calculateChartData(); + }) + } + + initModeAndAction(){ + if (this.procedureAction == ""&&this.hasAttribute("action")) { + this.procedureAction = this.getAttribute("action")||"" + } + if(this.hasAttribute("flame-mode")){ + let mode = this.getAttribute("flame-mode") + switch (mode){ + case "Call": + this.flameChartMode = ChartMode.Call + break; + case "Byte": + this.flameChartMode = ChartMode.Byte + break; + case "Count": + this.flameChartMode = ChartMode.Count + break; + case "Duration": + this.flameChartMode = ChartMode.Duration + break; + } + } + if(this.hasAttribute("query")){ + this.queryFuncName = this.getAttribute("query")||"" + } + } + + getParentTree(src: Array, target: MerageBean, parents: Array): boolean { + for (let call of src) { + if (call.id == target.id) { + parents.push(call) + return true + } else { + if (this.getParentTree(call.children as Array, target, parents)) { + parents.push(call); + return true; + } + } + } + return false; + } + + getChildTree(src: Array, id: string, children: Array): boolean { + for (let call of src) { + if (call.id == id && call.children.length == 0) { + children.push(call) + return true + } else { + if (this.getChildTree(call.children as Array, id, children)) { + children.push(call); + return true; + } + } + } + return false; + } + + setRightTableData(call: MerageBean) { + let parents: Array = []; + let children: Array = []; + this.getParentTree(this.dataSource, call, parents); + let maxId = call.id; + let maxDur = 0; + + function findMaxStack(call: MerageBean) { + if (call.children.length == 0) { + if (call.dur > maxDur) { + maxDur = call.dur; + maxId = call.id; + } + } else { + call.children.map((callChild:any) => { + findMaxStack(callChild); + }) + } + } + + findMaxStack(call); + this.getChildTree(call.children as Array, maxId, children); + let arr = parents.reverse().concat(children.reverse()); + for (let data of arr) { + data.type = (data.libName.endsWith(".so.1") || data.libName.endsWith(".dll") || data.libName.endsWith(".so")) ? 0 : 1; + } + let len = arr.length; + this.rightSource = arr; + this.tbr!.dataSource = len == 0 ? [] : arr + } + + showButtomMenu(isShow: boolean) { + if (isShow) { + this.filter.setAttribute('tree', ''); + this.filter.setAttribute('input', ''); + this.filter.setAttribute('inputLeftText', ''); + } else { + this.filter.removeAttribute('tree'); + this.filter.removeAttribute('input'); + this.filter.removeAttribute('inputLeftText') + } + } + + connectedCallback() { + this.parentElement!.onscroll = () => { + this.frameChart!.tabPaneScrollTop = this.parentElement!.scrollTop; + }; + this.frameChart!.addChartClickListener((needShowMenu: boolean) => { + this.parentElement!.scrollTo(0, 0); + this.showButtomMenu(needShowMenu) + this.needShowMenu = needShowMenu; + }); + let filterHeight = 0; + new ResizeObserver((entries) => { + let tabPaneFilter = this.shadowRoot!.querySelector("#filter") as HTMLElement; + if (tabPaneFilter.clientHeight > 0) filterHeight = tabPaneFilter.clientHeight; + if (this.parentElement!.clientHeight > filterHeight) { + tabPaneFilter.style.display = "flex"; + } else { + tabPaneFilter.style.display = "none"; + } + if (this.tbl!.style.visibility == "hidden") { + tabPaneFilter.style.display = "none"; + } + if (this.parentElement?.clientHeight != 0) { + if (this.isChartShow) { + this.frameChart?.updateCanvas(false, entries[0].contentRect.width); + this.frameChart?.calculateChartData(); + } + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 10 - 35) + "px" + this.tbl?.reMeauseHeight() + // @ts-ignore + this.tbr?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45 - 21) + "px" + this.tbr?.reMeauseHeight() + this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px" + } + }).observe(this.parentElement!) + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-calltree'); + this.progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar + this.frameChart = this.shadowRoot?.querySelector('#framechart'); + this.loadingPage = this.shadowRoot?.querySelector('.loading'); + + this.tbl!.rememberScrollTop = true; + this.filter = this.shadowRoot?.querySelector("#filter") + this.tbl!.addEventListener('row-click', (evt: any) => { + // @ts-ignore + let data = (evt.detail.data as MerageBean); + this.setRightTableData(data); + data.isSelected = true; + this.currentSelectedData = data; + this.tbr?.clearAllSelection(data); + this.tbr?.setCurrentSelection(data); + // @ts-ignore + if ((evt.detail as any).callBack) { + // @ts-ignore + (evt.detail as any).callBack(true) + } + }) + this.tbr = this.shadowRoot?.querySelector('#tb-list'); + this.tbr!.addEventListener('row-click', (evt: any) => { + // @ts-ignore + let data = (evt.detail.data as MerageBean); + this.tbl?.clearAllSelection(data); + (data as any).isSelected = true + this.tbl!.scrollToData(data) + // @ts-ignore + if ((evt.detail as any).callBack) { + // @ts-ignore + (evt.detail as any).callBack(true) + } + }) + let filterFunc = (data: any) => { + let args: any[] = [] + if (data.type == "check") { + if (data.item.checked) { + args.push({ + funcName: "splitTree", + funcArgs: [data.item.name, data.item.select == "0", data.item.type == "symbol"] + }) + } else { + args.push({ + funcName: "resotreAllNode", + funcArgs: [[data.item.name]] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + args.push({ + funcName: "clearSplitMapData", + funcArgs: [data.item.name] + }) + } + } else if (data.type == "select") { + args.push({ + funcName: "resotreAllNode", + funcArgs: [[data.item.name]] + }) + args.push({ + funcName: "clearSplitMapData", + funcArgs: [data.item.name] + }) + args.push({ + funcName: "splitTree", + funcArgs: [data.item.name, data.item.select == "0", data.item.type == "symbol"] + }) + } else if (data.type == "button") { + if (data.item == "symbol") { + if (this.currentSelectedData && !this.currentSelectedData.canCharge) { + return + } + if (this.currentSelectedData != undefined) { + this.filter!.addDataMining({name: this.currentSelectedData.symbolName}, data.item) + args.push({ + funcName: "splitTree", + funcArgs: [this.currentSelectedData.symbolName, false, true] + }) + } else { + return + } + } else if (data.item == "library") { + if (this.currentSelectedData && !this.currentSelectedData.canCharge) { + return + } + if (this.currentSelectedData != undefined && this.currentSelectedData.libName != "") { + this.filter!.addDataMining({name: this.currentSelectedData.libName}, data.item) + args.push({ + funcName: "splitTree", + funcArgs: [this.currentSelectedData.libName, false, false] + }) + } else { + return + } + } else if (data.item == "restore") { + if (data.remove != undefined && data.remove.length > 0) { + let list = data.remove.map((item: any) => { + return item.name + }) + args.push({ + funcName: "resotreAllNode", + funcArgs: [list] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + list.forEach((symbolName: string) => { + args.push({ + funcName: "clearSplitMapData", + funcArgs: [symbolName] + }) + }) + } + } + } + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + if (this.isChartShow) this.frameChart?.calculateChartData(); + this.tbl!.move1px() + if (this.currentSelectedData) { + this.currentSelectedData.isSelected = false; + this.tbl?.clearAllSelection(this.currentSelectedData) + this.tbr!.recycleDataSource = [] + this.currentSelectedData = undefined + } + }) + } + this.filter!.getDataLibrary(filterFunc) + this.filter!.getDataMining(filterFunc) + this.filter!.getCallTreeData((data: any) => { + if (data.value == 0) { + this.refreshAllNode({...this.filter!.getFilterTreeData(), callTree: data.checks}) + } else { + let args: any[] = [] + if (data.checks[1]) { + args.push({ + funcName: "hideSystemLibrary", + funcArgs: [] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + } else { + args.push({ + funcName: "resotreAllNode", + funcArgs: [[this.systmeRuleName]] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + args.push({ + funcName: "clearSplitMapData", + funcArgs: [this.systmeRuleName] + }) + } + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + if (this.isChartShow) this.frameChart?.calculateChartData(); + }) + + } + }) + this.filter!.getCallTreeConstraintsData((data: any) => { + let args: any[] = [{ + funcName: "resotreAllNode", + funcArgs: [[this.numRuleName]] + }, { + funcName: "clearSplitMapData", + funcArgs: [this.numRuleName] + }] + if (data.checked) { + args.push({ + funcName: "hideNumMaxAndMin", + funcArgs: [parseInt(data.min), data.max] + }) + } + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + if (this.isChartShow) this.frameChart?.calculateChartData(); + }) + + }) + this.filter!.getFilterData((data: FilterData) => { + if (this.searchValue != this.filter!.filterValue) { + this.searchValue = this.filter!.filterValue + let args = [ + { + funcName: "setSearchValue", + funcArgs: [this.searchValue] + }, + { + funcName: "resetAllNode", + funcArgs: [] + } + ] + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + this.switchFlameChart(data) + }) + }else { + this.switchFlameChart(data) + } + + }) + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key + // @ts-ignore + this.sortType = evt.detail.sort + // @ts-ignore + this.setLTableData(this.dataSource) + this.frameChart!.data = this.dataSource; + }); + } + + switchFlameChart(data:any){ + let pageTab = this.shadowRoot?.querySelector('#show_table'); + let pageChart = this.shadowRoot?.querySelector('#show_chart'); + if (data.icon == 'block') { + pageChart?.setAttribute('class', 'show'); + pageTab?.setAttribute('class', ''); + this.isChartShow = true; + this.filter!.disabledMining = true; + this.showButtomMenu(this.needShowMenu); + this.frameChart!.data = this.dataSource; + this.frameChart?.calculateChartData(); + } else if (data.icon == 'tree') { + pageChart?.setAttribute('class', ''); + pageTab?.setAttribute('class', 'show'); + this.showButtomMenu(true); + this.isChartShow = false; + this.filter!.disabledMining = false; + this.frameChart!.clearCanvas(); + this.tbl!.reMeauseHeight() + } + } + + + refreshAllNode(filterData: any) { + let args:any[] = [] + let isTopDown: boolean = !filterData.callTree[0]; + let isHideSystemLibrary = filterData.callTree[1]; + let list = filterData.dataMining.concat(filterData.dataLibrary); + args.push({ + funcName: "getCallChainsBySampleIds", + funcArgs: [isTopDown,this.queryFuncName] + }) + this.tbr!.recycleDataSource = [] + if (isHideSystemLibrary) { + args.push({ + funcName: "hideSystemLibrary", + funcArgs: [] + }) + } + if (filterData.callTreeConstraints.checked) { + args.push({ + funcName: "hideNumMaxAndMin", + funcArgs: [parseInt(filterData.callTreeConstraints.inputs[0]), filterData.callTreeConstraints.inputs[1]] + }) + } + args.push({ + funcName: "splitAllProcess", + funcArgs: [list] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + if (this.isChartShow) this.frameChart?.calculateChartData(); + }) + } + + setLTableData(resultData:any[]) { + this.dataSource = this.sortTree(resultData) + this.tbl!.recycleDataSource = this.dataSource + } + + sortTree(arr: Array): Array { + let sortArr = arr.sort((a, b) => { + if (this.sortKey == 'self') { + if (this.sortType == 0) { + return b.dur - a.dur; + } else if (this.sortType == 1) { + return a.selfDur - b.selfDur; + } else { + return b.selfDur - a.selfDur; + } + } else { + if (this.sortType == 0) { + return b.dur - a.dur; + } else if (this.sortType == 1) { + return a.dur - b.dur; + } else { + return b.dur - a.dur; + } + } + }) + sortArr.map((call) => { + call.children = this.sortTree(call.children); + }) + return sortArr; + } + + getDataByWorker(args: any[], handler: Function) { + this.loadingList.push(1) + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + procedurePool.submitWithName("logic0",this.procedureAction, {args,callType:this.queryFuncName},undefined,(results:any)=>{ + handler(results) + this.loadingList.splice(0,1) + if(this.loadingList.length == 0) { + this.progressEL!.loading = false + this.loadingPage.style.visibility = "hidden" + } + }) + } + + initHtml(): string { + return ` + +
+ + + +
+ + + + + + + +
+ + + Heaviest Stack Trace + + + + + + +
+ + + + + + + +
+
`; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemCalltree.ts b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemCalltree.ts new file mode 100644 index 0000000000000000000000000000000000000000..71bbf90f932fe8df1e0563a46537eb510b150522 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemCalltree.ts @@ -0,0 +1,613 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {FrameChart} from "../../../chart/FrameChart.js"; +import "../../../chart/FrameChart.js"; +import {DisassemblingWindow} from "../../../DisassemblingWindow.js"; +import "../../../DisassemblingWindow.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {ChartMode} from "../../../../bean/FrameChartStruct.js"; +import {FilterData, TabPaneFilter} from "../TabPaneFilter.js"; +import "../TabPaneFilter.js"; +import {procedurePool} from "../../../../database/Procedure.js"; +import {FileMerageBean} from "../../../../database/logic-worker/ProcedureLogicWorkerFileSystem.js"; + +@element('tabpane-filesystem-calltree') +export class TabpaneFilesystemCalltree extends BaseElement { + private tbl: LitTable | null | undefined; + private tbr: LitTable | null | undefined; + private progressEL:LitProgressBar | null | undefined; + private rightSource: Array = []; + private filter: any + private dataSource: any[] = [] + private sortKey = "weight"; + private sortType = 0; + private currentSelectedData: any = undefined + private frameChart: FrameChart | null | undefined; + private isChartShow: boolean = false; + private systmeRuleName = "/system/" + private numRuleName = "/max/min/" + private modal: DisassemblingWindow | null | undefined; + private needShowMenu = true; + private searchValue: string = "" + private loadingList:number[] = [] + private loadingPage:any; + private currentSelection:SelectionParam|undefined + + set data(val: SelectionParam | any) { + if(val == this.currentSelection){ + return; + } + this.searchValue = ""; + this.currentSelection = val + this.modal!.style.display = 'none'; + this.tbl!.style.visibility = "visible"; + if (this.parentElement!.clientHeight > this.filter!.clientHeight) { + this.filter!.style.display = "flex"; + } else { + this.filter!.style.display = "none"; + } + this.filter!.initializeFilterTree(true, true, true) + this.filter!.filterValue = "" + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + this.getDataByWorker([{ + funcName: "setSearchValue", + funcArgs: [""] + }, { + funcName: "getCurrentDataFromDb", + funcArgs: [{queryFuncName:"fileSystem",...val}] + }], (results: any[]) => { + this.setLTableData(results) + this.tbr!.recycleDataSource = [] + this.frameChart!.mode = ChartMode.Duration; + this.frameChart!.data = this.dataSource; + this.frameChart?.updateCanvas(true, this.clientWidth); + this.frameChart?.calculateChartData(); + }) + } + + getParentTree(src: Array, target: FileMerageBean, parents: Array): boolean { + for (let call of src) { + if (call.id == target.id) { + parents.push(call) + return true + } else { + if (this.getParentTree(call.children as Array, target, parents)) { + parents.push(call); + return true; + } + } + } + return false; + } + + getChildTree(src: Array, id: string, children: Array): boolean { + for (let call of src) { + if (call.id == id && call.children.length == 0) { + children.push(call) + return true + } else { + if (this.getChildTree(call.children as Array, id, children)) { + children.push(call); + return true; + } + } + } + return false; + } + + setRightTableData(call: FileMerageBean) { + let parents: Array = []; + let children: Array = []; + this.getParentTree(this.dataSource, call, parents); + let maxId = call.id; + let maxDur = 0; + + function findMaxStack(call: FileMerageBean) { + if (call.children.length == 0) { + if (call.dur > maxDur) { + maxDur = call.dur; + maxId = call.id; + } + } else { + call.children.map((callChild:any) => { + findMaxStack(callChild); + }) + } + } + + findMaxStack(call); + this.getChildTree(call.children as Array, maxId, children); + let arr = parents.reverse().concat(children.reverse()); + for (let data of arr) { + data.type = (data.libName.endsWith(".so.1") || data.libName.endsWith(".dll") || data.libName.endsWith(".so")) ? 0 : 1; + } + let len = arr.length; + this.rightSource = arr; + this.tbr!.dataSource = len == 0 ? [] : arr + } + + showButtomMenu(isShow: boolean) { + if (isShow) { + this.filter.setAttribute('tree', ''); + this.filter.setAttribute('input', ''); + this.filter.setAttribute('inputLeftText', ''); + } else { + this.filter.removeAttribute('tree'); + this.filter.removeAttribute('input'); + this.filter.removeAttribute('inputLeftText') + } + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-filesystem-calltree'); + this.progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar + this.frameChart = this.shadowRoot?.querySelector('#framechart'); + this.modal = this.shadowRoot?.querySelector('tab-native-data-modal'); + this.loadingPage = this.shadowRoot?.querySelector('.loading'); + this.frameChart!.addChartClickListener((needShowMenu: boolean) => { + this.parentElement!.scrollTo(0, 0); + this.showButtomMenu(needShowMenu) + this.needShowMenu = needShowMenu; + }); + this.tbl!.rememberScrollTop = true; + this.filter = this.shadowRoot?.querySelector("#filter") + this.tbl!.addEventListener('row-click', (evt: any) => { + // @ts-ignore + let data = (evt.detail.data as FileMerageBean); + this.setRightTableData(data); + data.isSelected = true; + this.currentSelectedData = data; + this.tbr?.clearAllSelection(data); + this.tbr?.setCurrentSelection(data); + // @ts-ignore + if ((evt.detail as any).callBack) { + // @ts-ignore + (evt.detail as any).callBack(true) + } + }) + this.tbr = this.shadowRoot?.querySelector('#tb-filesystem-list'); + this.tbr!.addEventListener('row-click', (evt: any) => { + // @ts-ignore + let data = (evt.detail.data as FileMerageBean); + this.tbl?.clearAllSelection(data); + (data as any).isSelected = true + this.tbl!.scrollToData(data) + // @ts-ignore + if ((evt.detail as any).callBack) { + // @ts-ignore + (evt.detail as any).callBack(true) + } + }) + this.modal!.setCloseListener(() => { + this.modal!.style.display = 'none'; + this.tbl!.style.visibility = "visible"; + this.shadowRoot!.querySelector("#filter")!.style.display = 'flex'; + }); + let filterFunc = (data: any) => { + let args: any[] = [] + if (data.type == "check") { + if (data.item.checked) { + args.push({ + funcName: "splitTree", + funcArgs: [data.item.name, data.item.select == "0", data.item.type == "symbol"] + }) + } else { + args.push({ + funcName: "resotreAllNode", + funcArgs: [[data.item.name]] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + args.push({ + funcName: "clearSplitMapData", + funcArgs: [data.item.name] + }) + } + } else if (data.type == "select") { + args.push({ + funcName: "resotreAllNode", + funcArgs: [[data.item.name]] + }) + args.push({ + funcName: "clearSplitMapData", + funcArgs: [data.item.name] + }) + args.push({ + funcName: "splitTree", + funcArgs: [data.item.name, data.item.select == "0", data.item.type == "symbol"] + }) + } else if (data.type == "button") { + if (data.item == "symbol") { + if (this.currentSelectedData && !this.currentSelectedData.canCharge) { + return + } + if (this.currentSelectedData != undefined) { + this.filter!.addDataMining({name: this.currentSelectedData.symbolName}, data.item) + args.push({ + funcName: "splitTree", + funcArgs: [this.currentSelectedData.symbolName, false, true] + }) + } else { + return + } + } else if (data.item == "library") { + if (this.currentSelectedData && !this.currentSelectedData.canCharge) { + return + } + if (this.currentSelectedData != undefined && this.currentSelectedData.libName != "") { + this.filter!.addDataMining({name: this.currentSelectedData.libName}, data.item) + args.push({ + funcName: "splitTree", + funcArgs: [this.currentSelectedData.libName, false, false] + }) + } else { + return + } + } else if (data.item == "restore") { + if (data.remove != undefined && data.remove.length > 0) { + let list = data.remove.map((item: any) => { + return item.name + }) + args.push({ + funcName: "resotreAllNode", + funcArgs: [list] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + list.forEach((symbolName: string) => { + args.push({ + funcName: "clearSplitMapData", + funcArgs: [symbolName] + }) + }) + } + } + } + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + if (this.isChartShow) this.frameChart?.calculateChartData(); + this.tbl!.move1px() + if (this.currentSelectedData) { + this.currentSelectedData.isSelected = false; + this.tbl?.clearAllSelection(this.currentSelectedData) + this.tbr!.recycleDataSource = [] + this.currentSelectedData = undefined + } + }) + } + this.filter!.getDataLibrary(filterFunc) + this.filter!.getDataMining(filterFunc) + this.filter!.getCallTreeData((data: any) => { + if (data.value == 0) { + this.refreshAllNode({...this.filter!.getFilterTreeData(), callTree: data.checks}) + } else { + let args: any[] = [] + if (data.checks[1]) { + args.push({ + funcName: "hideSystemLibrary", + funcArgs: [] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + } else { + args.push({ + funcName: "resotreAllNode", + funcArgs: [[this.systmeRuleName]] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + args.push({ + funcName: "clearSplitMapData", + funcArgs: [this.systmeRuleName] + }) + } + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + if (this.isChartShow) this.frameChart?.calculateChartData(); + }) + + } + }) + this.filter!.getCallTreeConstraintsData((data: any) => { + let args: any[] = [{ + funcName: "resotreAllNode", + funcArgs: [[this.numRuleName]] + }, { + funcName: "clearSplitMapData", + funcArgs: [this.numRuleName] + }] + if (data.checked) { + args.push({ + funcName: "hideNumMaxAndMin", + funcArgs: [parseInt(data.min), data.max] + }) + } + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + if (this.isChartShow) this.frameChart?.calculateChartData(); + }) + + }) + this.filter!.getFilterData((data: FilterData) => { + if (this.searchValue != this.filter!.filterValue) { + this.searchValue = this.filter!.filterValue + let args = [ + { + funcName: "setSearchValue", + funcArgs: [this.searchValue] + }, + { + funcName: "resetAllNode", + funcArgs: [] + } + ] + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + this.switchFlameChart(data) + }) + }else { + this.switchFlameChart(data) + } + + }) + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key + // @ts-ignore + this.sortType = evt.detail.sort + // @ts-ignore + this.setLTableData(this.dataSource) + this.frameChart!.data = this.dataSource; + }); + } + + connectedCallback() { + super.connectedCallback(); + let filterHeight = 0; + new ResizeObserver((entries) => { + let tabPaneFilter = this.shadowRoot!.querySelector("#filter") as HTMLElement; + if (tabPaneFilter.clientHeight > 0) filterHeight = tabPaneFilter.clientHeight; + if (this.parentElement!.clientHeight > filterHeight) { + tabPaneFilter.style.display = "flex"; + } else { + tabPaneFilter.style.display = "none"; + } + this.modal!.style.height = this.tbl!.clientHeight - 2 + 'px'; //2 is borderWidth + if (this.tbl!.style.visibility == "hidden") { + tabPaneFilter.style.display = "none"; + } + if (this.parentElement?.clientHeight != 0) { + if (this.isChartShow) { + this.frameChart?.updateCanvas(false, entries[0].contentRect.width); + this.frameChart?.calculateChartData(); + } + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 10 - 35) + "px" + this.tbl?.reMeauseHeight() + // @ts-ignore + this.tbr?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45 - 21) + "px" + this.tbr?.reMeauseHeight() + this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px" + } + }).observe(this.parentElement!); + this.parentElement!.onscroll = () => { + this.frameChart!.tabPaneScrollTop = this.parentElement!.scrollTop; + }; + } + + switchFlameChart(data:any){ + let pageTab = this.shadowRoot?.querySelector('#show_table'); + let pageChart = this.shadowRoot?.querySelector('#show_chart'); + if (data.icon == 'block') { + pageChart?.setAttribute('class', 'show'); + pageTab?.setAttribute('class', ''); + this.isChartShow = true; + this.filter!.disabledMining = true; + this.showButtomMenu(this.needShowMenu); + this.frameChart!.data = this.dataSource; + this.frameChart?.calculateChartData(); + } else if (data.icon == 'tree') { + pageChart?.setAttribute('class', ''); + pageTab?.setAttribute('class', 'show'); + this.showButtomMenu(true); + this.isChartShow = false; + this.filter!.disabledMining = false; + this.frameChart!.clearCanvas(); + this.tbl!.reMeauseHeight() + } + } + + + refreshAllNode(filterData: any) { + let args:any[] = [] + let isTopDown: boolean = !filterData.callTree[0]; + let isHideSystemLibrary = filterData.callTree[1]; + let list = filterData.dataMining.concat(filterData.dataLibrary); + args.push({ + funcName: "getCallChainsBySampleIds", + funcArgs: [isTopDown,"fileSystem"] + }) + this.tbr!.recycleDataSource = [] + if (isHideSystemLibrary) { + args.push({ + funcName: "hideSystemLibrary", + funcArgs: [] + }) + } + if (filterData.callTreeConstraints.checked) { + args.push({ + funcName: "hideNumMaxAndMin", + funcArgs: [parseInt(filterData.callTreeConstraints.inputs[0]), filterData.callTreeConstraints.inputs[1]] + }) + } + args.push({ + funcName: "splitAllProcess", + funcArgs: [list] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + if (this.isChartShow) this.frameChart?.calculateChartData(); + }) + } + + setLTableData(resultData:any[]) { + this.dataSource = this.sortTree(resultData) + this.tbl!.recycleDataSource = this.dataSource + } + + sortTree(arr: Array): Array { + let sortArr = arr.sort((a, b) => { + if (this.sortKey == 'self') { + if (this.sortType == 0) { + return b.dur - a.dur; + } else if (this.sortType == 1) { + return a.selfDur - b.selfDur; + } else { + return b.selfDur - a.selfDur; + } + } else { + if (this.sortType == 0) { + return b.dur - a.dur; + } else if (this.sortType == 1) { + return a.dur - b.dur; + } else { + return b.dur - a.dur; + } + } + }) + sortArr.map((call) => { + call.children = this.sortTree(call.children); + }) + return sortArr; + } + + getDataByWorker(args: any[], handler: Function) { + this.loadingList.push(1) + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + procedurePool.submitWithName("logic0","fileSystem-action", {args,callType:"fileSystem"},undefined,(results:any)=>{ + handler(results) + this.loadingList.splice(0,1) + if(this.loadingList.length == 0) { + this.progressEL!.loading = false + this.loadingPage.style.visibility = "hidden" + } + }) + } + + initHtml(): string { + return ` + +
+ + + +
+ + + + + + + + +
+ + + Heaviest Stack Trace + + + + + + +
+ + + + + + + +
+
`; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemDescHistory.ts b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemDescHistory.ts new file mode 100644 index 0000000000000000000000000000000000000000..a493007b8597ce1c4c8c8e1aa1cfe5a77b9b200f --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemDescHistory.ts @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import "../../../../../base-ui/slicer/lit-slicer.js"; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {FilterData, TabPaneFilter} from "../TabPaneFilter.js"; +import {FileSysEvent} from "../../../../database/logic-worker/ProcedureLogicWorkerFileSystem.js"; +import {procedurePool} from "../../../../database/Procedure.js"; + +@element('tabpane-filesystem-desc-history') +export class TabPaneFileSystemDescHistory extends BaseElement { + private tbl: LitTable | null | undefined; + private tblData: LitTable | null | undefined; + private filter: TabPaneFilter | null | undefined; + private progressEL:LitProgressBar | null | undefined; + private loadingList:number[] = [] + private loadingPage:any; + private source: Array = []; + private filterSource: Array = []; + private sortKey: string = "startTs"; + private sortType: number = 0; + private filterEventType: string = "0"; + private filterProcess: string = "0"; + private filterPath: string = "0" + private currentSelection: SelectionParam | undefined | null + private eventList:string[] | null |undefined; + private processList:string[] | null |undefined; + private pathList:string[] | null |undefined; + + set data(val: SelectionParam | null | undefined) { + if (val == this.currentSelection) { + return + } + this.currentSelection = val + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20 - 31) + "px" + // @ts-ignore + this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20 - 31) + "px" + this.tbl!.recycleDataSource = []; + this.tblData!.recycleDataSource = []; + if (val) { + this.loadingList.push(1) + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + this.source = []; + procedurePool.submitWithName("logic0","fileSystem-queryFileSysEvents", + {leftNs:val.leftNs,rightNs:val.rightNs,typeArr:[0,1],tab:"history"},undefined,(res:any)=>{ + this.source = this.source.concat(res.data) + res.data = null; + if(!res.isSending){ + this.tbl!.recycleDataSource = this.source; + this.filterSource = this.source; + this.setProcessFilter(); + this.loadingList.splice(0,1) + if(this.loadingList.length == 0) { + this.progressEL!.loading = false + this.loadingPage.style.visibility = "hidden" + } + } + }) + } + } + + setProcessFilter(){ + this.processList = ["All Process"]; + this.pathList = ["All Path"] + this.source.map(it => { + if(this.processList!.findIndex(a => a === it.process) == -1){ + this.processList!.push(it.process); + } + if(this.pathList!.findIndex(a => a === it.path) == -1){ + this.pathList!.push(it.path) + } + }) + this.filter!.setSelectList(this.eventList,this.processList,"","",this.pathList,""); + this.filter!.firstSelect = "0"; + this.filter!.secondSelect = "0"; + this.filter!.thirdSelect = "0"; + this.filterProcess = "0" + this.filterPath = "0" + this.filterEventType = "0" + } + + filterData(){ + let pfv = parseInt(this.filterProcess) + let pathIndex = parseInt(this.filterPath) + this.filterSource = this.source.filter((it) => { + let pathFilter = true + let eventFilter = true + let processFilter = true + if(this.filterPath != "0"){ + pathFilter = it.path == this.pathList![pathIndex] + } + if(this.filterEventType == "1"){ + eventFilter = it.type == 0 + }else if(this.filterEventType == "2"){ + eventFilter = it.type == 1 + } + if(this.filterProcess != "0"){ + processFilter = it.process == this.processList![pfv] + } + return pathFilter&&eventFilter&&processFilter + }) + this.tblData!.recycleDataSource = []; + this.sortTable(this.sortKey,this.sortType); + } + + initElements(): void { + this.loadingPage = this.shadowRoot?.querySelector('.loading'); + this.progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar; + this.tbl = this.shadowRoot?.querySelector('#tbl'); + this.tblData = this.shadowRoot?.querySelector('#tbr'); + this.tbl!.addEventListener('row-click', (e) => { + // @ts-ignore + let data = (e.detail.data as FileSysEvent); + (data as any).isSelected = true; + // @ts-ignore + if ((e.detail as any).callBack) { + // @ts-ignore + (e.detail as any).callBack(true) + } + procedurePool.submitWithName("logic0","fileSystem-queryStack", + { callchainId : data.callchainId },undefined,(res:any)=>{ + this.tblData!.recycleDataSource = res; + }) + }); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key + // @ts-ignore + this.sortType = evt.detail.sort + // @ts-ignore + this.sortTable(evt.detail.key,evt.detail.sort) + }) + this.filter = this.shadowRoot?.querySelector("#filter"); + this.eventList = ['All FD Event','All Open Event','All Close Event']; + this.processList = ['All Process']; + this.pathList = ["All Path"] + this.filter!.setSelectList(this.eventList,this.processList,"","",this.pathList,""); + this.filter!.firstSelect = "0"; + this.filter!.getFilterData((data: FilterData) => { + this.filterEventType = data.firstSelect || "0"; + this.filterProcess = data.secondSelect || "0"; + this.filterPath = data.thirdSelect || "0"; + this.filterData(); + }) + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) - 10 - 31 + "px"; + this.tbl?.reMeauseHeight(); + // @ts-ignore + this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) - 10 -31 + "px" + this.tblData?.reMeauseHeight() + this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px" + } + }).observe(this.parentElement!); + } + + sortTable(key: string,type:number){ + if(type == 0){ + this.tbl!.recycleDataSource = this.filterSource + }else{ + let arr = Array.from(this.filterSource) + arr.sort((a,b):number=>{ + if(key == "startTsStr"){ + if(type == 1){ + return a.startTs - b.startTs ; + }else{ + return b.startTs - a.startTs ; + } + }else if(key == "durStr"){ + if(type == 1){ + return a.dur - b.dur ; + }else{ + return b.dur - a.dur ; + } + }else if(key == "process"){ + if (a.process > b.process) { + return type === 2 ? 1 : -1; + } else if (a.process == b.process) { + return 0; + } else { + return type === 2 ? -1 : 1; + } + } else if(key == "typeStr"){ + if (a.typeStr > b.typeStr) { + return type === 2 ? 1 : -1; + } else if (a.typeStr == b.typeStr) { + return 0; + } else { + return type === 2 ? -1 : 1; + } + } else if(key == "fd"){ + if(type == 1){ + return a.fd - b.fd ; + }else{ + return b.fd - a.fd ; + } + }else{ + return 0; + } + }) + this.tbl!.recycleDataSource = arr; + } + } + + initHtml(): string { + return ` + +
+
+ +
+ + + + + + + + + + + +
+ + + + + + + + +
+
+ + +
+
+`; + } + +} diff --git a/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemDescTimeSlice.ts b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemDescTimeSlice.ts new file mode 100644 index 0000000000000000000000000000000000000000..7d9a07d2d32de9eda31ca8dc5f108ae4e4c11d30 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemDescTimeSlice.ts @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import "../../../../../base-ui/slicer/lit-slicer.js"; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {FileSysEvent} from "../../../../database/logic-worker/ProcedureLogicWorkerFileSystem.js"; +import {procedurePool} from "../../../../database/Procedure.js"; + +@element('tabpane-filesystem-desc-time-slice') +export class TabPaneFileSystemDescTimeSlice extends BaseElement { + private tbl: LitTable | null | undefined; + private tblData: LitTable | null | undefined; + private progressEL:LitProgressBar | null | undefined; + private loadingList:number[] = [] + private loadingPage:any; + private source: Array = []; + private sortKey: string = "startTs"; + private sortType: number = 0; + private currentSelection: SelectionParam | undefined | null + + set data(val: SelectionParam | null | undefined) { + if (val == this.currentSelection) { + return + } + this.currentSelection = val + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20 - 31) + "px" + // @ts-ignore + this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20 - 31) + "px" + this.tbl!.recycleDataSource = []; + this.tblData!.recycleDataSource = []; + if (val) { + this.loadingList.push(1) + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + let startNs = (window as any).recordStartNS ?? 0; + this.source = []; + procedurePool.submitWithName("logic0","fileSystem-queryFileSysEvents", + {leftNs:startNs + val.leftNs,rightNs: startNs + val.rightNs,typeArr:[0],tab:"time-slice"},undefined,(res:any)=>{ + this.source = this.source.concat(res.data) + res.data = null; + if(!res.isSending){ + this.tbl!.recycleDataSource = this.source; + this.loadingList.splice(0,1) + if(this.loadingList.length == 0) { + this.progressEL!.loading = false + this.loadingPage.style.visibility = "hidden" + } + } + }) + } + } + + initElements(): void { + this.loadingPage = this.shadowRoot?.querySelector('.loading'); + this.progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar; + this.tbl = this.shadowRoot?.querySelector('#tbl'); + this.tblData = this.shadowRoot?.querySelector('#tbr'); + this.tbl!.addEventListener('row-click', (e) => { + // @ts-ignore + let data = (e.detail.data as FileSysEvent); + (data as any).isSelected = true; + // @ts-ignore + if ((e.detail as any).callBack) { + // @ts-ignore + (e.detail as any).callBack(true) + } + procedurePool.submitWithName("logic0","fileSystem-queryStack", + { callchainId : data.callchainId },undefined,(res:any)=>{ + this.tblData!.recycleDataSource = res; + }) + }); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key + // @ts-ignore + this.sortType = evt.detail.sort + // @ts-ignore + this.sortTable(evt.detail.key,evt.detail.sort) + }) + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) - 10 - 31 + "px"; + this.tbl?.reMeauseHeight(); + // @ts-ignore + this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) - 10 -31 + "px" + this.tblData?.reMeauseHeight() + this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px" + } + }).observe(this.parentElement!); + } + + sortTable(key: string,type:number){ + if(type == 0){ + this.tbl!.recycleDataSource = this.source + }else{ + let arr = Array.from(this.source) + arr.sort((a,b):number=>{ + if(key == "startTsStr"){ + if(type == 1){ + return a.startTs - b.startTs ; + }else{ + return b.startTs - a.startTs ; + } + } else if(key == "durStr"){ + if(type == 1){ + return a.dur - b.dur ; + }else{ + return b.dur - a.dur ; + } + } else if(key == "process"){ + if (a.process > b.process) { + return type === 2 ? 1 : -1; + } else if (a.process == b.process) { + return 0; + } else { + return type === 2 ? -1 : 1; + } + } else if(key == "fd"){ + if(type == 1){ + return a.fd - b.fd ; + }else{ + return b.fd - a.fd ; + } + }else{ + return 0; + } + }) + this.tbl!.recycleDataSource = arr; + } + } + + initHtml(): string { + return ` + +
+
+ +
+ + + + + + + + + + +
+ + + + + + + + +
+
+ + +
+
+`; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemEvents.ts b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemEvents.ts new file mode 100644 index 0000000000000000000000000000000000000000..e6cf6b7ecd2748f4163bfdf97eb4c8299c005011 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemEvents.ts @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import "../../../../../base-ui/slicer/lit-slicer.js"; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {procedurePool} from "../../../../database/Procedure.js"; +import {FileSysEvent} from "../../../../database/logic-worker/ProcedureLogicWorkerFileSystem.js"; +import {FilterData, TabPaneFilter} from "../TabPaneFilter.js"; +import "../TabPaneFilter.js"; + +@element('tabpane-filesystem-event') +export class TabPaneFileSystemEvents extends BaseElement { + private tbl: LitTable | null | undefined; + private tblData: LitTable | null | undefined; + private progressEL:LitProgressBar | null | undefined; + private filter: TabPaneFilter | null | undefined; + private loadingList:number[] = [] + private loadingPage:any; + private source: Array = []; + private filterSource: Array = []; + private sortKey: string = "startTs"; + private sortType: number = 0; + private currentSelection: SelectionParam | undefined | null + private filterEventType: string = "0"; + private filterProcess: string = "0"; + private filterPath: string = "0" + private eventList:string[] | null |undefined; + private processList:string[] | null |undefined; + private pathList:string[] | null |undefined; + + + set data(val: SelectionParam | null | undefined) { + if (val == this.currentSelection) { + return + } + this.currentSelection = val + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20 - 31) + "px" + // @ts-ignore + this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20 - 31) + "px" + this.filterEventType = "0" + this.filterProcess = "0"; + this.queryData(val) + } + + queryData(val: SelectionParam | null | undefined){ + this.tbl!.recycleDataSource = []; + this.tblData!.recycleDataSource = []; + if (val) { + this.loadingList.push(1) + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + this.source = []; + procedurePool.submitWithName("logic0","fileSystem-queryFileSysEvents", + {leftNs:val.leftNs,rightNs:val.rightNs,typeArr:val.fileSystemType,tab:"events"},undefined,(res:any)=>{ + this.source = this.source.concat(res.data) + res.data = null; + if(!res.isSending){ + this.setProcessFilter(); + this.filterData() + this.loadingList.splice(0,1) + if(this.loadingList.length == 0) { + this.progressEL!.loading = false + this.loadingPage.style.visibility = "hidden" + } + } + }) + } + } + + setProcessFilter(){ + this.processList = ["All Process"]; + this.source.map(it => { + if(this.processList!.findIndex(a => a === it.process) == -1){ + this.processList!.push(it.process); + } + if(this.pathList!.findIndex(a => a === it.path) == -1){ + this.pathList!.push(it.path) + } + }) + this.filter!.setSelectList(this.eventList,this.processList,"","",this.pathList,""); + if(this.filterProcess == "-1"){ + this.filterProcess = this.processList.indexOf(`${this.currentSelection?.fileSystemFsData.name}[${this.currentSelection?.fileSystemFsData.pid}]`) + "" + } + this.filter!.firstSelect = this.filterEventType; + this.filter!.secondSelect = this.filterProcess; + this.filter!.thirdSelect = this.filterPath + } + + filterData(){ + let pfv = parseInt(this.filterProcess) + let pathIndex = parseInt(this.filterPath) + let eventType = parseInt(this.filterEventType) - 1 + this.filterSource = this.source.filter((it) => { + let pathFilter = true + let eventFilter = it.type == eventType||eventType == -1; + let processFilter = true + if(this.filterPath != "0"){ + pathFilter = it.path == this.pathList![pathIndex] + } + if(this.filterProcess != "0"){ + processFilter = it.process == this.processList![pfv] + } + return pathFilter&&eventFilter&&processFilter + }) + this.tblData!.recycleDataSource = []; + this.sortTable(this.sortKey,this.sortType); + } + + initElements(): void { + this.loadingPage = this.shadowRoot?.querySelector('.loading'); + this.progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar; + this.tbl = this.shadowRoot?.querySelector('#tbl'); + this.tblData = this.shadowRoot?.querySelector('#tbr'); + this.tbl!.addEventListener('row-click', (e) => { + // @ts-ignore + let data = (e.detail.data as FileSysEvent); + (data as any).isSelected = true; + // @ts-ignore + if ((e.detail as any).callBack) { + // @ts-ignore + (e.detail as any).callBack(true) + } + procedurePool.submitWithName("logic0","fileSystem-queryStack", + { callchainId : data.callchainId },undefined,(res:any)=>{ + this.tblData!.recycleDataSource = res; + }) + }); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key + // @ts-ignore + this.sortType = evt.detail.sort + // @ts-ignore + this.sortTable(evt.detail.key,evt.detail.sort) + }) + this.filter = this.shadowRoot?.querySelector("#filter"); + this.eventList = ['All Event','All Open Event','All Close Event','All Read Event','All Write Event']; + this.processList = ['All Process']; + this.pathList = ["All Path"] + this.filter!.setSelectList(this.eventList,this.processList,"","",this.pathList,""); + this.filter!.firstSelect = "0"; + this.filter!.getFilterData((data: FilterData) => { + this.filterEventType = data.firstSelect || "0"; + this.filterProcess = data.secondSelect || "0"; + this.filterPath = data.thirdSelect || "0"; + this.filterData(); + }) + } + + fromStastics(val: SelectionParam | any) { + if(val.fileSystemFsData == undefined){ + return + } + if(val.fileSystemFsData.title == "All"){ + this.filterEventType = "0"; + this.filterProcess = "0"; + } else if(val.fileSystemFsData.pid == undefined){ + this.filterEventType = "" + (val.fileSystemFsData.type+1); + this.filterProcess = "0"; + } else { + this.filterEventType = "" + (val.fileSystemFsData.type+1); + this.filterProcess = "-1"; + } + this.filterPath = "0" + if(this.currentSelection == val){ + if(this.filterProcess == "-1"){ + this.filterProcess = this.processList?.indexOf(`${val.fileSystemFsData.name}[${val.fileSystemFsData.pid}]`) + ""; + } + this.filter!.firstSelect = this.filterEventType + this.filter!.secondSelect = this.filterProcess + this.filter!.thirdSelect = this.filterPath + this.filterData() + } else { + this.currentSelection = val + this.queryData(val) + } + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) - 10 - 33 + "px"; + this.tbl?.reMeauseHeight(); + // @ts-ignore + this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) - 10 -33 + "px" + this.tblData?.reMeauseHeight() + this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px" + } + }).observe(this.parentElement!); + } + + sortTable(key: string,type:number){ + if(type == 0){ + this.tbl!.recycleDataSource = this.filterSource + }else{ + let arr = Array.from(this.filterSource) + arr.sort((a,b):number=>{ + if(key == "startTsStr"){ + if(type == 1){ + return a.startTs - b.startTs ; + }else{ + return b.startTs - a.startTs ; + } + }else if(key == "durStr"){ + if(type == 1){ + return a.dur - b.dur ; + }else{ + return b.dur - a.dur ; + } + }else if(key == "process"){ + if (a.process > b.process) { + return type === 2 ? 1 : -1; + } else if (a.process == b.process) { + return 0; + } else { + return type === 2 ? -1 : 1; + } + }else if(key == "thread"){ + if (a.thread > b.thread) { + return type === 2 ? 1 : -1; + } else if (a.thread == b.thread) { + return 0; + } else { + return type === 2 ? -1 : 1; + } + } else if(key == "typeStr"){ + if (a.typeStr > b.typeStr) { + return type === 2 ? 1 : -1; + } else if (a.typeStr == b.typeStr) { + return 0; + } else { + return type === 2 ? -1 : 1; + } + } else if(key == "fd"){ + if(type == 1){ + return (a.fd||0) - (b.fd||0) ; + }else{ + return (b.fd||0) - (a.fd||0) ; + } + } else if(key == "path"){ + if (a.path > b.path) { + return type === 2 ? 1 : -1; + } else if (a.path == b.path) { + return 0; + } else { + return type === 2 ? -1 : 1; + } + }else{ + return 0; + } + }) + this.tbl!.recycleDataSource = arr; + } + } + + initHtml(): string { + return ` + +
+
+ +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+ + +
+
+`; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFilesystemStatistics.ts b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFilesystemStatistics.ts new file mode 100644 index 0000000000000000000000000000000000000000..050a385685d75efa1a6264216db6484e7846f191 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFilesystemStatistics.ts @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import { + getTabPaneFilesystemStatistics, +} from "../../../../database/SqlLite.js"; +import {Utils} from "../../base/Utils.js"; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; + +@element('tabpane-file-statistics') +export class TabPaneFileStatistics extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private loadDataInCache: boolean = true; + private selectionParam:SelectionParam | null | undefined; + private progressEL:LitProgressBar | null | undefined; + private loadingPage:any; + private loadingList:number[] = []; + private source: Array = []; + private typeList: Array = ["OPEN", "CLOSE", "READ" , "WRITE"]; + private sortKey: string = ""; + private sortType: number = 0; + + set data(val: SelectionParam | any) { + if(val == this.selectionParam){ + return; + } + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + this.selectionParam = val; + // @ts-ignore + this.tbl!.shadowRoot!.querySelector(".table").style.height = (this.parentElement!.clientHeight - 25) + "px" + this.queryDataByDB(val) + } + + initElements(): void { + this.progressEL = this.shadowRoot!.querySelector('.progress') + this.loadingPage = this.shadowRoot!.querySelector('.loading'); + this.tbl = this.shadowRoot!.querySelector('#tb-states'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key + // @ts-ignore + this.sortType = evt.detail.sort; + + let newSource = JSON.parse(JSON.stringify(this.source)); + if (this.sortType != 0 && newSource.length > 0) this.sortTable(newSource[0],this.sortKey); + this.tbl!.recycleDataSource = newSource; + }) + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement!.clientHeight != 0) { + // @ts-ignore + this.tbl!.shadowRoot!.querySelector(".table").style.height = (this.parentElement!.clientHeight - 25) + "px" + this.tbl!.reMeauseHeight() + this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px" + } + }).observe(this.parentElement!); + } + + getInitData(item:any){ + return { + ...item, + title : item.name+"("+item.pid+")", + logicalWrites : Utils.getBinaryByteWithUnit(item.logicalWrites), + logicalReads : Utils.getBinaryByteWithUnit(item.logicalReads), + otherFile : Utils.getBinaryByteWithUnit(item.otherFile), + allDuration : Utils.getProbablyTime(item.allDuration), + minDuration : Utils.getProbablyTime(item.minDuration), + maxDuration : Utils.getProbablyTime(item.maxDuration), + avgDuration : Utils.getProbablyTime(item.avgDuration), + node:{...item,children:[]}, + } + } + + queryDataByDB(val: SelectionParam | any) { + this.loadingList.push(1) + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible"; + getTabPaneFilesystemStatistics(val.leftNs + val.recordStartNs,val.rightNs + val.recordStartNs,val.fileSystemType).then(result => { + this.loadingList.splice(0,1) + if(this.loadingList.length == 0) { + this.progressEL!.loading = false + this.loadingPage.style.visibility = "hidden" + } + let fatherMap = new Map() + let allNode:any = { + title:"All", + count:0, + logicalReads:0, + logicalWrites:0, + otherFile:0, + allDuration:0, + minDuration:0, + maxDuration:0, + avgDuration:"", + children:[], + }; + result.forEach((item,idx)=>{ + if (fatherMap.has(item.type)) { + let obj1 = fatherMap.get(item.type); + obj1.count += item.count; + obj1.logicalReads += item.logicalReads; + obj1.logicalWrites += item.logicalWrites; + obj1.otherFile += item.otherFile; + obj1.allDuration += item.allDuration; + obj1.minDuration = obj1.minDuration<=item.minDuration?obj1.minDuration:item.minDuration; + obj1.maxDuration = obj1.maxDuration>=item.maxDuration?obj1.maxDuration:item.maxDuration; + obj1.children.push(this.getInitData(item)); + }else { + fatherMap.set(item.type,{ + type:item.type, + count:item.count, + logicalReads:item.logicalReads, + logicalWrites:item.logicalWrites, + otherFile:item.otherFile, + allDuration:item.allDuration, + minDuration:item.minDuration, + maxDuration:item.maxDuration, + children:[this.getInitData(item)] + }) + } + if (idx == 0) { + allNode.minDuration = item.minDuration; + }else { + allNode.minDuration = allNode.minDuration<=item.minDuration?allNode.minDuration:item.minDuration; + } + allNode.count += item.count; + allNode.logicalReads += item.logicalReads; + allNode.logicalWrites += item.logicalWrites; + allNode.otherFile += item.otherFile; + allNode.allDuration += item.allDuration; + allNode.maxDuration = allNode.maxDuration>=item.maxDuration?allNode.maxDuration:item.maxDuration; + }) + fatherMap.forEach((item)=>{ + item.avgDuration = item.allDuration/item.count; + let node = this.getInitData(item); + if (item.type < 4) { + node.title = this.typeList[item.type] + }else { + node.title = item.type; + } + allNode.children.push(node) + }) + allNode.avgDuration = allNode.allDuration/allNode.count; + allNode = this.getInitData(allNode); + allNode.title = "All"; + this.source = result.length > 0 ? [allNode] : []; + let newSource = JSON.parse(JSON.stringify(this.source)); + if (this.sortType != 0 && result.length > 0) this.sortTable(newSource[0],this.sortKey); + this.tbl!.recycleDataSource = newSource; + }) + } + + sortTable(allNode:any,key:string){ + allNode.children.sort((a:any, b:any) => { + if (this.sortType == 1) { + return a.node[key] - b.node[key] + }else if (this.sortType == 2) { + return b.node[key] - a.node[key] + } + }); + allNode.children.forEach((item:any)=>{ + item.children.sort((a:any, b:any) => { + if (this.sortType == 1) { + return a.node[key] - b.node[key] + }else if (this.sortType == 2) { + return b.node[key] - a.node[key] + } + }) + }); + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + + + + + + + + + +
+ `; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/file-system/TabPaneIOCallTree.ts b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneIOCallTree.ts new file mode 100644 index 0000000000000000000000000000000000000000..4727d700cfca12d92cf2d1d0f63def0c3eb6be55 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneIOCallTree.ts @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import "./TabPaneCallTree.js" +import {TabPaneCallTree} from "./TabPaneCallTree.js"; + +@element('tabpane-io-calltree') +export class TabPaneIOCallTree extends TabPaneCallTree { + constructor() { + super(); + this.queryFuncName = "io" + this.procedureAction = "fileSystem-action" + } +} + +@element('tabpane-vm-calltree') +export class TabPaneVMCallTree extends TabPaneCallTree { + constructor() { + super(); + this.queryFuncName = "virtualMemory" + this.procedureAction = "fileSystem-action" + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/file-system/TabPaneIOTierStatistics.ts b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneIOTierStatistics.ts new file mode 100644 index 0000000000000000000000000000000000000000..8b06ccec01d30cf1db072ae5e78427b4dd1b360e --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneIOTierStatistics.ts @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import { + getTabPaneIOTierStatisticsData, +} from "../../../../database/SqlLite.js"; +import {Utils} from "../../base/Utils.js"; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {TabPaneFilter} from "../TabPaneFilter.js"; +import {SpSystemTrace} from "../../../SpSystemTrace.js"; + +@element('tabpane-io-tier-statistics') +export class TabPaneIOTierStatistics extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private loadDataInCache: boolean = true; + private selectionParam:SelectionParam | null | undefined; + private progressEL:LitProgressBar | null | undefined; + private filter: TabPaneFilter | null | undefined; + private loadingPage:any; + private loadingList:number[] = []; + private source: Array = []; + private typeList: Array = ["OPEN", "CLOSE", "READ" , "WRITE"]; + private sortKey: string = ""; + private sortType: number = 0; + private resultData: Array = []; + + set data(val: SelectionParam | any) { + if(val == this.selectionParam){ + return; + } + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + this.selectionParam = val; + // @ts-ignore + this.tbl!.shadowRoot!.querySelector(".table").style.height = (this.parentElement!.clientHeight - 20) + "px" + this.queryDataByDB(val) + } + + initElements(): void { + this.progressEL = this.shadowRoot!.querySelector('.progress') + this.loadingPage = this.shadowRoot!.querySelector('.loading'); + this.tbl = this.shadowRoot!.querySelector('#tb-states'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key + // @ts-ignore + this.sortType = evt.detail.sort; + + let newSource = JSON.parse(JSON.stringify(this.source)); + if (this.sortType != 0 && newSource.length > 0) this.sortTable(newSource[0],this.sortKey); + this.tbl!.recycleDataSource = newSource; + }) + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement!.clientHeight != 0) { + // @ts-ignore + this.tbl!.shadowRoot!.querySelector(".table").style.height = (this.parentElement!.clientHeight - 25) + "px" + this.tbl!.reMeauseHeight() + this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px" + } + }).observe(this.parentElement!); + } + + getInitData(item:any,nameTitle:any = "pname",subtitle:any = null){ + if (nameTitle == "path") {item.path = item.path != null ? SpSystemTrace.DATA_DICT.get(parseInt(item.path)) : "-"} + return { + ...item, + title : item[nameTitle]+(subtitle?("("+item[subtitle]+")"):""), + allDuration : Utils.getProbablyTime(item.allDuration), + minDuration : Utils.getProbablyTime(item.minDuration), + maxDuration : Utils.getProbablyTime(item.maxDuration), + avgDuration : Utils.getProbablyTime(item.avgDuration), + node:{...item,children:[]}, + } + } + + queryDataByDB(val: SelectionParam | any) { + this.loadingList.push(1) + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible"; + getTabPaneIOTierStatisticsData(val.leftNs + val.recordStartNs,val.rightNs + val.recordStartNs,val.diskIOipids).then(result => { + this.loadingList.splice(0,1) + if(this.loadingList.length == 0) { + this.progressEL!.loading = false + this.loadingPage.style.visibility = "hidden" + } + this.resultData = JSON.parse(JSON.stringify(result)); + this.sortStatus(result,"tier","ipid") + }) + } + + sortStatus(result:Array,firstLevel:string,secondLevel:string){ + let fatherMap = new Map(); + let childMap = new Map(); + let allNode:any = { + title:"All", + count:0, + allDuration:0, + minDuration:0, + maxDuration:0, + avgDuration:"", + children:[], + }; + result.forEach((item,idx)=>{ + if (childMap.has(item[firstLevel]+"_"+item[secondLevel])) { + let obj1 = childMap.get(item[firstLevel]+"_"+item[secondLevel]); + obj1.count += item.count; + obj1.allDuration += item.allDuration; + obj1.minDuration = obj1.minDuration<=item.minDuration?obj1.minDuration:item.minDuration; + obj1.maxDuration = obj1.maxDuration>=item.maxDuration?obj1.maxDuration:item.maxDuration; + obj1.children.push(this.getInitData(item,"path",null)); + }else { + childMap.set(item[firstLevel]+"_"+item[secondLevel],{ + ...item, + children:[this.getInitData(item,"path",null)] + }) + } + + if (fatherMap.has(item[firstLevel])) { + let obj1 = fatherMap.get(item[firstLevel]); + obj1.count += item.count; + obj1.allDuration += item.allDuration; + obj1.minDuration = obj1.minDuration<=item.minDuration?obj1.minDuration:item.minDuration; + obj1.maxDuration = obj1.maxDuration>=item.maxDuration?obj1.maxDuration:item.maxDuration; + obj1.children.push(this.getInitData(item)); + }else { + fatherMap.set(item[firstLevel],{ + ...item, + children:[this.getInitData(item)] + }) + } + if (idx == 0) { + allNode.minDuration = item.minDuration; + }else { + allNode.minDuration = allNode.minDuration<=item.minDuration?allNode.minDuration:item.minDuration; + } + allNode.count += item.count; + allNode.allDuration += item.allDuration; + allNode.maxDuration = allNode.maxDuration>=item.maxDuration?allNode.maxDuration:item.maxDuration; + }) + + for (let ks of fatherMap.keys()) { + let sp = fatherMap.get(ks) + sp!.children = []; + sp.avgDuration = sp.allDuration/sp.count; + let node = this.getInitData(sp,"tier",null); + node.path = {tier:node.tier,pid:null,path:null,value:node.title} + for (let kst of childMap.keys()) { + if (kst.startsWith(ks + "_")) { + let spt = childMap.get(kst) + let data = this.getInitData(spt!,"pname","pid") + data.path = {tier:node.tier,pid:data.pid,path:null,value:"All-"+node.title+"-"+data.title} + data.children.forEach((e:any)=>{ + e.path = {tier:node.tier,pid:data.pid,path:e.path,value:"All-"+node.title+"-"+data.title+"-"+e.title} + }) + sp!.children.push(data); + } + } + allNode.children.push(node) + } + + allNode.avgDuration = allNode.allDuration/allNode.count; + allNode = this.getInitData(allNode); + allNode.title = "All"; + allNode.path = {tier:null,pid:null,path:null,value:"All"} + this.source = result.length > 0 ? [allNode] : []; + let newSource = JSON.parse(JSON.stringify(this.source)); + if (this.sortType != 0 && result.length > 0) this.sortTable(newSource[0],this.sortKey); + this.tbl!.recycleDataSource = newSource; + } + + sortTable(allNode:any,key:string){ + allNode.children.sort((a:any, b:any) => { + if (this.sortType == 1) { + return a.node[key] - b.node[key] + }else if (this.sortType == 2) { + return b.node[key] - a.node[key] + } + }); + allNode.children.forEach((item:any)=>{ + item.children.sort((a:any, b:any) => { + if (this.sortType == 1) { + return a.node[key] - b.node[key] + }else if (this.sortType == 2) { + return b.node[key] - a.node[key] + } + }) + item.children.forEach((i:any)=>{ + i.children.sort((a:any, b:any) => { + if (this.sortType == 1) { + return a.node[key] - b.node[key] + }else if (this.sortType == 2) { + return b.node[key] - a.node[key] + } + }) + }); + }); + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + + + +
+ `; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/file-system/TabPaneIoCompletionTimes.ts b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneIoCompletionTimes.ts new file mode 100644 index 0000000000000000000000000000000000000000..cb29409932a920c4ec5f92fd95a376cd7891fcb2 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneIoCompletionTimes.ts @@ -0,0 +1,363 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import "../../../../../base-ui/slicer/lit-slicer.js"; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {procedurePool} from "../../../../database/Procedure.js"; +import { + DISKIO_TYPE_MAP, + FileSysEvent, + IoCompletionTimes, VirtualMemoryEvent, + VM_TYPE_MAP +} from "../../../../database/logic-worker/ProcedureLogicWorkerFileSystem.js"; +import {FilterData, TabPaneFilter} from "../TabPaneFilter.js"; +import {getTabIoCompletionTimesType, getTabVirtualMemoryType} from "../../../../database/SqlLite.js"; + +@element('tabpane-io-completiontimes') +export class TabPaneIoCompletionTimes extends BaseElement { + private defaultNativeTypes = ["All",...Object.values(VM_TYPE_MAP)]; + private native_type: Array = [...this.defaultNativeTypes]; + private tbl: LitTable | null | undefined; + private tblData: LitTable | null | undefined; + private progressEL:LitProgressBar | null | undefined; + private loadingList:number[] = [] + private loadingPage:any; + private sortKey: string = "startTs"; + private sortType: number = 0; + private currentSelection: SelectionParam | undefined | null + private source: Array = []; + private queryDataSource: Array = []; + private statsticsSelection: Array = [] + + set data(val: SelectionParam | null | undefined) { + if (val == this.currentSelection) { + return + } + this.currentSelection = val + this.initFilterTypes(val!).then(()=>{ + this.queryData(val!) + }); + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20 - 31) + "px" + // @ts-ignore + this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20 - 31) + "px" + this.tbl!.recycleDataSource = []; + this.tblData!.recycleDataSource = []; + + } + + connectedCallback() { + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) - 10 - 33 + "px"; + this.tbl?.reMeauseHeight(); + // @ts-ignore + this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) - 10 -33 + "px" + this.tblData?.reMeauseHeight() + this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px" + } + }).observe(this.parentElement!) + } + + initElements(): void { + this.loadingPage = this.shadowRoot?.querySelector('.loading'); + this.progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar; + this.tbl = this.shadowRoot?.querySelector('#tbl'); + this.tblData = this.shadowRoot?.querySelector('#tbr'); + this.tbl!.addEventListener('row-click', (e) => { + // @ts-ignore + let data = (e.detail.data as FileSysEvent); + procedurePool.submitWithName("logic0","fileSystem-queryStack", + { callchainId : data.callchainId },undefined,(res:any)=>{ + this.tblData!.recycleDataSource = res; + }) + }); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key + // @ts-ignore + this.sortType = evt.detail.sort + // @ts-ignore + this.sortTable(evt.detail.key,evt.detail.sort) + }) + this.shadowRoot?.querySelector("#filter")!.getFilterData((data: FilterData) => { + let index = parseInt(data.firstSelect||"0"); + if(index > this.defaultNativeTypes.length -1){ + this.filterTypeData(this.statsticsSelection[index - this.defaultNativeTypes.length]) + }else { + this.filterTypeData(undefined) + } + this.tbl!.recycleDataSource = this.source + }) + } + + async initFilterTypes(val: SelectionParam){ + let filter = this.shadowRoot?.querySelector("#filter") + let typeKeys = await getTabIoCompletionTimesType(val.leftNs,val.rightNs); + this.defaultNativeTypes = ["All"] + this.statsticsSelection = [] + typeKeys.forEach((item)=>{ + // @ts-ignore + this.defaultNativeTypes.push(item.tier+"") + }) + this.native_type = [...this.defaultNativeTypes] + filter!.setSelectList([...this.defaultNativeTypes],null,"Tier") + filter!.firstSelect = "0" + } + + async fromStastics(val: SelectionParam | any) { + if(val.fileSystemIoData == undefined){ + return + } + this.tblData!.recycleDataSource = [] + this.tblData?.clearAllSelection(undefined) + let filter = this.shadowRoot?.querySelector("#filter") + if (this.currentSelection != val) { + await this.initFilterTypes(val) + } + let typeIndexOf = this.native_type.indexOf(val.fileSystemIoData.path.value); + if(typeIndexOf == -1){ + this.statsticsSelection.push(val.fileSystemIoData.path) + this.native_type.push(val.fileSystemIoData.path.value) + typeIndexOf = this.native_type.length - 1 + } + if (this.currentSelection != val) { + this.currentSelection = val + filter!.setSelectList(this.native_type, null,"Tier") + filter!.firstSelect = typeIndexOf + "" + this.queryData(val) + }else { + if(typeIndexOf == parseInt(filter!.firstSelect)){ + return + } + filter!.setSelectList(this.native_type, null,"Tier") + filter!.firstSelect = typeIndexOf + "" + this.filterTypeData(val?.fileSystemIoData?.path||undefined) + val.fileSystemIoData = undefined + this.tbl!.recycleDataSource = this.source + } + } + + queryData(val: SelectionParam){ + this.loadingList.push(1) + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + this.source = []; + this.queryDataSource = []; + procedurePool.submitWithName("logic0","fileSystem-queryIOEvents", + {leftNs:val.leftNs,rightNs:val.rightNs,diskIOipids:val.diskIOipids},undefined,(res:any)=>{ + this.source = this.source.concat(res.data) + this.queryDataSource = this.queryDataSource.concat(res.data) + this.filterTypeData(val?.fileSystemIoData?.path||undefined) + val.fileSystemIoData = undefined + res.data = null; + if(!res.isSending){ + this.tbl!.recycleDataSource = this.source; + this.loadingList.splice(0,1) + if(this.loadingList.length == 0) { + this.progressEL!.loading = false + this.loadingPage.style.visibility = "hidden" + } + } + }) + } + + filterTypeData(pathData:any){ + let filter = this.shadowRoot?.querySelector("#filter") + let firstSelect = filter!.firstSelect; + let tier = -1; + let path = ""; + let pid = -1; + if(parseInt(firstSelect) <= this.defaultNativeTypes.length - 1){ + let index = parseInt(firstSelect); + tier = index == 0?-1:parseInt(this.defaultNativeTypes[index]) + }else if(pathData!=undefined){ + tier = parseInt(pathData.tier); + path = pathData.path||""; + pid = pathData.pid||-1; + }else if(pathData==undefined){ + return + } + let isTierFilter = false; + let isPidFilter = false; + let isPathFilter = false; + this.source = this.queryDataSource.filter((item)=>{ + if(tier == -1){ + isTierFilter = true + }else { + isTierFilter = item.tier == tier + } + if(pid == -1){ + isPidFilter = true + }else{ + isPidFilter = item.pid == pid + } + isPathFilter = path == "" || item.path == path; + return isTierFilter&&isPidFilter&&isPathFilter + }) + } + + sortTable(key: string,type:number){ + if(type == 0){ + this.tbl!.recycleDataSource = this.source + }else{ + let arr = Array.from(this.source) + arr.sort((a,b):number=>{ + if(key == "startTsStr"){ + if(type == 1){ + return a.startTs - b.startTs ; + }else{ + return b.startTs - a.startTs ; + } + }else if(key == "durStr"){ + if(type == 1){ + return a.dur - b.dur ; + }else{ + return b.dur - a.dur ; + } + }else if(key == "process"){ + if (a.process > b.process) { + return type === 2 ? 1 : -1; + } else if (a.process == b.process) { + return 0; + } else { + return type === 2 ? -1 : 1; + } + }else if(key == "durPer4kStr"){ + if(type == 1){ + return a.durPer4k - b.durPer4k ; + }else{ + return b.durPer4k - a.durPer4k ; + } + }else if(key == "thread"){ + if (a.thread > b.thread) { + return type === 2 ? 1 : -1; + } else if (a.thread == b.thread) { + return 0; + } else { + return type === 2 ? -1 : 1; + } + }else if(key == "operation"){ + if (a.operation > b.operation) { + return type === 2 ? 1 : -1; + } else if (a.operation == b.operation) { + return 0; + } else { + return type === 2 ? -1 : 1; + } + }else if(key == "sizeStr"){ + if(type == 1){ + return a.size - b.size ; + }else{ + return b.size - a.size ; + } + }else if(key == "tier"){ + if(type == 1){ + return a.tier - b.tier ; + }else{ + return b.tier - a.tier ; + } + }else { + return 0; + } + }) + this.tbl!.recycleDataSource = arr; + } + } + + initHtml(): string { + return ` + +
+
+ +
+ + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+ + +
+
+`; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/file-system/TabPaneVMEvents.ts b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneVMEvents.ts new file mode 100644 index 0000000000000000000000000000000000000000..edfdc88ecfb04d835b9bb57c145e4ac41009514e --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneVMEvents.ts @@ -0,0 +1,328 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import "../../../../../base-ui/slicer/lit-slicer.js"; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {procedurePool} from "../../../../database/Procedure.js"; +import { + FileSysEvent, + VirtualMemoryEvent, + VM_TYPE_MAP +} from "../../../../database/logic-worker/ProcedureLogicWorkerFileSystem.js"; +import {FilterData, TabPaneFilter} from "../TabPaneFilter.js"; +import {getTabVirtualMemoryType} from "../../../../database/SqlLite.js"; + +@element('tabpane-virtualmemory-event') +export class TabPaneVirtualMemoryEvents extends BaseElement { + private defaultNativeTypes = ["All",...Object.values(VM_TYPE_MAP)]; + private native_type: Array = [...this.defaultNativeTypes]; + private tbl: LitTable | null | undefined; + private tblData: LitTable | null | undefined; + private progressEL:LitProgressBar | null | undefined; + private loadingList:number[] = [] + private loadingPage:any; + private source: Array = []; + private queryDataSource: Array = []; + private sortKey: string = "startTs"; + private sortType: number = 0; + private currentSelection: SelectionParam | undefined | null + private statsticsSelection: Array = [] + + set data(val: SelectionParam | null | undefined) { + if (val == this.currentSelection) { + return + } + this.currentSelection = val + this.initFilterTypes(val!).then(()=>{ + this.queryData(val!) + }); + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20 - 31) + "px" + // @ts-ignore + this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20 - 31) + "px" + this.tbl!.recycleDataSource = []; + this.tblData!.recycleDataSource = []; + } + + connectedCallback() { + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) - 10 - 33 + "px"; + this.tbl?.reMeauseHeight(); + // @ts-ignore + this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) - 10 -33 + "px" + this.tblData?.reMeauseHeight() + this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px" + } + }).observe(this.parentElement!) + } + + initElements(): void { + this.loadingPage = this.shadowRoot?.querySelector('.loading'); + this.progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar; + this.tbl = this.shadowRoot?.querySelector('#tbl'); + this.tblData = this.shadowRoot?.querySelector('#tbr'); + this.tbl!.addEventListener('row-click', (e) => { + // @ts-ignore + let data = e.detail.data; + (data as any).isSelected = true; + // @ts-ignore + if ((e.detail as any).callBack) { + // @ts-ignore + (e.detail as any).callBack(true) + } + procedurePool.submitWithName("logic0","fileSystem-queryStack", + { callchainId : data.callchainId },undefined,(res:any)=>{ + this.tblData!.recycleDataSource = res; + }) + }); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key + // @ts-ignore + this.sortType = evt.detail.sort + // @ts-ignore + this.sortTable(evt.detail.key,evt.detail.sort) + }) + this.shadowRoot?.querySelector("#filter")!.getFilterData((data: FilterData) => { + let index = parseInt(data.firstSelect||"0"); + if(index > this.defaultNativeTypes.length -1){ + this.filterTypeData(this.statsticsSelection[index - this.defaultNativeTypes.length]) + }else { + this.filterTypeData(undefined) + } + this.tbl!.recycleDataSource = this.source + }) + } + + async initFilterTypes(val: SelectionParam){ + let filter = this.shadowRoot?.querySelector("#filter") + let typeKeys = await getTabVirtualMemoryType(val.leftNs,val.rightNs); + this.defaultNativeTypes = ["All"] + this.statsticsSelection = [] + typeKeys.forEach((item)=>{ + // @ts-ignore + this.defaultNativeTypes.push(VM_TYPE_MAP[item.type+""]) + }) + this.native_type = [...this.defaultNativeTypes] + filter!.setSelectList([...this.defaultNativeTypes],null,"Operation Type") + filter!.firstSelect = "0" + } + + async fromStastics(val: SelectionParam | any) { + if(val.fileSystemVMData == undefined){ + return + } + this.tblData!.recycleDataSource = [] + this.tblData?.clearAllSelection(undefined) + let filter = this.shadowRoot?.querySelector("#filter") + if (this.currentSelection != val) { + await this.initFilterTypes(val) + } + let typeIndexOf = this.native_type.indexOf(val.fileSystemVMData.path.value); + if(typeIndexOf == -1){ + this.statsticsSelection.push(val.fileSystemVMData.path) + this.native_type.push(val.fileSystemVMData.path.value) + typeIndexOf = this.native_type.length - 1 + } + if (this.currentSelection != val) { + this.currentSelection = val + filter!.setSelectList(this.native_type, null,"Operation Type") + filter!.firstSelect = typeIndexOf + "" + this.queryData(val) + }else { + if(typeIndexOf == parseInt(filter!.firstSelect)){ + return + } + filter!.setSelectList(this.native_type, null,"Operation Type") + filter!.firstSelect = typeIndexOf + "" + this.filterTypeData(val?.fileSystemVMData?.path||undefined) + val.fileSystemVMData = undefined + this.tbl!.recycleDataSource = this.source + } + } + + queryData(val: SelectionParam){ + this.loadingList.push(1) + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + this.source = []; + this.queryDataSource = []; + procedurePool.submitWithName("logic0","fileSystem-queryVMEvents", + {leftNs:val.leftNs,rightNs:val.rightNs,typeArr:val.fileSystemType},undefined,(res:any)=>{ + this.source = this.source.concat(res.data) + this.queryDataSource = this.queryDataSource.concat(res.data) + this.filterTypeData(val?.fileSystemVMData?.path||undefined) + val.fileSystemVMData = undefined + res.data = null; + if(!res.isSending){ + this.tbl!.recycleDataSource = this.source; + this.loadingList.splice(0,1) + if(this.loadingList.length == 0) { + this.progressEL!.loading = false + this.loadingPage.style.visibility = "hidden" + } + } + }) + } + + filterTypeData(pathData:any){ + let filter = this.shadowRoot?.querySelector("#filter") + let firstSelect = filter!.firstSelect; + let type = -1; + let tid = -1; + let pid = -1; + if(parseInt(firstSelect) <= this.defaultNativeTypes.length - 1){ + let typeEntry = Object.entries(VM_TYPE_MAP).find((entry)=>{ + return entry[1] == this.defaultNativeTypes[parseInt(firstSelect)] + }) + type = typeEntry?parseInt(typeEntry[0]):0 + }else if(pathData!=undefined){ + type = parseInt(pathData.type||0); + tid = pathData.tid||-1; + pid = pathData.pid||-1; + }else if(pathData==undefined){ + return + } + let isTidFilter = false; + let isPidFilter = false; + let isTypeFilter = false; + this.source = this.queryDataSource.filter((item)=>{ + if(tid == -1){ + isTidFilter = true + }else { + isTidFilter = item.tid == tid + } + if(pid == -1){ + isPidFilter = true + }else{ + isPidFilter = item.pid == pid + } + isTypeFilter = type == 0 || item.type == type; + return isTidFilter&&isPidFilter&&isTypeFilter + }) + } + + sortTable(key: string,type:number){ + if(type == 0){ + this.tbl!.recycleDataSource = this.source + }else{ + let arr = Array.from(this.source) + arr.sort((a,b):number=>{ + if(key == "startTsStr"){ + if(type == 1){ + return a.startTs - b.startTs ; + }else{ + return b.startTs - a.startTs ; + } + }else if(key == "durStr"){ + if(type == 1){ + return a.dur - b.dur ; + }else{ + return b.dur - a.dur ; + } + }else if(key == "thread"){ + if (a.thread > b.thread) { + return type === 2 ? 1 : -1; + } else if (a.thread == b.thread) { + return 0; + } else { + return type === 2 ? -1 : 1; + } + }else if(key == "sizeStr"){ + if(type == 1){ + return a.size - b.size ; + }else{ + return b.size - a.size ; + } + }else{ + return 0; + } + }) + this.tbl!.recycleDataSource = arr; + } + } + + initHtml(): string { + return ` + +
+
+ +
+ + + + + + + + +
+ + + + + + + + +
+
+ + +
+
+`; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatistics.ts b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatistics.ts new file mode 100644 index 0000000000000000000000000000000000000000..0e0421e8ab5728d3d688b56a6a178577085d70d9 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatistics.ts @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import { + getTabPaneVirtualMemoryStatisticsData, +} from "../../../../database/SqlLite.js"; +import {Utils} from "../../base/Utils.js"; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {TabPaneFilter} from "../TabPaneFilter.js"; +import "../TabPaneFilter.js"; +import {VM_TYPE_MAP} from "../../../../database/logic-worker/ProcedureLogicWorkerFileSystem.js"; + +@element('tabpane-virtual-memory-statistics') +export class TabPaneVirtualMemoryStatistics extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private loadDataInCache: boolean = true; + private selectionParam:SelectionParam | null | undefined; + private progressEL:LitProgressBar | null | undefined; + private filter: TabPaneFilter | null | undefined; + private loadingPage:any; + private loadingList:number[] = []; + private source: Array = []; + private typeList: Array = ["OPEN", "CLOSE", "READ" , "WRITE"]; + private sortKey: string = ""; + private sortType: number = 0; + private resultData: Array = []; + + set data(val: SelectionParam | any) { + if(val == this.selectionParam){ + return; + } + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + this.selectionParam = val; + // @ts-ignore + this.tbl!.shadowRoot!.querySelector(".table").style.height = (this.parentElement!.clientHeight - 20) + "px" + this.queryDataByDB(val) + } + + initElements(): void { + this.progressEL = this.shadowRoot!.querySelector('.progress') + this.loadingPage = this.shadowRoot!.querySelector('.loading'); + this.tbl = this.shadowRoot!.querySelector('#tb-states'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key + // @ts-ignore + this.sortType = evt.detail.sort; + + let newSource = JSON.parse(JSON.stringify(this.source)); + if (this.sortType != 0 && newSource.length > 0) this.sortTable(newSource[0],this.sortKey); + this.tbl!.recycleDataSource = newSource; + }) + this.filter = this.shadowRoot!.querySelector("#filter"); + this.filter!.getStatisticsTypeData((type)=>{ + if (type=="operation") { + this.sortStatus(this.resultData,"ipid","itid") + }else { + this.sortStatus(this.resultData,"type","ipid") + } + this.tbl!.shadowRoot!.querySelector("div > div.thead > div > div:nth-child(1) > label")!.textContent = type=="operation"?"Process/Thread/Operation":"Operation/Process/Thread" + }) + + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement!.clientHeight != 0) { + // @ts-ignore + this.tbl!.shadowRoot!.querySelector(".table").style.height = (this.parentElement!.clientHeight - 10 -32) + "px" + this.tbl!.reMeauseHeight() + this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px" + } + }).observe(this.parentElement!); + } + + getInitData(item:any,nameTitle:any = "pname",subtitle:any = null){ + // @ts-ignore + let title = (nameTitle == "type")?VM_TYPE_MAP[item[nameTitle]]:item[nameTitle]; + return { + ...item, + title : title+(subtitle?("("+item[subtitle]+")"):""), + allDuration : Utils.getProbablyTime(item.allDuration), + minDuration : Utils.getProbablyTime(item.minDuration), + maxDuration : Utils.getProbablyTime(item.maxDuration), + avgDuration : Utils.getProbablyTime(item.avgDuration), + node:{...item,children:[]}, + } + } + + queryDataByDB(val: SelectionParam | any) { + this.loadingList.push(1) + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible"; + getTabPaneVirtualMemoryStatisticsData(val.leftNs + val.recordStartNs,val.rightNs + val.recordStartNs).then(result => { + this.loadingList.splice(0,1) + if(this.loadingList.length == 0) { + this.progressEL!.loading = false + this.loadingPage.style.visibility = "hidden" + } + this.resultData = JSON.parse(JSON.stringify(result)); + this.sortStatus(result,"type","ipid") + }) + } + + sortStatus(result:Array,firstLevel:string,secondLevel:string){ + let fatherMap = new Map(); + let childMap = new Map(); + let allNode:any = { + title:"All", + count:0, + allDuration:0, + minDuration:0, + maxDuration:0, + avgDuration:"", + children:[], + }; + result.forEach((item,idx)=>{ + if (childMap.has(item[firstLevel]+"_"+item[secondLevel])) { + let obj1 = childMap.get(item[firstLevel]+"_"+item[secondLevel]); + obj1.count += item.count; + obj1.allDuration += item.allDuration; + obj1.minDuration = obj1.minDuration<=item.minDuration?obj1.minDuration:item.minDuration; + obj1.maxDuration = obj1.maxDuration>=item.maxDuration?obj1.maxDuration:item.maxDuration; + obj1.children.push(this.getInitData(item,firstLevel=="type"?"tname":"type",firstLevel=="type"?"tid":null)); + }else { + childMap.set(item[firstLevel]+"_"+item[secondLevel],{ + ...item, + children:[this.getInitData(item,firstLevel=="type"?"tname":"type",firstLevel=="type"?"tid":null)] + }) + } + + if (fatherMap.has(item[firstLevel])) { + let obj1 = fatherMap.get(item[firstLevel]); + obj1.count += item.count; + obj1.allDuration += item.allDuration; + obj1.minDuration = obj1.minDuration<=item.minDuration?obj1.minDuration:item.minDuration; + obj1.maxDuration = obj1.maxDuration>=item.maxDuration?obj1.maxDuration:item.maxDuration; + obj1.children.push(this.getInitData(item)); + }else { + fatherMap.set(item[firstLevel],{ + ...item, + children:[this.getInitData(item)] + }) + } + if (idx == 0) { + allNode.minDuration = item.minDuration; + }else { + allNode.minDuration = allNode.minDuration<=item.minDuration?allNode.minDuration:item.minDuration; + } + allNode.count += item.count; + allNode.allDuration += item.allDuration; + allNode.maxDuration = allNode.maxDuration>=item.maxDuration?allNode.maxDuration:item.maxDuration; + }) + + for (let ks of fatherMap.keys()) { + let sp = fatherMap.get(ks) + sp!.children = []; + sp.avgDuration = sp.allDuration/sp.count; + let node = this.getInitData(sp,firstLevel=="type"?"type":"pname",firstLevel=="type"?null:"pid"); + node.path = {type:null,tid:null,pid:null,value:node.title} + node.path[firstLevel=="type"?"type":"pid"] = node[firstLevel=="type"?"type":"pid"]; + for (let kst of childMap.keys()) { + if (kst.startsWith(ks + "_")) { + let spt = childMap.get(kst) + let data = this.getInitData(spt!,firstLevel=="type"?"pname":"tname",firstLevel=="type"?"pid":"tid") + data.path = {type:null,tid:null,pid:null,value:"All-"+node.title+"-"+data.title} + data.path[firstLevel=="type"?"type":"pid"] = node[firstLevel=="type"?"type":"pid"]; + data.path[firstLevel=="type"?"pid":"tid"] = data[firstLevel=="type"?"pid":"tid"]; + data.children.forEach((e:any)=>{ + e.path = {type:null,tid:null,pid:null,value:"All-"+node.title+"-"+data.title+"-"+e.title} + e.path[firstLevel=="type"?"type":"pid"] = node[firstLevel=="type"?"type":"pid"]; + e.path[firstLevel=="type"?"pid":"tid"] = data[firstLevel=="type"?"pid":"tid"]; + e.path[firstLevel=="type"?"tid":"type"] = e[firstLevel=="type"?"tid":"type"]; + }) + sp!.children.push(data); + } + } + allNode.children.push(node) + } + + allNode.avgDuration = allNode.allDuration/allNode.count; + allNode = this.getInitData(allNode); + allNode.title = "All"; + allNode.path = {type:null,tid:null,pid:null,value:"All"}; + this.source = result.length > 0 ? [allNode] : []; + let newSource = JSON.parse(JSON.stringify(this.source)); + if (this.sortType != 0 && result.length > 0) this.sortTable(newSource[0],this.sortKey); + this.tbl!.recycleDataSource = newSource; + } + + sortTable(allNode:any,key:string){ + allNode.children.sort((a:any, b:any) => { + if (this.sortType == 1) { + return a.node[key] - b.node[key] + }else if (this.sortType == 2) { + return b.node[key] - a.node[key] + } + }); + allNode.children.forEach((item:any)=>{ + item.children.sort((a:any, b:any) => { + if (this.sortType == 1) { + return a.node[key] - b.node[key] + }else if (this.sortType == 2) { + return b.node[key] - a.node[key] + } + }) + item.children.forEach((i:any)=>{ + i.children.sort((a:any, b:any) => { + if (this.sortType == 1) { + return a.node[key] - b.node[key] + }else if (this.sortType == 2) { + return b.node[key] - a.node[key] + } + }) + }); + }); + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + + + + +
+ `; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneFps.ts b/host/ide/src/trace/component/trace/sheet/fps/TabPaneFps.ts similarity index 51% rename from host/ide/src/trace/component/trace/sheet/TabPaneFps.ts rename to host/ide/src/trace/component/trace/sheet/fps/TabPaneFps.ts index c98bab228108ded48609e6dc37e0f80771b2db85..03c7947de332fe1c83dbb8736e3d00faf7c1e600 100644 --- a/host/ide/src/trace/component/trace/sheet/TabPaneFps.ts +++ b/host/ide/src/trace/component/trace/sheet/fps/TabPaneFps.ts @@ -13,11 +13,12 @@ * limitations under the License. */ -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import {SelectionParam} from "../../../bean/BoxSelection.js"; -import {getTabFps} from "../../../database/SqlLite.js"; -import {Utils} from "../base/Utils.js"; +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabFps} from "../../../../database/SqlLite.js"; +import {Utils} from "../../base/Utils.js"; +import {log} from "../../../../../log/Log.js"; @element('tabpane-fps') export class TabPaneFps extends BaseElement { @@ -28,42 +29,56 @@ export class TabPaneFps extends BaseElement { this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" getTabFps(val.leftNs, val.rightNs).then((result) => { if (result != null && result.length > 0) { + log("getTabFps result size : " + result.length) + let index = result.findIndex((d) => d.startNS >= val.leftNs); if (index != -1) { let arr = result.splice(index > 0 ? index - 1 : index) arr.map(e => e.timeStr = Utils.getTimeString(e.startNS)) - this.tbl!.dataSource = arr + this.tbl!.recycleDataSource = arr } else { let last = result[result.length - 1] last.timeStr = Utils.getTimeString(last.startNS) - this.tbl!.dataSource = [last] + this.tbl!.recycleDataSource = [last] } } else { - this.tbl!.dataSource = [] + this.tbl!.recycleDataSource = [] } }); } initElements(): void { this.tbl = this.shadowRoot?.querySelector('#tb-fps'); - this.range = this.shadowRoot?.querySelector('#time-range') + this.range = this.shadowRoot?.querySelector('#time-range'); + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!); } initHtml(): string { return ` - - - - - - + + + + + + + + `; } - } \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/freq/TabPaneCpuFreqLimits.ts b/host/ide/src/trace/component/trace/sheet/freq/TabPaneCpuFreqLimits.ts new file mode 100644 index 0000000000000000000000000000000000000000..edf9b36bf3523394e33bed96a6d0888a531b842d --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/freq/TabPaneCpuFreqLimits.ts @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {Utils} from "../../base/Utils.js"; +import {ColorUtils} from "../../base/ColorUtils.js"; +import {CpuFreqLimitsStruct} from "../../../../database/ui-worker/ProcedureWorkerCpuFreqLimits.js"; + +@element('tabpane-cpu-freq-limits') +export class TabPaneCpuFreqLimits extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private loadDataInCache: boolean = true; + private selectionParam:SelectionParam | null | undefined; + private source:CpuFreqLimit[] = [] + private sortKey: string = "cpu"; + private sortType: number = 0; + + set data(val: SelectionParam | any) { + if(val == this.selectionParam){ + return; + } + this.selectionParam = val; + // @ts-ignore + this.tbl!.shadowRoot!.querySelector(".table").style.height = (this.parentElement!.clientHeight - 25) + "px" + let list:any[] = [] + val.cpuFreqLimitDatas.forEach((limitRowDatas:any)=>{ + for (let i = 0, len = limitRowDatas.length; i < len; i++) { + let it = limitRowDatas[i]; + if(it.startNs > val.rightNs){ + break; + } + if (i === limitRowDatas.length - 1) { + it.dur = (val.rightNs || 0) - (it.startNs || 0) + } else { + it.dur = (limitRowDatas[i + 1].startNs || 0) - (it.startNs || 0) + } + list.push(it) + } + }) + this.formatData(list,val.leftNs,val.rightNs) + } + + initElements(): void { + this.tbl = this.shadowRoot!.querySelector('#tb-states'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key + // @ts-ignore + this.sortType = evt.detail.sort + // @ts-ignore + this.sortTable(evt.detail.key,evt.detail.sort) + }) + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement!.clientHeight != 0) { + // @ts-ignore + this.tbl!.shadowRoot!.querySelector(".table").style.height = (this.parentElement!.clientHeight - 25) + "px" + this.tbl!.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + formatData(list:CpuFreqLimitsStruct[],start:number,end:number){ + let limitsMap = new Map(); + let groupMapData = (time:number,id:string,item:CpuFreqLimitsStruct) => { + if (limitsMap.has(id)) { + limitsMap.get(id)!.time += (time) + }else { + let isMax = id.endsWith("max"); + let limit = new CpuFreqLimit(); + limit.cpu = `Cpu ${item.cpu}`; + limit.time = time; + limit.type = isMax?"Max Freqency":"Min Frequency" + limit.value = isMax?item.max!:item.min!; + limitsMap.set(id,limit) + } + } + list.forEach((item)=>{ + if(item.startNs!>end){ + return + } + let max = Math.max(item.startNs||0,start) + let min = Math.min((item.startNs||0)+item.dur,end) + if(max < min){ + let maxId = `${item.cpu}-${item.max}-max` + let minId = `${item.cpu}-${item.min}-min` + groupMapData(min - max,maxId,item) + groupMapData(min - max,minId,item) + } + }) + this.source = Array.from(limitsMap.values()).map((item) => { + item.timeStr = Utils.getProbablyTime(item.time); + item.valueStr = `${ColorUtils.formatNumberComma(item.value!)} kHz` + return item + }) + this.sortTable(this.sortKey,this.sortType) + } + + sortTable(key: string,type:number){ + if(type == 0){ + this.tbl!.recycleDataSource = this.source + }else{ + let arr = Array.from(this.source) + arr.sort((a,b):number=>{ + if(key == "timeStr"){ + if(type == 1){ + return a.time - b.time ; + }else{ + return b.time - a.time ; + } + }else if(key == "valueStr"){ + if(type == 1){ + return a.value - b.value ; + }else{ + return b.value - a.value ; + } + }else if(key == "cpu"){ + if (a.cpu > b.cpu) { + return type === 2 ? -1 : 1; + } else if (a.cpu == b.cpu) { + return 0; + } else { + return type === 2 ? 1 : -1; + } + }else if(key == "type"){ + if (a.type > b.type) { + return type === 2 ? 1 : -1; + } else if (a.type == b.type) { + return 0; + } else { + return type === 2 ? -1 : 1; + } + }else{ + return 0; + } + }) + this.tbl!.recycleDataSource = arr; + } + } + + initHtml(): string { + return ` + + + + + + + + + + + + `; + } +} + +class CpuFreqLimit{ + cpu:string = ""; + type:string = ""; + time:number = 0; + value:number = 0; + timeStr:string = ""; + valueStr:string = ""; + +} diff --git a/host/ide/src/trace/component/trace/sheet/freq/TabPaneFreq.ts b/host/ide/src/trace/component/trace/sheet/freq/TabPaneFreq.ts new file mode 100644 index 0000000000000000000000000000000000000000..5ee9e46be4587db92ef740abe8e5eaf13609dda0 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/freq/TabPaneFreq.ts @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {ColorUtils} from "../../base/ColorUtils.js"; +import {Utils} from "../../base/Utils.js"; + +@element('tabpane-freq') +export class TabPaneFreq extends BaseElement { + private tbl: LitTable | null | undefined; + + set data(freq:any) { + if(freq){ + this.tbl!.dataSource = [{ + startNS:Utils.getTimeString(freq.startNS >=0?freq.startNS:0), + absoluteTime:(freq.startNS + (window as any).recordStartNS)/1000000000, + dur:Utils.getProbablyTime(freq.dur), + freq:`${ColorUtils.formatNumberComma(freq.value!)} kHz`, + cpu:`Cpu ${freq.cpu}` + }] + } + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-freq'); + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!) + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + `; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/freq/TabPaneFreqLimit.ts b/host/ide/src/trace/component/trace/sheet/freq/TabPaneFreqLimit.ts new file mode 100644 index 0000000000000000000000000000000000000000..a2422133a291314aa7a2edb03d637474e50d0721 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/freq/TabPaneFreqLimit.ts @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {ColorUtils} from "../../base/ColorUtils.js"; +import {Utils} from "../../base/Utils.js"; + +@element('tabpane-freq-limit') +export class TabPaneFreqLimit extends BaseElement { + private tbl: LitTable | null | undefined; + + set data(freq:any) { + if(freq){ + this.tbl!.dataSource = [{ + startNs:Utils.getTimeString(freq.startNs >=0?freq.startNs:0), + absoluteTime:(freq.startNs + (window as any).recordStartNS)/1000000000, + dur:Utils.getProbablyTime(freq.dur), + maxFreq:`${ColorUtils.formatNumberComma(freq.max!)} kHz`, + minFreq:`${ColorUtils.formatNumberComma(freq.min!)} kHz`, + cpu:`Cpu ${freq.cpu}` + }] + } + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-freq'); + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!) + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + + + `; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.ts b/host/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..28b6425200c7774f509c926dff8f1380159f090e --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.ts @@ -0,0 +1,658 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import "../TabPaneFilter.js"; +import {FilterData, TabPaneFilter} from "../TabPaneFilter.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {PerfCallChainMerageData} from "../../../../bean/PerfProfile.js"; +import "../../../chart/FrameChart.js"; +import {FrameChart} from "../../../chart/FrameChart.js"; +import {ChartMode} from "../../../../bean/FrameChartStruct.js"; +import '../../../DisassemblingWindow.js' +import {DisassemblingWindow} from "../../../DisassemblingWindow.js"; +import {Cmd} from "../../../../../command/Cmd.js"; +import {SpApplication} from "../../../../SpApplication.js"; +import "../../../../../base-ui/slicer/lit-slicer.js"; +import "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {query, queryPerfSampleIdsByTimeRange} from "../../../../database/SqlLite.js"; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {procedurePool} from "../../../../database/Procedure.js"; +import {SpHiPerf} from "../../../chart/SpHiPerf.js"; + +@element('tabpane-perf-profile') +export class TabpanePerfProfile extends BaseElement { + private tbl: LitTable | null | undefined; + private tbr: LitTable | null | undefined; + private progressEL:LitProgressBar | null | undefined; + private rightSource: Array = []; + private filter: any + private dataSource: any[] = [] + private sortKey = "weight"; + private sortType = 0; + private currentSelectedData: any = undefined + private frameChart: FrameChart | null | undefined; + private isChartShow: boolean = false; + private systmeRuleName = "/system/" + private numRuleName = "/max/min/" + private modal: DisassemblingWindow | null | undefined; + private needShowMenu = true; + private searchValue: string = "" + private loadingList:number[] = [] + private loadingPage:any; + private currentSelection:SelectionParam|undefined + private isCurrentIsTopDown:boolean = true + + set data(val: SelectionParam | any) { + if(val == this.currentSelection){ + return; + } + this.searchValue = ""; + this.currentSelection = val + this.modal!.style.display = 'none'; + this.tbl!.style.visibility = "visible"; + if (this.parentElement!.clientHeight > this.filter!.clientHeight) { + this.filter!.style.display = "flex"; + } else { + this.filter!.style.display = "none"; + } + this.filter!.initializeFilterTree(true, true, true) + this.filter!.filterValue = "" + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + this.isCurrentIsTopDown = true; + this.getDataByWorker([{ + funcName: "setSearchValue", + funcArgs: [""] + }, { + funcName: "getCurrentDataFromDb", + funcArgs: [val] + }], (results: any[]) => { + this.setLTableData(results) + this.tbr!.recycleDataSource = [] + this.frameChart!.mode = ChartMode.Count; + this.frameChart!.data = this.dataSource; + this.frameChart?.updateCanvas(true, this.clientWidth); + this.frameChart?.calculateChartData(); + }) + } + + getParentTree(src: Array, target: PerfCallChainMerageData, parents: Array): boolean { + for (let call of src) { + if (call.id == target.id) { + parents.push(call) + return true + } else { + if (this.getParentTree(call.children as Array, target, parents)) { + parents.push(call); + return true; + } + } + } + return false; + } + + getChildTree(src: Array, id: string, children: Array): boolean { + for (let call of src) { + if (call.id == id && call.children.length == 0) { + children.push(call) + return true + } else { + if (this.getChildTree(call.children as Array, id, children)) { + children.push(call); + return true; + } + } + } + return false; + } + + setRightTableData(call: PerfCallChainMerageData) { + let parents: Array = []; + let children: Array = []; + this.getParentTree(this.dataSource, call, parents); + let maxId = call.id; + let maxDur = 0; + + function findMaxStack(call: PerfCallChainMerageData) { + if (call.children.length == 0) { + if (call.dur > maxDur) { + maxDur = call.dur; + maxId = call.id; + } + } else { + call.children.map((callChild) => { + findMaxStack(callChild); + }) + } + } + + findMaxStack(call); + this.getChildTree(call.children as Array, maxId, children); + let arr = parents.reverse().concat(children.reverse()); + for (let data of arr) { + data.type = (data.libName.endsWith(".so.1") || data.libName.endsWith(".dll") || data.libName.endsWith(".so")) ? 0 : 1; + } + let len = arr.length; + this.rightSource = arr; + let rightSource:Array = [] + if(len != 0){ + rightSource = this.rightSource.filter((item)=>{ + return item.canCharge + }) + } + this.tbr!.dataSource = rightSource; + } + + showButtomMenu(isShow: boolean) { + if (isShow) { + this.filter.setAttribute('tree', ''); + this.filter.setAttribute('input', ''); + this.filter.setAttribute('inputLeftText', ''); + } else { + this.filter.removeAttribute('tree'); + this.filter.removeAttribute('input'); + this.filter.removeAttribute('inputLeftText') + } + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-perf-profile'); + this.progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar + this.frameChart = this.shadowRoot?.querySelector('#framechart'); + this.modal = this.shadowRoot?.querySelector('tab-native-data-modal'); + this.loadingPage = this.shadowRoot?.querySelector('.loading'); + this.frameChart!.addChartClickListener((needShowMenu: boolean) => { + this.parentElement!.scrollTo(0, 0); + this.showButtomMenu(needShowMenu) + this.needShowMenu = needShowMenu; + }); + this.tbl!.rememberScrollTop = true; + this.filter = this.shadowRoot?.querySelector("#filter") + this.tbl!.addEventListener('row-click', (evt: any) => { + // @ts-ignore + let data = (evt.detail.data as PerfCallChainMerageData); + this.setRightTableData(data); + data.isSelected = true; + this.currentSelectedData = data; + this.tbr?.clearAllSelection(data); + this.tbr?.setCurrentSelection(data); + // @ts-ignore + if ((evt.detail as any).callBack) { + // @ts-ignore + (evt.detail as any).callBack(true) + } + }) + this.tbr = this.shadowRoot?.querySelector('#tb-perf-list'); + let lastClikTime = 0; + this.tbr!.addEventListener('row-click', (evt: any) => { + // @ts-ignore + let data = (evt.detail.data as PerfCallChainMerageData); + this.tbl?.clearAllSelection(data); + (data as any).isSelected = true + this.tbl!.scrollToData(data) + // @ts-ignore + if ((evt.detail as any).callBack) { + // @ts-ignore + (evt.detail as any).callBack(true) + } + let spApplication = document.getElementsByTagName("sp-application")[0]; + if (Date.now() - lastClikTime < 200 && spApplication.vs) { + this.tbl!.style.visibility = "hidden"; + this.filter.style.display = "none"; + new ResizeObserver((entries) => { + this.modal!.style.width = this.tbl!.clientWidth + 'px'; + this.modal!.style.height = this.tbl!.clientHeight + 'px'; + }).observe(this.tbl!) + this.modal!.showLoading(); + // @ts-ignore + let data = (evt.detail.data as PerfCallChainMerageData); + let path = data.path; + let addr = data.vaddrInFile; + let addrHex = addr.toString(16); + if (path.trim() === '[kernel.kallsyms]') { + this.modal?.showContent(`error : Symbol ${data.symbol} lib is [kernel.kallsyms] ,not support `, addrHex); + } else if (path.trim() === '') { + this.modal?.showContent(`error : Symbol ${data.symbol} lib is null `, addrHex); + } else if (addr < 0) { + this.modal?.showContent(`error : Symbol ${data.symbol} current addr is error ` + addrHex, addrHex); + } else { + const binDir = 'C:/binary_cache'; + let binPath = binDir + path; + let cmd = 'C:/binary_cache/llvm-objdump.exe -S ' + binPath; + Cmd.execObjDump(cmd, addrHex, (result: any) => { + this.modal?.showContent(result, addrHex); + }) + } + } + lastClikTime = Date.now(); + }) + this.modal!.setCloseListener(() => { + this.modal!.style.display = 'none'; + this.tbl!.style.visibility = "visible"; + this.shadowRoot!.querySelector("#filter")!.style.display = 'flex'; + }); + this.tbr = this.shadowRoot?.querySelector('#tb-perf-list'); + let filterFunc = (data: any) => { + let args: any[] = [] + if (data.type == "check") { + if (data.item.checked) { + args.push({ + funcName: "splitTree", + funcArgs: [data.item.name, data.item.select == "0", data.item.type == "symbol"] + }) + } else { + args.push({ + funcName: "resotreAllNode", + funcArgs: [[data.item.name]] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + args.push({ + funcName: "clearSplitMapData", + funcArgs: [data.item.name] + }) + } + } else if (data.type == "select") { + args.push({ + funcName: "resotreAllNode", + funcArgs: [[data.item.name]] + }) + args.push({ + funcName: "clearSplitMapData", + funcArgs: [data.item.name] + }) + args.push({ + funcName: "splitTree", + funcArgs: [data.item.name, data.item.select == "0", data.item.type == "symbol"] + }) + } else if (data.type == "button") { + if (data.item == "symbol") { + if (this.currentSelectedData && !this.currentSelectedData.canCharge) { + return + } + if (this.currentSelectedData != undefined) { + this.filter!.addDataMining({name: this.currentSelectedData.symbolName}, data.item) + args.push({ + funcName: "splitTree", + funcArgs: [this.currentSelectedData.symbolName, false, true] + }) + } else { + return + } + } else if (data.item == "library") { + if (this.currentSelectedData && !this.currentSelectedData.canCharge) { + return + } + if (this.currentSelectedData != undefined && this.currentSelectedData.libName != "") { + this.filter!.addDataMining({name: this.currentSelectedData.libName}, data.item) + args.push({ + funcName: "splitTree", + funcArgs: [this.currentSelectedData.libName, false, false] + }) + } else { + return + } + } else if (data.item == "restore") { + if (data.remove != undefined && data.remove.length > 0) { + let list = data.remove.map((item: any) => { + return item.name + }) + args.push({ + funcName: "resotreAllNode", + funcArgs: [list] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + list.forEach((symbolName: string) => { + args.push({ + funcName: "clearSplitMapData", + funcArgs: [symbolName] + }) + }) + } + } + } + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + if (this.isChartShow) this.frameChart?.calculateChartData(); + this.tbl!.move1px() + if (this.currentSelectedData) { + this.currentSelectedData.isSelected = false; + this.tbl?.clearAllSelection(this.currentSelectedData) + this.tbr!.recycleDataSource = [] + this.currentSelectedData = undefined + } + }) + } + this.filter!.getDataLibrary(filterFunc) + this.filter!.getDataMining(filterFunc) + this.filter!.getCallTreeData((data: any) => { + if (data.value == 0) { + this.refreshAllNode({...this.filter!.getFilterTreeData(), callTree: data.checks}) + } else { + let args: any[] = [] + if (data.checks[1]) { + args.push({ + funcName: "hideSystemLibrary", + funcArgs: [] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + } else { + args.push({ + funcName: "resotreAllNode", + funcArgs: [[this.systmeRuleName]] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + args.push({ + funcName: "clearSplitMapData", + funcArgs: [this.systmeRuleName] + }) + } + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + if (this.isChartShow) this.frameChart?.calculateChartData(); + }) + + } + }) + this.filter!.getCallTreeConstraintsData((data: any) => { + let args: any[] = [{ + funcName: "resotreAllNode", + funcArgs: [[this.numRuleName]] + }, { + funcName: "clearSplitMapData", + funcArgs: [this.numRuleName] + }] + if (data.checked) { + args.push({ + funcName: "hideNumMaxAndMin", + funcArgs: [parseInt(data.min), data.max] + }) + } + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + if (this.isChartShow) this.frameChart?.calculateChartData(); + }) + + }) + this.filter!.getFilterData((data: FilterData) => { + if (this.searchValue != this.filter!.filterValue) { + this.searchValue = this.filter!.filterValue + let args = [ + { + funcName: "setSearchValue", + funcArgs: [this.searchValue] + }, + { + funcName: "resetAllNode", + funcArgs: [] + } + ] + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + this.switchFlameChart(data) + }) + }else { + this.switchFlameChart(data) + } + + }) + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key + // @ts-ignore + this.sortType = evt.detail.sort + // @ts-ignore + this.setLTableData(this.dataSource) + this.frameChart!.data = this.dataSource; + }); + } + + connectedCallback() { + super.connectedCallback(); + this.parentElement!.onscroll = () => { + this.frameChart!.tabPaneScrollTop = this.parentElement!.scrollTop; + }; + let filterHeight = 0; + new ResizeObserver((entries) => { + let tabPaneFilter = this.shadowRoot!.querySelector("#filter") as HTMLElement; + if (tabPaneFilter.clientHeight > 0) filterHeight = tabPaneFilter.clientHeight; + if (this.parentElement!.clientHeight > filterHeight) { + tabPaneFilter.style.display = "flex"; + } else { + tabPaneFilter.style.display = "none"; + } + this.modal!.style.height = this.tbl!.clientHeight - 2 + 'px'; //2 is borderWidth + if (this.tbl!.style.visibility == "hidden") { + tabPaneFilter.style.display = "none"; + } + if (this.parentElement?.clientHeight != 0) { + if (this.isChartShow) { + this.frameChart?.updateCanvas(false, entries[0].contentRect.width); + this.frameChart?.calculateChartData(); + } + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 10 - 35) + "px" + this.tbl?.reMeauseHeight() + // @ts-ignore + this.tbr?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45 - 21) + "px" + this.tbr?.reMeauseHeight() + this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px" + } + }).observe(this.parentElement!); + } + + switchFlameChart(data:any){ + let pageTab = this.shadowRoot?.querySelector('#show_table'); + let pageChart = this.shadowRoot?.querySelector('#show_chart'); + if (data.icon == 'block') { + pageChart?.setAttribute('class', 'show'); + pageTab?.setAttribute('class', ''); + this.isChartShow = true; + this.filter!.disabledMining = true; + this.showButtomMenu(this.needShowMenu); + this.frameChart!.data = this.dataSource; + this.frameChart?.calculateChartData(); + } else if (data.icon == 'tree') { + pageChart?.setAttribute('class', ''); + pageTab?.setAttribute('class', 'show'); + this.showButtomMenu(true); + this.isChartShow = false; + this.filter!.disabledMining = false; + this.frameChart!.clearCanvas(); + this.tbl!.reMeauseHeight() + } + } + + + refreshAllNode(filterData: any) { + let args:any[] = [] + let isTopDown: boolean = !filterData.callTree[0]; + this.isCurrentIsTopDown = isTopDown + let isHideSystemLibrary = filterData.callTree[1]; + let list = filterData.dataMining.concat(filterData.dataLibrary); + args.push({ + funcName: "getCallChainsBySampleIds", + funcArgs: [isTopDown] + }) + this.tbr!.recycleDataSource = [] + if (isHideSystemLibrary) { + args.push({ + funcName: "hideSystemLibrary", + funcArgs: [] + }) + } + if (filterData.callTreeConstraints.checked) { + args.push({ + funcName: "hideNumMaxAndMin", + funcArgs: [parseInt(filterData.callTreeConstraints.inputs[0]), filterData.callTreeConstraints.inputs[1]] + }) + } + args.push({ + funcName: "splitAllProcess", + funcArgs: [list] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + if (this.isChartShow) this.frameChart?.calculateChartData(); + }) + } + + setLTableData(resultData:any[]) { + this.dataSource = this.sortTree(resultData) + this.tbl!.recycleDataSource = this.dataSource + } + + sortTree(arr: Array): Array { + let sortArr = arr.sort((a, b) => { + if (this.sortKey == 'self') { + if (this.sortType == 0) { + return b.dur - a.dur; + } else if (this.sortType == 1) { + return a.selfDur - b.selfDur; + } else { + return b.selfDur - a.selfDur; + } + } else { + if (this.sortType == 0) { + return b.dur - a.dur; + } else if (this.sortType == 1) { + return a.dur - b.dur; + } else { + return b.dur - a.dur; + } + } + }) + sortArr.map((call) => { + call.children = this.sortTree(call.children); + }) + return sortArr; + } + + getDataByWorker(args: any[], handler: Function) { + this.loadingList.push(1) + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + procedurePool.submitWithName("logic0","perf-action",args,undefined,(results:any)=>{ + handler(results) + this.loadingList.splice(0,1) + if(this.loadingList.length == 0) { + this.progressEL!.loading = false + this.loadingPage.style.visibility = "hidden" + } + }) + } + + initHtml(): string { + return ` + +
+ + + +
+ + + + + + + + +
+ + + Heaviest Stack Trace + + + + + +
+ + + + + + + +
+
`; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/hiperf/TabPerfSampleList.ts b/host/ide/src/trace/component/trace/sheet/hiperf/TabPerfSampleList.ts new file mode 100644 index 0000000000000000000000000000000000000000..80503ad6e38b26c3ea935851e0323558efaf7858 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/hiperf/TabPerfSampleList.ts @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {perfDataQuery} from "../../../chart/PerfDataQuery.js"; +import {queryPerfProcess, queryPerfSampleCallChain, queryPerfSampleListByTimeRange} from "../../../../database/SqlLite.js"; +import {PerfFile, PerfSample, PerfStack, PerfThread} from "../../../../bean/PerfProfile.js"; +import {Utils} from "../../base/Utils.js"; +import '../../../DisassemblingWindow.js' +import {DisassemblingWindow} from "../../../DisassemblingWindow.js"; +import {SpApplication} from "../../../../SpApplication.js"; +import {log} from "../../../../../log/Log.js"; +import "../../../../../base-ui/slicer/lit-slicer.js"; +import {Cmd} from "../../../../../command/Cmd.js"; + +@element('tabpane-perf-sample') +export class TabPanePerfSample extends BaseElement { + private tbl: LitTable | null | undefined; + private tblData: LitTable | null | undefined; + private source: Array = []; + private processMap: Map = new Map(); + private modal: DisassemblingWindow | null | undefined; + private sortKey: string = "timeString"; + private sortType: number = 0; + + set data(val: SelectionParam | null | undefined) { + this.modal!.style.display = 'none'; + this.tbl!.style.visibility = "visible"; + // @ts-ignore + this.tbl?.shadowRoot?.querySelector(".table")?.style?.height = (this.parentElement!.clientHeight - 40) + "px"; + this.tbl!.recycleDataSource = []; + // @ts-ignore + this.tblData?.shadowRoot?.querySelector(".table")?.style?.height = (this.parentElement!.clientHeight - 25) + "px"; + this.tblData!.recycleDataSource = []; + if (val) { + Promise.all([queryPerfProcess(), + queryPerfSampleListByTimeRange(val.leftNs, val.rightNs, val.perfAll ? [] : val.perfCpus, val.perfAll ? [] : val.perfProcess, val.perfAll ? [] : val.perfThread) + ]).then((results) => { + let processes = results[0] as Array; + log("queryPerfProcess size : " + processes.length) + let samples = results[1] as Array; + log("queryPerfSampleListByTimeRange size : " + samples.length) + this.processMap.clear(); + for (let process of processes) { + this.processMap.set(process.pid, process) + } + for (let sample of samples) { + let process = this.processMap.get(sample.pid); + sample.processName = process == null || process == undefined ? `Process(${sample.pid})` : `${process!.processName||'Process'}(${sample.pid})`; + sample.threadName = sample.threadName == null || sample.threadName == undefined ? `Thread(${sample.tid})` : `${sample.threadName}(${sample.tid})`; + sample.coreName = `CPU ${sample.core}`; + sample.timeString = Utils.getTimeString(sample.time); + sample.backtrace = []; + let call = perfDataQuery.callChainMap.get(sample.sampleId); + if (call == undefined || call == null) { + sample.depth = 0; + sample.backtrace.push("No Effective Call Stack") + } else { + sample.depth = call.depth; + sample.backtrace.push(call.name) + sample.backtrace.push(`(${sample.depth} other frames)`); + } + } + this.source = samples; + this.sortTable(this.sortKey,this.sortType) + }) + } + } + + setRightTableData(sample: PerfSample) { + queryPerfSampleCallChain(sample.sampleId).then((result) => { + for (let stack of result) { + let files = (perfDataQuery.filesData[stack.fileId] ?? []) as Array; + stack.path = files[stack.symbolId].path + stack.type = (stack.path.endsWith(".so.1") || stack.path.endsWith(".dll") || stack.path.endsWith(".so")) ? 0 : 1; + } + this.tblData!.dataSource = result + }) + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-perf-sample'); + this.tblData = this.shadowRoot?.querySelector('#tb-stack-data'); + this.modal = this.shadowRoot?.querySelector('tab-native-data-modal'); + this.tbl!.addEventListener('row-click', (e) => { + // @ts-ignore + let data = (e.detail.data as PerfSample); + this.setRightTableData(data); + }); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key + // @ts-ignore + this.sortType = evt.detail.sort + // @ts-ignore + this.sortTable(evt.detail.key,evt.detail.sort) + }) + let lastClikTime = 0; + let spApplication = document.getElementsByTagName("sp-application")[0]; + this.tblData!.addEventListener("row-click", (e) => { + if (Date.now() - lastClikTime < 200 && spApplication.vs){ + this.tbl!.style.visibility = "hidden"; + new ResizeObserver((entries) => { + this.modal!.style.width = this.tbl!.clientWidth + 'px'; + this.modal!.style.height = this.tbl!.clientHeight + 'px'; + }).observe(this.tbl!) + this.modal!.showLoading(); + // @ts-ignore + let data = (e.detail.data as PerfStack); + let path = data.path; + let addr = data.vaddrInFile; + let addrHex = addr.toString(16); + if (path.trim() === '[kernel.kallsyms]') { + this.modal?.showContent(`error : Symbol ${data.symbol} lib is [kernel.kallsyms] ,not support `, addrHex); + } else if (path.trim() === '') { + this.modal?.showContent(`error : Symbol ${data.symbol} lib is null `, addrHex); + } else if (addr < 0) { + this.modal?.showContent(`error : Symbol ${data.symbol} current addr is error ` + addrHex, addrHex); + } else { + const binDir = 'C:/binary_cache'; + let binPath = binDir + path; + let cmd = 'C:/binary_cache/llvm-objdump.exe -S ' + binPath; + Cmd.execObjDump(cmd, addrHex, (result: any) => { + this.modal?.showContent(result, addrHex); + }) + } + } + lastClikTime = Date.now(); + }); + this.modal!.setCloseListener(() => { + this.modal!.style.display = 'none'; + this.tbl!.style.visibility = "visible"; + }); + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 40) + "px" + // @ts-ignore + this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 25) + "px" + this.tbl?.reMeauseHeight() + this.tblData?.reMeauseHeight(); + } + this.modal!.style.height = this.tbl!.clientHeight - 2 + 'px'; //2 is borderWidth + }).observe(this.parentElement!); + } + + sortTable(key: string,type:number){ + this.source.sort((a,b):number=>{ + if(key == "timeString"){ + if(type == 0){ + return a.time - b.time ; + }else if(type == 1){ + return a.time - b.time ; + }else{ + return b.time - a.time ; + } + }else { + if(type == 0){ + return a.core - b.core ; + }else if(type == 1){ + return a.core - b.core ; + }else{ + return b.core - a.core ; + } + } + }) + this.tbl!.recycleDataSource = this.source; + } + + initHtml(): string { + return ` + +
+ +
+ + + + + + + + + + + +
+ + + + + + + +
+
`; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMCallInfo.ts b/host/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMCallInfo.ts new file mode 100644 index 0000000000000000000000000000000000000000..f61ea9f58ff9d2cbd3fc63988fa4bd1257930663 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMCallInfo.ts @@ -0,0 +1,420 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {query, queryNativeHookEventTid} from "../../../../database/SqlLite.js"; +import {NativeHookCallInfo, NativeHookStatistics} from "../../../../bean/NativeHook.js"; +import "../TabPaneFilter.js" +import {FilterData, TabPaneFilter} from "../TabPaneFilter.js"; +import "../../../chart/FrameChart.js"; +import "../../../../../base-ui/slicer/lit-slicer.js"; +import {FrameChart} from "../../../chart/FrameChart.js"; +import {ChartMode} from "../../../../bean/FrameChartStruct.js"; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {procedurePool} from "../../../../database/Procedure.js"; + + +@element('tabpane-native-callinfo') +export class TabPaneNMCallInfo extends BaseElement { + private tbl: LitTable | null | undefined; + private tblData: LitTable | null | undefined; + private progressEL:LitProgressBar | null | undefined; + private loadingList:number[] = [] + private loadingPage:any; + private source: Array = [] + private rightSource: Array = [] + private queryResult: Array = [] + private native_type: Array = ["All Heap & Anonymous VM", "All Heap", "All Anonymous VM"]; + private filterAllocationType: string = "0" + private filterNativeType: string = "0" + private currentSelection: SelectionParam | undefined + private frameChart: FrameChart | null | undefined; + private isChartShow: boolean = false; + private sortColumn: string = ''; + private sortType: number = 0; + + set data(val: SelectionParam | any) { + if(val == this.currentSelection){ + return; + } + this.currentSelection = val + this.initFilterTypes() + let types: Array = [] + if (val.nativeMemory.indexOf(this.native_type[0]) != -1) { + types.push("'AllocEvent'"); + types.push("'MmapEvent'"); + } else { + if (val.nativeMemory.indexOf(this.native_type[1]) != -1) { + types.push("'AllocEvent'"); + } + if (val.nativeMemory.indexOf(this.native_type[2]) != -1) { + types.push("'MmapEvent'"); + } + } + // @ts-ignore + this.tbl?.shadowRoot?.querySelector(".table").style.height = (this.parentElement.clientHeight - 20 - 31) + "px" + // @ts-ignore + this.tblData?.shadowRoot?.querySelector(".table").style.height = (this.parentElement.clientHeight) + "px" + // @ts-ignore + this.tblData?.recycleDataSource = []; + // @ts-ignore + this.tbl?.recycleDataSource = []; + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + queryNativeHookEventTid(val.leftNs, val.rightNs, types).then((result) => { + this.queryResult = result; + this.getDataByNativeMemoryWorker(val) + }) + } + + getDataByNativeMemoryWorker(val: SelectionParam | any){ + let args = new Map(); + args.set("data",this.queryResult); + args.set("filterAllocType",this.filterAllocationType); + args.set("filterEventType",this.filterNativeType); + args.set("leftNs",val.leftNs); + args.set("rightNs",val.rightNs); + args.set("actionType","call-info"); + this.startWorker(args,(results: any[]) => { + this.tblData!.recycleDataSource = [] + this.progressEL!.loading = false + if (results.length > 0) { + this.source = results; + this.sortTreeByColumn(this.sortColumn,this.sortType); + this.frameChart!.mode = ChartMode.Byte; + this.frameChart!.data = this.source; + this.frameChart?.updateCanvas(true,this.clientWidth); + this.frameChart?.calculateChartData(); + }else { + this.source = [] + this.tbl!.recycleDataSource = []; + this.frameChart!.data = []; + this.frameChart!.clearCanvas() + } + }) + } + + startWorker(args: Map, handler: Function) { + this.loadingList.push(1) + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + procedurePool.submitWithName("logic1","native-memory-action",args,undefined,(res:any)=>{ + handler(res); + this.loadingList.splice(0,1) + if(this.loadingList.length == 0) { + this.progressEL!.loading = false + this.loadingPage.style.visibility = "hidden" + } + }) + } + + getParentTree(src: Array, target: NativeHookCallInfo, parents: Array): boolean { + for (let hook of src) { + if (hook.id == target.id) { + parents.push(hook) + return true + } else { + if (this.getParentTree(hook.children as Array, target, parents)) { + parents.push(hook); + return true; + } + } + } + return false; + } + + getChildTree(src: Array, eventId: number, children: Array): boolean { + for (let hook of src) { + if (hook.eventId == eventId && hook.children.length == 0) { + children.push(hook) + return true + } else { + if (this.getChildTree(hook.children as Array, eventId, children)) { + children.push(hook); + return true; + } + } + } + return false; + } + + setRightTableData(hook: NativeHookCallInfo) { + let parents: Array = []; + let children: Array = []; + this.getParentTree(this.source, hook, parents); + let maxEventId = hook.eventId; + let maxHeap = 0; + + function findMaxStack(hook: NativeHookCallInfo) { + if (hook.children.length == 0) { + if (hook.size > maxHeap) { + maxHeap = hook.size; + maxEventId = hook.eventId; + } + } else { + hook.children.map((hookChild) => { + findMaxStack(hookChild); + }) + } + } + + findMaxStack(hook); + this.getChildTree(hook.children as Array, maxEventId, children); + this.rightSource = parents.reverse().concat(children.reverse()); + let len = this.rightSource.length; + // @ts-ignore + this.tblData?.dataSource = len == 0 ? [] : this.rightSource.slice(1, len); + + } + + initFilterTypes() { + let filter = this.shadowRoot?.querySelector("#filter") + this.queryResult = [] + filter!.firstSelect = "0" + filter!.secondSelect = "0" + this.filterAllocationType = "0" + this.filterNativeType = "0" + } + + sortTreeByColumn(column:string,sort:number){ + this.sortColumn = column; + this.sortType = sort; + this.tbl!.recycleDataSource = this.sortTree(this.source,column,sort) + } + + sortTree(arr: Array, column: string, sort: number): Array { + let sortArr = arr.sort((a, b) => { + if (column == 'size') { + if (sort == 0) { + return a.eventId - b.eventId; + } else if (sort == 1) { + return a.size - b.size; + } else { + return b.size - a.size; + } + } else { + if (sort == 0) { + return a.eventId - b.eventId; + } else if (sort == 1) { + return a.count - b.count; + } else { + return b.count - a.count; + } + } + }) + sortArr.map((call) => { + call.children = this.sortTree(call.children as Array, column, sort); + }) + return sortArr; + } + + showButtomMenu(isShow : boolean){ + let filter = this.shadowRoot?.querySelector("#filter")! + if (isShow) { + filter.setAttribute('first',''); + filter.setAttribute('second',''); + } else { + filter.removeAttribute('first'); + filter.removeAttribute('second'); + } + } + + initElements(): void { + this.loadingPage = this.shadowRoot?.querySelector('.loading'); + this.progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar + this.tbl = this.shadowRoot?.querySelector('#tb-native-callinfo'); + this.tblData = this.shadowRoot?.querySelector('#tb-native-data'); + this.frameChart = this.shadowRoot?.querySelector('#framechart'); + let pageTab = this.shadowRoot?.querySelector('#show_table'); + let pageChart = this.shadowRoot?.querySelector('#show_chart'); + this.frameChart?.addChartClickListener((showMenu : boolean) => { + this.parentElement!.scrollTo(0,0); + this.showButtomMenu(showMenu) + }); + + this.tbl!.addEventListener("row-click", (e) => { + // @ts-ignore + let data = (e.detail.data as NativeHookCallInfo); + this.setRightTableData(data); + data.isSelected = true; + this.tblData?.clearAllSelection(data) + this.tblData?.setCurrentSelection(data) + // @ts-ignore + if ((e.detail as any).callBack) { + // @ts-ignore + (e.detail as any).callBack(true) + } + }) + this.tblData!.addEventListener("row-click", (e) => { + // @ts-ignore + let detail = e.detail.data as NativeHookCallInfo; + this.tbl?.clearAllSelection(detail) + detail.isSelected = true + this.tbl!.scrollToData(detail); + // @ts-ignore + if ((e.detail as any).callBack) { + // @ts-ignore + (e.detail as any).callBack(true) + } + }) + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortTreeByColumn((evt.detail.key == "countValue"||evt.detail.key == "countPercent") ? 'countValue':'size',evt.detail.sort) + }); + + this.shadowRoot?.querySelector("#filter")!.getFilterData((data: FilterData) => { + this.filterAllocationType = data.firstSelect || "0" + this.filterNativeType = data.secondSelect || "0" + this.getDataByNativeMemoryWorker(this.currentSelection) + if (data.icon == 'block') { + pageChart?.setAttribute('class', 'show'); + pageTab?.setAttribute('class', ''); + this.isChartShow = true; + this.frameChart!.data = this.source; + this.frameChart?.calculateChartData(); + } else if (data.icon == 'tree') { + pageChart?.setAttribute('class', ''); + pageTab?.setAttribute('class', 'show'); + this.isChartShow = false; + this.frameChart!.clearCanvas(); + this.tbl!.reMeauseHeight(); + } + }); + this.initFilterTypes() + } + + connectedCallback() { + super.connectedCallback(); + this.parentElement!.onscroll = () => { + this.frameChart!.tabPaneScrollTop = this.parentElement!.scrollTop; + }; + let filterHeight = 0; + new ResizeObserver((entries) => { + let tabPaneFilter = this.shadowRoot!.querySelector("#filter") as HTMLElement; + if (tabPaneFilter.clientHeight > 0) filterHeight = tabPaneFilter.clientHeight; + if (this.parentElement!.clientHeight > filterHeight) { + tabPaneFilter.style.display = "flex"; + } else { + tabPaneFilter.style.display = "none"; + } + if (this.parentElement?.clientHeight != 0) { + if (!this.isChartShow) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) + "px" + this.tbl?.reMeauseHeight(); + } else { + // @ts-ignore + this.frameChart?.updateCanvas(false,entries[0].contentRect.width); + this.frameChart?.calculateChartData(); + } + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) - 10 - 31 + "px"; + this.tbl?.reMeauseHeight(); + // @ts-ignore + this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) - 10 - 31 + "px"; + this.tblData?.reMeauseHeight() + this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px" + } + }).observe(this.parentElement!); + } + + initHtml(): string { + return ` + +
+ + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+ + + + + +
+
+ `; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMCallTree.ts b/host/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMCallTree.ts new file mode 100644 index 0000000000000000000000000000000000000000..4b953ff3225bfd81d1b35f429851d65bda377ab5 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMCallTree.ts @@ -0,0 +1,702 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {FrameChart} from "../../../chart/FrameChart.js"; +import {DisassemblingWindow} from "../../../DisassemblingWindow.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {ChartMode} from "../../../../bean/FrameChartStruct.js"; +import {FilterData, TabPaneFilter} from "../TabPaneFilter.js"; +import {procedurePool} from "../../../../database/Procedure.js"; +import {FileMerageBean} from "../../../../database/logic-worker/ProcedureLogicWorkerFileSystem.js"; + +@element('tabpane-nm-calltree') +export class TabpaneNMCalltree extends BaseElement { + private tbl: LitTable | null | undefined; + private tbr: LitTable | null | undefined; + private progressEL:LitProgressBar | null | undefined; + private rightSource: Array = []; + private filter: any + private dataSource: any[] = [] + private native_type: Array = ["All Heap & Anonymous VM", "All Heap", "All Anonymous VM"]; + private sortKey = "heapSizeStr"; + private sortType = 0; + private currentSelectedData: any = undefined + private frameChart: FrameChart | null | undefined; + private isChartShow: boolean = false; + private systmeRuleName = "/system/" + private numRuleName = "/max/min/" + private modal: DisassemblingWindow | null | undefined; + private needShowMenu = true; + private searchValue: string = "" + private loadingList:number[] = [] + private loadingPage:any; + private currentSelection:SelectionParam|undefined + private filterAllocationType: string = "0" + private filterNativeType: string = "0" + private filterResponseType: number = -1 + private filterResponseSelect: string = "0" + private responseTypes:any[] = [] + + + set data(val: SelectionParam | any) { + if(val == this.currentSelection){ + return; + } + this.searchValue = ""; + this.currentSelection = val + this.modal!.style.display = 'none'; + this.tbl!.style.visibility = "visible"; + if (this.parentElement!.clientHeight > this.filter!.clientHeight) { + this.filter!.style.display = "flex"; + } else { + this.filter!.style.display = "none"; + } + this.filter!.initializeFilterTree(true, true, true) + this.filter!.filterValue = "" + this.initFilterTypes() + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + let types: Array = [] + if (val.nativeMemory.indexOf(this.native_type[0]) != -1) { + types.push("'AllocEvent'"); + types.push("'MmapEvent'"); + } else { + if (val.nativeMemory.indexOf(this.native_type[1]) != -1) { + types.push("'AllocEvent'"); + } + if (val.nativeMemory.indexOf(this.native_type[2]) != -1) { + types.push("'MmapEvent'"); + } + } + this.getDataByWorkerQuery({ + leftNs:val.leftNs, + rightNs:val.rightNs, + types + }, (results: any[]) => { + this.setLTableData(results) + this.tbr!.recycleDataSource = [] + this.frameChart!.mode = ChartMode.Byte; + this.frameChart!.data = this.dataSource; + this.frameChart?.updateCanvas(true, this.clientWidth); + this.frameChart?.calculateChartData(); + }) + } + + getParentTree(src: Array, target: FileMerageBean, parents: Array): boolean { + for (let call of src) { + if (call.id == target.id) { + parents.push(call) + return true + } else { + if (this.getParentTree(call.children as Array, target, parents)) { + parents.push(call); + return true; + } + } + } + return false; + } + + getChildTree(src: Array, id: string, children: Array): boolean { + for (let call of src) { + if (call.id == id && call.children.length == 0) { + children.push(call) + return true + } else { + if (this.getChildTree(call.children as Array, id, children)) { + children.push(call); + return true; + } + } + } + return false; + } + + setRightTableData(call: FileMerageBean) { + let parents: Array = []; + let children: Array = []; + this.getParentTree(this.dataSource, call, parents); + let maxId = call.id; + let maxDur = 0; + + function findMaxStack(call: any) { + if (call.children.length == 0) { + if (call.heapSize > maxDur) { + maxDur = call.heapSize; + maxId = call.id; + } + } else { + call.children.map((callChild:any) => { + findMaxStack(callChild); + }) + } + } + + findMaxStack(call); + this.getChildTree(call.children as Array, maxId, children); + let arr = parents.reverse().concat(children.reverse()); + for (let data of arr) { + data.type = (data.libName.endsWith(".so.1") || data.libName.endsWith(".dll") || data.libName.endsWith(".so")) ? 0 : 1; + } + let len = arr.length; + this.rightSource = arr; + this.tbr!.dataSource = len == 0 ? [] : arr + } + + showButtomMenu(isShow: boolean) { + if (isShow) { + this.filter.setAttribute('tree', ''); + this.filter.setAttribute('input', ''); + this.filter.setAttribute('inputLeftText', ''); + } else { + this.filter.removeAttribute('tree'); + this.filter.removeAttribute('input'); + this.filter.removeAttribute('inputLeftText') + } + } + + initFilterTypes() { + let filter = this.shadowRoot?.querySelector("#filter") + procedurePool.submitWithName("logic1","native-memory-get-responseType",{},undefined,(res:any)=> { + this.responseTypes = res; + let nullIndex = this.responseTypes.findIndex((item)=>{ + return item.key == 0 + }) + if(nullIndex!=-1){ + this.responseTypes.splice(nullIndex,1) + } + filter!.setSelectList(null, null,"Allocation Lifespan" + ,"Allocation Type",this.responseTypes.map((item:any)=>{ + return item.value + })) + filter!.setFilterModuleSelect("#first-select","width","150px") + filter!.setFilterModuleSelect("#second-select","width","150px") + filter!.setFilterModuleSelect("#third-select","width","150px") + filter!.firstSelect = "0" + filter!.secondSelect = "0" + filter!.thirdSelect = "0" + this.filterAllocationType = "0" + this.filterNativeType = "0" + this.filterResponseSelect = "0" + this.filterResponseType = -1; + }) + + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-filesystem-calltree'); + this.progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar + this.frameChart = this.shadowRoot?.querySelector('#framechart'); + this.modal = this.shadowRoot?.querySelector('tab-native-data-modal'); + this.loadingPage = this.shadowRoot?.querySelector('.loading'); + this.frameChart!.addChartClickListener((needShowMenu: boolean) => { + this.parentElement!.scrollTo(0, 0); + this.showButtomMenu(needShowMenu) + this.needShowMenu = needShowMenu; + }); + this.tbl!.rememberScrollTop = true; + this.filter = this.shadowRoot?.querySelector("#filter") + this.tbl!.addEventListener('row-click', (evt: any) => { + // @ts-ignore + let data = (evt.detail.data as FileMerageBean); + this.setRightTableData(data); + data.isSelected = true; + this.currentSelectedData = data; + this.tbr?.clearAllSelection(data); + this.tbr?.setCurrentSelection(data); + // @ts-ignore + if ((evt.detail as any).callBack) { + // @ts-ignore + (evt.detail as any).callBack(true) + } + }) + this.tbr = this.shadowRoot?.querySelector('#tb-filesystem-list'); + this.tbr!.addEventListener('row-click', (evt: any) => { + // @ts-ignore + let data = (evt.detail.data as FileMerageBean); + this.tbl?.clearAllSelection(data); + (data as any).isSelected = true + this.tbl!.scrollToData(data) + // @ts-ignore + if ((evt.detail as any).callBack) { + // @ts-ignore + (evt.detail as any).callBack(true) + } + }) + this.modal!.setCloseListener(() => { + this.modal!.style.display = 'none'; + this.tbl!.style.visibility = "visible"; + this.shadowRoot!.querySelector("#filter")!.style.display = 'flex'; + }); + let filterFunc = (data: any) => { + let args: any[] = [] + if (data.type == "check") { + if (data.item.checked) { + args.push({ + funcName: "splitTree", + funcArgs: [data.item.name, data.item.select == "0", data.item.type == "symbol"] + }) + } else { + args.push({ + funcName: "resotreAllNode", + funcArgs: [[data.item.name]] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + args.push({ + funcName: "clearSplitMapData", + funcArgs: [data.item.name] + }) + } + } else if (data.type == "select") { + args.push({ + funcName: "resotreAllNode", + funcArgs: [[data.item.name]] + }) + args.push({ + funcName: "clearSplitMapData", + funcArgs: [data.item.name] + }) + args.push({ + funcName: "splitTree", + funcArgs: [data.item.name, data.item.select == "0", data.item.type == "symbol"] + }) + } else if (data.type == "button") { + if (data.item == "symbol") { + if (this.currentSelectedData && !this.currentSelectedData.canCharge) { + return + } + if (this.currentSelectedData != undefined) { + this.filter!.addDataMining({name: this.currentSelectedData.symbolName}, data.item) + args.push({ + funcName: "splitTree", + funcArgs: [this.currentSelectedData.symbolName, false, true] + }) + } else { + return + } + } else if (data.item == "library") { + if (this.currentSelectedData && !this.currentSelectedData.canCharge) { + return + } + if (this.currentSelectedData != undefined && this.currentSelectedData.libName != "") { + this.filter!.addDataMining({name: this.currentSelectedData.libName}, data.item) + args.push({ + funcName: "splitTree", + funcArgs: [this.currentSelectedData.libName, false, false] + }) + } else { + return + } + } else if (data.item == "restore") { + if (data.remove != undefined && data.remove.length > 0) { + let list = data.remove.map((item: any) => { + return item.name + }) + args.push({ + funcName: "resotreAllNode", + funcArgs: [list] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + list.forEach((symbolName: string) => { + args.push({ + funcName: "clearSplitMapData", + funcArgs: [symbolName] + }) + }) + } + } + } + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + if (this.isChartShow) this.frameChart?.calculateChartData(); + this.tbl!.move1px() + if (this.currentSelectedData) { + this.currentSelectedData.isSelected = false; + this.tbl?.clearAllSelection(this.currentSelectedData) + this.tbr!.recycleDataSource = [] + this.currentSelectedData = undefined + } + }) + } + this.filter!.getDataLibrary(filterFunc) + this.filter!.getDataMining(filterFunc) + this.filter!.getCallTreeData((data: any) => { + if (data.value == 0) { + this.refreshAllNode({...this.filter!.getFilterTreeData(), callTree: data.checks}) + } else { + let args: any[] = [] + if (data.checks[1]) { + args.push({ + funcName: "hideSystemLibrary", + funcArgs: [] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + } else { + args.push({ + funcName: "resotreAllNode", + funcArgs: [[this.systmeRuleName]] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + args.push({ + funcName: "clearSplitMapData", + funcArgs: [this.systmeRuleName] + }) + } + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + if (this.isChartShow) this.frameChart?.calculateChartData(); + }) + + } + }) + this.filter!.getCallTreeConstraintsData((data: any) => { + let args: any[] = [{ + funcName: "resotreAllNode", + funcArgs: [[this.numRuleName]] + }, { + funcName: "clearSplitMapData", + funcArgs: [this.numRuleName] + }] + if (data.checked) { + args.push({ + funcName: "hideNumMaxAndMin", + funcArgs: [parseInt(data.min), data.max] + }) + } + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + if (this.isChartShow) this.frameChart?.calculateChartData(); + }) + + }) + this.filter!.getFilterData((data: FilterData) => { + if(this.filterAllocationType != data.firstSelect + || this.filterNativeType != data.secondSelect + || this.filterResponseSelect !=data.thirdSelect){ + this.filterAllocationType = data.firstSelect || "0" + this.filterNativeType = data.secondSelect || "0" + this.filterResponseSelect = data.thirdSelect || "0'" + let thirdIndex = parseInt(data.thirdSelect||"0") + if(this.responseTypes.length > thirdIndex){ + this.filterResponseType = this.responseTypes[thirdIndex].key||-1 + } + this.refreshAllNode(this.filter!.getFilterTreeData()) + }else if (this.searchValue != this.filter!.filterValue) { + this.searchValue = this.filter!.filterValue + let args = [ + { + funcName: "setSearchValue", + funcArgs: [this.searchValue] + }, + { + funcName: "resetAllNode", + funcArgs: [] + } + ] + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + this.switchFlameChart(data) + }) + }else { + this.switchFlameChart(data) + } + + }) + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key + // @ts-ignore + this.sortType = evt.detail.sort + // @ts-ignore + this.setLTableData(this.dataSource) + this.frameChart!.data = this.dataSource; + }); + } + + connectedCallback() { + super.connectedCallback(); + let filterHeight = 0; + new ResizeObserver((entries) => { + let tabPaneFilter = this.shadowRoot!.querySelector("#filter") as HTMLElement; + if (tabPaneFilter.clientHeight > 0) filterHeight = tabPaneFilter.clientHeight; + if (this.parentElement!.clientHeight > filterHeight) { + tabPaneFilter.style.display = "flex"; + } else { + tabPaneFilter.style.display = "none"; + } + this.modal!.style.height = this.tbl!.clientHeight - 2 + 'px'; //2 is borderWidth + if (this.tbl!.style.visibility == "hidden") { + tabPaneFilter.style.display = "none"; + } + if (this.parentElement?.clientHeight != 0) { + if (this.isChartShow) { + this.frameChart?.updateCanvas(false, entries[0].contentRect.width); + this.frameChart?.calculateChartData(); + } + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 10 - 35) + "px" + this.tbl?.reMeauseHeight() + // @ts-ignore + this.tbr?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45 - 21) + "px" + this.tbr?.reMeauseHeight() + this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px" + } + }).observe(this.parentElement!); + this.parentElement!.onscroll = () => { + this.frameChart!.tabPaneScrollTop = this.parentElement!.scrollTop; + }; + } + + switchFlameChart(data:any){ + let pageTab = this.shadowRoot?.querySelector('#show_table'); + let pageChart = this.shadowRoot?.querySelector('#show_chart'); + if (data.icon == 'block') { + pageChart?.setAttribute('class', 'show'); + pageTab?.setAttribute('class', ''); + this.isChartShow = true; + this.filter!.disabledMining = true; + this.showButtomMenu(this.needShowMenu); + this.frameChart!.data = this.dataSource; + this.frameChart?.calculateChartData(); + } else if (data.icon == 'tree') { + pageChart?.setAttribute('class', ''); + pageTab?.setAttribute('class', 'show'); + this.showButtomMenu(true); + this.isChartShow = false; + this.filter!.disabledMining = false; + this.frameChart!.clearCanvas(); + this.tbl!.reMeauseHeight() + } + } + + + refreshAllNode(filterData: any) { + let args:any[] = [] + let isTopDown: boolean = !filterData.callTree[0]; + let isHideSystemLibrary = filterData.callTree[1]; + let list = filterData.dataMining.concat(filterData.dataLibrary); + let groupArgs = new Map(); + groupArgs.set("filterAllocType",this.filterAllocationType); + groupArgs.set("filterEventType",this.filterNativeType); + groupArgs.set("filterResponseType",this.filterResponseType) + groupArgs.set("leftNs",this.currentSelection?.leftNs||0); + groupArgs.set("rightNs",this.currentSelection?.rightNs||0); + args.push({ + funcName: "groupCallchainSample", + funcArgs: [groupArgs] + },{ + funcName: "getCallChainsBySampleIds", + funcArgs: [isTopDown] + }) + this.tbr!.recycleDataSource = [] + if (isHideSystemLibrary) { + args.push({ + funcName: "hideSystemLibrary", + funcArgs: [] + }) + } + if (filterData.callTreeConstraints.checked) { + args.push({ + funcName: "hideNumMaxAndMin", + funcArgs: [parseInt(filterData.callTreeConstraints.inputs[0]), filterData.callTreeConstraints.inputs[1]] + }) + } + args.push({ + funcName: "splitAllProcess", + funcArgs: [list] + }) + args.push({ + funcName: "resetAllNode", + funcArgs: [] + }) + this.getDataByWorker(args, (result: any[]) => { + this.setLTableData(result) + this.frameChart!.data = this.dataSource; + if (this.isChartShow) this.frameChart?.calculateChartData(); + }) + } + + setLTableData(resultData:any[]) { + this.dataSource = this.sortTree(resultData) + this.tbl!.recycleDataSource = this.dataSource + } + + sortTree(arr: Array): Array { + let sortArr = arr.sort((a, b) => { + if (this.sortKey == 'heapSizeStr' || this.sortKey == 'heapPercent') { + if (this.sortType == 0) { + return b.size - a.size; + } else if (this.sortType == 1) { + return a.size - b.size; + } else { + return b.size - a.size; + } + } else { + if (this.sortType == 0) { + return b.count - a.count; + } else if (this.sortType == 1) { + return a.count - b.count; + } else { + return b.count - a.count; + } + } + }) + sortArr.map((call) => { + call.children = this.sortTree(call.children); + }) + return sortArr; + } + + getDataByWorker(args: any[], handler: Function) { + this.loadingList.push(1) + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + procedurePool.submitWithName("logic1","native-memory-calltree-action",args,undefined,(results:any)=>{ + handler(results) + this.loadingList.splice(0,1) + if(this.loadingList.length == 0) { + this.progressEL!.loading = false; + this.loadingPage.style.visibility = "hidden"; + } + }) + } + + getDataByWorkerQuery(args: any, handler: Function){ + this.loadingList.push(1) + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + procedurePool.submitWithName("logic1","native-memory-queryCallchainsSamples",args,undefined,(results:any)=>{ + handler(results) + this.loadingList.splice(0,1) + if(this.loadingList.length == 0) { + this.progressEL!.loading = false; + this.loadingPage.style.visibility = "hidden"; + } + }) + } + + initHtml(): string { + return ` + +
+ + + +
+ + + + + + + + + + + + + + + + + +
+ + + Heaviest Stack Trace + + + + + +
+ + + + + + + +
+
`; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneNMSampleList.ts b/host/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMSampleList.ts similarity index 43% rename from host/ide/src/trace/component/trace/sheet/TabPaneNMSampleList.ts rename to host/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMSampleList.ts index df7e7eb1fddf4b477df473ed2b30cf8f1a00fd88..2a931ba8ef93f2620865c620bb4dff26aae2699d 100644 --- a/host/ide/src/trace/component/trace/sheet/TabPaneNMSampleList.ts +++ b/host/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMSampleList.ts @@ -13,26 +13,27 @@ * limitations under the License. */ -import "../../../../base-ui/table/lit-table-column.js"; -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import {Counter, SelectionData, SelectionParam} from "../../../bean/BoxSelection.js"; -import { - getTabCounters, queryAllHookData, - queryNativeHookEventId, - queryNativeHookSnapshot, - queryNativeHookSnapshotTypes -} from "../../../database/SqlLite.js"; -import {SpSystemTrace} from "../../SpSystemTrace.js"; +import "../../../../../base-ui/table/lit-table-column.js"; +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import { queryAllHookData, queryNativeHookSnapshotTypes} from "../../../../database/SqlLite.js"; import { NativeHookCallInfo, NativeHookSampleQueryInfo, NativeHookSamplerInfo, NativeMemory -} from "../../../bean/NativeHook.js"; -import {Utils} from "../base/Utils.js"; -import "./TabPaneFilter.js" -import {FilterData, TabPaneFilter} from "./TabPaneFilter.js"; +} from "../../../../bean/NativeHook.js"; +import {Utils} from "../../base/Utils.js"; +import "../TabPaneFilter.js" +import {FilterData, TabPaneFilter} from "../TabPaneFilter.js"; +import "../../../../../base-ui/slicer/lit-slicer.js"; +import {procedurePool} from "../../../../database/Procedure.js"; +import { + formatRealDateMs, + getTimeString +} from "../../../../database/logic-worker/ProcedureLogicWorkerCommon.js"; +import {SpNativeMemoryChart} from "../../../chart/SpNativeMemoryChart.js"; @element('tabpane-native-sample') export class TabPaneNMSampleList extends BaseElement { @@ -41,200 +42,145 @@ export class TabPaneNMSampleList extends BaseElement { static filter: any static filterSelect: string = "0" static source: Array = []; - static groups:any = undefined; - static types:Array = [] - static native_type:Array = ["All Heap & Anonymous VM","All Heap","All Anonymous VM"]; + static types: Array = [] + static native_type: Array = ["All Heap & Anonymous VM", "All Heap", "All Anonymous VM"]; static tableMarkData: Array = [] - static selectionParam:SelectionParam|undefined = undefined - static sampleTypes:Array = [] - static sampleTypesList:any[] = [] + static selectionParam: SelectionParam | undefined = undefined + static sampleTypes: Array = [] + static sampleTypesList: any[] = [] + set data(val: SelectionParam | any) { TabPaneNMSampleList.serSelection(val) this.filterAllList() } - static serSelection(val: SelectionParam){ - if(this.selectionParam !== val){ + static serSelection(val: SelectionParam) { + if (this.selectionParam !== val) { this.clearData() this.selectionParam = val this.initTypes() } - if(val.nativeMemory.indexOf(this.native_type[0]) != -1){ + if (val.nativeMemory.indexOf(this.native_type[0]) != -1) { this.types.push("'AllocEvent'"); this.types.push("'MmapEvent'"); - }else{ - if(val.nativeMemory.indexOf(this.native_type[1]) != -1){ + } else { + if (val.nativeMemory.indexOf(this.native_type[1]) != -1) { this.types.push("'AllocEvent'"); } - if(val.nativeMemory.indexOf(this.native_type[2]) != -1){ + if (val.nativeMemory.indexOf(this.native_type[2]) != -1) { this.types.push("'MmapEvent'"); } } } - static initTypes(){ - queryNativeHookSnapshotTypes().then((result)=>{ - if(result.length>0){ + static initTypes() { + queryNativeHookSnapshotTypes().then((result) => { + if (result.length > 0) { this.sampleTypes = result } }) } - static addSampleData(data:any){ - if(TabPaneNMSampleList.tableMarkData.indexOf(data)!=-1){ + static addSampleData(data: any) { + if (TabPaneNMSampleList.tableMarkData.indexOf(data) != -1) { return } TabPaneNMSampleList.tableMarkData.push(data) - this.initGroups() let rootSample = new NativeHookSamplerInfo() - rootSample.snapshot = "Snapshot"+this.numberToWord(this.source.length+1) + rootSample.snapshot = "Snapshot" + this.numberToWord(this.source.length + 1) rootSample.startTs = data.startTs - rootSample.timestamp = Utils.getTimeString(data.startTs) + rootSample.timestamp = SpNativeMemoryChart.REAL_TIME_DIF == 0?getTimeString(data.startTs):formatRealDateMs(data.startTs + SpNativeMemoryChart.REAL_TIME_DIF); rootSample.eventId = data.eventId - this.queryAllHookInfo(data,rootSample) + rootSample.threadId = data.threadId + rootSample.threadName = data.threadName + this.queryAllHookInfo(data, rootSample) } - static querySnapshot(data:any,rootSample:NativeHookSamplerInfo){ - let copyTypes = this.sampleTypes.map((type)=>{ - let copyType = new NativeHookSampleQueryInfo() - copyType.eventType = type.eventType - copyType.subType = type.subType - return copyType - }) - queryNativeHookSnapshot(data.startTs).then((result)=>{ - if(result.length>0){ - let nameGroup:any = {} - copyTypes.forEach((item)=> { - nameGroup[item.eventType] = nameGroup[item.eventType] || [] - nameGroup[item.eventType].push(item) - }) - result.forEach((item)=>{ - if(nameGroup[item.eventType]!=undefined){ - if(item.subType == null){ - nameGroup[item.eventType][0].existing = item.existing - nameGroup[item.eventType][0].growth = item.growth - }else{ - let filter = nameGroup[item.eventType].filter((type:any)=>{ - return type.subType == item.subType - }) - if (filter.length > 0) { - filter[0].existing = item.existing - filter[0].growth = item.growth - } - } - } - }) - if(this.sampleTypesList.length>0){ - let sampleTypesListElement = this.sampleTypesList[this.sampleTypesList.length-1]; - sampleTypesListElement.forEach((item:any,index:number)=>{ - copyTypes[index].current = copyTypes[index].growth - if(index{ - item.current = item.growth - }) - } - this.sampleTypesList.push(copyTypes) - this.createTree(nameGroup,rootSample) - rootSample.tempList = [...rootSample.children] - this.source.push(rootSample) - } - }) - } - static merageSampleData(leftTime:number,startNs:number,rootSample:NativeHookSampleQueryInfo,merageSample:NativeHookSampleQueryInfo){ - if(merageSample.endTs >= startNs){ + static merageSampleData(leftTime: number, startNs: number, rootSample: NativeHookSampleQueryInfo, merageSample: NativeHookSampleQueryInfo) { + if (merageSample.endTs >= startNs) { rootSample.growth += merageSample.growth } - if(merageSample.startTs > leftTime){ + if (merageSample.startTs > leftTime) { rootSample.existing++; let childSample = new NativeHookSamplerInfo()//新增最下层的叶子节点 - childSample.snapshot = "0x"+merageSample.addr + childSample.snapshot = "0x" + merageSample.addr childSample.eventId = merageSample.eventId; childSample.heapSize = merageSample.growth childSample.growth = Utils.getByteWithUnit(merageSample.growth) childSample.totalGrowth = childSample.growth childSample.startTs = merageSample.startTs - childSample.timestamp = Utils.getTimeString(merageSample.startTs); + childSample.timestamp = SpNativeMemoryChart.REAL_TIME_DIF == 0?getTimeString(merageSample.startTs):formatRealDateMs((merageSample.startTs + SpNativeMemoryChart.REAL_TIME_DIF)); + childSample.threadId = merageSample.threadId; + childSample.threadName = merageSample.threadName; (childSample as any).existing = "" rootSample.children.push(childSample) } rootSample.total += merageSample.growth } - static queryAllHookInfo(data:any,rootSample:NativeHookSamplerInfo){ - let copyTypes = this.sampleTypes.map((type)=>{ + static queryAllHookInfo(data: any, rootSample: NativeHookSamplerInfo) { + let copyTypes = this.sampleTypes.map((type) => { let copyType = new NativeHookSampleQueryInfo() copyType.eventType = type.eventType copyType.subType = type.subType return copyType }) - queryAllHookData(data.startTs).then((result)=>{ - if(result.length > 0){ - let nameGroup:any = {} - copyTypes.forEach((item)=> { + queryAllHookData(data.startTs).then((result) => { + if (result.length > 0) { + let nameGroup: any = {} + copyTypes.forEach((item) => { nameGroup[item.eventType] = nameGroup[item.eventType] || [] nameGroup[item.eventType].push(item) }) - let leftTime = TabPaneNMSampleList.tableMarkData.length == 1?0:TabPaneNMSampleList.tableMarkData[TabPaneNMSampleList.tableMarkData.length - 2].startTs - result.forEach((item)=>{ - if(nameGroup[item.eventType]!=undefined){ - if(item.subType == null){ - this.merageSampleData(leftTime,data.startTs,nameGroup[item.eventType][0],item) - }else{ - let filter = nameGroup[item.eventType].filter((type:any)=>{ + let leftTime = TabPaneNMSampleList.tableMarkData.length == 1 ? 0 : TabPaneNMSampleList.tableMarkData[TabPaneNMSampleList.tableMarkData.length - 2].startTs + result.forEach((item) => { + item.threadId = rootSample.threadId; + item.threadName = rootSample.threadName; + if (nameGroup[item.eventType] != undefined) { + if (item.subType == null) { + this.merageSampleData(leftTime, data.startTs, nameGroup[item.eventType][0], item) + } else { + let filter = nameGroup[item.eventType].filter((type: any) => { return type.subType == item.subType }) if (filter.length > 0) { - this.merageSampleData(leftTime,data.startTs,filter[0],item) + this.merageSampleData(leftTime, data.startTs, filter[0], item) } } } }) - if(this.sampleTypesList.length>0){ - let sampleTypesListElement = this.sampleTypesList[this.sampleTypesList.length-1]; - sampleTypesListElement.forEach((item:any,index:number)=>{ + if (this.sampleTypesList.length > 0) { + let sampleTypesListElement = this.sampleTypesList[this.sampleTypesList.length - 1]; + sampleTypesListElement.forEach((item: any, index: number) => { copyTypes[index].current = copyTypes[index].growth - if(index{ + } else { + copyTypes.forEach((item: any, index: number) => { item.current = item.growth }) } this.sampleTypesList.push(copyTypes) - this.createTree(nameGroup,rootSample) + this.createTree(nameGroup, rootSample) rootSample.tempList = [...rootSample.children] this.source.push(rootSample) } }) } - static initGroups(){ - if(this.groups==undefined){ - this.groups = {} - SpSystemTrace.HEAP_FRAME_DATA.map((frame)=>{ - this.groups[frame.eventId] = this.groups[frame.eventId]||[] - this.groups[frame.eventId].push(frame) - }) - } - } - - static createTree(nameGroup:any,rootSample:NativeHookSamplerInfo){ - Object.keys(nameGroup).forEach((key)=>{ + static createTree(nameGroup: any, rootSample: NativeHookSamplerInfo) { + Object.keys(nameGroup).forEach((key) => { let parentSample = new NativeHookSamplerInfo() parentSample.snapshot = key if (nameGroup[key].length > 0) { - nameGroup[key].forEach((child:any)=>{ + nameGroup[key].forEach((child: any) => { let childSample = new NativeHookSamplerInfo() - childSample.snapshot = child.subType||child.eventType + childSample.snapshot = child.subType || child.eventType childSample.heapSize = child.growth childSample.growth = Utils.getByteWithUnit(child.growth) childSample.total = child.total @@ -242,11 +188,13 @@ export class TabPaneNMSampleList extends BaseElement { childSample.existing = child.existing childSample.currentSize = child.current childSample.current = Utils.getByteWithUnit(child.current) + childSample.threadName = rootSample.threadName + childSample.threadId = rootSample.threadId parentSample.merageObj(childSample) - if(childSample.snapshot != parentSample.snapshot){//根据名称是否一致来判断是否需要添加子节点 + if (childSample.snapshot != parentSample.snapshot) {//根据名称是否一致来判断是否需要添加子节点 childSample.children.push(...child.children) parentSample.children.push(childSample) - }else { + } else { parentSample.children.push(...child.children) } }) @@ -256,25 +204,25 @@ export class TabPaneNMSampleList extends BaseElement { }) } - static prepChild(currentSample:NativeHookSamplerInfo,rootSample:NativeHookSamplerInfo){ + static prepChild(currentSample: NativeHookSamplerInfo, rootSample: NativeHookSamplerInfo) { currentSample.heapSize -= rootSample.heapSize currentSample.growth = Utils.getByteWithUnit(currentSample.heapSize) - let currentMap:any = {} - currentSample.children.forEach((currentChild)=>{ + let currentMap: any = {} + currentSample.children.forEach((currentChild) => { currentMap[currentChild.snapshot] = currentChild }) - rootSample.children.forEach((rootChild)=>{ + rootSample.children.forEach((rootChild) => { if (currentMap[rootChild.snapshot] == undefined) { let perpSample = new NativeHookSamplerInfo() - perpSample.snapshot =rootChild.snapshot + perpSample.snapshot = rootChild.snapshot currentMap[rootChild.snapshot] = perpSample currentSample.children.push(perpSample) } - this.prepChild(currentMap[rootChild.snapshot],rootChild) + this.prepChild(currentMap[rootChild.snapshot], rootChild) }) } - static clearData(){ + static clearData() { this.types = [] this.source = [] this.tblData!.dataSource = [] @@ -284,59 +232,54 @@ export class TabPaneNMSampleList extends BaseElement { TabPaneNMSampleList.filter!.firstSelect = "0" } - static numberToWord(num:number){ + static numberToWord(num: number) { let word = "" - while (num>0){ - let end = num%26 - end = end === 0?(end = 26):end; - word = String.fromCharCode(96 + end)+word - num = ( num - end ) / 26 + while (num > 0) { + let end = num % 26 + end = end === 0 ? (end = 26) : end; + word = String.fromCharCode(96 + end) + word + num = (num - end) / 26 } return word.toUpperCase() } - setRightTableData(eventId:number){ - let arr:Array = []; - let frameArr = TabPaneNMSampleList.groups[eventId]; - if(frameArr){ - frameArr.map((frame:any)=>{ - let target = new NativeHookCallInfo(); - target.eventId = parseInt(frame.eventId); - target.depth = frame.depth; - let sym_arr = frame.AllocationFunction?.split("/"); - let lib_arr = frame.MoudleName?.split("/"); - target.symbol = sym_arr![sym_arr!.length - 1]; - target.library = lib_arr![lib_arr!.length - 1]; - target.title = `[ ${target.symbol} ] ${target.library}`; - target.type = (target.library.endsWith(".so.1") || target.library.endsWith(".dll") || target.library.endsWith(".so")) ? 0 : 1; - arr.push(target); - }) - } - // @ts-ignore - TabPaneNMSampleList.tblData?.recycleDataSource = arr; + startWorker(args: Map, handler: Function) { + procedurePool.submitWithName("logic1","native-memory-action",args,undefined,(res:any)=>{ + handler(res); + }) + } + + setRightTableData(sample: NativeHookSamplerInfo) { + let args = new Map(); + args.set("eventId",sample.eventId); + args.set("actionType","memory-stack"); + this.startWorker(args,(results: any[]) => { + let source = []; + if(results.length > 0){ + let thread = new NativeHookCallInfo(); + thread.threadId = sample.threadId; + thread.threadName = sample.threadName; + thread.title = `${sample.threadName ?? ""}【${sample.threadId}】`; + thread.type = -1 + source.push(thread) + source.push(...results) + } + // @ts-ignore + TabPaneNMSampleList.tblData?.dataSource = source; + }) } initElements(): void { TabPaneNMSampleList.tbl = this.shadowRoot?.querySelector('#tb-native-sample'); - TabPaneNMSampleList.tbl!.addEventListener('row-click', (evt:any) => { + TabPaneNMSampleList.tbl!.addEventListener('row-click', (evt: any) => { // @ts-ignore - this.setRightTableData(evt.detail.eventId); + this.setRightTableData(evt.detail.data); }) TabPaneNMSampleList.tblData = this.shadowRoot?.querySelector('#tb-native-data'); - new ResizeObserver((entries) => { - if (this.parentElement?.clientHeight != 0) { - // @ts-ignore - TabPaneNMSampleList.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 10 - 31)+"px" - TabPaneNMSampleList.tbl?.reMeauseHeight() - // @ts-ignore - TabPaneNMSampleList.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 10)+"px" - TabPaneNMSampleList.tblData?.reMeauseHeight() - } - }).observe(this.parentElement!) TabPaneNMSampleList.filter = this.shadowRoot?.querySelector("#filter") - this.shadowRoot?.querySelector("#filter")!.setSelectList(TabPaneNMSampleList.native_type,null) - this.shadowRoot?.querySelector("#filter")!.getFilterData((data:FilterData)=>{ - if(data.firstSelect){ + this.shadowRoot?.querySelector("#filter")!.setSelectList(TabPaneNMSampleList.native_type, null) + this.shadowRoot?.querySelector("#filter")!.getFilterData((data: FilterData) => { + if (data.firstSelect) { TabPaneNMSampleList.filterSelect = data.firstSelect this.filterAllList() } @@ -345,42 +288,56 @@ export class TabPaneNMSampleList extends BaseElement { } - filterAllList(){ - TabPaneNMSampleList.source.forEach((rootSample)=>{ + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + TabPaneNMSampleList.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 10 - 31) + "px" + TabPaneNMSampleList.tbl?.reMeauseHeight() + // @ts-ignore + TabPaneNMSampleList.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 10) + "px" + TabPaneNMSampleList.tblData?.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + filterAllList() { + TabPaneNMSampleList.source.forEach((rootSample) => { rootSample.heapSize = 0 rootSample.existing = 0 rootSample.total = 0 - if(TabPaneNMSampleList.filterSelect == "0"){ - rootSample.children = [...rootSample.tempList] - rootSample.tempList.forEach((parentSample)=>{ - rootSample.heapSize +=parentSample.heapSize - rootSample.existing +=parentSample.existing - rootSample.total +=parentSample.total + if (TabPaneNMSampleList.filterSelect == "0") { + rootSample.children = [...rootSample.tempList] + rootSample.tempList.forEach((parentSample) => { + rootSample.heapSize += parentSample.heapSize + rootSample.existing += parentSample.existing + rootSample.total += parentSample.total }) rootSample.growth = Utils.getByteWithUnit(rootSample.heapSize) - rootSample.totalGrowth =Utils.getByteWithUnit(rootSample.total) - }else if(TabPaneNMSampleList.filterSelect == "2"){ - if(rootSample.tempList.length>1){ + rootSample.totalGrowth = Utils.getByteWithUnit(rootSample.total) + } else if (TabPaneNMSampleList.filterSelect == "2") { + if (rootSample.tempList.length > 1) { rootSample.children = [rootSample.tempList[1]] - rootSample.heapSize +=rootSample.tempList[1].heapSize - rootSample.existing +=rootSample.tempList[1].existing + rootSample.heapSize += rootSample.tempList[1].heapSize + rootSample.existing += rootSample.tempList[1].existing rootSample.growth = Utils.getByteWithUnit(rootSample.heapSize) rootSample.total += rootSample.tempList[1].total rootSample.totalGrowth = Utils.getByteWithUnit(rootSample.total) - }else { + } else { rootSample.children = [] rootSample.growth = "" rootSample.totalGrowth = "" } - }else { - if(rootSample.tempList.length>0){ + } else { + if (rootSample.tempList.length > 0) { rootSample.children = [rootSample.tempList[0]] - rootSample.heapSize +=rootSample.tempList[0].heapSize - rootSample.existing +=rootSample.tempList[0].existing + rootSample.heapSize += rootSample.tempList[0].heapSize + rootSample.existing += rootSample.tempList[0].existing rootSample.growth = Utils.getByteWithUnit(rootSample.heapSize) rootSample.total += rootSample.tempList[0].total rootSample.totalGrowth = Utils.getByteWithUnit(rootSample.total) - }else { + } else { rootSample.children = [] rootSample.growth = "" rootSample.totalGrowth = "" @@ -392,65 +349,42 @@ export class TabPaneNMSampleList extends BaseElement { initHtml(): string { return ` - -
-
- - - - - - - - -
-
+ + +
+ + + + + + + + + + + + + +
+ - + - + + -
-
+ `; } - - sortByColumn(detail: any) { - // @ts-ignore - function compare(property, sort, type) { - return function (a: SelectionData, b: SelectionData) { - if (a.process == " " || b.process == " ") { - return 0; - } - if (type === 'number') { - // @ts-ignore - return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); - } else { - // @ts-ignore - if (b[property] > a[property]) { - return sort === 2 ? 1 : -1; - } else { // @ts-ignore - if (b[property] == a[property]) { - return 0; - } else { - return sort === 2 ? -1 : 1; - } - } - } - } - } - - TabPaneNMSampleList.tbl!.recycleDataSource = TabPaneNMSampleList.source; - } - -} \ No newline at end of file +} diff --git a/host/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.ts b/host/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.ts new file mode 100644 index 0000000000000000000000000000000000000000..e5d8064af3878885d021aa64b19a6fe93eb2dbfb --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.ts @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import { + queryNativeHookResponseTypes, + queryNativeHookStatistics, + queryNativeHookStatisticsMalloc, + queryNativeHookStatisticsSubType +} from "../../../../database/SqlLite.js"; +import {NativeHookMalloc, NativeHookStatisticsTableData} from "../../../../bean/NativeHook.js"; +import {Utils} from "../../base/Utils.js"; +import {SpSystemTrace} from "../../../SpSystemTrace.js"; +import "../TabProgressBar.js" +import {SpNativeMemoryChart} from "../../../chart/SpNativeMemoryChart.js"; +import {procedurePool} from "../../../../database/Procedure.js"; + +@element('tabpane-native-statistics') +export class TabPaneNMStatstics extends BaseElement { + private tbl: LitTable | null | undefined; + private source: Array = [] + private native_type: Array = ["All Heap & Anonymous VM", "All Heap", "All Anonymous VM"]; + private allMax: number = 0; + private sortColumn: string = ''; + private sortType: number = 0; + private currentSelection: SelectionParam | undefined + + set data(val: SelectionParam | any) { + if(val == this.currentSelection){ + return; + } + this.currentSelection = val; + this.allMax = 0; + SpNativeMemoryChart.EVENT_HEAP.map((heap) => { + this.allMax += heap.sumHeapSize; + }); + this.initResponseTypeList(val) + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20) + "px" + // @ts-ignore + this.tbl?.recycleDataSource = []; + Promise.all([queryNativeHookStatistics(val.leftNs, val.rightNs), + queryNativeHookStatisticsSubType(val.leftNs, val.rightNs), + queryNativeHookStatisticsMalloc(val.leftNs, val.rightNs) + ]).then((values) => { + let arr: Array = []; + let index1 = val.nativeMemory.indexOf(this.native_type[0]) + let index2 = val.nativeMemory.indexOf(this.native_type[1]) + let index3 = val.nativeMemory.indexOf(this.native_type[2]) + this.setMemoryTypeData(val, values[0], arr); + if (index1 != -1 || index3 != -1) { + this.setSubTypeTableData(values[1], arr); + } + let type = 0; + if(index1 != -1 || (index2 != -1 && index3 != -1)){ + type = 0; + }else{ + type = index2 != -1 ? 1 : 2; + } + this.setMallocTableData(values[2], arr,type); + this.source = arr; + this.sortByColumn(this.sortColumn,this.sortType) + }) + } + + setMallocTableData(result: Array, arr: Array,type:number) { + result.map((malloc) => { + let data = new NativeHookStatisticsTableData(); + if(malloc.eventType == "AllocEvent"){ + data.memoryTap = "Malloc " + Utils.getByteWithUnit(malloc.heapSize); + }else{ + data.memoryTap = "Mmap " + Utils.getByteWithUnit(malloc.heapSize); + } + data.existing = malloc.allocByte - malloc.freeByte + data.allocCount = malloc.allocCount - malloc.freeCount; + data.freeCount = malloc.freeCount; + data.freeByte = malloc.freeByte; + data.totalBytes = malloc.allocByte; + data.totalCount = malloc.allocCount; + data.max = malloc.heapSize; + data.existingString = Utils.getByteWithUnit(data.existing); + data.freeByteString = Utils.getByteWithUnit(malloc.freeByte); + data.totalBytesString = Utils.getByteWithUnit(data.totalBytes); + data.maxStr = Utils.getByteWithUnit(malloc.heapSize); + data.existingValue = [data.existing, data.totalBytes, this.allMax]; + if(type == 0){ + arr.push(data); + } else if(type == 1 && malloc.eventType == "AllocEvent"){ + arr.push(data) + }else if(type ==2 && malloc.eventType == "MmapEvent"){ + arr.push(data) + }else{} + }) + } + + setSubTypeTableData(result: Array, arr: Array) { + result.map((sub) => { + let subType = SpSystemTrace.DATA_DICT.get(sub.subTypeId); + if (subType != null && subType != undefined) { + let data = new NativeHookStatisticsTableData(); + data.memoryTap = subType; + data.existing = sub.allocByte - sub.freeByte + data.allocCount = sub.allocCount - sub.freeCount; + data.freeCount = sub.freeCount; + data.freeByte = sub.freeByte; + data.totalBytes = sub.allocByte; + data.totalCount = sub.allocCount; + data.max = sub.max; + data.freeByteString = Utils.getByteWithUnit(sub.freeByte); + data.existingString = Utils.getByteWithUnit(data.existing); + data.totalBytesString = Utils.getByteWithUnit(data.totalBytes); + data.maxStr = Utils.getByteWithUnit(sub.max); + data.existingValue = [data.existing, data.totalBytes, this.allMax]; + arr.push(data); + } + }) + } + + initResponseTypeList(val: SelectionParam | any){ + let types: Array = [] + if (val.nativeMemory.indexOf("All Heap & Anonymous VM") != -1) { + types.push("'AllocEvent'"); + types.push("'MmapEvent'"); + } else { + if (val.nativeMemory.indexOf("All Heap") != -1) { + types.push("'AllocEvent'"); + } + if (val.nativeMemory.indexOf("All Anonymous VM") != -1) { + types.push("'MmapEvent'"); + } + } + queryNativeHookResponseTypes(val.leftNs, val.rightNs,types).then((res)=>{ + procedurePool.submitWithName("logic1","native-memory-init-responseType",res,undefined,()=>{}) + }) + } + + setMemoryTypeData(val: SelectionParam, result: Array, arr: Array) { + let all: NativeHookStatisticsTableData | null = null + let heap: NativeHookStatisticsTableData | null = null + let anonymous: NativeHookStatisticsTableData | null = null + if (val.nativeMemory.indexOf(this.native_type[0]) != -1) { + all = new NativeHookStatisticsTableData(); + all.memoryTap = this.native_type[0]; + } + if (val.nativeMemory.indexOf(this.native_type[1]) != -1) { + heap = new NativeHookStatisticsTableData(); + heap.memoryTap = this.native_type[1]; + } + if (val.nativeMemory.indexOf(this.native_type[2]) != -1) { + anonymous = new NativeHookStatisticsTableData(); + anonymous.memoryTap = this.native_type[2]; + } + for (let hook of result) { + if (all != null) { + all.totalBytes += hook.allocByte; + all.totalCount += hook.allocCount; + all.freeByte += hook.freeByte; + all.freeCount += hook.freeCount; + if (hook.max > all.max) { + all.max = hook.max; + all.maxStr = Utils.getByteWithUnit(all.max); + } + } + if (heap != null && hook.eventType == "AllocEvent") { + heap.totalBytes += hook.allocByte; + heap.totalCount += hook.allocCount; + heap.freeByte += hook.freeByte; + heap.freeCount += hook.freeCount; + if (hook.max > heap.max) { + heap.max = hook.max; + heap.maxStr = Utils.getByteWithUnit(heap.max); + } + } + if (anonymous != null && hook.eventType == "MmapEvent") { + anonymous.totalBytes += hook.allocByte; + anonymous.totalCount += hook.allocCount; + anonymous.freeByte += hook.freeByte; + anonymous.freeCount += hook.freeCount; + if (hook.max > anonymous.max) { + anonymous.max = hook.max; + anonymous.maxStr = Utils.getByteWithUnit(anonymous.max); + } + } + } + if (all != null) { + all.existing = all.totalBytes - all.freeByte; + all.allocCount = all.totalCount - all.freeCount; + all.existingString = Utils.getByteWithUnit(all.existing) + all.totalBytesString = Utils.getByteWithUnit(all.totalBytes) + all.freeByteString = Utils.getByteWithUnit(all.freeByte); + all.existingValue = [all.existing, all.totalBytes, this.allMax] + arr.push(all) + } + if (heap != null) { + heap.existing = heap.totalBytes - heap.freeByte; + heap.allocCount = heap.totalCount - heap.freeCount; + heap.existingString = Utils.getByteWithUnit(heap.existing) + heap.totalBytesString = Utils.getByteWithUnit(heap.totalBytes) + heap.freeByteString = Utils.getByteWithUnit(heap.freeByte); + heap.existingValue = [heap.existing, heap.totalBytes, this.allMax] + arr.push(heap) + } + if (anonymous != null) { + anonymous.existing = anonymous.totalBytes - anonymous.freeByte; + anonymous.allocCount = anonymous.totalCount - anonymous.freeCount; + anonymous.existingString = Utils.getByteWithUnit(anonymous.existing) + anonymous.totalBytesString = Utils.getByteWithUnit(anonymous.totalBytes) + anonymous.freeByteString = Utils.getByteWithUnit(anonymous.totalBytes - anonymous.existing) + anonymous.existingValue = [anonymous.existing, anonymous.totalBytes, this.allMax] + arr.push(anonymous) + } + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-native-statstics'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail.key, evt.detail.sort) + }); + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + sortByColumn(column: string, sort: number) { + this.sortColumn = column; + this.sortType = sort; + if (sort == 0) { + this.tbl!.recycleDataSource = this.source + } else { + let arr = [...this.source] + if (column == "existingString") { + this.tbl!.recycleDataSource = arr.sort((a, b) => { + return sort == 1 ? a.existing - b.existing : b.existing - a.existing + }) + } else if (column == "allocCount") { + this.tbl!.recycleDataSource = arr.sort((a, b) => { + return sort == 1 ? a.allocCount - b.allocCount : b.allocCount - a.allocCount + }) + } else if (column == "freeByteString") { + this.tbl!.recycleDataSource = arr.sort((a, b) => { + return sort == 1 ? (a.totalBytes - a.existing) - (b.totalBytes - b.existing) : (b.totalBytes -b.existing) - (a.totalBytes - a.existing) + }) + } else if (column == "freeCount") { + this.tbl!.recycleDataSource = arr.sort((a, b) => { + return sort == 1 ? a.freeCount - b.freeCount : b.freeCount - a.freeCount + }) + } else if (column == "totalBytesString") { + this.tbl!.recycleDataSource = arr.sort((a, b) => { + return sort == 1 ? a.totalBytes - b.totalBytes : b.totalBytes - a.totalBytes + }) + } else if (column == "maxStr") { + this.tbl!.recycleDataSource = arr.sort((a, b) => { + return sort == 1 ? a.max - b.max : b.max - a.max + }) + } else if (column == "totalCount") { + this.tbl!.recycleDataSource = arr.sort((a, b) => { + return sort == 1 ? a.totalCount - b.totalCount : b.totalCount - a.totalCount + }) + } + } + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + + `; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMemory.ts b/host/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMemory.ts new file mode 100644 index 0000000000000000000000000000000000000000..d3f0caac84e0b08b070c3d203af5c167e4222fbe --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMemory.ts @@ -0,0 +1,464 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import "../../../../../base-ui/slicer/lit-slicer.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {query, queryNativeHookEventTid} from "../../../../database/SqlLite.js"; +import { NativeHookStatistics, NativeMemory,NativeHookCallInfo} from "../../../../bean/NativeHook.js"; +import "../TabPaneFilter.js" +import {FilterData, TabPaneFilter} from "../TabPaneFilter.js"; +import {TabPaneNMSampleList} from "./TabPaneNMSampleList.js"; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {procedurePool} from "../../../../database/Procedure.js"; + +@element('tabpane-native-memory') +export class TabPaneNMemory extends BaseElement { + private defaultNativeTypes = ["All Heap & Anonymous VM", "All Heap", "All Anonymous VM"]; + private tbl: LitTable | null | undefined; + private tblData: LitTable | null | undefined; + private progressEL:LitProgressBar | null | undefined; + private loadingList:number[] = [] + private loadingPage:any; + private source: Array = [] + private native_type: Array = [...this.defaultNativeTypes]; + private statsticsSelection: Array = [] + private queryResult: Array = [] + private filterAllocationType: string = "0" + private filterNativeType: string = "0" + private filterResponseType: number = -1 + private filterResponseSelect: string = "0" + private currentSelection: SelectionParam | undefined + private rowSelectData: any = undefined; + private sortColumn: string = ''; + private sortType: number = 0; + private leftNs:number = 0; + private rightNs:number = 0; + private responseTypes:any[] = [] + + set data(val: SelectionParam | any) { + if (val == this.currentSelection) { + return + } + this.currentSelection = val + this.initFilterTypes() + this.queryData(val) + } + + queryData(val: SelectionParam | any) { + let types: Array = [] + if (val.nativeMemory.indexOf(this.defaultNativeTypes[0]) != -1) { + types.push("'AllocEvent'"); + types.push("'MmapEvent'"); + } else { + if (val.nativeMemory.indexOf(this.defaultNativeTypes[1]) != -1) { + types.push("'AllocEvent'"); + } + if (val.nativeMemory.indexOf(this.defaultNativeTypes[2]) != -1) { + types.push("'MmapEvent'"); + } + } + TabPaneNMSampleList.serSelection(val) + // @ts-ignore + this.tbl?.shadowRoot?.querySelector(".table").style.height = (this.parentElement.clientHeight - 20 - 31) + "px" + // @ts-ignore + this.tblData?.shadowRoot?.querySelector(".table").style.height = (this.parentElement.clientHeight - 20 - 31) + "px" + // @ts-ignore + this.tblData?.recycleDataSource = []; + // @ts-ignore + this.tbl?.recycleDataSource = []; + this.leftNs = val.leftNs; + this.rightNs = val.rightNs; + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + queryNativeHookEventTid(val.leftNs, val.rightNs, types).then((result) => { + this.queryResult = result + this.getDataByNativeMemoryWorker(val); + }) + } + + getDataByNativeMemoryWorker(val: SelectionParam | any){ + let args = new Map(); + args.set("data",this.queryResult); + args.set("filterAllocType",this.filterAllocationType); + args.set("filterEventType",this.filterNativeType); + args.set("filterResponseType",this.filterResponseType); + args.set("leftNs",val.leftNs); + args.set("rightNs",val.rightNs); + let selections:Array = []; + if(this.statsticsSelection.length > 0){ + this.statsticsSelection.map((memory) => { + selections.push({memoryTap:memory.memoryTap, max:memory.max}) + }) + } + args.set("statisticsSelection",selections); + args.set("actionType","native-memory"); + this.startWorker(args,(results: any[]) => { + this.tblData!.recycleDataSource = [] + this.progressEL!.loading = false + if (results.length > 0) { + this.source = results; + this.sortByColumn(this.sortColumn,this.sortType); + }else { + this.source = [] + this.tbl!.recycleDataSource = []; + } + }) + } + + startWorker(args: Map, handler: Function) { + this.loadingList.push(1) + this.progressEL!.loading = true + this.loadingPage.style.visibility = "visible" + procedurePool.submitWithName("logic1","native-memory-action",args,undefined,(res:any)=>{ + handler(res); + this.loadingList.splice(0,1) + if(this.loadingList.length == 0) { + this.progressEL!.loading = false + this.loadingPage.style.visibility = "hidden" + } + }) + } + + fromStastics(val: SelectionParam | any) { + let filter = this.shadowRoot?.querySelector("#filter") + if (this.currentSelection != val) { + this.initFilterTypes(()=>{ + this.currentSelection = val + filter!.setSelectList(null, this.native_type,"Allocation Lifespan" + ,"Allocation Type",this.responseTypes.map((item:any)=>{ + return item.value + })) + filter!.secondSelect = typeIndexOf + "" + filter!.thirdSelect = this.filterResponseSelect + this.filterNativeType = typeIndexOf + "" + this.queryData(val) + }) + } + let typeIndexOf = this.native_type.indexOf(val.statisticsSelectData.memoryTap); + if (this.statsticsSelection.indexOf(val.statisticsSelectData) == -1 && typeIndexOf == -1) { + this.statsticsSelection.push(val.statisticsSelectData) + this.native_type.push(val.statisticsSelectData.memoryTap) + typeIndexOf = this.native_type.length - 1 + }else{ + let index = this.statsticsSelection.findIndex((mt) => mt.memoryTap == val.statisticsSelectData.memoryTap); + if(index != -1){ + this.statsticsSelection[index] = val.statisticsSelectData; + } + } + if (this.currentSelection == val) { + this.tblData!.recycleDataSource = []; + this.rowSelectData = undefined + filter!.setSelectList(null, this.native_type,"Allocation Lifespan" + ,"Allocation Type",this.responseTypes.map((item:any)=>{ + return item.value + })) + filter!.secondSelect = typeIndexOf + "" + filter!.thirdSelect = this.filterResponseSelect + this.filterNativeType = typeIndexOf + "" + //直接将当前数据过滤即可 + this.getDataByNativeMemoryWorker(val) + } + } + + initFilterTypes(initCallback?:()=>void) { + let filter = this.shadowRoot?.querySelector("#filter") + this.queryResult = [] + this.native_type = [...this.defaultNativeTypes] + this.statsticsSelection = [] + procedurePool.submitWithName("logic1","native-memory-get-responseType",{},undefined,(res:any)=>{ + filter!.setSelectList(null, this.native_type,"Allocation Lifespan" + ,"Allocation Type",res.map((item:any)=>{ + return item.value + })) + filter!.setFilterModuleSelect("#first-select","width","150px") + filter!.setFilterModuleSelect("#second-select","width","150px") + filter!.setFilterModuleSelect("#third-select","width","150px") + this.responseTypes = res; + filter!.firstSelect = "0" + filter!.secondSelect = "0" + filter!.thirdSelect = "0" + this.filterResponseSelect = "0" + this.filterAllocationType = "0" + this.filterNativeType = "0" + this.filterResponseType = -1; + this.rowSelectData = undefined + if(initCallback){ + initCallback() + } + }) + } + + initElements(): void { + this.loadingPage = this.shadowRoot?.querySelector('.loading'); + this.progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar + this.tbl = this.shadowRoot?.querySelector('#tb-native-memory'); + this.tblData = this.shadowRoot?.querySelector('#tb-native-data'); + this.tbl!.addEventListener("row-click", (e) => { + // @ts-ignore + let data = (e.detail.data as NativeMemory); + this.rowSelectData = data + this.setRightTableData(data); + document.dispatchEvent(new CustomEvent('triangle-flag', {detail: {time: data.startTs, type: "triangle"}})); + }) + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail.key,evt.detail.sort) + }); + let filter = this.shadowRoot?.querySelector("#filter") + + this.shadowRoot?.querySelector("#filter")!.getFilterData((data: FilterData) => { + if (data.mark) { + document.dispatchEvent(new CustomEvent('triangle-flag', { + detail: { + time: "", type: "square", timeCallback: (t: any) => { + let minTs = 0 + let minItem: any = undefined + let filterTemp = this.source.filter((tempItem) => { + if (minTs == 0 || (tempItem.startTs - t != 0 && Math.abs(tempItem.startTs - t) < minTs)) { + minTs = Math.abs(tempItem.startTs - t) + minItem = tempItem + } + return tempItem.startTs == t + }) + if (filterTemp.length > 0) { + filterTemp[0].isSelected = true + } else { + if (minItem) { + filterTemp.push(minItem) + minItem.isSelected = true + } + } + if (filterTemp.length > 0) { + this.rowSelectData = filterTemp[0] + let currentSelection = this.queryResult.filter((item) => { + return item.startTs == this.rowSelectData.startTs + }) + if (currentSelection.length > 0) { + currentSelection[0].isSelected = true + } + TabPaneNMSampleList.addSampleData(this.rowSelectData) + this.tbl!.scrollToData(this.rowSelectData) + } + } + } + })); + } else { + this.filterAllocationType = data.firstSelect || "0" + this.filterNativeType = data.secondSelect || "0" + this.filterResponseSelect = data.thirdSelect || "0" + let thirdIndex = parseInt(data.thirdSelect||"0") + if(this.responseTypes.length > thirdIndex){ + this.filterResponseType = this.responseTypes[thirdIndex].key == undefined?-1:this.responseTypes[thirdIndex].key + } + this.getDataByNativeMemoryWorker(this.currentSelection) + } + }) + filter!.firstSelect = "1" + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) - 10 - 31 + "px"; + this.tbl?.reMeauseHeight(); + // @ts-ignore + this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) - 10 -31 + "px" + this.tblData?.reMeauseHeight() + this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px" + } + }).observe(this.parentElement!); + } + + sortByColumn(column:string,sort:number){ + this.sortColumn = column; + this.sortType = sort; + if(sort == 0){ + this.tbl!.recycleDataSource = this.source + }else{ + let arr = [...this.source] + if(column == "index"){ + this.tbl!.recycleDataSource = arr.sort((a,b)=>{ + return sort == 1 ? a.index - b.index : b.index - a.index + }) + }else if(column == "addr"){ + this.tbl!.recycleDataSource = arr.sort((a,b)=>{ + if(sort == 1){ + if(a.addr > b.addr){ + return 1 + }else if(a.addr == b.addr){ + return 0; + }else{ + return -1; + } + }else{ + if(b.addr > a.addr){ + return 1 + }else if(a.addr == b.addr){ + return 0; + }else{ + return -1; + } + } + }) + }else if(column == "timestamp"){ + this.tbl!.recycleDataSource = arr.sort((a,b)=>{ + return sort == 1 ? a.startTs - b.startTs : b.startTs - a.startTs + }) + }else if(column == "heapSizeUnit"){ + this.tbl!.recycleDataSource = arr.sort((a,b)=>{ + return sort == 1 ? a.heapSize - b.heapSize : b.heapSize - a.heapSize + }) + }else if(column == "library"){ + this.tbl!.recycleDataSource = arr.sort((a,b)=>{ + if(sort == 1){ + if(a.library > b.library){ + return 1 + }else if(a.library == b.library){ + return 0; + }else{ + return -1; + } + }else{ + if(b.library > a.library){ + return 1 + }else if(a.library == b.library){ + return 0; + }else{ + return -1; + } + } + }) + }else if(column == "symbol"){ + this.tbl!.recycleDataSource = arr.sort((a,b)=>{ + if(sort == 1){ + if(a.symbol > b.symbol){ + return 1 + }else if(a.symbol == b.symbol){ + return 0; + }else{ + return -1; + } + }else{ + if(b.symbol > a.symbol){ + return 1 + }else if(a.symbol == b.symbol){ + return 0; + }else{ + return -1; + } + } + }) + } + } + } + + setRightTableData(hook: NativeMemory) { + let args = new Map(); + args.set("eventId",hook.eventId); + args.set("actionType","memory-stack"); + this.startWorker(args,(results: any[]) => { + let thread = new NativeHookCallInfo(); + thread.threadId = hook.threadId; + thread.threadName = hook.threadName; + thread.title = `${hook.threadName ?? ""}【${hook.threadId}】`; + thread.type = -1 + let source = []; + source.push(thread); + source.push(...results) + this.progressEL!.loading = false + this.tblData!.dataSource = source; + }) + } + + initHtml(): string { + return ` + +
+
+ +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+ + +
+
+ `; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneCounter.ts b/host/ide/src/trace/component/trace/sheet/process/TabPaneCounter.ts similarity index 65% rename from host/ide/src/trace/component/trace/sheet/TabPaneCounter.ts rename to host/ide/src/trace/component/trace/sheet/process/TabPaneCounter.ts index 582811f47cd5d8fe5010859197fb228720f38110..08474fc67c4af6f410bf556e3a268432393a4f47 100644 --- a/host/ide/src/trace/component/trace/sheet/TabPaneCounter.ts +++ b/host/ide/src/trace/component/trace/sheet/process/TabPaneCounter.ts @@ -13,10 +13,10 @@ * limitations under the License. */ -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import {Counter, SelectionData, SelectionParam} from "../../../bean/BoxSelection.js"; -import {getTabCounters} from "../../../database/SqlLite.js"; +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {Counter, SelectionData, SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabCounters, getTabVirtualCounters} from "../../../../database/SqlLite.js"; @element('tabpane-counter') export class TabPaneCounter extends BaseElement { @@ -25,15 +25,17 @@ export class TabPaneCounter extends BaseElement { private source: Array = [] set data(val: SelectionParam | any) { + //@ts-ignore + this.tbl?.shadowRoot?.querySelector(".table")?.style?.height = (this.parentElement!.clientHeight - 45) + "px"; this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" - getTabCounters(val.trackIds, val.rightNs).then((result) => { + getTabCounters(val.processTrackIds, val.virtualTrackIds, val.rightNs).then((result) => { if (result != null && result.length > 0) { let dataSource: Array = []; let collect = this.groupByTrackIdToMap(result); let sumCount = 0; for (let key of collect.keys()) { let counters = collect.get(key); - let list:Array = []; + let list: Array = []; let index = counters!.findIndex((item) => item.startTime >= val.leftNs); if (index != -1) { list = counters!.splice(index > 0 ? index - 1 : index) @@ -49,10 +51,10 @@ export class TabPaneCounter extends BaseElement { sumData.process = " "; dataSource.splice(0, 0, sumData); this.source = dataSource - this.tbl!.dataSource = dataSource + this.tbl!.recycleDataSource = dataSource } else { this.source = []; - this.tbl!.dataSource = this.source + this.tbl!.recycleDataSource = this.source } }); } @@ -66,33 +68,54 @@ export class TabPaneCounter extends BaseElement { }); } + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!); + } + initHtml(): string { return ` - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + `; } groupByTrackIdToMap(arr: Array): Map> { let map = new Map>(); for (let counter of arr) { + counter.name = counter.name.replace("sys.virtual.mem.", "") if (map.has(counter.trackId)) { map.get(counter.trackId)!.push(counter); } else { @@ -166,7 +189,7 @@ export class TabPaneCounter extends BaseElement { } else { this.source.sort(compare(detail.key, detail.sort, 'number')) } - this.tbl!.dataSource = this.source; + this.tbl!.recycleDataSource = this.source; } } \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneSlices.ts b/host/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts similarity index 44% rename from host/ide/src/trace/component/trace/sheet/TabPaneSlices.ts rename to host/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts index 705749bde1c3f9c88721b02cb51372de1f4bb241..26cd30000c7541157896e70cff74cc0f013f477f 100644 --- a/host/ide/src/trace/component/trace/sheet/TabPaneSlices.ts +++ b/host/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts @@ -13,10 +13,10 @@ * limitations under the License. */ -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import {SelectionData, SelectionParam} from "../../../bean/BoxSelection.js"; -import {getTabSlices} from "../../../database/SqlLite.js"; +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionData, SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabSlices, getTabSlicesAsyncFunc} from "../../../../database/SqlLite.js"; @element('tabpane-slices') export class TabPaneSlices extends BaseElement { @@ -26,28 +26,37 @@ export class TabPaneSlices extends BaseElement { set data(val: SelectionParam | any) { this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" - getTabSlices(val.funTids, val.leftNs, val.rightNs).then((result) => { - if (result != null && result.length > 0) { - let sumWall = 0.0; - let sumOcc = 0; - for (let e of result) { - e.name = e.name == null ? "" : e.name - sumWall += e.wallDuration - sumOcc += e.occurrences - e.wallDuration = parseFloat((e.wallDuration / 1000000.0).toFixed(5)); - e.avgDuration = parseFloat((e.avgDuration / 1000000.0).toFixed(5)); + let asyncNames: Array = []; + let asyncPid: Array = []; + val.funAsync.forEach((it: any) => { + asyncNames.push(it.name) + asyncPid.push(it.pid) + }) + getTabSlicesAsyncFunc(asyncNames, asyncPid, val.leftNs, val.rightNs).then(res => { + getTabSlices(val.funTids, val.leftNs, val.rightNs).then((res2) => { + let result = (res || []).concat(res2 || []); + if (result != null && result.length > 0) { + let sumWall = 0.0; + let sumOcc = 0; + for (let e of result) { + e.name = e.name == null ? "" : e.name + sumWall += e.wallDuration + sumOcc += e.occurrences + e.wallDuration = parseFloat((e.wallDuration / 1000000.0).toFixed(5)); + e.avgDuration = parseFloat((e.avgDuration / 1000000.0).toFixed(5)); + } + let count = new SelectionData() + count.process = " "; + count.wallDuration = parseFloat((sumWall / 1000000.0).toFixed(5)); + count.occurrences = sumOcc; + result.splice(0, 0, count) + this.source = result + this.tbl!.recycleDataSource = result + } else { + this.source = []; + this.tbl!.recycleDataSource = this.source; } - let count = new SelectionData() - count.process = " "; - count.wallDuration = parseFloat((sumWall / 1000000.0).toFixed(5)); - count.occurrences = sumOcc; - result.splice(0, 0, count) - this.source = result - this.tbl!.dataSource = result - } else { - this.source = []; - this.tbl!.dataSource = this.source; - } + }); }); } @@ -60,22 +69,37 @@ export class TabPaneSlices extends BaseElement { }); } + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!) + } + initHtml(): string { return ` - - - - - - - - + + + + + + + + + + + + `; } @@ -109,7 +133,7 @@ export class TabPaneSlices extends BaseElement { } else { this.source.sort(compare(detail.key, detail.sort, 'number')) } - this.tbl!.dataSource = this.source; + this.tbl!.recycleDataSource = this.source; } } \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneThreadStates.ts b/host/ide/src/trace/component/trace/sheet/process/TabPaneThreadStates.ts similarity index 56% rename from host/ide/src/trace/component/trace/sheet/TabPaneThreadStates.ts rename to host/ide/src/trace/component/trace/sheet/process/TabPaneThreadStates.ts index a9ab4a43b2d40ff482493d0631ddca5e9c622c19..356df7c8b991cbbd0b56c6860b285fa6a629375a 100644 --- a/host/ide/src/trace/component/trace/sheet/TabPaneThreadStates.ts +++ b/host/ide/src/trace/component/trace/sheet/process/TabPaneThreadStates.ts @@ -13,13 +13,14 @@ * limitations under the License. */ -import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; -import {LitTable} from "../../../../base-ui/table/lit-table.js"; -import {SelectionData, SelectionParam} from "../../../bean/BoxSelection.js"; -import "../../StackBar.js" -import {getTabThreadStates} from "../../../database/SqlLite.js"; -import {Utils} from "../base/Utils.js"; -import {StackBar} from "../../StackBar.js"; +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionData, SelectionParam} from "../../../../bean/BoxSelection.js"; +import "../../../StackBar.js" +import {getTabThreadStates} from "../../../../database/SqlLite.js"; +import {Utils} from "../../base/Utils.js"; +import {StackBar} from "../../../StackBar.js"; +import {log} from "../../../../../log/Log.js"; @element('tabpane-thread-states') export class TabPaneThreadStates extends BaseElement { @@ -29,10 +30,13 @@ export class TabPaneThreadStates extends BaseElement { private source: Array = [] set data(val: SelectionParam | any) { + //@ts-ignore + this.tbl?.shadowRoot?.querySelector(".table")?.style?.height = (this.parentElement!.clientHeight - 45) + "px"; // // @ts-ignore this.range!.textContent = "Selected range: " + ((val.rightNs - val.leftNs) / 1000000.0).toFixed(5) + " ms" getTabThreadStates(val.threadIds, val.leftNs, val.rightNs).then((result) => { if (result != null && result.length > 0) { + log("getTabThreadStates result size : " + result.length) let sumWall = 0.0; let sumOcc = 0; for (let e of result) { @@ -52,12 +56,12 @@ export class TabPaneThreadStates extends BaseElement { count.occurrences = sumOcc; result.splice(0, 0, count) this.source = result; - this.tbl!.dataSource = result + this.tbl!.recycleDataSource = result this.stackBar!.data = result; } else { this.source = [] this.stackBar!.data = [] - this.tbl!.dataSource = [] + this.tbl!.recycleDataSource = [] } }) } @@ -71,29 +75,48 @@ export class TabPaneThreadStates extends BaseElement { }); } + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!) + } + initHtml(): string { return ` - -
- - -
- - - - - - - - - - + +
+ + +
+ + + + + + + + + + + + + + + + + + `; } @@ -122,7 +145,7 @@ export class TabPaneThreadStates extends BaseElement { } else { this.source.sort(compare(detail.key, detail.sort, 'number')) } - this.tbl!.dataSource = this.source; + this.tbl!.recycleDataSource = this.source; } } \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/sdk/TabPaneSdkCounter.ts b/host/ide/src/trace/component/trace/sheet/sdk/TabPaneSdkCounter.ts new file mode 100644 index 0000000000000000000000000000000000000000..0039c957c23145c778cd6ee2ece4c0e11db1c605 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/sdk/TabPaneSdkCounter.ts @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionData, SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabSdkCounterData, getTabSdkCounterLeftData, queryStartTime} from "../../../../database/SqlLite.js"; +import "../../../SpFilter.js"; +import {LitTableColumn} from "../../../../../base-ui/table/lit-table-column"; +import {Utils} from "../../base/Utils.js"; +import {SpSystemTrace} from "../../../SpSystemTrace.js"; + +@element('tabpane-sdk-counter') +export class TabPaneSdkCounter extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private keyList: Array | undefined; + private statDataArray: any = [] + private columnMap: any = {} + private sqlMap: Map = new Map(); + + set data(val: SelectionParam | any) { + this.range!.textContent = "Selected range: " + ((val.rightNs - val.leftNs) / 1000000.0).toFixed(5) + " ms"; + this.queryDataByDB(val) + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-counter'); + this.range = this.shadowRoot?.querySelector('#time-range'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail) + }); + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + queryDataByDB(val: SelectionParam | any) { + queryStartTime().then(res => { + let startTime = res[0].start_ts; + this.parseJson(SpSystemTrace.SDK_CONFIG_MAP); + let counters: Array = [] + let componentId: number = -1 + for (let index = 0; index < val.sdkCounterIds.length; index++) { + let values = val.sdkCounterIds[index].split("-") + let value = values[0]; + componentId = Number(values[1]); + counters.push(value) + } + let sqlObj = this.sqlMap.get(componentId) + let sql = sqlObj.TabCounterLeftData + getTabSdkCounterLeftData(sql, val.leftNs + startTime, counters, componentId).then(res => { + let leftTime = res[res.length - 1].max_value - startTime + let sql = sqlObj.TabCounterData + getTabSdkCounterData(sql, startTime, leftTime, val.rightNs, counters, componentId).then(item => { + this.keyList = []; + this.tbl!.innerHTML = '' + this.statDataArray = [] + if (item.length != null && item.length > 0) { + for (let index = 0; index < item.length; index++) { + const dataResult = item[index]; + let keys = Object.keys(dataResult); + let values = Object.values(dataResult); + let jsonText = '{'; + for (let keyIndex = 0; keyIndex < keys.length; keyIndex++) { + let key = keys[keyIndex]; + if (this.keyList.indexOf(key) <= -1) { + this.keyList.push(key) + } + let value = values[keyIndex]; + if (this.columnMap[key] == 'TimeStamp') { + value = Utils.getTimeString(Number(value)) + } else if (this.columnMap[key] == 'ClockTime') { + value = Utils.getTimeStampHMS(Number(value)) + } else if (this.columnMap[key] == 'RangTime') { + value = Utils.getDurString(Number(value)) + } else if (this.columnMap[key] == 'PercentType') { + value = value + "%" + } else if (this.columnMap[key] == 'CurrencyType') { + // @ts-ignore + value = value.toString().replace(/\B(?=(\d{3})+$)/g, ",") + } + if (typeof value == "string") { + value = value.replace(//gi, ">") + } + jsonText += '"' + key + '"' + ': ' + '"' + value + '"'; + if (keyIndex != keys.length - 1) { + jsonText += ',' + } else { + jsonText += '}'; + } + } + this.statDataArray.push(JSON.parse(jsonText)) + } + this.tbl!.recycleDataSource = this.statDataArray; + } else { + this.tbl!.recycleDataSource = []; + } + this.initDataElement() + + setTimeout(() => { + this.tbl!.recycleDataSource = this.statDataArray; + new ResizeObserver(() => { + if (this.parentElement?.clientHeight != 0) { + this.tbl!.style.height = '100%' + this.tbl!.reMeauseHeight() + } + }).observe(this.parentElement!) + }, 200) + }) + + }) + }); + } + + parseJson(map: Map): string { + let keys = map.keys(); + for (let key of keys) { + let configObj: any = map.get(key); + if (configObj != undefined) { + let configStr = configObj.jsonConfig; + let json = JSON.parse(configStr); + let tableConfig = json.tableConfig + if (tableConfig != null) { + let showTypes = tableConfig.showType; + for (let i = 0; i < showTypes.length; i++) { + let showType = showTypes[i]; + let type = this.getTableType(showType); + if (type == "counter") { + let selectSql = "select "; + for (let j = 0; j < showType.columns.length; j++) { + this.columnMap[showType.columns[j].column] = showType.columns[j].displayName + if (showType.columns[j].showType.indexOf(3) > -1) { + selectSql += showType.columns[j].column + "," + } + } + let leftSql = "select max(ts) as max_value,counter_id from " + showType.tableName + " where ts <= $leftNs and counter_id in" + + " ($counters) group by counter_id order by max_value desc"; + let tabCounterDataSql = selectSql.substring(0, selectSql.length - 1) + " from " + showType.tableName + + " where counter_id in ($counters) and (ts - $startTime) between $leftNs and $rightNs"; + this.sqlMap.set(key, {TabCounterData: tabCounterDataSql, TabCounterLeftData: leftSql}) + } + } + } + } + } + return ""; + } + + private getTableType(showType: any) { + let columns = showType.columns; + for (let i = 0; i < columns.length; i++) { + let column = columns[i]; + let showType = column.showType + if (showType != null) { + if (showType.indexOf(1) != -1) { + return "counter" + } + if (showType.indexOf(2) != -1) { + return "slice" + } + } + } + return "" + } + + initDataElement() { + if (this.keyList) { + this.keyList.forEach((item) => { + let htmlElement = document.createElement('lit-table-column') as LitTableColumn; + htmlElement.setAttribute('title', item); + htmlElement.setAttribute('data-index', item); + htmlElement.setAttribute('key', item); + htmlElement.setAttribute('align', 'flex-start'); + htmlElement.setAttribute("width", "1fr"); + htmlElement.setAttribute("order", ""); + this.tbl!.appendChild(htmlElement); + }) + } + } + + initHtml(): string { + return ` + +
+ + +
+ + + `; + } + + sortByColumn(detail: any) { + // @ts-ignore + function compare(property, sort, type) { + return function (a: SelectionData, b: SelectionData) { + if (a.process == " " || b.process == " ") { + return 0; + } + if (type === 'number') { + // @ts-ignore + return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); + } + // @ts-ignore + if (b[property] > a[property]) { + return sort === 2 ? 1 : -1; + } else { // @ts-ignore + if (b[property] == a[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + } + + if (detail.key.indexOf("name") != -1) { + this.statDataArray.sort(compare(detail.key, detail.sort, 'string')) + } else { + this.statDataArray.sort(compare(detail.key, detail.sort, 'number')) + } + this.tbl!.recycleDataSource = this.statDataArray; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/sdk/TabPaneSdkSlice.ts b/host/ide/src/trace/component/trace/sheet/sdk/TabPaneSdkSlice.ts new file mode 100644 index 0000000000000000000000000000000000000000..4931265675381aac35a3b4f33c551c961f2cc958 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/sdk/TabPaneSdkSlice.ts @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionData, SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabSdkSliceData, queryStartTime, queryTotalTime} from "../../../../database/SqlLite.js"; +import "../../../SpFilter.js"; +import {LitTableColumn} from "../../../../../base-ui/table/lit-table-column.js"; +import {Utils} from "../../base/Utils.js"; +import {SpSystemTrace} from "../../../SpSystemTrace.js"; + +@element('tabpane-sdk-slice') +export class TabPaneSdkSlice extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private keyList: Array | undefined; + private statDataArray: any = [] + private columnMap: any = {} + private sqlMap: Map = new Map(); + + set data(val: SelectionParam | any) { + this.range!.textContent = "Selected range: " + ((val.rightNs - val.leftNs) / 1000000.0).toFixed(5) + " ms" + this.queryDataByDB(val) + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-sdk-slice'); + this.range = this.shadowRoot?.querySelector('#time-range'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail) + }); + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + queryDataByDB(val: SelectionParam | any) { + queryTotalTime().then(res => { + let startTime = res[0].recordStartNS; + let totalTime = res[0].total; + let componentId: number = -1 + let slices: Array = []; + for (let index = 0; index < val.sdkSliceIds.length; index++) { + let values = val.sdkSliceIds[index].split("-") + let value = values[0]; + componentId = Number(values[1]); + slices.push(value) + } + this.parseJson(SpSystemTrace.SDK_CONFIG_MAP) + let sql = this.sqlMap.get(componentId) + if (sql == undefined) { + return; + } + getTabSdkSliceData(sql, startTime, val.leftNs, val.rightNs, slices, componentId).then(item => { + this.keyList = []; + this.tbl!.innerHTML = '' + this.statDataArray = [] + if (item.length != null && item.length > 0) { + for (let index = 0; index < item.length; index++) { + const dataResult = item[index]; + let keys = Object.keys(dataResult); + let values = Object.values(dataResult); + let jsonText = '{'; + for (let keyIndex = 0; keyIndex < keys.length; keyIndex++) { + let key = keys[keyIndex]; + if (this.keyList.indexOf(key) <= -1) { + this.keyList.push(key) + } + let value = values[keyIndex]; + if (this.columnMap[key] == 'TimeStamp') { + value = Utils.getTimeString(Number(value)) + } else if (this.columnMap[key] == 'ClockTime') { + value = Utils.getTimeStampHMS(Number(value)) + } else if (this.columnMap[key] == 'RangTime') { + value = Utils.getDurString(Number(value)) + } else if (this.columnMap[key] == 'PercentType') { + value = value + "%" + } else if (this.columnMap[key] == 'CurrencyType') { + // @ts-ignore + value = value.toString().replace(/\B(?=(\d{3})+$)/g, ",") + } else if (this.columnMap[key] == 'FIXED') { + value = value.toFixed(2); + } + if (typeof value == "string") { + value = value.replace(//gi, ">") + } + jsonText += '"' + key + '"' + ': ' + '"' + value + '"'; + if (keyIndex != keys.length - 1) { + jsonText += ',' + } else { + jsonText += '}'; + } + } + let data = JSON.parse(jsonText); + if (data.start_ts != null && data.end_ts != null && data.start_ts > data.end_ts && data.end_ts == 0) { + data.end_ts = totalTime; + } + if (this.isDateIntersection(val.leftNs, val.rightNs, data.start_ts, data.end_ts)) { + this.statDataArray.push(data) + } + } + this.tbl!.recycleDataSource = this.statDataArray; + } else { + this.tbl!.recycleDataSource = []; + } + this.initDataElement() + + setTimeout(() => { + this.tbl!.recycleDataSource = this.statDataArray; + new ResizeObserver(() => { + if (this.parentElement?.clientHeight != 0) { + this.tbl!.style.height = '100%' + this.tbl!.reMeauseHeight() + } + }).observe(this.parentElement!) + }, 200) + }) + }) + + } + + private isDateIntersection(selectStartTime: number, selectEndTime: number, startTime: number, endTime: number) { + if (selectStartTime > startTime && selectStartTime < endTime) { + return true; + } + if (selectEndTime > startTime && selectEndTime < endTime) { + return true; + } + if (selectStartTime < startTime && selectEndTime > endTime) { + return true; + } + return false; + } + + parseJson(map: Map): string { + let keys = map.keys(); + for (let key of keys) { + let configObj: any = map.get(key); + if (configObj != undefined) { + let configStr = configObj.jsonConfig; + let json = JSON.parse(configStr); + let tableConfig = json.tableConfig + if (tableConfig != null) { + let showTypes = tableConfig.showType; + for (let i = 0; i < showTypes.length; i++) { + let showType = showTypes[i]; + let innerTableName = this.getInnerTableName(showType); + let type = this.getTableType(showType); + if (type == "slice") { + let selectSql = "select "; + for (let j = 0; j < showType.columns.length; j++) { + this.columnMap[showType.columns[j].column] = showType.columns[j].displayName + if (showType.columns[j].showType.indexOf(3) > -1) { + switch (showType.columns[j].column) { + case "slice_id": + selectSql += "a.slice_id,b.slice_name,"; + break; + case "start_ts": + selectSql += "(a.start_ts - $startTime) as start_ts,"; + break; + case "end_ts": + selectSql += "(a.end_ts - $startTime) as end_ts,"; + break; + default: + selectSql += "a." +showType.columns[j].column + "," + } + } + } + let sql = selectSql.substring(0, selectSql.length - 1) + " from " + showType.tableName + + " as a," + innerTableName + " as b"+ + " where a.slice_id in ($slices)" + + " and a.slice_id = b.slice_id" + + " and ((a.start_ts - $startTime) >= $leftNs and (a.end_ts - $startTime) <= $rightNs " + + "or (a.start_ts - $startTime) <= $leftNs and $leftNs <= (a.end_ts - $startTime) " + + "or (a.start_ts - $startTime) <= $rightNs and $rightNs <= (a.end_ts - $startTime))" + this.sqlMap.set(key, sql); + } + } + } + } + } + return "" + } + + initDataElement() { + if (this.keyList) { + this.keyList.forEach((item) => { + let htmlElement = document.createElement('lit-table-column') as LitTableColumn; + htmlElement.setAttribute('title', item); + htmlElement.setAttribute('data-index', item); + htmlElement.setAttribute('key', item); + htmlElement.setAttribute('align', 'flex-start'); + if (item == 'slice_id') { + htmlElement.setAttribute("width", "0.5fr"); + } else { + htmlElement.setAttribute("width", "1fr"); + } + htmlElement.setAttribute("order", ""); + this.tbl!.appendChild(htmlElement); + }) + } + } + + initHtml(): string { + return ` + +
+ + +
+ + + `; + } + + sortByColumn(detail: any) { + // @ts-ignore + function compare(property, sort, type) { + return function (a: SelectionData, b: SelectionData) { + if (a.process == " " || b.process == " ") { + return 0; + } + if (type === 'number') { + // @ts-ignore + return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); + } + // @ts-ignore + if (b[property] > a[property]) { + return sort === 2 ? 1 : -1; + } else { // @ts-ignore + if (b[property] == a[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + } + if (detail.key.indexOf("name") != -1) { + this.statDataArray.sort(compare(detail.key, detail.sort, 'string')) + } else { + this.statDataArray.sort(compare(detail.key, detail.sort, 'number')) + } + this.tbl!.recycleDataSource = this.statDataArray; + } + + private getInnerTableName(showType:any) { + let inner = showType.inner; + if (inner != null) { + return inner.tableName; + } + return ""; + } + private getTableType(showType: any) { + let columns = showType.columns; + for (let i = 0; i < columns.length; i++) { + let column = columns[i]; + let showType = column.showType + if (showType != null) { + if (showType.indexOf(1) != -1) { + return "counter" + } + if (showType.indexOf(2) != -1) { + return "slice" + } + } + } + return "" + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsRecord.ts b/host/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsRecord.ts new file mode 100644 index 0000000000000000000000000000000000000000..688f1e30ceb6a37517499378d8cc0e7a754dddfa --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsRecord.ts @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabSmapsData,} from "../../../../database/SqlLite.js"; +import {Utils} from "../../base/Utils.js"; +import {log} from "../../../../../log/Log.js"; +import {Smaps} from "../../../../bean/SmapsStruct.js"; + +@element('tabpane-smaps-record') +export class TabPaneSmapsRecord extends BaseElement { + private tbl: LitTable | null | undefined; + private source: Array = []; + private queryResult: Array = [] + + set data(val: SelectionParam | any) { + // @ts-ignore + this.tbl?.shadowRoot?.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.queryDataByDB(val) + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-smaps-record'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail) + }); + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + queryDataByDB(val: SelectionParam | any) { + getTabSmapsData(val.leftNs, val.rightNs).then(result => { + log("getTabSmapsData size :" + result.length); + if (result.length != null && result.length > 0) { + for (const smaps of result) { + switch (smaps.permission.trim()) { + case "rw-": + smaps.type = "DATA" + break; + case "r-x": + smaps.type = "TEXT" + break; + case "r--": + smaps.type = "CONST" + break; + default: + smaps.type = "OTHER" + break; + } + smaps.address = smaps.start_addr + " - " + smaps.end_addr + smaps.dirtyStr = Utils.getBinaryByteWithUnit(smaps.dirty * 1024) + smaps.swapperStr = Utils.getBinaryByteWithUnit(smaps.swapper * 1024) + smaps.rssStr = Utils.getBinaryByteWithUnit(smaps.rss * 1024) + smaps.pssStr = Utils.getBinaryByteWithUnit(smaps.pss * 1024) + smaps.sizeStr = Utils.getBinaryByteWithUnit(smaps.size * 1024) + let resideS = smaps.reside.toFixed(2) + if (resideS == "0.00") { + smaps.resideStr = "0 %" + } else { + smaps.resideStr = resideS + "%" + } + } + this.source = result + this.queryResult = result; + this.tbl!.recycleDataSource = this.source + } else { + this.source = [] + this.queryResult = [] + this.tbl!.recycleDataSource = [] + } + }) + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + + + + + + + + + + + `; + } + + sortByColumn(detail: any) { + // @ts-ignore + function compare(property, sort, type) { + return function (a: Smaps, b: Smaps) { + if (type === 'number') { + // @ts-ignore + return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); + } else { + // @ts-ignore + if (b[property] > a[property]) { + return sort === 2 ? 1 : -1; + } else { // @ts-ignore + if (b[property] == a[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + } + } + + if (detail.key === 'dirtyStr' || detail.key === 'swapperStr' || detail.key === 'rssStr' || detail.key === 'sizeStr' || detail.key === 'resideStr') { + let key = detail.key.substring(0, detail.key.indexOf("Str")) + this.source.sort(compare(key, detail.sort, 'number')) + } else { + this.source.sort(compare(detail.key, detail.sort, 'string')) + } + this.tbl!.recycleDataSource = this.source; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsStatistics.ts b/host/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsStatistics.ts new file mode 100644 index 0000000000000000000000000000000000000000..fd38c7a0d70cf3432da7feff8bbf6c6045e96121 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsStatistics.ts @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../../bean/BoxSelection.js"; +import {getTabSmapsData, getTabSmapsMaxRss,} from "../../../../database/SqlLite.js"; +import {Smaps, SmapsTreeObj} from "../../../../bean/SmapsStruct.js"; +import {Utils} from "../../base/Utils.js"; + +@element('tabpane-smaps-statistics') +export class TabPaneSmapsStatistics extends BaseElement { + private tbl: LitTable | null | undefined; + + set data(val: SelectionParam | any) { + // @ts-ignore + this.tbl?.shadowRoot?.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.queryDataByDB(val) + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-smaps-statistics'); + } + + connectedCallback() { + super.connectedCallback(); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + + queryDataByDB(val: SelectionParam | any) { + getTabSmapsMaxRss(val.leftNs, val.rightNs).then(maxRes => { + let sumRss = maxRes[0].max_value + let allTree: SmapsTreeObj = new SmapsTreeObj("All", "", "*All*"); + let dataTree: SmapsTreeObj = new SmapsTreeObj("DATA", "", "DATA"); + let textTree: SmapsTreeObj = new SmapsTreeObj("TEXT", "", "TEXT"); + let constTree: SmapsTreeObj = new SmapsTreeObj("CONST", "", "CONST"); + let otherTree: SmapsTreeObj = new SmapsTreeObj("OTHER", "", "OTHER"); + getTabSmapsData(val.leftNs, val.rightNs).then(result => { + if (result.length != null && result.length > 0) { + for (let id = 0; id < result.length; id++) { + let smaps = result[id] + switch (smaps.permission.trim()) { + case "rw-": + smaps.type = "DATA" + this.handleTree(smaps, id, "DATA", dataTree, sumRss); + break; + case "r-x": + smaps.type = "TEXT" + this.handleTree(smaps, id, "TEXT", textTree, sumRss); + break; + case "r--": + smaps.type = "CONST" + this.handleTree(smaps, id, "CONST", constTree, sumRss); + break; + default: + smaps.type = "OTHER" + this.handleTree(smaps, id, "OTHER", otherTree, sumRss); + break; + } + this.handleAllDataTree(smaps, id, "All", allTree, sumRss); + if (id == result.length - 1) { + this.handleSmapsTreeObj(dataTree, sumRss) + this.handleSmapsTreeObj(textTree, sumRss) + this.handleSmapsTreeObj(constTree, sumRss) + this.handleSmapsTreeObj(otherTree, sumRss) + this.handleSmapsTreeObj(allTree, sumRss) + } + } + this.tbl!.recycleDataSource = [allTree, dataTree, textTree, constTree, otherTree] + } else { + this.tbl!.recycleDataSource = [] + } + }) + }) + + } + + private calculatePercentage(divisor: number, dividend: number) { + if (dividend == 0) { + return 0 + } else { + return (divisor / dividend) * 100 + } + } + + private handleSmapsTreeObj(smapsTreeObj: SmapsTreeObj, sumRss: number) { + smapsTreeObj.rsspro = this.calculatePercentage(smapsTreeObj.rss, sumRss) + smapsTreeObj.rssproStr = smapsTreeObj.rsspro.toFixed(2) + "%" + smapsTreeObj.regStr = smapsTreeObj.reg + "" + smapsTreeObj.rssStr = Utils.getBinaryByteWithUnit(smapsTreeObj.rss * 1024) + smapsTreeObj.dirtyStr = Utils.getBinaryByteWithUnit(smapsTreeObj.dirty * 1024) + smapsTreeObj.swapperStr = Utils.getBinaryByteWithUnit(smapsTreeObj.swapper * 1024) + smapsTreeObj.sizeStr = Utils.getBinaryByteWithUnit(smapsTreeObj.size * 1024) + smapsTreeObj.respro = this.calculatePercentage(smapsTreeObj.rss, smapsTreeObj.size) + smapsTreeObj.pssStr = Utils.getBinaryByteWithUnit(smapsTreeObj.pss * 1024) + smapsTreeObj.resproStr = smapsTreeObj.respro.toFixed(2) + "%" + } + + + private handleAllDataTree(smaps: Smaps, id: number, parentId: string, dataTree: SmapsTreeObj, sumRss: number) { + let type = smaps.type + let obj = new SmapsTreeObj(id + "", parentId, type); + obj.path = smaps.path + obj.rss = smaps.rss + obj.rsspro = this.calculatePercentage(smaps.rss, sumRss) + obj.rssproStr = obj.rsspro.toFixed(2) + "%" + obj.rssStr = Utils.getBinaryByteWithUnit(smaps.rss * 1024) + obj.dirty = smaps.dirty + obj.dirtyStr = Utils.getBinaryByteWithUnit(smaps.dirty * 1024) + obj.swapper = smaps.swapper + obj.swapperStr = Utils.getBinaryByteWithUnit(smaps.swapper * 1024) + obj.size = smaps.size + obj.sizeStr = Utils.getBinaryByteWithUnit(smaps.size * 1024) + obj.pss = smaps.pss + obj.pssStr = Utils.getBinaryByteWithUnit(smaps.pss * 1024) + obj.respro = smaps.reside + obj.resproStr = smaps.reside.toFixed(2) + "%" + dataTree.reg += 1 + if (dataTree.children.length > 1 && dataTree.path != "< multiple >") { + dataTree.path = "< multiple >" + } + dataTree.rss += smaps.rss + dataTree.dirty += smaps.dirty + dataTree.swapper += smaps.swapper + dataTree.size += smaps.size + dataTree.respro += smaps.reside + dataTree.pss += smaps.pss + dataTree.children.push(obj) + } + + private handleTree(smaps: Smaps, id: number, parentId: string, dataTree: SmapsTreeObj, sumRss: number) { + let type = smaps.start_addr + " (" + smaps.size / 4 + " pages)" + let obj = new SmapsTreeObj(id + "", parentId, type); + obj.path = smaps.path + obj.rss = smaps.rss + obj.rsspro = this.calculatePercentage(smaps.rss, sumRss) + obj.rssproStr = obj.rsspro.toFixed(2) + "%" + obj.rssStr = Utils.getBinaryByteWithUnit(smaps.rss * 1024) + obj.dirty = smaps.dirty + obj.dirtyStr = Utils.getBinaryByteWithUnit(smaps.dirty * 1024) + obj.swapper = smaps.swapper + obj.swapperStr = Utils.getBinaryByteWithUnit(smaps.swapper * 1024) + obj.size = smaps.size + obj.sizeStr = Utils.getBinaryByteWithUnit(smaps.size * 1024) + obj.pss = smaps.pss + obj.pssStr = Utils.getBinaryByteWithUnit(smaps.pss * 1024) + obj.respro = smaps.reside + obj.resproStr = smaps.reside.toFixed(2) + "%" + dataTree.reg += 1 + if (dataTree.children.length > 1 && dataTree.path != "< multiple >") { + dataTree.path = "< multiple >" + } + dataTree.rss += smaps.rss + dataTree.dirty += smaps.dirty + dataTree.swapper += smaps.swapper + dataTree.size += smaps.size + dataTree.pss += smaps.pss + dataTree.children.push(obj) + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + + + + + + + + + + + `; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/timer-shaft/Flag.ts b/host/ide/src/trace/component/trace/timer-shaft/Flag.ts index aaf2f2974001db4f43d11bbf1b23b48b87768fdc..36762b5d372008b841699eb2d616437bf8b9bf5d 100644 --- a/host/ide/src/trace/component/trace/timer-shaft/Flag.ts +++ b/host/ide/src/trace/component/trace/timer-shaft/Flag.ts @@ -23,8 +23,9 @@ export class Flag { selected: boolean = false text: string = "" hidden: boolean = false; - type:string = ""; - constructor(x: number, y: number, width: number, height: number, time: number, color: string = "#999999", selected = false, type:string="") { + type: string = ""; + + constructor(x: number, y: number, width: number, height: number, time: number, color: string = "#999999", selected = false, type: string = "") { this.x = x; this.y = y; this.width = width; diff --git a/host/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts b/host/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts index 3836cbf27b5cef43a9db005bf5763996dd52e5b5..3d8a02f3b980e67c9b1e6cdeb8ff7585c6f438f0 100644 --- a/host/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts +++ b/host/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts @@ -17,7 +17,7 @@ import {Graph} from "./Graph.js"; import {Rect} from "./Rect.js"; import {ns2s, TimerShaftElement} from "../TimerShaftElement.js"; import {ColorUtils} from "../base/ColorUtils.js"; -import {CpuStruct} from "../../../bean/CpuStruct.js"; +import {CpuStruct} from "../../../database/ui-worker/ProcedureWorkerCPU.js"; const markPadding = 5; @@ -62,12 +62,19 @@ export class Mark extends Graph { } export interface TimeRange { + slicesTime: { + color: string | null | undefined; + startTime: number | null | undefined; + endTime: number | null | undefined; + }; + scale: number; totalNS: number startX: number endX: number startNS: number endNS: number xs: Array + refresh: boolean xsTxt: Array } @@ -76,6 +83,7 @@ export class RangeRuler extends Graph { public markA: Mark public markB: Mark public range: TimeRange; + private pressedKeys: Array = []; mouseDownOffsetX = 0 mouseDownMovingMarkX = 0 movingMark: Mark | undefined | null; @@ -85,14 +93,26 @@ export class RangeRuler extends Graph { markAX: number = 0; markBX: number = 0; isPress: boolean = false - pressFrameId: number = -1 + pressFrameIdW: number = -1 + pressFrameIdS: number = -1 + pressFrameIdA: number = -1 + pressFrameIdD: number = -1 + upFrameIdW: number = -1 + upFrameIdS: number = -1 + upFrameIdA: number = -1 + upFrameIdD: number = -1 currentDuration: number = 0 + cacheInterval: { interval: number, value: number, flag: boolean } = { + interval: 200, + value: 0, + flag: false + } centerXPercentage: number = 0; animaStartTime: number | undefined - animTime: number = 100; - p: number = 800; + p: number = 1000; private readonly notifyHandler: (r: TimeRange) => void; private scale: number = 0; + private delayTimer: any = null //缩放级别 private scales: Array = [50, 100, 200, 500, 1_000, 2_000, 5_000, 10_000, 20_000, 50_000, 100_000, 200_000, 500_000, 1_000_000, 2_000_000, 5_000_000, 10_000_000, 20_000_000, 50_000_000, 100_000_000, 200_000_000, 500_000_000, @@ -100,7 +120,7 @@ export class RangeRuler extends Graph { 100_000_000_000, 200_000_000_000, 500_000_000_000]; private _cpuUsage: Array<{ cpu: number, ro: number, rate: number }> = [] - constructor(timerShaftEL:TimerShaftElement, frame: Rect, range: TimeRange, notifyHandler: (r: TimeRange) => void) { + constructor(timerShaftEL: TimerShaftElement, frame: Rect, range: TimeRange, notifyHandler: (r: TimeRange) => void) { super(timerShaftEL.canvas, timerShaftEL.ctx!, frame) this.range = range; this.notifyHandler = notifyHandler; @@ -192,6 +212,7 @@ export class RangeRuler extends Graph { } else { this.range.xsTxt = [] } + this.range.scale = this.scale; if (yu != 0) { let firstNodeWidth = ((this.scale - yu) / this.scale * realW); startX += firstNodeWidth; @@ -205,6 +226,7 @@ export class RangeRuler extends Graph { this.range.xs.push(startX) this.range.xsTxt.push(ns2s(tmpNs)) } + if (!discardNotify) { this.notifyHandler(this.range) } @@ -243,6 +265,7 @@ export class RangeRuler extends Graph { } mouseMove(ev: MouseEvent) { + this.range.refresh = false; let x = ev.offsetX - (this.canvas?.offsetLeft || 0); let y = ev.offsetY - (this.canvas?.offsetTop || 0) this.centerXPercentage = x / (this.canvas?.clientWidth || 0) @@ -270,7 +293,12 @@ export class RangeRuler extends Graph { this.movingMark.frame.x = maxX } this.movingMark.inspectionFrame.x = this.movingMark.frame.x - markPadding - requestAnimationFrame(() => this.draw()); + this.recordMovingS() + requestAnimationFrame(() => { + this.draw() + this.range.refresh = false; + this.delayDraw() + }); } else if (this.rangeRect.containsWithPadding(x, y, markPadding, 0)) { document.body.style.cursor = "move" } else if (this.frame.containsWithMargin(x, y, 20, 0, 0, 0) && !this.rangeRect.containsWithMargin(x, y, 0, markPadding, 0, markPadding)) { @@ -296,7 +324,12 @@ export class RangeRuler extends Graph { this.markB.frame.x = maxX } this.markB.inspectionFrame.x = this.markB.frame.x - markPadding - requestAnimationFrame(() => this.draw()); + this.recordMovingS() + requestAnimationFrame(() => { + this.draw() + this.range.refresh = false; + this.delayDraw() + }); } else if (this.isNewRange) { this.markA.frame.x = this.mouseDownOffsetX; this.markA.inspectionFrame.x = this.mouseDownOffsetX - markPadding; @@ -308,10 +341,43 @@ export class RangeRuler extends Graph { this.markB.frame.x = maxX; } this.markB.inspectionFrame.x = this.markB.frame.x - markPadding; - requestAnimationFrame(() => this.draw()); + this.recordMovingS() + requestAnimationFrame(() => { + this.draw() + this.range.refresh = false; + this.delayDraw() + }); } } + recordMovingS() { + if (this.animaStartTime == undefined) { + let dat = new Date(); + dat.setTime(dat.getTime() - 400); + this.animaStartTime = dat.getTime(); + } + this.currentDuration = (new Date().getTime() - this.animaStartTime); + if (Math.trunc(this.currentDuration / this.cacheInterval.interval) != this.cacheInterval.value) { + this.cacheInterval.flag = true; + this.cacheInterval.value = Math.trunc(this.currentDuration / this.cacheInterval.interval) + } else { + this.cacheInterval.flag = false; + } + this.range.refresh = this.cacheInterval.flag; + } + + delayDraw() { + if (this.delayTimer) { + clearTimeout(this.delayTimer) + } + this.delayTimer = setTimeout(() => { + this.range.refresh = true; + this.draw() + this.range.refresh = false; + this.animaStartTime = undefined + }, this.cacheInterval.interval + 50) + } + mouseOut(ev: MouseEvent) { this.movingMark = null; } @@ -329,141 +395,278 @@ export class RangeRuler extends Graph { this.markB.inspectionFrame.x = this.markB.frame.x - markPadding } - setRangeNS(startNS:number,endNS:number) { + setRangeNS(startNS: number, endNS: number) { this.range.startNS = startNS this.range.endNS = endNS this.fillX() this.draw(); } - getRange():TimeRange{ + + getRange(): TimeRange { return this.range; } + cancelPressFrame() { + if (this.pressFrameIdA != -1) cancelAnimationFrame(this.pressFrameIdA); + if (this.pressFrameIdD != -1) cancelAnimationFrame(this.pressFrameIdD); + if (this.pressFrameIdW != -1) cancelAnimationFrame(this.pressFrameIdW); + if (this.pressFrameIdS != -1) cancelAnimationFrame(this.pressFrameIdS); + } + + cancelUpFrame() { + if (this.upFrameIdA != -1) cancelAnimationFrame(this.upFrameIdA); + if (this.upFrameIdD != -1) cancelAnimationFrame(this.upFrameIdD); + if (this.upFrameIdW != -1) cancelAnimationFrame(this.upFrameIdW); + if (this.upFrameIdS != -1) cancelAnimationFrame(this.upFrameIdS); + } + + keyPress(ev: KeyboardEvent) { - if (this.animaStartTime === undefined) { - this.animaStartTime = new Date().getTime(); + if (this.animaStartTime == undefined || + (this.pressedKeys.length > 0 && this.pressedKeys[this.pressedKeys.length - 1] != ev.key.toLocaleLowerCase()) + ) { + let dat = new Date(); + dat.setTime(dat.getTime() - 400); + this.animaStartTime = dat.getTime(); } - let startTime = new Date().getTime(); - let duration = (startTime - this.animaStartTime); - if (duration < this.animTime) duration = this.animTime - this.currentDuration = duration - if (this.isPress) return - this.isPress = true - switch (ev.key.toLocaleLowerCase()) { - case "w": - let animW = () => { - if (this.scale === 50) return; - this.range.startNS += (this.centerXPercentage * this.currentDuration * 2 * this.scale / this.p); - this.range.endNS -= ((1 - this.centerXPercentage) * this.currentDuration * 2 * this.scale / this.p); - this.fillX(); - this.draw(); - this.pressFrameId = requestAnimationFrame(animW) - } - this.pressFrameId = requestAnimationFrame(animW) - break; - case "s": - let animS = () => { - if (this.range.startNS <= 0 && this.range.endNS >= this.range.totalNS) return; - this.range.startNS -= (this.centerXPercentage * this.currentDuration * 2 * this.scale / this.p); - this.range.endNS += ((1 - this.centerXPercentage) * this.currentDuration * 2 * this.scale / this.p); - this.fillX(); - this.draw(); - this.pressFrameId = requestAnimationFrame(animS) - } - this.pressFrameId = requestAnimationFrame(animS) - break; - case "a": - let animA = () => { - if (this.range.startNS == 0) return; - let s = this.scale / this.p * this.currentDuration; - this.range.startNS -= s; - this.range.endNS -= s; - this.fillX(); - this.draw(); - this.pressFrameId = requestAnimationFrame(animA) - } - this.pressFrameId = requestAnimationFrame(animA) - break; - case "d": - let animD = () => { - if (this.range.endNS >= this.range.totalNS) return; - this.range.startNS += this.scale / this.p * this.currentDuration; - this.range.endNS += this.scale / this.p * this.currentDuration; - this.fillX(); - this.draw(); - this.pressFrameId = requestAnimationFrame(animD) - } - this.pressFrameId = requestAnimationFrame(animD) - break; + this.currentDuration = (new Date().getTime() - this.animaStartTime); + if (Math.trunc(this.currentDuration / this.cacheInterval.interval) != this.cacheInterval.value) { + this.cacheInterval.flag = true; + this.cacheInterval.value = Math.trunc(this.currentDuration / this.cacheInterval.interval) + } else { + this.cacheInterval.flag = false; + } + this.range.refresh = this.cacheInterval.flag; + if (this.pressedKeys.length > 0) { + if (this.pressedKeys[this.pressedKeys.length - 1] != ev.key.toLocaleLowerCase()) { + this.cancelPressFrame(); + this.cancelUpFrame(); + this.pressedKeys.push(ev.key.toLocaleLowerCase()); + let dat = new Date(); + dat.setTime(dat.getTime() - 400); + this.animaStartTime = dat.getTime(); + this.keyboardKeyPressMap[this.pressedKeys[this.pressedKeys.length - 1]]?.bind(this)(); + } + } else { + this.cancelPressFrame(); + this.cancelUpFrame(); + this.pressedKeys.push(ev.key.toLocaleLowerCase()); + let dat = new Date(); + dat.setTime(dat.getTime() - 400); + this.animaStartTime = dat.getTime(); + this.keyboardKeyPressMap[this.pressedKeys[this.pressedKeys.length - 1]]?.bind(this)(); + } + this.isPress = true; + } + + keyPressW() { + let animW = () => { + if (this.scale === 50) { + this.range.refresh = true; + this.notifyHandler(this.range); + this.range.refresh = false; + return; + } + this.range.startNS += (this.centerXPercentage * this.currentDuration * this.scale / this.p); + this.range.endNS -= ((1 - this.centerXPercentage) * this.currentDuration * this.scale / this.p); + this.fillX(); + this.draw(); + this.range.refresh = false; + this.pressFrameIdW = requestAnimationFrame(animW) + } + this.pressFrameIdW = requestAnimationFrame(animW) + } + + keyPressS() { + let animS = () => { + if (this.range.startNS <= 0 && this.range.endNS >= this.range.totalNS) { + this.range.refresh = true; + this.notifyHandler(this.range); + this.range.refresh = false; + return; + } + this.range.startNS -= (this.centerXPercentage * this.scale / this.p * this.currentDuration); + this.range.endNS += ((1 - this.centerXPercentage) * this.scale / this.p * this.currentDuration); + this.fillX(); + this.draw(); + this.range.refresh = false; + this.pressFrameIdS = requestAnimationFrame(animS) + } + this.pressFrameIdS = requestAnimationFrame(animS) + } + + keyPressA() { + let animA = () => { + if (this.range.startNS == 0) { + this.range.refresh = true; + this.notifyHandler(this.range); + this.range.refresh = false; + return; + } + let s = this.scale / this.p * this.currentDuration * .4; + this.range.startNS -= s; + this.range.endNS -= s; + this.fillX(); + this.draw(); + this.range.refresh = false; + this.pressFrameIdA = requestAnimationFrame(animA) + } + this.pressFrameIdA = requestAnimationFrame(animA) + } + + keyPressD() { + let animD = () => { + if (this.range.endNS >= this.range.totalNS) { + this.range.refresh = true; + this.notifyHandler(this.range); + this.range.refresh = false; + return; + } + let s = this.scale / this.p * this.currentDuration * .4; + this.range.startNS += s; + this.range.endNS += s; + this.fillX(); + this.draw(); + this.range.refresh = false; + this.pressFrameIdD = requestAnimationFrame(animD) } + this.pressFrameIdD = requestAnimationFrame(animD) + } + + keyboardKeyPressMap: any = { + "w": this.keyPressW, + "s": this.keyPressS, + "a": this.keyPressA, + "d": this.keyPressD, + } + + keyboardKeyUpMap: any = { + "w": this.keyUpW, + "s": this.keyUpS, + "a": this.keyUpA, + "d": this.keyUpD, } keyUp(ev: KeyboardEvent) { - this.animaStartTime = undefined; - this.isPress = false - if (this.pressFrameId != -1) { - cancelAnimationFrame(this.pressFrameId) + this.cacheInterval.value = 0; + if (this.pressedKeys.length > 0) { + let number = this.pressedKeys.findIndex((value) => value === ev.key.toLocaleLowerCase()); + if (number == this.pressedKeys.length - 1) { + this.animaStartTime = undefined; + this.cancelPressFrame(); + this.keyboardKeyUpMap[ev.key]?.bind(this)(); + } + if (number != -1) { + this.pressedKeys.splice(number, 1); + } } + this.isPress = false; + } + + + keyUpW() { let startTime = new Date().getTime(); - switch (ev.key) { - case "w": - let animW = () => { - if (this.scale === 50) return; - let dur = (new Date().getTime() - startTime); - this.range.startNS += (this.centerXPercentage * 100 * this.scale / this.p); - this.range.endNS -= ((1 - this.centerXPercentage) * 100 * this.scale / this.p); - this.fillX(); - this.draw(); - if (dur < 200) { - requestAnimationFrame(animW) - } - } - requestAnimationFrame(animW) - break; - case "s": - let animS = () => { - if (this.range.startNS <= 0 && this.range.endNS >= this.range.totalNS) return; - let dur = (new Date().getTime() - startTime); - this.range.startNS -= (this.centerXPercentage * 100 * this.scale / this.p); - this.range.endNS += ((1 - this.centerXPercentage) * 100 * this.scale / this.p); - this.fillX(); - this.draw(); - if (dur < 200) { - requestAnimationFrame(animS) - } - } - requestAnimationFrame(animS) - break; - case "a": - let animA = () => { - if (this.range.startNS <= 0) return - let dur = (new Date().getTime() - startTime); - let s = this.scale * 80 / this.p; - this.range.startNS -= s; - this.range.endNS -= s; - this.fillX(); - this.draw(); - if (dur < 200) { - requestAnimationFrame(animA) - } - } - animA(); - break; - case "d": - let animD = () => { - if (this.range.endNS >= this.range.totalNS) return; - let dur = (new Date().getTime() - startTime); - let s = this.scale * 80 / this.p; - this.range.startNS += s; - this.range.endNS += s; - this.fillX(); - this.draw(); - if (dur < 200) { - requestAnimationFrame(animD) - } - } - animD(); - break; + let animW = () => { + if (this.scale === 50) { + this.range.refresh = true; + this.notifyHandler(this.range); + this.range.refresh = false; + return; + } + let dur = (new Date().getTime() - startTime); + this.range.startNS += (this.centerXPercentage * 100 * this.scale / this.p); + this.range.endNS -= ((1 - this.centerXPercentage) * 100 * this.scale / this.p); + this.fillX(); + this.draw(); + this.range.refresh = false; + if (dur < 200) { + this.upFrameIdW = requestAnimationFrame(animW); + } else { + this.range.refresh = true; + this.notifyHandler(this.range); + this.range.refresh = false; + } + } + this.upFrameIdW = requestAnimationFrame(animW); + } + + keyUpS() { + let startTime = new Date().getTime(); + let animS = () => { + if (this.range.startNS <= 0 && this.range.endNS >= this.range.totalNS) { + this.range.refresh = true; + this.notifyHandler(this.range); + this.range.refresh = false; + return; + } + let dur = (new Date().getTime() - startTime); + this.range.startNS -= (this.centerXPercentage * 100 * this.scale / this.p); + this.range.endNS += ((1 - this.centerXPercentage) * 100 * this.scale / this.p); + this.fillX(); + this.draw(); + this.range.refresh = false; + if (dur < 200) { + this.upFrameIdS = requestAnimationFrame(animS); + } else { + this.range.refresh = true; + this.notifyHandler(this.range); + this.range.refresh = false; + } + } + this.upFrameIdS = requestAnimationFrame(animS); + } + + keyUpA() { + let startTime = new Date().getTime(); + let animA = () => { + if (this.range.startNS <= 0) { + this.range.refresh = true; + this.notifyHandler(this.range); + this.range.refresh = false; + return; + } + let dur = (new Date().getTime() - startTime); + let s = this.scale * 80 / this.p; + this.range.startNS -= s; + this.range.endNS -= s; + this.fillX(); + this.draw(); + this.range.refresh = false; + if (dur < 200) { + this.upFrameIdA = requestAnimationFrame(animA); + } else { + this.range.refresh = true; + this.notifyHandler(this.range); + this.range.refresh = false; + } + } + this.upFrameIdA = requestAnimationFrame(animA); + } + + keyUpD() { + let startTime = new Date().getTime(); + let animD = () => { + if (this.range.endNS >= this.range.totalNS) { + this.range.refresh = true; + this.notifyHandler(this.range); + this.range.refresh = false; + return; + } + let dur = (new Date().getTime() - startTime); + let s = this.scale * 80 / this.p; + this.range.startNS += s; + this.range.endNS += s; + this.fillX(); + this.draw(); + this.range.refresh = false; + if (dur < 200) { + this.upFrameIdD = requestAnimationFrame(animD); + } else { + this.range.refresh = true; + this.notifyHandler(this.range); + this.range.refresh = false; + } } + this.upFrameIdD = requestAnimationFrame(animD); } } diff --git a/host/ide/src/trace/component/trace/timer-shaft/Rect.ts b/host/ide/src/trace/component/trace/timer-shaft/Rect.ts index 1197ec56c284692d28d71c7d47ba3872d321a08a..b37ce9a584134d7cd68bf6d667bc94da2cdd86d5 100644 --- a/host/ide/src/trace/component/trace/timer-shaft/Rect.ts +++ b/host/ide/src/trace/component/trace/timer-shaft/Rect.ts @@ -56,6 +56,14 @@ export class Rect { } } + static getIntersect(r1: DOMRect|Rect, rect: DOMRect|Rect):Rect { + let maxX = Math.max(r1.x,rect.x) + let maxY = Math.max(r1.y,rect.y) + let width = Math.abs(Math.min(r1.x + r1.width,rect.x + rect.width) - Math.max(r1.x,rect.x) ) + let height = Math.abs(Math.min(r1.y + r1.height,rect.y + rect.height) - Math.max(r1.y,rect.y) ) + return new Rect(maxX, maxY, width, height) + } + contains(x: number, y: number): boolean { return this.x <= x && x <= this.x + this.width && this.y <= y && y <= this.y + this.height; } diff --git a/host/ide/src/trace/component/trace/timer-shaft/SportRuler.ts b/host/ide/src/trace/component/trace/timer-shaft/SportRuler.ts index ac43c903e494a2a8a152cae61103ba18ab84835a..2b258651851e6fc16ca07a834b8e163388c156ae 100644 --- a/host/ide/src/trace/component/trace/timer-shaft/SportRuler.ts +++ b/host/ide/src/trace/component/trace/timer-shaft/SportRuler.ts @@ -22,19 +22,27 @@ import {TraceRow} from "../base/TraceRow.js"; import {SpApplication} from "../../../SpApplication.js"; export class SportRuler extends Graph { + static isMouseInSportRuler = false; public flagList: Array = []; - private hoverFlag: Flag = new Flag(0, 0, 0, 0, 0); + isRangeSelect: boolean = false;//region selection + private hoverFlag: Flag = new Flag(-1, 0, 0, 0, 0); private lineColor: string | null = null; private rulerW = 0; private _range: TimeRange = {} as TimeRange; private readonly notifyHandler: ((hoverFlag: Flag | undefined | null, selectFlag: Flag | undefined | null) => void) | undefined; private readonly flagClickHandler: ((flag: Flag | undefined | null) => void) | undefined; private invertedTriangleTime: number | null | undefined = null; - isRangeSelect: boolean = false;//region selection + private slicesTime: { startTime: number | null | undefined, endTime: number | null | undefined, color: string | null } | null = { + startTime: null, + endTime: null, + color: null + }; + private timerShaftEL: TimerShaftElement|undefined|null; constructor(timerShaftEL: TimerShaftElement, frame: Rect, notifyHandler: (hoverFlag: Flag | undefined | null, selectFlag: Flag | undefined | null) => void, flagClickHandler: (flag: Flag | undefined | null) => void) { super(timerShaftEL.canvas, timerShaftEL.ctx!, frame) this.notifyHandler = notifyHandler; this.flagClickHandler = flagClickHandler; + this.timerShaftEL = timerShaftEL; } get range(): TimeRange { @@ -63,7 +71,7 @@ export class SportRuler extends Graph { draw(): void { this.rulerW = this.canvas!.offsetWidth - this.c.clearRect(this.frame.x, this.frame.y, this.frame.width, this.frame.height+1) + this.c.clearRect(this.frame.x, this.frame.y, this.frame.width, this.frame.height + 1) this.c.beginPath(); this.lineColor = window.getComputedStyle(this.canvas!, null).getPropertyValue("color"); this.c.strokeStyle = this.lineColor //"#dadada" @@ -134,8 +142,9 @@ export class SportRuler extends Graph { this.c.closePath(); } if (this.invertedTriangleTime != null && typeof (this.invertedTriangleTime) != undefined) { - this.drawInvertedTriangle(this.invertedTriangleTime,document.querySelector("sp-application")!.dark?"#FFFFFF":"#000000") + this.drawInvertedTriangle(this.invertedTriangleTime, document.querySelector("sp-application")!.dark ? "#FFFFFF" : "#000000") } + this.drawSlicesMark(this.slicesTime?.startTime, this.slicesTime?.endTime) } drawTriangle(time: number, type: string) { @@ -163,6 +172,17 @@ export class SportRuler extends Graph { } else if (type == "square") { if (i != -1) { this.flagList[i].type = ""; + } else { + let triangle = this.flagList.findIndex(it => it.type == "triangle"); + if (triangle !== -1) { + this.flagList[triangle].type = ""; + this.draw(); + this.notifyHandler && this.notifyHandler( + !this.hoverFlag.hidden ? this.hoverFlag : null, + this.flagList.find(it => it.selected) || null + ) + return this.flagList[triangle].time; + } } } else if (type == "inverted") { this.invertedTriangleTime = time @@ -175,10 +195,10 @@ export class SportRuler extends Graph { } } - removeTriangle(type:string){ + removeTriangle(type: string) { if (type == "inverted") { this.invertedTriangleTime = null; - }else { + } else { let i = this.flagList.findIndex(it => it.type == type) if (i !== -1) { this.flagList.splice(i, 1) @@ -189,16 +209,16 @@ export class SportRuler extends Graph { !this.hoverFlag.hidden ? this.hoverFlag : null, this.flagList.find(it => it.selected) || null ) - } + } - drawInvertedTriangle(time: number, color: string = "#000000"){ + drawInvertedTriangle(time: number, color: string = "#000000") { if (time != null && typeof (time) != undefined) { let x = Math.round(this.rulerW * (time - this.range.startNS) / (this.range.endNS - this.range.startNS)); this.c.beginPath(); this.c.fillStyle = color; this.c.strokeStyle = color; - this.c.moveTo(x-2, 142); - this.c.lineTo(x+2, 142); + this.c.moveTo(x - 3, 141); + this.c.lineTo(x + 3, 141); this.c.lineTo(x, 145); this.c.fill() this.c.closePath() @@ -206,8 +226,82 @@ export class SportRuler extends Graph { } } + setSlicesMark(startTime: number | null = null, endTime: number | null = null) { + if (startTime != null && typeof (startTime) != undefined && endTime != null && typeof (endTime) != undefined) { + this.slicesTime = { + startTime: startTime <= endTime ? startTime : endTime, + endTime: startTime <= endTime ? endTime : startTime, + color: null + }; + } else { + this.slicesTime = {startTime: null, endTime: null, color: null}; + } + this.range.slicesTime = this.slicesTime; + this.draw(); + this.timerShaftEL?.render(); + } + + drawSlicesMark(startTime: number | null = null, endTime: number | null = null) { + if (startTime != null && typeof (startTime) != undefined && endTime != null && typeof (endTime) != undefined) { + let startX = Math.round(this.rulerW * (startTime - this.range.startNS) / (this.range.endNS - this.range.startNS)); + let endX = Math.round(this.rulerW * (endTime - this.range.startNS) / (this.range.endNS - this.range.startNS)); + this.c.beginPath(); + if (document.querySelector("sp-application")!.dark) { + this.c.strokeStyle = "#FFF" + this.c.fillStyle = "#FFF" + this.range.slicesTime.color = "#FFF" + } else { + this.c.strokeStyle = "#344596" + this.c.fillStyle = "#344596" + this.range.slicesTime.color = "#344596" + } + this.c.moveTo(startX + 9, 132); + this.c.lineTo(startX, 141); + this.c.lineTo(startX, 132); + this.c.lineTo(startX + 9, 132); + + this.c.lineTo(endX - 9, 132); + this.c.lineTo(endX, 132); + this.c.lineTo(endX, 141); + this.c.lineTo(endX - 9, 132); + this.c.closePath() + this.c.stroke(); + + + this.c.beginPath(); + if (document.querySelector("sp-application")!.dark) { + this.c.strokeStyle = "#FFF" + this.c.fillStyle = "#FFF" + } else { + this.c.strokeStyle = "#000" + this.c.fillStyle = "#000" + } + let lineWidth = endX - startX; + let txt = ns2s((endTime || 0) - (startTime || 0)); + this.c.moveTo(startX, this.frame.y + 22); + this.c.lineTo(endX, this.frame.y + 22); + this.c.moveTo(startX, this.frame.y + 22 - 5); + this.c.lineTo(startX, this.frame.y + 22 + 5); + this.c.moveTo(endX, this.frame.y + 22 - 5); + this.c.lineTo(endX, this.frame.y + 22 + 5); + let txtWidth = this.c.measureText(txt).width; + if (lineWidth > txtWidth) { + this.c.fillText(`${txt}`, startX + (lineWidth - txtWidth) / 2, this.frame.y + 20) + } else { + if (endX + txtWidth >= this.frame.width) { + this.c.fillText(`${txt}`, startX - 5 - txtWidth, this.frame.y + 20) + } else { + this.c.fillText(`${txt}`, endX + 5, this.frame.y + 20) + } + } + this.c.stroke(); + this.c.closePath(); + } + } + //绘制旗子 drawFlag(x: number, color: string = "#999999", isFill: boolean = false, text: string = "", type: string = "") { + if (x < 0) return; this.c.beginPath(); this.c.fillStyle = color; this.c.strokeStyle = color; @@ -277,7 +371,6 @@ export class SportRuler extends Graph { ) } - static isMouseInSportRuler = false; edgeDetection(ev: MouseEvent): boolean { let x = ev.offsetX - (this.canvas?.offsetLeft || 0) diff --git a/host/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts b/host/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts index e397fbe1585bf9b62d7dc1b301f494d51d7eca01..263129547ef4732d9ca96b6d1fa0f25e6f5d8b65 100644 --- a/host/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts +++ b/host/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts @@ -29,14 +29,22 @@ export class TabPaneFlag extends BaseElement { document.dispatchEvent(new CustomEvent('flag-change', {detail: this.flag})); } }); - this.shadowRoot?.querySelector("#text-input")?.addEventListener("keydown", (event: any) => { + this.shadowRoot?.querySelector("#text-input")?.addEventListener("keyup", (event: any) => { + event.stopPropagation(); if (event.keyCode == "13") { if (this.flag) { + (window as any).flagInputFocus = false; this.flag.text = event?.target.value document.dispatchEvent(new CustomEvent('flag-change', {detail: this.flag})); } } }); + this.shadowRoot?.querySelector("#text-input")?.addEventListener("blur", (event: any) => { + (window as any).flagInputFocus = false; + }); + this.shadowRoot?.querySelector("#text-input")?.addEventListener("focus", (event: any) => { + (window as any).flagInputFocus = true; + }); this.shadowRoot?.querySelector("#remove-flag")?.addEventListener("click", (event: any) => { if (this.flag) { this.flag.hidden = true; @@ -54,50 +62,50 @@ export class TabPaneFlag extends BaseElement { initHtml(): string { return ` - -
-
Annotation at
- - Change color: - -
+ +
+
Annotation at
+ + Change color: + +
`; } diff --git a/host/ide/src/trace/database/ConfigWorker.ts b/host/ide/src/trace/database/ConfigWorker.ts new file mode 100644 index 0000000000000000000000000000000000000000..e1db9cf71b4903795f1c6a35b479ed6da4e00ee2 --- /dev/null +++ b/host/ide/src/trace/database/ConfigWorker.ts @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const mallocSize = 1024 * 1024; + +let Module_T: any = null; + +function initConfigWASM(wasmFunctionName:string) { + return new Promise((resolve, reject) => { + function callModelFun(functionName: string) { + let func = eval(functionName); + Module_T = new func({ + locateFile: (s: any) => { + return s + }, + print: (line: any) => { + }, + printErr: (line: any) => { + }, + onRuntimeInitialized: () => { + resolve("ok") + }, + onAbort: () => { + } + }); + } + callModelFun(wasmFunctionName) + }) +} + +self.onmessage = async (e: MessageEvent) => { + if (e.data.action === "open") { + let jsFile = e.data.wasmJsName + importScripts(jsFile) + await initConfigWASM(e.data.WasmName); + let dataCallBack = (heapPtr: number, size: number, isEnd: number, isConfig: number) => { + if (isConfig == 1) { + let jsonOut: Uint8Array = Module_T.HEAPU8.slice(heapPtr, heapPtr + size); + let decoder = new TextDecoder(); + let result = decoder.decode(jsonOut); + let json = JSON.parse(result); + self.postMessage({ + results: json, + }); + } + } + let fn = Module_T.addFunction(dataCallBack, "viiii"); + Module_T._Init(fn, mallocSize) + Module_T._TraceStreamer_In_JsonConfig(); + } +} diff --git a/host/ide/src/trace/database/Procedure.ts b/host/ide/src/trace/database/Procedure.ts index 8793eafdc3fb95164ad9ec762b3e35ab9fc83de4..6e3fe4df6eb918131eaaf89307af53fb0f6bfa09 100644 --- a/host/ide/src/trace/database/Procedure.ts +++ b/host/ide/src/trace/database/Procedure.ts @@ -13,6 +13,9 @@ * limitations under the License. */ + +import {query} from "./SqlLite.js"; + class ProcedureThread extends Worker { busy: boolean = false; isCancelled: boolean = false; @@ -36,7 +39,15 @@ class ProcedureThread extends Worker { } if (transfer) { try { - this.postMessage(pam, [transfer]); + if (Array.isArray(transfer)) { + if (transfer.length > 0) { + this.postMessage(pam, [...transfer]); + } else { + this.postMessage(pam); + } + } else { + this.postMessage(pam, [transfer]); + } } catch (e: any) { } } else { @@ -54,13 +65,14 @@ class ProcedurePool { static cpuCount = Math.floor((window.navigator.hardwareConcurrency || 4) / 2); maxThreadNumber: number = 1 works: Array = [] - proxyRunningNum: any; timelineChange: ((a: any) => void) | undefined | null = null; - cpusLen = ProcedurePool.build('cpu', 8); - freqLen = ProcedurePool.build('freq', 2); - processLen = ProcedurePool.build('process', 8); - // names = [...this.cpusLen, ...this.freqLen, ...this.processLen, ...this.memLen, ...this.threadLen, ...this.funcLen]; + cpusLen = ProcedurePool.build('cpu', 0); + freqLen = ProcedurePool.build('freq', 0); + processLen = ProcedurePool.build('process', 0); + logicDataLen = ProcedurePool.build('logic', 2); names = [...this.cpusLen, ...this.processLen, ...this.freqLen]; + logicDataHandles = [...this.logicDataLen] + onComplete: Function | undefined;//任务完成回调 constructor(threadBuild: (() => ProcedureThread) | undefined = undefined) { @@ -76,10 +88,13 @@ class ProcedurePool { for (let i = 0; i < this.maxThreadNumber; i++) { this.newThread(); } + for (let j = 0; j < this.logicDataHandles.length; j++) { + this.logicDataThread() + } } newThread() { - let thread: ProcedureThread = new ProcedureThread("trace/database/ProcedureWorker.js", {type: "module"}) + let thread: ProcedureThread = new ProcedureThread("trace/database/ui-worker/ProcedureWorker.js", {type: "module"}) thread.name = this.names[this.works.length] thread.onmessage = (event: MessageEvent) => { thread.busy = false; @@ -111,6 +126,57 @@ class ProcedurePool { return thread; } + logicDataThread(){ + let thread: ProcedureThread = new ProcedureThread("trace/database/logic-worker/ProcedureLogicWorker.js", {type: "module"}) + thread.name = this.logicDataHandles[this.works.length - this.names.length] + thread.onmessage = (event: MessageEvent) => { + thread.busy = false; + if(event.data.isQuery){ + query(event.data.type,event.data.sql,event.data.args,"exec-buf").then((res:any)=>{ + thread.postMessage({ + type:event.data.type, + params:{ + list:res + }, + id:event.data.id + }) + }) + return + } + if(event.data.isSending){ + if (Reflect.has(thread.taskMap, event.data.id)) { + if (event.data) { + let fun = thread.taskMap[event.data.id]; + if (fun) { + fun(event.data.results, event.data.hover); + } + return; + } + } + } + if (Reflect.has(thread.taskMap, event.data.id)) { + if (event.data) { + let fun = thread.taskMap[event.data.id]; + if (fun) { + fun(event.data.results, event.data.hover); + } + Reflect.deleteProperty(thread.taskMap, event.data.id) + } + } + if (this.isIdle() && this.onComplete) { + this.onComplete(); + } + } + thread.onmessageerror = e => { + } + thread.onerror = e => { + } + thread.id = this.works.length + thread.busy = false + this.works?.push(thread) + return thread; + } + close = () => { for (let i = 0; i < this.works.length; i++) { let thread = this.works[i]; @@ -137,6 +203,22 @@ class ProcedurePool { return thread; } + submitWithNamePromise(name: string, type: string, args: any, transfer: any): Promise { + return new Promise((resolve, reject) => { + let noBusyThreads = this.works.filter(it => it.name === name); + let thread: ProcedureThread | undefined + if (noBusyThreads.length > 0) { //取第一个空闲的线程进行任务 + thread = noBusyThreads[0]; + thread!.queryFunc(type, args, transfer, (res: any, hover: any) => { + resolve({ + res: res, + hover: hover, + }) + }); + } + }) + } + isIdle() { return this.works.every(it => !it.busy); } diff --git a/host/ide/src/trace/database/ProcedureWorker.ts b/host/ide/src/trace/database/ProcedureWorker.ts deleted file mode 100644 index 0adeae3816bf762cc8097be118c7f31ab7cdde7a..0000000000000000000000000000000000000000 --- a/host/ide/src/trace/database/ProcedureWorker.ts +++ /dev/null @@ -1,457 +0,0 @@ -/* - * Copyright (C) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {cpu, CpuStruct, WakeupBean} from "./ProcedureWorkerCPU.js"; -import {drawFlagLine, drawLines, ns2s, ns2x, Rect} from "./ProcedureWorkerCommon.js"; -import {CpuFreqStruct, freq} from "./ProcedureWorkerFreq.js"; -import {proc, ProcessStruct} from "./ProcedureWorkerProcess.js"; -import {mem, ProcessMemStruct} from "./ProcedureWorkerMem.js"; -import {thread, ThreadStruct} from "./ProcedureWorkerThread.js"; -import {func, FuncStruct} from "./ProcedureWorkerFunc.js"; -import {fps, FpsStruct} from "./ProcedureWorkerFPS.js"; -import {heap, HeapStruct} from "./ProcedureWorkerHeap.js"; -import {timeline} from "./ProcedureWorkerTimeline.js"; - -let dataList: any = {} -let dataFilter: any = {} -let canvasList: any = {} -let contextList: any = {} - -function drawSelection(context: any, params: any) { - if (params.isRangeSelect) { - params.rangeSelectObject!.startX = Math.floor(ns2x(params.rangeSelectObject!.startNS!, params.startNS, params.endNS, params.totalNS, params.frame)); - params.rangeSelectObject!.endX = Math.floor(ns2x(params.rangeSelectObject!.endNS!, params.startNS, params.endNS, params.totalNS, params.frame)); - if (context) { - context.globalAlpha = 0.5 - context.fillStyle = "#666666" - context.fillRect(params.rangeSelectObject!.startX!, params.frame.y, params.rangeSelectObject!.endX! - params.rangeSelectObject!.startX!, params.frame.height) - context.globalAlpha = 1 - } - } -} - -function drawWakeUp(context: CanvasRenderingContext2D | any, wake: WakeupBean | null, startNS: number, endNS: number, totalNS: number, frame: Rect, selectCpuStruct: CpuStruct | undefined = undefined, currentCpu: number | undefined = undefined) { - if (wake) { - let x1 = Math.floor(ns2x((wake.wakeupTime || 0), startNS, endNS, totalNS, frame)); - context.beginPath(); - context.lineWidth = 2; - context.fillStyle = "#000000"; - if (x1 > 0 && x1 < frame.x + frame.width) { - context.moveTo(x1, frame.y); - context.lineTo(x1, frame.y + frame.height); - if (currentCpu == wake.cpu) { - let centerY = Math.floor(frame.y + frame.height / 2); - context.moveTo(x1, centerY - 6); - context.lineTo(x1 + 4, centerY); - context.lineTo(x1, centerY + 6); - context.lineTo(x1 - 4, centerY); - context.lineTo(x1, centerY - 6); - context.fill(); - } - } - if (selectCpuStruct) { - let x2 = Math.floor(ns2x((selectCpuStruct.startTime || 0), startNS, endNS, totalNS, frame)); - let y = frame.y + frame.height - 10; - context.moveTo(x1, y); - context.lineTo(x2, y); - - let s = ns2s((selectCpuStruct.startTime || 0) - (wake.wakeupTime || 0)); - let distance = x2 - x1; - if (distance > 12) { - context.moveTo(x1, y); - context.lineTo(x1 + 6, y - 3); - context.moveTo(x1, y); - context.lineTo(x1 + 6, y + 3); - context.moveTo(x2, y); - context.lineTo(x2 - 6, y - 3); - context.moveTo(x2, y); - context.lineTo(x2 - 6, y + 3); - let measure = context.measureText(s); - let tHeight = measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent - let xStart = x1 + Math.floor(distance / 2 - measure.width / 2); - if (distance > measure.width + 4) { - context.fillStyle = "#ffffff" - context.fillRect(xStart - 2, y - 4 - tHeight, measure.width + 4, tHeight + 4); - context.font = "10px solid"; - context.fillStyle = "#000000"; - context.textBaseline = "bottom"; - context.fillText(s, xStart, y - 2); - } - - } - } - context.strokeStyle = "#000000"; - context.stroke(); - context.closePath(); - } -} - -self.onmessage = function (e: any) { - if ((e.data.type as string).startsWith("clear")) { - dataList = {}; - dataFilter = {}; - canvasList = {}; - contextList = {}; - // @ts-ignore - self.postMessage({ - id: e.data.id, - type: e.data.type, - results: null, - }); - return; - } - let res: any - if (e.data.params.list) { - dataList[e.data.type] = e.data.params.list; - dataFilter[e.data.type] = new Set(); - if (e.data.params.offscreen) { - canvasList[e.data.type] = e.data.params.offscreen; - contextList[e.data.type] = e.data.params.offscreen!.getContext('2d'); - contextList[e.data.type].scale(e.data.params.dpr, e.data.params.dpr); - } - } - if(!dataFilter[e.data.type]){ - dataFilter[e.data.type] = new Set(); - } - let canvas = canvasList[e.data.type]; - let context = contextList[e.data.type]; - let type = e.data.type as string; - let params = e.data.params; - let isRangeSelect = e.data.params.isRangeSelect; - let isHover = e.data.params.isHover; - let xs = e.data.params.xs; - let frame = e.data.params.frame; - let flagMoveInfo = e.data.params.flagMoveInfo; - let flagSelectedInfo = e.data.params.flagSelectedInfo; - let hoverX = e.data.params.hoverX; - let hoverY = e.data.params.hoverY; - let startNS = e.data.params.startNS; - let endNS = e.data.params.endNS; - let totalNS = e.data.params.totalNS; - let canvasWidth = e.data.params.canvasWidth; - let canvasHeight = e.data.params.canvasHeight; - let useCache = e.data.params.useCache; - let lineColor = e.data.params.lineColor; - let wakeupBean: WakeupBean | null = e.data.params.wakeupBean; - if (canvas) { - if (canvas.width !== canvasWidth || canvas.height !== canvasHeight) { - canvas.width = canvasWidth; - canvas.height = canvasHeight; - context.scale(e.data.params.dpr, e.data.params.dpr); - } - } - if (type.startsWith("timeline")) { - timeline(canvas, context, startNS, endNS, totalNS, frame, - e.data.params.keyPressCode, e.data.params.keyUpCode, - e.data.params.mouseDown, e.data.params.mouseUp, - e.data.params.mouseMove, e.data.params.mouseOut, - e.data.params.offsetLeft, e.data.params.offsetTop, - (a: any) => { - //@ts-ignore - self.postMessage({ - id: "timeline", - type: "timeline-range-changed", - results: a, - }); - } - ); - // @ts-ignore - self.postMessage({ - id: e.data.id, - type: type, - results: null, - }); - } else if (type.startsWith("cpu")) { - if (!useCache) { - cpu(dataList[type], dataFilter[type], startNS, endNS, totalNS, frame); - } - if (canvas) { - context.clearRect(0, 0, canvas.width, canvas.height); - context.beginPath(); - drawLines(context, xs, frame.height, lineColor); - CpuStruct.hoverCpuStruct = undefined; - if (isHover) { - for (let re of dataFilter[e.data.type]) { - if (hoverX >= re.frame.x && hoverX <= re.frame.x + re.frame.width && hoverY >= re.frame.y && hoverY <= re.frame.y + re.frame.height) { - CpuStruct.hoverCpuStruct = re; - break; - } - } - } else { - CpuStruct.hoverCpuStruct = e.data.params.hoverCpuStruct; - } - CpuStruct.selectCpuStruct = e.data.params.selectCpuStruct; - for (let re of dataFilter[type]) { - CpuStruct.draw(context, re); - } - drawSelection(context, params); - context.closePath(); - drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); - let currentCpu = parseInt(type.replace("cpu", "")); - drawWakeUp(context, wakeupBean, startNS, endNS, totalNS, frame, type == `cpu${CpuStruct.selectCpuStruct?.cpu || 0}` ? CpuStruct.selectCpuStruct : undefined, currentCpu); - } - // @ts-ignore - self.postMessage({ - id: e.data.id, - type: type, - results: canvas ? undefined : dataFilter[type], - hover: CpuStruct.hoverCpuStruct - }); - } else if (type.startsWith("fps")) { - if (!useCache) { - fps(dataList[type], dataFilter[type], startNS, endNS, totalNS, frame); - } - if (canvas) { - context.clearRect(0, 0, canvas.width, canvas.height); - context.beginPath(); - drawLines(context, xs, frame.height, lineColor) - for (let re of dataFilter[type]) { - FpsStruct.draw(context, re) - } - drawSelection(context, params); - context.closePath(); - let maxFps = FpsStruct.maxFps + "FPS" - let textMetrics = context.measureText(maxFps); - context.globalAlpha = 0.8 - context.fillStyle = "#f0f0f0" - context.fillRect(0, 5, textMetrics.width + 8, 18) - context.globalAlpha = 1 - context.fillStyle = "#333" - context.textBaseline = "middle" - context.fillText(maxFps, 4, 5 + 9); - drawWakeUp(context, wakeupBean, startNS, endNS, totalNS, frame); - drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); - } - // @ts-ignore - self.postMessage({id: e.data.id, type: type, results: canvas ? undefined : dataFilter[type], hover: undefined}); - } else if (type.startsWith("freq")) { - if (!useCache) { - freq(dataList[type], dataFilter[type], startNS, endNS, totalNS, frame) - } - if (canvas) { - context.clearRect(0, 0, canvas.width, canvas.height); - context.beginPath(); - CpuFreqStruct.maxFreq = e.data.params.maxFreq; - CpuFreqStruct.maxFreqName = e.data.params.maxFreqName; - drawLines(context, xs, frame.height, lineColor) - CpuFreqStruct.hoverCpuFreqStruct = undefined; - if (isHover) { - for (let re of dataFilter[type]) { - if (hoverX >= re.frame.x && hoverX <= re.frame.x + re.frame.width && hoverY >= re.frame.y && hoverY <= re.frame.y + re.frame.height) { - CpuFreqStruct.hoverCpuFreqStruct = re; - break; - } - } - } else { - CpuFreqStruct.hoverCpuFreqStruct = e.data.params.hoverCpuFreqStruct; - } - CpuFreqStruct.selectCpuFreqStruct = e.data.params.selectCpuFreqStruct; - for (let re of dataFilter[type]) { - CpuFreqStruct.draw(context, re) - } - drawSelection(context, params); - context.closePath(); - let s = CpuFreqStruct.maxFreqName - let textMetrics = context.measureText(s); - context.globalAlpha = 0.8 - context.fillStyle = "#f0f0f0" - context.fillRect(0, 5, textMetrics.width + 8, 18) - context.globalAlpha = 1 - context.fillStyle = "#333" - context.textBaseline = "middle" - context.fillText(s, 4, 5 + 9) - drawWakeUp(context, wakeupBean, startNS, endNS, totalNS, frame); - drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); - } - // @ts-ignore - self.postMessage({ - id: e.data.id, - type: type, - results: canvas ? undefined : dataFilter[type], - hover: CpuFreqStruct.hoverCpuFreqStruct - }); - } else if (type.startsWith("process")) { - if (!useCache) { - proc(dataList[type], dataFilter[type], startNS, endNS, totalNS, frame) - } - if (canvas) { - context.clearRect(0, 0, canvas.width, canvas.height); - context.beginPath(); - CpuStruct.cpuCount = e.data.params.cpuCount; - drawLines(context, xs, frame.height, lineColor) - for (let re of dataFilter[type]) { - ProcessStruct.draw(context, re) - } - drawSelection(context, params); - drawWakeUp(context, wakeupBean, startNS, endNS, totalNS, frame); - context.closePath(); - drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); - } - // @ts-ignore - self.postMessage({id: e.data.id, type: type, results: canvas ? undefined : dataFilter[type], hover: undefined}); - } else if (type.startsWith("heap")) { - if (!useCache) { - heap(dataList[type], dataFilter[type], startNS, endNS, totalNS, frame); - } - if (canvas) { - context.clearRect(0, 0, canvas.width, canvas.height); - context.beginPath(); - drawLines(context, xs, frame.height, lineColor) - HeapStruct.hoverHeapStruct = undefined; - if (isHover) { - for (let re of dataFilter[e.data.type]) { - if (hoverX >= re.frame.x && hoverX <= re.frame.x + re.frame.width && hoverY >= re.frame.y && hoverY <= re.frame.y + re.frame.height) { - HeapStruct.hoverHeapStruct = re; - break; - } - } - } else { - HeapStruct.hoverHeapStruct = e.data.params.hoverHeapStruct; - } - // HeapStruct.selectHeapStruct = e.data.params.selectHeapStruct; - for (let re of dataFilter[type]) { - HeapStruct.draw(context, re) - } - drawSelection(context, params); - drawWakeUp(context, wakeupBean, startNS, endNS, totalNS, frame); - context.closePath(); - drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); - } - // @ts-ignore - self.postMessage({ - id: e.data.id, - type: type, - results: canvas ? undefined : dataFilter[type], - hover: HeapStruct.hoverHeapStruct - }); - } else if (type.startsWith("mem")) { - if (!useCache) { - mem(dataList[type], dataFilter[type], startNS, endNS, totalNS, frame) - } - if (canvas) { - context.clearRect(0, 0, canvas.width, canvas.height); - context.beginPath(); - drawLines(context, xs, frame.height, lineColor) - for (let re of dataFilter[type]) { - ProcessMemStruct.draw(context, re) - } - drawSelection(context, params); - drawWakeUp(context, wakeupBean, startNS, endNS, totalNS, frame); - context.closePath(); - drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); - } - // @ts-ignore - self.postMessage({id: e.data.id, type: type, results: canvas ? undefined : dataFilter[type], hover: undefined}); - } else if (type.startsWith("thread")) { - if (!useCache) { - thread(dataList[type], dataFilter[type], startNS, endNS, totalNS, frame) - } - if (canvas) { - context.clearRect(0, 0, canvas.width, canvas.height); - context.beginPath(); - drawLines(context, xs, frame.height, lineColor) - ThreadStruct.hoverThreadStruct = undefined; - if (isHover) { - for (let re of dataFilter[e.data.type]) { - if (hoverX >= re.frame.x && hoverX <= re.frame.x + re.frame.width && hoverY >= re.frame.y && hoverY <= re.frame.y + re.frame.height) { - ThreadStruct.hoverThreadStruct = re; - break; - } - } - } else { - ThreadStruct.hoverThreadStruct = e.data.params.hoverThreadStruct; - } - ThreadStruct.selectThreadStruct = e.data.params.selectThreadStruct; - for (let re of dataFilter[type]) { - ThreadStruct.draw(context, re) - } - drawSelection(context, params); - drawWakeUp(context, wakeupBean, startNS, endNS, totalNS, frame); - context.closePath(); - drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); - } - // @ts-ignore - self.postMessage({ - id: e.data.id, - type: type, - results: canvas ? undefined : dataFilter[type], - hover: ThreadStruct.hoverThreadStruct - }); - } else if (type.startsWith("func")) { - if (!useCache) { - func(dataList[type], dataFilter[type], startNS, endNS, totalNS, frame) - } - if (canvas) { - if (canvas.height == 150) { - canvas.width = frame.width; - canvas.height = e.data.params.maxHeight; - context.scale(e.data.params.dpr, e.data.params.dpr); - } - // canvasList[type]!.width = frame.width; - // canvasList[type]!.height = frame.height; - context.clearRect(0, 0, canvas.width, canvas.height); - context.beginPath(); - drawLines(context, xs, frame.height, lineColor) - FuncStruct.hoverFuncStruct = undefined; - if (isHover) { - for (let re of dataFilter[type]) { - if (re.dur && re.dur > 0 && hoverX >= re.frame.x && hoverX <= re.frame.x + re.frame.width && hoverY >= re.frame.y + (re.depth * 20) && hoverY <= re.frame.y + re.frame.height + (re.depth * 20)) { - FuncStruct.hoverFuncStruct = re; - break; - } - } - } else { - FuncStruct.hoverFuncStruct = e.data.params.hoverFuncStruct; - } - FuncStruct.selectFuncStruct = e.data.params.selectFuncStruct; - for (let re of dataFilter[type]) { - FuncStruct.draw(context, re) - } - drawSelection(context, params); - drawWakeUp(context, wakeupBean, startNS, endNS, totalNS, frame); - context.closePath(); - drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); - } - // @ts-ignore - self.postMessage({ - id: e.data.id, - type: type, - results: canvas ? undefined : dataFilter[type], - hover: FuncStruct.hoverFuncStruct - }); - } else if (type.startsWith("native")) { - if (canvas) { - context.clearRect(0, 0, canvas.width, canvas.height); - context.beginPath(); - drawLines(context, xs, frame.height, lineColor) - drawSelection(context, params); - context.closePath(); - drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); - } - // @ts-ignore - self.postMessage({ - id: e.data.id, - type: type, - results: canvas ? undefined : dataFilter[type], - hover: ThreadStruct.hoverThreadStruct - }); - } -}; -self.onmessageerror = function (e: any) { -} - - - - diff --git a/host/ide/src/trace/database/SqlLite.ts b/host/ide/src/trace/database/SqlLite.ts index 3e49266ed2312ad5ec66644a424bc3683a278de2..bef055fb1389da33b1d3f1fd6c5c38b2fd6ce341 100644 --- a/host/ide/src/trace/database/SqlLite.ts +++ b/host/ide/src/trace/database/SqlLite.ts @@ -14,27 +14,79 @@ */ import './sql-wasm.js' -import {CpuStruct} from "../bean/CpuStruct.js"; -import {CpuFreqStruct} from "../bean/CpuFreqStruct.js"; -import {ThreadStruct} from "../bean/ThreadStruct.js"; -import {ProcessMemStruct} from "../bean/ProcessMemStruct.js"; + import {Counter, Fps, SelectionData} from "../bean/BoxSelection.js"; -import {FuncStruct} from "../bean/FuncStruct.js"; import {WakeUpTimeBean} from "../bean/WakeUpTimeBean.js"; import {WakeupBean} from "../bean/WakeupBean.js"; import {BinderArgBean} from "../bean/BinderArgBean.js"; -import {FpsStruct} from "../bean/FpsStruct.js"; -import {HeapBean} from "../bean/HeapBean.js"; -import {SPT, SPTChild, StateProcessThread} from "../bean/StateProcessThread.js"; +import {SPT, SPTChild} from "../bean/StateProcessThread.js"; import {CpuUsage, Freq} from "../bean/CpuUsage.js"; -import {HeapStruct} from "../bean/HeapStruct.js"; -import {HeapTreeDataBean} from "../bean/HeapTreeDataBean.js"; + import { - NativeEventHeap, NativeHookMalloc, + NativeEvent, + NativeEventHeap, + NativeHookMalloc, NativeHookProcess, NativeHookSampleQueryInfo, NativeHookStatistics } from "../bean/NativeHook.js"; +import { + LiveProcess, + ProcessHistory, + SystemCpuSummary, + SystemDiskIOSummary, + SystemNetworkSummary +} from "../bean/AbilityMonitor.js"; + +import { + PerfCall, + PerfCallChain, + PerfCmdLine, + PerfFile, + PerfSample, + PerfStack, + PerfThread +} from "../bean/PerfProfile.js"; +import {SearchFuncBean} from "../bean/SearchFuncBean.js"; +import {CounterSummary, SdkSliceSummary} from "../bean/SdkSummary.js"; +import {Smaps} from "../bean/SmapsStruct.js"; +import {CpuFreqRowLimit} from "../component/chart/SpFreqChart.js"; +import {CpuFreqLimitsStruct} from "./ui-worker/ProcedureWorkerCpuFreqLimits.js"; +import {CpuStruct} from "./ui-worker/ProcedureWorkerCPU.js"; +import {CpuFreqStruct} from './ui-worker/ProcedureWorkerFreq.js'; +import { ThreadStruct } from './ui-worker/ProcedureWorkerThread.js'; +import { FuncStruct } from './ui-worker/ProcedureWorkerFunc.js'; +import { ProcessMemStruct } from './ui-worker/ProcedureWorkerMem.js'; +import { HeapTreeDataBean } from './logic-worker/ProcedureLogicWorkerNativeNemory.js'; +import {FpsStruct} from "./ui-worker/ProcedureWorkerFPS.js"; +import {CpuAbilityMonitorStruct} from "./ui-worker/ProcedureWorkerCpuAbility.js"; +import {MemoryAbilityMonitorStruct} from "./ui-worker/ProcedureWorkerMemoryAbility.js"; +import {DiskAbilityMonitorStruct} from "./ui-worker/ProcedureWorkerDiskIoAbility.js"; +import {NetworkAbilityMonitorStruct} from "./ui-worker/ProcedureWorkerNetworkAbility.js"; +import {EnergyAnomalyStruct} from "./ui-worker/ProcedureWorkerEnergyAnomaly.js"; +import {EnergyStateStruct} from "./ui-worker/ProcedureWorkerEnergyState.js"; +import {CounterStruct} from "./ui-worker/ProduceWorkerSdkCounter.js"; +import {SdkSliceStruct} from "./ui-worker/ProduceWorkerSdkSlice.js"; +import {SystemDetailsEnergy} from "../bean/EnergyStruct.js"; +class DataWorkerThread extends Worker { + taskMap: any = {}; + uuid(): string { + // @ts-ignore + return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11) + .replace(/[018]/g, (c: any) => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)); + } + //发送方法名 参数 回调 + queryFunc(action: string, args: any, handler: Function) { + let id = this.uuid(); + this.taskMap[id] = handler + let msg = { + id: id, + action: action, + args: args, + } + this.postMessage(msg); + } +} class DbThread extends Worker { busy: boolean = false; @@ -45,28 +97,30 @@ class DbThread extends Worker { uuid(): string { // @ts-ignore - return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)); + return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11) + .replace(/[018]/g, (c: any) => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)); } - queryFunc(name: string, sql: string, args: any, handler: Function) { + queryFunc(name: string, sql: string, args: any, handler: Function, action: string | null) { this.busy = true; let id = this.uuid(); this.taskMap[id] = handler - this.postMessage({ + let msg = { id: id, name: name, - action: "exec", + action: action || "exec", sql: sql, params: args, - }) + } + this.postMessage(msg); } - dbOpen = async (): Promise<{ status: boolean, msg: string }> => { + dbOpen = async (sdkWasmConfig?:string): Promise<{ status: boolean, msg: string, buffer: ArrayBuffer, sdkConfigMap: any}> => { return new Promise((resolve, reject) => { let id = this.uuid(); this.taskMap[id] = (res: any) => { if (res.init) { - resolve({status: res.init, msg: res.msg}); + resolve({status: res.init, msg: res.msg, sdkConfigMap:res.configSqlMap, buffer: res.buffer}); } else { resolve({status: res.init, msg: res.msg}); } @@ -74,6 +128,7 @@ class DbThread extends Worker { this.postMessage({ id: id, action: "open", + wasmConfig: sdkWasmConfig, buffer: DbPool.sharedBuffer!, /*Optional. An ArrayBuffer representing an SQLite Database file*/ }, [DbPool.sharedBuffer!]); }) @@ -86,8 +141,11 @@ export class DbPool { works: Array = []; progress: Function | undefined | null; num = Math.floor(Math.random() * 10 + 1) + 20; + cutDownTimer:any|undefined; + dataWorker: DataWorkerThread | undefined | null; init = async (type: string, threadBuild: (() => DbThread) | undefined = undefined) => { // wasm | server | sqlite await this.close(); + const { port1, port2 } = new MessageChannel(); if (type === "wasm") { this.maxThreadNumber = 1; } else if (type === "server") { @@ -121,7 +179,11 @@ export class DbPool { Reflect.deleteProperty(thread.taskMap, event.data.id); } else if (Reflect.has(event.data, 'ready')) { this.progress!("database opened", this.num + event.data.index) + this.progressTimer(this.num + event.data.index,this.progress!) } else if (Reflect.has(event.data, 'init')) { + if(this.cutDownTimer!=undefined){ + clearInterval(this.cutDownTimer); + } this.progress!("database ready", 40) let fun = thread.taskMap[event.data.id]; if (fun) { @@ -163,22 +225,27 @@ export class DbPool { } return {status: true, msg: "ok"}; } - initSqlite = async (buf: ArrayBuffer, progress: Function) => { + initSqlite = async (buf: ArrayBuffer, sdkWasmConfig: string, progress: Function) => { this.progress = progress; progress("database loaded", 15) DbPool.sharedBuffer = buf; progress("parse database", 20) + let configMap; for (let i = 0; i < this.works.length; i++) { let thread = this.works[i]; - let {status, msg} = await thread.dbOpen() + let {status, msg, buffer, sdkConfigMap} = await thread.dbOpen(sdkWasmConfig) if (!status) { return {status, msg} + } else { + configMap = sdkConfigMap; + DbPool.sharedBuffer = buffer; } } - return {status: true, msg: "ok"}; + return {status: true, msg: "ok", sdkConfigMap: configMap}; } close = async () => { + clearInterval(this.cutDownTimer); for (let i = 0; i < this.works.length; i++) { let thread = this.works[i]; thread.terminate(); @@ -186,689 +253,2563 @@ export class DbPool { this.works.length = 0; } - submit(name: string, sql: string, args: any, handler: Function) { + submit(name: string, sql: string, args: any, handler: Function, action: string | null) { let noBusyThreads = this.works.filter(it => !it.busy); let thread: DbThread if (noBusyThreads.length > 0) { //取第一个空闲的线程进行任务 thread = noBusyThreads[0]; - thread.queryFunc(name, sql, args, handler) + thread.queryFunc(name, sql, args, handler, action) } else { // 随机插入一个线程中 thread = this.works[Math.floor(Math.random() * this.works.length)] - thread.queryFunc(name, sql, args, handler) + thread.queryFunc(name, sql, args, handler, action) } } + + //new method replace submit() method + submitTask(action:string,args:any,handler:Function){ + this.dataWorker?.queryFunc(action, args, handler); + } + + progressTimer(num:number,progress:Function){ + let currentNum = num; + clearInterval(this.cutDownTimer); + this.cutDownTimer = setInterval(()=>{ + currentNum += Math.floor(Math.random() * 3) + if(currentNum >= 50){ + progress("database opened",40); + clearInterval(this.cutDownTimer); + }else { + progress("database opened",currentNum); + } + },Math.floor(Math.random() * 2500 + 1000)) + } } export const threadPool = new DbPool() -function query(name: string, sql: string, args: any = null): Promise> { +export function query(name: string, sql: string, args: any = null, action: string | null = null): Promise> { return new Promise>((resolve, reject) => { threadPool.submit(name, sql, args, (res: any) => { resolve(res) - }) + }, action); }) } -export const querySql = (sql: string): Promise> => query("queryProcess", sql) -/*-------------------------------------------------------------------------------------*/ +export const queryEventCountMap = ():Promise> => query("queryEventCountMap",`select event_name as eventName,count from stat where stat_type = 'received';`); + export const queryProcess = (): Promise> => - query("queryProcess", `SELECT pid,processName FROM temp_query_process`) -/*-------------------------------------------------------------------------------------*/ -export const queryTotalTime = (): Promise> => - query("queryTotalTime", `select end_ts-start_ts as total from trace_section;`) -/*-------------------------------------------------------------------------------------*/ -export const queryCpu = async (): Promise> => - query("queryCpu", `select cpu from cpu_measure_filter where name='cpu_idle' order by cpu;`) -/*-------------------------------------------------------------------------------------*/ + query("queryProcess", ` + SELECT + pid, processName + FROM + temp_query_process where pid != 0`) + +export const queryProcessByTable = (): Promise> => + query("queryProcessByTable", ` + SELECT + pid, name as processName + FROM + process where pid != 0`) + +export const queryProcessAsyncFunc = ():Promise> => query("queryProcessAsyncFunc",` +select tid, + P.pid, + A.name as threadName, + is_main_thread, + c.callid as track_id, + c.ts-D.start_ts as startTs, + c.dur, + c.name as funName, + c.parent_id, + c.id, + c.cookie, + c.depth, + c.argsetid +from thread A,trace_range D +left join callstack C on A.id = C.callid +left join process P on P.id = A.ipid +where startTs not null and cookie not null ;`, {}) + +export const queryTotalTime = (): Promise> => + query("queryTotalTime", ` + select + start_ts as recordStartNS,end_ts as recordEndNS,end_ts-start_ts as total + from + trace_range;`) + export const getAsyncEvents = (): Promise> => - query("getAsyncEvents", `select *,p.pid as pid,c.ts - t.start_ts as "startTime" from callstack c,trace_section t -left join process p on c.callid = p.id where cookie is not null;`) + query("getAsyncEvents", ` + select + *, + p.pid as pid, + c.ts - t.start_ts as "startTime" + from + callstack c,trace_range t + left join + process p + on + c.callid = p.id + where + cookie is not null;`) export const getCpuUtilizationRate = (startNS: number, endNS: number): Promise> => - query("getCpuUtilizationRate", `select * from temp_get_cpu_rate;`, {}) -/*-------------------------------------------------------------------------------------*/ + query("getCpuUtilizationRate", ` + with cpu as ( + select + cpu, + ts, + dur, + (case when ro < 99 then ro else 99 end) as ro , + (case when ro < 99 then stime+ro*cell else stime + 99 * cell end) as st, + (case when ro < 99 then stime + (ro+1)*cell else etime end) as et + from ( + select + cpu, + ts, + A.dur, + ((ts+A.dur)-D.start_ts)/((D.end_ts-D.start_ts)/100) as ro, + D.start_ts as stime, + D.end_ts etime, + (D.end_ts-D.start_ts)/100 as cell + from + sched_slice A + left join + trace_range D + left join + thread B on A.itid = B.id + left join + process C on B.ipid = C.id + where + tid != 0 + and (A.ts) + between D.start_ts and D.end_ts)) + select cpu,ro, + sum(case + when ts <= st and ts + dur <= et then (ts + dur - st) + when ts <= st and ts + dur > et then et-st + when ts > st and ts + dur <= et then dur + when ts > st and ts + dur > et then et - ts end)/cast(et-st as float) as rate + from cpu + group by cpu,ro;`, {}) + export const getFps = () => - query("getFps", `select distinct(ts-tb.start_ts) as startNS,fps -from hidump c ,trace_section tb -where startNS >= 0 -order by startNS;`, {}) + query("getFps", ` + select + distinct(ts-tb.start_ts) as startNS, fps + from + hidump c ,trace_range tb + where + startNS >= 0 + --order by startNS; + `, {}) -/*-------------------------------------------------------------------------------------*/ export const getFunDataByTid = (tid: number): Promise> => - query("getFunDataByTid", `select * from temp_query_thread_function where tid = $tid`, {$tid: tid}) -/*-------------------------------------------------------------------------------------*/ -export const getStatesProcessThreadDataCount = (): Promise> => - query("getStatesProcessThreadData", `select count(1) as count from (select IP.name as process, - IP.pid as processId, - A.name as thread, - B.state as state, - A.tid as threadId, - B.dur, - (B.ts - TR.start_ts + B.dur) as end_ts, - (B.ts - TR.start_ts) as start_ts, - B.cpu, - C.priority, - '-' as note -from thread_state as B - left join thread as A on B.itid = A.id - left join process as IP on A.ipid = IP.id - left join trace_section as TR - left join sched_slice as C on B.itid = C.itid and C.ts = B.ts -where - B.dur > 0 and IP.pid not null and (B.ts - TR.start_ts) >= 0); -`, {}); -export const getStatesProcessThreadData = (limit:number,offset:number): Promise> => - query("getStatesProcessThreadData", `select IP.name as process, - IP.pid as processId, - A.name as thread, - B.state as state, - A.tid as threadId, - B.dur, - (B.ts - TR.start_ts + B.dur) as end_ts, - (B.ts - TR.start_ts) as start_ts, - B.cpu, - C.priority, - '-' as note -from thread_state as B - left join thread as A on B.itid = A.id + query("getFunDataByTid", ` + select + --tid, + --A.name as threadName, + c.ts-D.start_ts as startTs, + c.dur, + c.name as funName, + c.argsetid, + c.depth +from thread A,trace_range D +left join callstack C on A.id = C.callid +where startTs not null and c.cookie is null and tid = $tid`, {$tid: tid}) + +export const getMaxDepthByTid = (): Promise> => + query("getMaxDepthByTid", ` + select +tid, + MAX(c.depth + 1) as maxDepth +from thread A +left join callstack C on A.id = C.callid +where c.ts not null and c.cookie is null group by tid`, {}) + + +export const getStatesProcessThreadDataByRange = (leftNs: number, rightNs: number): Promise> => + query("getStatesProcessThreadDataByRange", ` + select + IP.name as process, + IP.pid as processId, + A.name as thread, + B.state as state, + A.tid as threadId, + B.dur, + (B.ts - TR.start_ts + B.dur) as end_ts, + (B.ts - TR.start_ts) as start_ts, + B.cpu + from + thread_state as B + left join thread as A on B.itid = A.id left join process as IP on A.ipid = IP.id - left join trace_section as TR - left join sched_slice as C on B.itid = C.itid and C.ts = B.ts -where - B.dur > 0 and IP.pid not null and (B.ts - TR.start_ts) >= 0 limit $limit offset $offset; -`, {$limit: limit, $offset: offset}); - -export const getTabStatesGroupByProcessThread = (leftNs: number, rightNs: number): Promise> => - query("getTabStatesGroupByProcessThread", `select process, - processId, - thread, - threadId, - sum(dur) as wallDuration, - round(avg(dur),2) as avgDuration, - min(dur) as minDuration, - max(dur) as maxDuration, - count(threadId) as count -from temp_get_process_thread_state_data -where not (end_ts < $leftNS or start_ts > $rightNS) -group by process, processId,thread,threadId`, {$leftNS: leftNs, $rightNS: rightNs}); - -export const getTabStatesGroupByProcess = (leftNs: number, rightNs: number): Promise> => - query("getTabStatesGroupByProcess", `select process, processId, - sum(dur) as wallDuration, - round(avg(dur),2) as avgDuration, - min(dur) as minDuration, - max(dur) as maxDuration, - count(processId) as count -from temp_get_process_thread_state_data -where not (end_ts < $leftNS or start_ts > $rightNS) -group by process,processId`, {$leftNS: leftNs, $rightNS: rightNs}); - -// todo wasm模式报错 -export const getTabStatesGroupByState = (leftNs: number, rightNs: number): Promise> => - query("getTabStatesGroupByState", `select state, - sum(dur) as wallDuration, - round(avg(dur),2) as avgDuration, - min(dur) as minDuration, - max(dur) as maxDuration, - count(state) as count -from temp_get_process_thread_state_data -where not (end_ts < $leftNS or start_ts > $rightNS) -group by state`, {$leftNS: leftNs, $rightNS: rightNs}); - -export const getTabStatesGroupByStatePid = (leftNs: number, rightNs: number): Promise> => - query("getTabStatesGroupByStatePid", `select process, - processId, - state, - sum(dur) as wallDuration, - round(avg(dur),2) as avgDuration, - min(dur) as minDuration, - max(dur) as maxDuration, - count(processId) as count -from temp_get_process_thread_state_data -where not (end_ts < $leftNS or start_ts > $rightNS) -group by process,processId,state`, {$leftNS: leftNs, $rightNS: rightNs}); - -export const getTabStatesGroupByStatePidTid = (leftNs: number, rightNs: number): Promise> => - query("getTabStatesGroupByStatePidTid", `select process, - processId, - thread, - state, - threadId, - sum(dur) as wallDuration, - round(avg(dur),2) as avgDuration, - min(dur) as minDuration, - max(dur) as maxDuration, - count(threadId) as count -from temp_get_process_thread_state_data -where not (end_ts < $leftNS or start_ts > $rightNS) -group by process, processId, thread, threadId,state`, {$leftNS: leftNs, $rightNS: rightNs}); - -export const getTabBoxChildData = (leftNs: number, rightNs: number, state: string | undefined, processId: number | undefined, threadId: number | undefined): Promise> => - query("getTabBoxChildData", `select IP.name as process, - IP.pid as processId, - A.name as thread, - B.state as state, - A.tid as threadId, - B.dur as duration, - B.ts - TR.start_ts as startNs, - B.cpu, - C.priority, - '-' as note -from thread_state AS B - left join thread as A on B.itid = A.id - left join process AS IP on A.ipid = IP.id - left join trace_section AS TR - left join sched_slice as C on B.itid = C.itid and C.ts = B.ts -where - B.dur > 0 and IP.pid not null - and not ((B.ts - TR.start_ts + B.dur < $leftNS) or (B.ts - TR.start_ts > $rightNS)) - ${state != undefined && state != '' ? 'and B.state = $state' : ''} - ${processId != undefined && processId != -1 ? 'and IP.pid = $processID' : ''} - ${threadId != undefined && threadId != -1 ? 'and A.tid = $threadID' : ''} + left join trace_range as TR + where B.dur > 0 + and IP.pid not null + and (B.ts - TR.start_ts) >= $leftNs + and (B.ts - TR.start_ts + B.dur) <= $rightNs +`, {$leftNs:leftNs,$rightNs:rightNs}); + +export const getTabBoxChildData = (leftNs: number, rightNs: number, state: string | undefined, + processId: number | undefined, threadId: number | undefined): Promise> => + query("getTabBoxChildData", ` + select + IP.name as process, + IP.pid as processId, + A.name as thread, + B.state as state, + A.tid as threadId, + B.dur as duration, + B.ts - TR.start_ts as startNs, + B.cpu, + C.priority + from + thread_state AS B + left join + thread as A + on + B.itid = A.id + left join + process AS IP + on + A.ipid = IP.id + left join + trace_range AS TR + left join + sched_slice as C + on + B.itid = C.itid + and + C.ts = B.ts + where + B.dur > 0 + and + IP.pid not null + and + not ((B.ts - TR.start_ts + B.dur < $leftNS) or (B.ts - TR.start_ts > $rightNS)) + ${state != undefined && state != '' ? 'and B.state = $state' : ''} + ${processId != undefined && processId != -1 ? 'and IP.pid = $processID' : ''} + ${threadId != undefined && threadId != -1 ? 'and A.tid = $threadID' : ''} `, {$leftNS: leftNs, $rightNS: rightNs, $state: state, $processID: processId, $threadID: threadId}) -/*-------------------------------------------------------------------------------------*/ export const getTabCpuUsage = (cpus: Array, leftNs: number, rightNs: number): Promise> => - query("getTabCpuUsage", `select cpu, - sum(case - when (A.ts - B.start_ts) < $leftNS then (A.ts - B.start_ts + A.dur - $leftNS) - when (A.ts - B.start_ts) >= $leftNS and (A.ts - B.start_ts + A.dur) <= $rightNS then A.dur - when (A.ts - B.start_ts + A.dur) > $rightNS then ($rightNS - (A.ts - B.start_ts)) end) / cast($rightNS - $leftNS as float) as usage -from thread_state A ,trace_section B -where (A.ts - B.start_ts) > 0 and A.dur > 0 - and cpu in (${cpus.join(",")}) - and (A.ts - B.start_ts + A.dur) > $leftNS and (A.ts - B.start_ts) < $rightNS -group by cpu`, {$leftNS: leftNs, $rightNS: rightNs}) + query("getTabCpuUsage", ` + select + cpu, + sum(case + when (A.ts - B.start_ts) < $leftNS + then (A.ts - B.start_ts + A.dur - $leftNS) + when (A.ts - B.start_ts) >= $leftNS + and (A.ts - B.start_ts + A.dur) <= $rightNS + then A.dur + when (A.ts - B.start_ts + A.dur) > $rightNS + then ($rightNS - (A.ts - B.start_ts)) end) / cast($rightNS - $leftNS as float) as usage + from + thread_state A, + trace_range B + where + (A.ts - B.start_ts) > 0 and A.dur > 0 + and + cpu in (${cpus.join(",")}) + and + (A.ts - B.start_ts + A.dur) > $leftNS + and + (A.ts - B.start_ts) < $rightNS + group by + cpu`, {$leftNS: leftNs, $rightNS: rightNs}) export const getTabCpuFreq = (cpus: Array, leftNs: number, rightNs: number): Promise> => - query("getTabCpuFreq", `select cpu,value,(ts - tb.start_ts) as startNs -from measure c ,trace_section tb -inner join cpu_measure_filter t on c.filter_id = t.id -where (name = 'cpufreq' or name='cpu_frequency') - and cpu in (${cpus.join(",")}) - and startNs > 0 - and startNs < $rightNS - order by startNs`, {$leftNS: leftNs, $rightNS: rightNs}) -/*-------------------------------------------------------------------------------------*/ + query("getTabCpuFreq", ` + select + cpu, + value, + (ts - tb.start_ts) as startNs + from + measure c, + trace_range tb + inner join + cpu_measure_filter t + on + c.filter_id = t.id + where + (name = 'cpufreq' or name='cpu_frequency') + and + cpu in (${cpus.join(",")}) + and + startNs > 0 + and + startNs < $rightNS + --order by startNs + `, {$leftNS: leftNs, $rightNS: rightNs}) + export const getTabFps = (leftNs: number, rightNs: number): Promise> => - query("getTabFps", `select distinct(ts-tb.start_ts) as startNS,fps -from hidump c ,trace_section tb -where startNS <= $rightNS and startNS >= 0 -order by startNS;`, {$leftNS: leftNs, $rightNS: rightNs}) -/*-------------------------------------------------------------------------------------*/ -export const getTabCounters = (filterIds: Array, startTime: number) => - query("getTabCounters", `select t1.filter_id as trackId,t2.name,value, t1.ts - t3.start_ts as startTime -from measure t1 -left join process_measure_filter t2 on t1.filter_id = t2.id -left join trace_section t3 where filter_id in (${filterIds.join(",")}) -and startTime <= $startTime -order by startTime asc;`, {$startTime: startTime}) -/*-------------------------------------------------------------------------------------*/ + query("getTabFps", ` + select + distinct(ts-tb.start_ts) as startNS, + fps + from + hidump c, + trace_range tb + where + startNS <= $rightNS + and + startNS >= 0 + --order by startNS; + `, {$leftNS: leftNs, $rightNS: rightNs}) + +export const getTabCounters = (processFilterIds: Array,virtualFilterIds:Array, startTime: number) => + query("getTabCounters", ` + select + t1.filter_id as trackId, + t2.name, + value, + t1.ts - t3.start_ts as startTime + from + process_measure t1 + left join + process_measure_filter t2 + on + t1.filter_id = t2.id + left join + trace_range t3 + where + filter_id in (${processFilterIds.join(",")}) + and + startTime <= $startTime +union + select + t1.filter_id as trackId, + t2.name, + value, + t1.ts - t3.start_ts as startTime + from + sys_mem_measure t1 + left join + sys_event_filter t2 + on + t1.filter_id = t2.id + left join + trace_range t3 + where + filter_id in (${virtualFilterIds.join(",")}) + and + startTime <= $startTime + `, {$startTime: startTime}) + +export const getTabVirtualCounters = (virtualFilterIds:Array, startTime: number) => + query("getTabVirtualCounters", ` + select + t1.filter_id as trackId, + t2.name, + value, + t1.ts - t3.start_ts as startTime + from + sys_mem_measure t1 + left join + sys_event_filter t2 + on + t1.filter_id = t2.id + left join + trace_range t3 + where + filter_id in (${virtualFilterIds.join(",")}) + and + startTime <= $startTime + `, {$startTime: startTime}) + export const getTabCpuByProcess = (cpus: Array, leftNS: number, rightNS: number) => - query("getTabCpuByProcess", `select IP.name as process, - IP.pid as pid, - sum(B.dur) as wallDuration, - avg(B.dur) as avgDuration, - count(A.tid) as occurrences -from thread_state AS B - left join thread as A on B.itid = A.id - left join trace_section AS TR - left join process AS IP on A.ipid = IP.id -where B.cpu in (${cpus.join(",")}) - and not ((B.ts - TR.start_ts + B.dur < $leftNS) or (B.ts - TR.start_ts > $rightNS )) -group by IP.name, IP.pid -order by wallDuration desc;`, {$rightNS: rightNS, $leftNS: leftNS}) -/*-------------------------------------------------------------------------------------*/ + query("getTabCpuByProcess", ` + select + IP.name as process, + IP.pid as pid, + sum(B.dur) as wallDuration, + avg(B.dur) as avgDuration, + count(A.tid) as occurrences + from + thread_state AS B + left join + thread as A + on + B.itid = A.id + left join + trace_range AS TR + left join + process AS IP + on + A.ipid = IP.id + where + B.cpu in (${cpus.join(",")}) + and + not ((B.ts - TR.start_ts + B.dur < $leftNS) or (B.ts - TR.start_ts > $rightNS )) + group by + IP.name, + IP.pid + order by + wallDuration desc;`, {$rightNS: rightNS, $leftNS: leftNS}) + export const getTabCpuByThread = (cpus: Array, leftNS: number, rightNS: number) => - query("getTabCpuByThread", `select IP.name as process, - IP.pid as pid, - A.name as thread, - A.tid as tid, - sum(B.dur) as wallDuration, - avg(B.dur) as avgDuration, - count(A.tid) as occurrences -from thread_state AS B - left join thread as A on B.itid = A.id - left join trace_section AS TR - left join process AS IP on A.ipid = IP.id -where B.cpu in (${cpus.join(",")}) - and not ((B.ts - TR.start_ts + B.dur < $leftNS) or (B.ts - TR.start_ts > $rightNS)) -group by IP.name, IP.pid, A.name, A.tid -order by wallDuration desc;`, {$rightNS: rightNS, $leftNS: leftNS}) -/*-------------------------------------------------------------------------------------*/ + query("getTabCpuByThread", ` + select + IP.name as process, + IP.pid as pid, + A.name as thread, + A.tid as tid, + sum(B.dur) as wallDuration, + avg(B.dur) as avgDuration, + count(A.tid) as occurrences + from + thread_state AS B + left join + thread as A + on + B.itid = A.id + left join + trace_range AS TR + left join + process AS IP + on + A.ipid = IP.id + where + B.cpu in (${cpus.join(",")}) + and + not ((B.ts - TR.start_ts + B.dur < $leftNS) or (B.ts - TR.start_ts > $rightNS)) + group by + IP.name, + IP.pid, + A.name, + A.tid + order by + wallDuration desc;`, {$rightNS: rightNS, $leftNS: leftNS}) + export const getTabSlices = (funTids: Array, leftNS: number, rightNS: number): Promise> => - query("getTabSlices", `select + query("getTabSlices", ` + select c.name as name, sum(c.dur) as wallDuration, avg(c.dur) as avgDuration, count(c.name) as occurrences -from thread A,trace_section D -left join callstack C on A.id = C.callid -where C.ts not null - and c.dur >= 0 - and A.tid in (${funTids.join(",")}) - and c.name not like 'binder%' - and not ((C.ts - D.start_ts + C.dur < $leftNS) or (C.ts - D.start_ts > $rightNS)) -group by c.name -order by wallDuration desc;`, {$leftNS: leftNS, $rightNS: rightNS}) -/*-------------------------------------------------------------------------------------*/ + from + thread A, trace_range D + left join + callstack C + on + A.id = C.callid + where + C.ts not null + and + c.dur >= 0 + and + A.tid in (${funTids.join(",")}) + and + c.name != 'binder transaction async' + and + c.name != 'binder async rcv' + and + c.cookie is null + and + not ((C.ts - D.start_ts + C.dur < $leftNS) or (C.ts - D.start_ts > $rightNS)) + group by + c.name + order by + wallDuration desc;`, {$leftNS: leftNS, $rightNS: rightNS}) + +export const getTabSlicesAsyncFunc = (asyncNames:Array,asyncPid: Array, leftNS: number, rightNS: number): Promise> => + query("getTabSlicesAsyncFunc", ` + select + c.name as name, + sum(c.dur) as wallDuration, + avg(c.dur) as avgDuration, + count(c.name) as occurrences + from + thread A, trace_range D + left join + callstack C + on + A.id = C.callid + left join process P on P.id = A.ipid + where + C.ts not null + and + c.dur >= -1 + and + c.cookie not null + and + P.pid in (${asyncPid.join(",")}) + and + c.name in (${asyncNames.map(it=>"'"+it+"'").join(",")}) + and + not ((C.ts - D.start_ts + C.dur < $leftNS) or (C.ts - D.start_ts > $rightNS)) + group by + c.name + order by + wallDuration desc;`, {$leftNS: leftNS, $rightNS: rightNS}) + export const getTabThreadStates = (tIds: Array, leftNS: number, rightNS: number): Promise> => - query("getTabThreadStates", `select - IP.name as process, - IP.pid, - A.name as thread, - A.tid, - B.state, - sum(B.dur) as wallDuration, - avg(ifnull(B.dur,0)) as avgDuration, - count(A.tid) as occurrences -from thread_state AS B -left join thread as A on A.id = B.itid -left join trace_section AS TR -left join process AS IP on IP.id=ipid -where A.tid in (${tIds.join(",")}) -and not ((B.ts - TR.start_ts + ifnull(B.dur,0) < $leftNS) or (B.ts - TR.start_ts > $rightNS)) -group by IP.name, IP.pid, A.name, A.tid, B.state -order by wallDuration desc;`, {$leftNS: leftNS, $rightNS: rightNS}) -/*-------------------------------------------------------------------------------------*/ -export const getThreadFuncData = (tId: number): Promise> => - query("getThreadFuncData", `select tid, - A.start_ts, - A.end_ts, - A.name as threadName, - is_main_thread, - c.callid as track_id, - c.ts-D.start_ts as startTs, - c.ts + c.dur as endTs, - c.dur, - c.name as funName, - c.depth, - c.parent_id, - c.id -from thread A,trace_section D -left join callstack C on A.id = C.callid -where startTs not null and A.tid = $tid;`, {$tid: tId}) -/*-------------------------------------------------------------------------------------*/ + query("getTabThreadStates", ` + select + IP.name as process, + IP.pid, + A.name as thread, + A.tid, + B.state, + sum(B.dur) as wallDuration, + avg(ifnull(B.dur,0)) as avgDuration, + count(A.tid) as occurrences + from + thread_state AS B + left join + thread as A + on + A.id = B.itid + left join + trace_range AS TR + left join + process AS IP + on + IP.id=A.ipid + where + A.tid in (${tIds.join(",")}) + and + not ((B.ts - TR.start_ts + ifnull(B.dur,0) < $leftNS) or (B.ts - TR.start_ts > $rightNS)) + group by + IP.name, IP.pid, A.name, A.tid, B.state + order by + wallDuration desc;`, {$leftNS: leftNS, $rightNS: rightNS}) + export const queryBinderArgsByArgset = (argset: number): Promise> => - query("queryBinderArgsByArgset", `select * from args_view where argset = $argset;`, {$argset: argset}) -/*-------------------------------------------------------------------------------------*/ -export const queryClockFrequency = (): Promise> => - query("queryClockFrequency", `with freq as ( select measure.filter_id, measure.ts, measure.type, measure.value from clock_event_filter -left join measure -where clock_event_filter.name = '%s' and clock_event_filter.type = 'clock_set_rate' and clock_event_filter.id = measure.filter_id -order by measure.ts) -select freq.filter_id,freq.ts - r.start_ts as ts,freq.type,freq.value from freq,trace_section r;`, {}) -/*-------------------------------------------------------------------------------------*/ -export const queryClockList = (): Promise> => - query("queryClockList", `with list as ( - select distinct name from clock_event_filter - where clock_event_filter.type = 'clock_set_rate' order by name -),freq as( - select measure.filter_id, measure.ts, measure.type, measure.value , clock_event_filter.name from clock_event_filter - left join measure - where clock_event_filter.type = 'clock_set_rate' and clock_event_filter.id = measure.filter_id - order by measure.ts -),state as ( - select filter_id, ts, endts, endts-ts as dur, type, value,name from - (select measure.filter_id, measure.ts, lead(ts, 1, null) over( order by measure.ts) endts, measure.type, measure.value,clock_event_filter.name from clock_event_filter,trace_section - left join measure - where clock_event_filter.type != 'clock_set_rate' and clock_event_filter.id = measure.filter_id - order by measure.ts) -),count_freq as ( - select COUNT(*) num,name srcname from freq group by name -),count_state as ( - select COUNT(*) num,name srcname from state group by name -) -select count_freq.srcname||' Frequency' as name,* from count_freq union select count_state.srcname||' State' as name,* from count_state order by name;`) -/*-------------------------------------------------------------------------------------*/ -export const queryClockState = (): Promise> => - query("queryClockState", `with state as ( -select filter_id, ts, endts, endts-ts as dur, type, value from -(select measure.filter_id, measure.ts, lead(ts, 1, null) over( order by measure.ts) endts, measure.type, measure.value from clock_event_filter,trace_section -left join measure -where clock_event_filter.name = '%s' and clock_event_filter.type != 'clock_set_rate' and clock_event_filter.id = measure.filter_id -order by measure.ts)) --- select * from state; -select s.filter_id,s.ts-r.start_ts as ts,s.type,s.value,s.dur from state s,trace_section r;`) -/*-------------------------------------------------------------------------------------*/ + query("queryBinderArgsByArgset", ` + select + * + from + args_view + where + argset = $argset;`, {$argset: argset}) + export const queryCpuData = (cpu: number, startNS: number, endNS: number): Promise> => - query("queryCpuData", `select * from temp_query_cpu_data where cpu = $cpu and startTime between $startNS and $endNS;`, { + query("queryCpuData", ` + SELECT + IP.name as processName, + IP.name processCmdLine, + IP.pid as processId, + B.cpu, + A.name, + C.id as schedId, + A.tid, + A.id, + A.type, + B.dur, + B.ts - TR.start_ts AS startTime, + C.priority, + C.end_state +from thread_state AS B + left join thread as A on B.itid = A.id + left join sched_slice AS C on B.itid = C.itid and B.ts = C.ts + left join trace_range AS TR + left join process AS IP on A.ipid = IP.id +where C.itid is not null + and + B.cpu = $cpu + and + startTime between $startNS and $endNS;`, { $cpu: cpu, $startNS: startNS, $endNS: endNS }) -/*-------------------------------------------------------------------------------------*/ -export const queryCpuFreq = (): Promise> => -query("queryCpuFreq", `select cpu from cpu_measure_filter where (name='cpufreq' or name='cpu_frequency') order by cpu;`) -/*-------------------------------------------------------------------------------------*/ + +export const queryCpuFreq = (): Promise> => + query("queryCpuFreq", ` + select + cpu,id as filterId + from + cpu_measure_filter + where + (name='cpufreq' or name='cpu_frequency') + order by cpu; + `) + export const queryCpuFreqData = (cpu: number): Promise> => - query("queryCpuFreqData", `select cpu,value,ts-tb.start_ts as startNS -from measure c ,trace_section tb -inner join cpu_measure_filter t on c.filter_id = t.id -where (name = 'cpufreq' or name='cpu_frequency') and cpu= $cpu -order by ts;`, {$cpu: cpu}); -/*-------------------------------------------------------------------------------------*/ + query("queryCpuFreqData", ` + select + cpu, + value, + ts-tb.start_ts as startNS + from + measure c, + trace_range tb + inner join + cpu_measure_filter t + on + c.filter_id = t.id + where + (name = 'cpufreq' or name='cpu_frequency') + and + cpu= $cpu + --order by ts; + `, {$cpu: cpu},); + export const queryCpuMax = (): Promise> => - query("queryCpuMax", `select cpu from sched_slice order by cpu desc limit 1;`) -/*-------------------------------------------------------------------------------------*/ + query("queryCpuMax", ` + select + cpu + from + sched_slice + order by + cpu + desc limit 1;`) + +export const queryCpuStateFilter = ():Promise> => + query("queryCpuStateFilter",`select cpu,id as filterId from cpu_measure_filter where name = 'cpu_idle' order by cpu;`,{}) + +export const queryCpuState = (cpuFilterId:number) :Promise> => + query('queryCpuState',` + select (A.ts - B.start_ts) as startTs, + value + from measure A,trace_range B + where filter_id = $filterId;`,{$filterId:cpuFilterId},"exec-buf") + export const queryCpuMaxFreq = (): Promise> => -query("queryCpuMaxFreq", `select max(value) as maxFreq -from measure c -inner join cpu_measure_filter t on c.filter_id = t.id -where (name = 'cpufreq' or name='cpu_frequency');`) -// /*-------------------------------------------------------------------------------------*/ -export const queryLogs = (): Promise> => - query("queryLogs", `select l.*,l.ts-t.start_ts as "startTime" from log as l left join trace_section AS t - where "startTime" between %s and %s order by "startTime" - limit %s offset %s;`) -/*-------------------------------------------------------------------------------------*/ -export const queryLogsCount = (): Promise> => - query("queryLogsCount", `select l.*,l.ts-t.start_ts as "startTime" from log as l left join trace_section AS t - where "startTime" between %s and %s;`) -/*-------------------------------------------------------------------------------------*/ -export const queryProcessData = (pid: number, startNS: number, endNS: number): Promise> => - query("queryProcessData", `select * from temp_query_process_data where tid != 0 and pid = $pid and startTime between $startNS and $endNS;`, { + query("queryCpuMaxFreq", ` + select + max(value) as maxFreq + from + measure c + inner join + cpu_measure_filter t + on + c.filter_id = t.id + where + (name = 'cpufreq' or name='cpu_frequency');`) + +export const queryProcessData = (pid:number,startNS:number,endNS:number):Promise> => + query("queryProcessData",` + select ta.cpu, + dur, + ts-${(window as any).recordStartNS} as startTime +from thread_state ta +where ta.cpu is not null and pid=$pid and startTime between $startNS and $endNS;`, { $pid: pid, $startNS: startNS, $endNS: endNS - }) -/*-------------------------------------------------------------------------------------*/ -export const queryProcessDataCount = (): Promise> => - query("queryProcessDataCount", `select ta.id,type, ts, dur, ta.cpu, itid as utid, state - ,ts-tb.start_ts as startTime,tc.tid,tc.pid,tc.process,tc.thread -from thread_state ta,trace_section tb -left join ( - select it.id,tid,pid,ip.name as process,it.name as thread from thread as it left join process ip on it.ipid = ip.id - ) tc on ta.itid = tc.id -where tc.pid = %d - and startTime between %s and %s -and ta.cpu is not null -order by startTime;`) -/*-------------------------------------------------------------------------------------*/ -export const queryProcessDataLimit = (pid: number, startNS: number, endNS: number, limit: number): Promise> => - query("queryProcessDataLimit", `with list as (select ta.id,type, ts, dur, ta.cpu, itid as utid, state - ,ts-tb.start_ts as startTime,tc.tid,tc.pid,tc.process,tc.thread -from thread_state ta,trace_section tb -left join ( - select it.id,tid,pid,ip.name as process,it.name as thread from thread as it left join process ip on it.ipid = ip.id - ) tc on ta.itid = tc.id -where tc.pid = $pid - and startTime between $startNS and $endNS -and ta.cpu is not null -order by startTime ) -select * from list order by random() limit $limit;`, {$pid: pid, $startNS: startNS, $endNS: endNS, $limit: limit}) -/*-------------------------------------------------------------------------------------*/ + }); + export const queryProcessMem = (): Promise> => - query("queryProcessMem", `select process_measure_filter.id as trackId, - process_measure_filter.name as trackName, - ipid as upid, - process_view.pid, - process_view.name as processName -from process_measure_filter join process_view using (ipid) -order by trackName;`) -/*-------------------------------------------------------------------------------------*/ + query("queryProcessMem", ` + select + process_measure_filter.id as trackId, + process_measure_filter.name as trackName, + ipid as upid, + process.pid, + process.name as processName + from + process_measure_filter + join + process using (ipid) + order by trackName;`) + +export const queryProcessThreadDataCount = ():Promise> => + query(`queryProcessThreadDataCount`,`select pid,count(id) as count + from thread_state + where ts between ${(window as any).recordStartNS} and ${(window as any).recordEndNS} group by pid;`,{}); + +export const queryProcessFuncDataCount = ():Promise> => + query(`queryProcessFuncDataCount`,`select + P.pid, + count(tid) as count + from callstack C + left join thread A on A.id = C.callid + left join process AS P on P.id = A.ipid + where C.ts between ${(window as any).recordStartNS} and ${(window as any).recordEndNS} + group by pid;`,{}); + +export const queryProcessMemDataCount = ():Promise> => + query(`queryProcessMemDataCount`,`select + p.pid as pid, count(value) count + from process_measure c + left join process_measure_filter f on f.id = c.filter_id + left join process p on p.ipid = f.ipid +where f.id not NULL and value>0 + and c.ts between ${(window as any).recordStartNS} and ${(window as any).recordEndNS} +group by p.pid`,{}); + export const queryProcessMemData = (trackId: number): Promise> => - query("queryProcessMemData", `select c.type, - ts, value, - filter_id as track_id, - c.ts-tb.start_ts startTime -from measure c,trace_section tb where filter_id = $id;`, {$id: trackId}) -/*-------------------------------------------------------------------------------------*/ -export const queryProcessNOrder = (): Promise> => - query("queryProcessNOrder", `select pid,name as processName from process;`) -/*-------------------------------------------------------------------------------------*/ + query("queryProcessMemData", ` + select + c.type, + ts, + value, + filter_id as track_id, + c.ts-tb.start_ts startTime + from + process_measure c, + trace_range tb + where + filter_id = $id;`, {$id: trackId}) + +export const queryDataDICT = (): Promise> => + query("queryDataDICT", `select * from data_dict;`) +export const queryProcessContentCount = ():Promise> => + query(`queryProcessContentCount`,`select pid,swtich_count as switch_count,thread_count,slice_count,mem_count from process;`); +export const queryProcessThreadsByTable = (): Promise> => + query("queryProcessThreadsByTable", ` + select p.pid as pid,t.tid as tid,p.name as processName,t.name as threadName from thread t left join process p on t.ipid = p.id where t.tid != 0; + `) +export const queryVirtualMemory = ():Promise> => + query("queryVirtualMemory",`select id,name from sys_event_filter where type='sys_virtual_memory_filter'`); +export const queryVirtualMemoryData = (filterId:number):Promise> => + query("queryVirtualMemoryData",`select ts-${(window as any).recordStartNS} as startTime,value,filter_id as filterID from sys_mem_measure where filter_id=$filter_id`,{$filter_id:filterId}); export const queryProcessThreads = (): Promise> => - query("queryProcessThreads", `select - the_tracks.ipid as upid, - the_tracks.itid as utid, - total_dur as hasSched, - process_view.pid as pid, - thread_view.tid as tid, - process_view.name as processName, - thread_view.name as threadName -from ( - select ipid, itid from sched_view join thread_view using(itid) group by itid -) the_tracks -left join (select ipid, sum(dur) as total_dur - from sched_view join thread_view using(itid) - group by ipid -) using(ipid) -left join thread_view using(itid) -left join process_view using(ipid) -order by - total_dur desc, - the_tracks.ipid, - the_tracks.itid;`, {}) -/*-------------------------------------------------------------------------------------*/ -export const queryProcessThreadsNOrder = (): Promise> => - query("queryProcessThreadsNOrder", `select p.id as upid, - t.id as utid, - p.pid, - t.tid, - p.name as processName, - t.name as threadName - from thread t left join process p on t.ipid = p.id;`) -/*-------------------------------------------------------------------------------------*/ -export const queryScreenState = (): Promise> => - query("queryScreenState", `select m.type, m.ts-r.start_ts as ts, value, filter_id from measure m,trace_section r where filter_id in (select id from process_measure_filter where name = 'ScreenState');`) -/*-------------------------------------------------------------------------------------*/ + query("queryProcessThreads", ` + select + the_tracks.ipid as upid, + the_tracks.itid as utid, + total_dur as hasSched, + process.pid as pid, + thread.tid as tid, + process.name as processName, + thread.name as threadName + from ( + select ipid,itid from sched_slice group by itid + ) the_tracks + left join (select itid,sum(dur) as total_dur from thread_state where state != 'S' group by itid) using(itid) + left join thread using(itid) + left join process using(ipid) + order by total_dur desc,the_tracks.ipid,the_tracks.itid;`, {}) + export const queryThreadData = (tid: number): Promise> => - query("queryThreadData", `select * from temp_query_thread_data where tid = $tid;`, {$tid: tid}) -/*-------------------------------------------------------------------------------------*/ + query("queryThreadData", ` + select + A.id + , B.tid + , A.name + , B.cpu + , B.ts - TR.start_ts AS startTime + , B.dur + , B.state + , B.pid + , IP.name as processName +from thread_state AS B + left join thread as A on A.id = B.itid + left join trace_range AS TR + left join process AS IP on IP.id = A.ipid +where B.tid = $tid;`, {$tid: tid}) + export const queryWakeUpThread_Desc = (): Promise> => query("queryWakeUpThread_Desc", `This is the interval from when the task became eligible to run (e.g.because of notifying a wait queue it was a suspended on) to when it started running.`) + /*-------------------------------------------------------------------------------------*/ -export const queryWakeUpThread_WakeThread = (wakets: number): Promise> => - query("queryWakeUpThread_WakeThread", `select TB.tid,TB.name as thread,TA.cpu,TC.pid,TC.name as process -from sched_view TA +export const queryWakeUpFromThread_WakeThread = (wakets: number): Promise> => + query("queryWakeUpFromThread_WakeThread", `select TB.tid,TB.name as thread,TA.cpu,(TA.ts - TR.start_ts) as ts,TC.pid,TC.name as process +from sched_slice TA left join thread TB on TA.itid = TB.id left join process TC on TB.ipid = TC.id -where itid = (select itid from raw where name = 'sched_waking' and ts = $wakets ) +left join trace_range TR +where TA.itid = (select itid from raw where name = 'sched_waking' and ts = $wakets ) and TA.ts < $wakets - and Ta.ts + Ta.dur >= $wakets`, {$wakets: wakets}) + and TA.ts + Ta.dur >= $wakets`, {$wakets: wakets}) + /*-------------------------------------------------------------------------------------*/ -export const queryWakeUpThread_WakeTime = (tid: number, startTime: number): Promise> => - query("queryWakeUpThread_WakeTime", `select * from - ( select ts as wakeTs,start_ts as startTs from instants_view,trace_section +export const queryWakeUpFromThread_WakeTime = (itid: number, startTime: number): Promise> => + query("queryWakeUpFromThread_WakeTime", `select * from + ( select ts as wakeTs,start_ts as startTs from instant,trace_range where name = 'sched_waking' - and ref = $tid + and ref = $itid and ts < start_ts + $startTime order by ts desc limit 1) TA left join - (select ts as preRow from sched_view,trace_section - where itid = $tid + (select ts as preRow from sched_slice,trace_range + where itid = $itid and ts < start_ts + $startTime - order by ts desc limit 1) TB`, {$tid: tid, $startTime: startTime}) + order by ts desc limit 1) TB`, {$itid: itid, $startTime: startTime}) /*-------------------------------------------------------------------------------------*/ -export const queryThreadsByPid = (pid: number): Promise> => - query("queryThreadsByPid", `select - the_tracks.ipid as upid, - the_tracks.itid as utid, - total_dur as hasSched, - process_view.pid as pid, - thread_view.tid as tid, - process_view.name as processName, - thread_view.name as threadName - from ( - select ipid, itid from sched_view join thread_view using(itid) group by itid - ) the_tracks - left join (select ipid, sum(dur) as total_dur - from sched_view join thread_view using(itid) - group by ipid - ) using(ipid) - left join thread_view using(itid) - left join process_view using(ipid) - where pid = $pid - order by - total_dur desc, - the_tracks.ipid, - the_tracks.itid`, {$pid: pid}) + +export const queryThreadWakeUp = (itid: number, startTime: number,dur:number): Promise> => + query("queryThreadWakeUp", ` +select TA.tid,min(TA.ts - TR.start_ts) as ts,TA.pid +from + (select min(ts) as wakeTs,ref as itid from instant,trace_range + where name = 'sched_wakeup' + and wakeup_from = $itid + and ts > start_ts + $startTime + and ts < start_ts + $startTime + $dur + group by ref + ) TW +left join thread_state TA on TW.itid = TA.itid +left join trace_range TR +where TA.ts > TW.wakeTs +group by TA.tid,TA.pid; + `, {$itid: itid, $startTime: startTime,$dur:dur}) + +export const queryThreadWakeUpFrom = (itid: number, startTime: number,dur:number): Promise> => + query("queryThreadWakeUpFrom", ` +select TA.tid,TA.cpu,(TA.ts - TR.start_ts) as ts,TA.pid +from + (select ts as wakeTs,wakeup_from as wakeupFromTid from instant,trace_range + where name = 'sched_wakeup' + and ref = $itid + and ts > start_ts + $startTime + and ts < start_ts + $startTime + $dur) TW +left join thread_state TA on TW.wakeupFromTid = TA.itid +left join trace_range TR +where TA.ts < TW.wakeTs and TA.ts + TA.dur >= TW.wakeTs +limit 1; + `, {$itid: itid, $startTime: startTime,$dur:dur}) /*-------------------------------------------------------------------------------------*/ -export const queryHeapByPid = (startTs: number, endTs: number, ipid: number): Promise> => - query("queryHeapByPid", `select a.maxheap maxHeapSize,current_size_dur as dur,h.all_heap_size heapsize,h.start_ts - t.start_ts as startTime,h.end_ts - t.start_ts as endTime -from native_hook h left join trace_section t left join (select max(all_heap_size) maxheap from native_hook) a where ipid = ${ipid} and startTime between ${startTs} and ${endTs}; -`, {$ipid: ipid, $startTs: startTs, $endTs: endTs}) export const queryHeapGroupByEvent = (): Promise> => - query("queryHeapGroupByEvent", `select event_type as eventType,sum(heap_size) as sumHeapSize from native_hook group by event_type`, {}) - -export const queryHeapByEventType = (startTs: number, endTs: number, arg1: string,arg2: string): Promise> => - query("queryHeapByEventType", ` -select a.maxHeap maxHeapSize, - current_size_dur as dur, - h.all_heap_size heapsize, - h.start_ts - t.start_ts as startTime, - h.end_ts - t.start_ts as endTime, - h.event_type as eventType -from native_hook h -left join trace_section t -left join ( -select max(all_heap_size) maxHeap -from native_hook ${arg1}) a -where startTime between ${startTs} and ${endTs} ${arg2} -`, {$startTs: startTs, $endTs: endTs,$arg1:arg1,$arg2:arg2}) -/*-------------------------------------------------------------------------------------*/ -export const queryHeapPid = (): Promise> => - query("queryHeapPid", `select ipid,pid from native_hook h left join process p on h.ipid = p.id group by ipid,pid`, {}) -/*-------------------------------------------------------------------------------------*/ -export const queryHeapTable = (startTs: number, endTs: number, ipids: Array): Promise> => - query("queryHeapTable", `select *,Allocations - Deallocations Total,AllocationSize - DeAllocationSize RemainingSize from (select f.file_path MoudleName, - sum(case when h.event_type = 'AllocEvent' then 1 else 0 end) Allocations, - sum(case when h.event_type = 'FreeEvent' then 1 else 0 end) Deallocations, - sum(case when h.event_type = 'AllocEvent' then heap_size else 0 end) AllocationSize, - sum(case when h.event_type = 'FreeEvent' then heap_size else 0 end) DeAllocationSize, - f.symbol_name AllocationFunction - from (select native_hook.start_ts - t.start_ts as startTime,* from native_hook - left join trace_range t where ipid in (${ipids.join(",")}) and startTime between ${startTs} and ${endTs}) h - left join (select * from native_hook_frame where depth = 0) f - on f.eventId = h.eventId group by f.file_path)`, - {ipids: ipids, $startTs: startTs, $endTs: endTs}) -export const queryHeapTreeTable = (startTs: number, endTs: number, ipids: Array): Promise> => - query("queryHeapTable", ` - select h.start_ts - t.start_ts as startTs, - h.end_ts - t.start_ts as endTs, - h.heap_size as heapSize, - h.event_type as eventType, - f.symbol_name as AllocationFunction, - f.file_path as MoudleName, - f.depth, - f.eventId - from native_hook h - inner join trace_range t - inner join native_hook_frame f on h.eventId = f.eventId where event_type = 'AllocEvent' - and ipid in (${ipids.join(",")}) - and (h.start_ts - t.start_ts between ${startTs} and ${endTs} or h.end_ts - t.start_ts between ${startTs} and ${endTs})`, - {ipids: ipids, $startTs: startTs, $endTs: endTs}) -export const queryHeapAllTable = (limit: number, offset: number): Promise> => - query("queryHeapAllTable", ` - select - h.symbol_name as AllocationFunction, - h.file_path as MoudleName, - h.depth, - h.eventId - from native_hook_frame h limit $limit offset $offset`, - { $limit: limit, $offset: offset}) + query("queryHeapGroupByEvent", ` + select + event_type as eventType, + sum(heap_size) as sumHeapSize + from + native_hook + where event_type = 'AllocEvent' or event_type = 'MmapEvent' + group by event_type`, {}) + +export const queryAllHeapByEvent = (): Promise> => + query("queryAllHeapByEvent", ` + select * from ( + select h.start_ts - t.start_ts as startTime, + h.heap_size as heapSize, + h.event_type as eventType +from native_hook h ,trace_range t +where h.start_ts >= t.start_ts and h.start_ts <= t.end_ts +and (h.event_type = 'AllocEvent' or h.event_type = 'MmapEvent') +union +select h.end_ts - t.start_ts as startTime, + h.heap_size as heapSize, + (case when h.event_type = 'AllocEvent' then 'FreeEvent' else 'MunmapEvent' end) as eventType +from native_hook h ,trace_range t +where h.start_ts >= t.start_ts and h.start_ts <= t.end_ts +and (h.event_type = 'AllocEvent' or h.event_type = 'MmapEvent') +and h.end_ts not null ) order by startTime; +`, {}) + export const queryHeapAllData = (startTs: number, endTs: number, ipids: Array): Promise> => query("queryHeapAllData", ` - select h.start_ts - t.start_ts as startTs, - h.end_ts - t.start_ts as endTs, - h.heap_size as heapSize, - h.event_type as eventType, - h.eventId - from native_hook h - inner join trace_range t - where event_type = 'AllocEvent' - and ipid in (${ipids.join(",")}) - and (h.start_ts - t.start_ts between ${startTs} and ${endTs} or h.end_ts - t.start_ts between ${startTs} and ${endTs})`, + select + h.start_ts - t.start_ts as startTs, + h.end_ts - t.start_ts as endTs, + h.heap_size as heapSize, + h.event_type as eventType, + h.callchain_id as eventId + from + native_hook h + inner join + trace_range t + where + event_type = 'AllocEvent' + and + ipid in (${ipids.join(",")}) + and + (h.start_ts - t.start_ts between ${startTs} and ${endTs} or h.end_ts - t.start_ts between ${startTs} and ${endTs})`, {ipids: ipids, $startTs: startTs, $endTs: endTs}) -export const queryHeapFrameCount = (): Promise> => - query("queryHeapAllTable", ` + +export const queryNativeHookStatistics = (leftNs: number, rightNs: number): Promise> => + query("queryNativeHookStatistics", ` + select + event_type as eventType, + sub_type_id as subTypeId, + max(heap_size) as max, + sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then heap_size else 0 end) as allocByte, + sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then 1 else 0 end) as allocCount, + sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then heap_size else 0 end) as freeByte, + sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then 1 else 0 end) as freeCount + from + native_hook A, + trace_range B + where + (A.start_ts - B.start_ts) between ${leftNs} and ${rightNs} + and (event_type = 'AllocEvent' or event_type = 'MmapEvent') + group by event_type;`, {$leftNs: leftNs, $rightNs: rightNs}) + +export const queryNativeHookStatisticsMalloc = (leftNs: number, rightNs: number): Promise> => + query('queryNativeHookStatisticsMalloc', ` + select + event_type as eventType, + heap_size as heapSize, + sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then heap_size else 0 end) as allocByte, + sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then 1 else 0 end) as allocCount, + sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then heap_size else 0 end) as freeByte, + sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then 1 else 0 end) as freeCount + from + native_hook A, + trace_range B + where + (A.start_ts - B.start_ts) between ${leftNs} and ${rightNs} + and + (event_type = 'AllocEvent' or event_type = 'MmapEvent') + and + sub_type_id is null + group by + event_type, + heap_size + order by heap_size desc + `, {$leftNs: leftNs, $rightNs: rightNs}) + +export const queryNativeHookStatisticsSubType = (leftNs: number, rightNs: number): Promise> => + query('queryNativeHookStatisticsSubType', ` + select + event_type as eventType, + sub_type_id as subTypeId, + max(heap_size) as max, + sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then heap_size else 0 end) as allocByte, + sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then 1 else 0 end) as allocCount, + sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then heap_size else 0 end) as freeByte, + sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then 1 else 0 end) as freeCount + from + native_hook A, + trace_range B + where + (A.start_ts - B.start_ts) between ${leftNs} and ${rightNs} + and + (event_type = 'MmapEvent') + group by + event_type,sub_type_id; + `, {$leftNs: leftNs, $rightNs: rightNs}) + + +export const queryNativeHookEventTid = (leftNs: number, rightNs: number, types: Array): Promise> => + query("queryNativeHookEventTid", ` + select + callchain_id as eventId, + event_type as eventType, + heap_size as heapSize, + addr, + (A.start_ts - B.start_ts) as startTs, + (A.end_ts - B.start_ts) as endTs, + tid, + sub_type_id as subTypeId, + ifnull(last_lib_id,0) as lastLibId, + t.name as threadName + from + native_hook A, + trace_range B + left join + thread t + on + A.itid = t.id + where + A.start_ts - B.start_ts + between ${leftNs} and ${rightNs} and A.event_type in (${types.join(",")})` + , {$leftNs: leftNs, $rightNs: rightNs, $types: types}) + +export const queryNativeHookProcess = (): Promise> => + query("queryNativeHookProcess", ` + select + distinct native_hook.ipid, + pid, + name + from + native_hook + left join + process p + on + native_hook.ipid = p.id`, {}) + +export const queryNativeHookSnapshotTypes = (): Promise> => + query("queryNativeHookSnapshotTypes", ` +select + event_type as eventType, + data as subType + from + native_hook left join data_dict on native_hook.sub_type_id = data_dict.id + where + (event_type = 'AllocEvent' or event_type = 'MmapEvent') + group by + event_type,data;`, {}) + +export const queryAllHookData = (rightNs: number): Promise> => + query("queryAllHookData", ` + select + callchain_id as eventId, + event_type as eventType, + data as subType, + addr, + heap_size as growth, + (n.start_ts - t.start_ts) as startTs, + (n.end_ts - t.start_ts) as endTs + from + native_hook n left join data_dict on n.sub_type_id = data_dict.id, + trace_range t + where + (event_type = 'AllocEvent' or event_type = 'MmapEvent') + and + n.start_ts between t.start_ts and ${rightNs} + t.start_ts`, {$rightNs: rightNs}) + +export const queryNativeHookResponseTypes = (leftNs: number, rightNs: number, types: Array): Promise> => + query("queryNativeHookResponseTypes", ` + select last_lib_id as lastLibId,data_dict.data as value from + native_hook A ,trace_range B + left join data_dict on A.last_lib_id = data_dict.id + where + A.start_ts - B.start_ts + between ${leftNs} and ${rightNs} and A.event_type in (${types.join(",")}) + group by last_lib_id; + `,{$leftNs: leftNs, $rightNs: rightNs, $types: types}) +/** + * HiPerf + */ +export const queryHiPerfEventList = (): Promise> => + query("queryHiPerfEventList", `select id,report_value from perf_report where report_type='config_name'`, {}) +export const queryHiPerfEventListData = (eventTypeId:number): Promise> => + query("queryHiPerfEventListData", ` + select s.callchain_id, + (s.timestamp_trace-t.start_ts) startNS + from perf_sample s,trace_range t + where + event_type_id=${eventTypeId} + and s.thread_id != 0; +`, {$eventTypeId:eventTypeId}) +export const queryHiPerfEventData = (eventTypeId:number,cpu:number): Promise> => + query("queryHiPerfEventList", ` + select s.callchain_id, + (s.timestamp_trace-t.start_ts) startNS + from perf_sample s,trace_range t + where + event_type_id=${eventTypeId} + and cpu_id=${cpu} + and s.thread_id != 0; +`, {$eventTypeId:eventTypeId,$cpu:cpu}) +export const queryHiPerfCpuData = (cpu: number): Promise> => + query("queryHiPerfCpuData", ` + select s.callchain_id, + (s.timestamp_trace-t.start_ts) startNS + from perf_sample s,trace_range t + where + cpu_id=${cpu} + and s.thread_id != 0;`, {$cpu: cpu}) +export const queryHiPerfCpuMergeData = (): Promise> => + query("queryHiPerfCpuData", + `select s.callchain_id,(s.timestamp_trace-t.start_ts) startNS from perf_sample s,trace_range t where s.thread_id != 0;`, {}) +export const queryHiPerfCpuMergeData2 = (): Promise> => + query("queryHiPerfCpuData2", + `select distinct cpu_id from perf_sample where thread_id != 0 order by cpu_id desc;`, {}) + +export const queryHiPerfProcessData = (pid: number): Promise> => query("queryHiPerfProcessData", ` +SELECT sp.callchain_id, + th.thread_name, + th.thread_id tid, + th.process_id pid, + sp.timestamp_trace - tr.start_ts startNS +from perf_sample sp, + trace_range tr + left join perf_thread th on th.thread_id = sp.thread_id +where pid = ${pid} and sp.thread_id != 0;`, {$pid: pid}) + +export const queryHiPerfThreadData = (tid: number): Promise> => query("queryHiPerfThreadData", ` +SELECT sp.callchain_id, + th.thread_name, + th.thread_id tid, + th.process_id pid, + sp.timestamp_trace - tr.start_ts startNS +from perf_sample sp, + trace_range tr + left join perf_thread th on th.thread_id = sp.thread_id +where tid = ${tid} and sp.thread_id != 0;`, {$tid: tid}) + +export const querySelectTraceStats = (): Promise> => + query('querySelectTraceStats', 'select event_name,stat_type,count,source,serverity from stat'); + +export const queryCustomizeSelect = (sql: string): Promise> => + query('queryCustomizeSelect', sql); + +export const queryDistributedTerm = (): Promise> => + query('queryDistributedTerm', ` + select + group_concat(thread.id,',') as threadId, + group_concat(thread.name,',') as threadName, + group_concat(process.id,',') as processId, + group_concat(process.name,',') as processName, + group_concat(callstack.name,',') as funName, + group_concat(callstack.dur,',') as dur, + group_concat(callstack.ts,',') as ts, + cast(callstack.chainId as varchar) as chainId, + callstack.spanId as spanId, + callstack.parentSpanId as parentSpanId, + group_concat(callstack.flag,',') as flag, + (select + value + from + meta + where + name='source_name') as trace_name + from + callstack + inner join thread on callstack.callid = thread.id + inner join process on process.id = thread.ipid + where (callstack.flag='S' or callstack.flag='C') + group by callstack.chainId,callstack.spanId,callstack.parentSpanId`); + +export const queryTraceCpu = (): Promise> => + query('queryTraceCpu', `SELECT + itid AS tid, + ipid AS pid, + group_concat(cpu, ',') AS cpu, + group_concat(dur, ',') AS dur, + group_concat(min_freq, ',') AS min_freq, + group_concat(max_freq, ',') AS max_freq, + group_concat(avg_frequency, ',') AS avg_frequency + FROM + (SELECT + itid, + ipid, + cpu, + CAST (SUM(dur) AS INT) AS dur, + CAST (MIN(freq) AS INT) AS min_freq, + CAST (MAX(freq) AS INT) AS max_freq, + CAST ( (SUM(dur * freq) / SUM(dur) ) AS INT) AS avg_frequency + from + result + group by + itid, cpu + ) + GROUP BY + ipid, itid + ORDER BY + ipid + `); + +export const queryTraceCpuTop = (): Promise> => + query('queryTraceCpuTop', `SELECT + itid AS tid, + ipid AS pid, + group_concat(cpu, ',') AS cpu, + group_concat(dur, ',') AS dur, + group_concat(min_freq, ',') AS min_freq, + group_concat(max_freq, ',') AS max_freq, + group_concat(avg_frequency, ',') AS avg_frequency, + sum(dur * avg_frequency) AS sumNum + FROM + (SELECT + itid, + ipid, + cpu, + CAST (SUM(dur) AS INT) AS dur, + CAST (MIN(freq) AS INT) AS min_freq, + CAST (MAX(freq) AS INT) AS max_freq, + CAST ( (SUM(dur * freq) / SUM(dur) ) AS INT) AS avg_frequency + from result group by itid, cpu + ) + GROUP BY + ipid, itid + ORDER BY + sumNum + DESC + LIMIT 10; + `); + +export const queryTraceMemory = (): Promise> => + query('queryTraceMemory', ` + select + max(value) as maxNum, + min(value) as minNum, + avg(value) as avgNum, + filter.name as name, + p.name as processName + from process_measure + left join process_measure_filter as filter on filter.id= filter_id + left join process as p on p.id = filter.ipid + where + filter_id > 0 + and + filter.name = 'mem.rss.anon' + group by + filter_id + order by + avgNum desc`); + +export const queryTraceMemoryTop = (): Promise> => + query('queryTraceMemoryTop', ` + select + max(value) as maxNum, + min(value) as minNum, + avg(value) as avgNum, + filter.name as name, + p.name as processName + from process_measure + left join process_measure_filter as filter on filter.id= filter_id + left join process as p on p.id = filter.ipid + where + filter_id > 0 + and + filter.name = 'mem.rss.anon' + group by + filter_id + order by + avgNum desc limit 10`); + +export const queryTraceMemoryUnAgg = (): Promise> => + query('queryTraceMemoryUnAgg', ` + select + p.name as processName, + group_concat(filter.name) as name, + cast(group_concat(value) as varchar) as value, + cast(group_concat(ts) as varchar) as ts + from process_measure m + left join process_measure_filter as filter on filter.id= m.filter_id + left join process as p on p.id = filter.ipid + where + filter.name = 'mem.rss.anon' + or + filter.name = 'mem.rss.file' + or + filter.name = 'mem.swap' + or + filter.name = 'oom_score_adj' + group by + p.name,filter.ipid + order by + filter.ipid`); + +export const queryTraceTaskName = (): Promise> => + query('queryTraceTaskName', ` + select + P.id as id, + P.pid as pid, + P.name as process_name, + group_concat(T.name,',') as thread_name + from process as P left join thread as T where P.id = T.ipid + group by pid`); + +export const queryTraceMetaData = (): Promise> => + query('queryTraceMetaData', ` + select + cast(name as varchar) as name, + cast(value as varchar) as valueText + from meta + UNION + select 'start_ts',cast(start_ts as varchar) from trace_range + UNION + select 'end_ts',cast(end_ts as varchar) from trace_range`); + +export const querySystemCalls = (): Promise> => + query('querySystemCalls', ` + select + count(*) as frequency, + min(dur) as minDur, + max(dur) as maxDur, + avg(dur) as avgDur, + name as funName + from + callstack + group by name + order by + frequency desc limit 100`); + +export const querySystemCallsTop = (): Promise> => + query('querySystemCallsTop', `SELECT + cpu.tid AS tid, + cpu.pid AS pid, + callstack.name AS funName, + count(callstack.name) AS frequency, + min(callstack.dur) AS minDur, + max(callstack.dur) AS maxDur, + round(avg(callstack.dur)) AS avgDur + FROM + callstack + INNER JOIN + (SELECT + itid AS tid, + ipid AS pid, + group_concat(cpu, ',') AS cpu, + group_concat(dur, ',') AS dur, + group_concat(min_freq, ',') AS min_freq, + group_concat(max_freq, ',') AS max_freq, + group_concat(avg_frequency, ',') AS avg_frequency, + sum(dur * avg_frequency) AS sumNum + FROM + (SELECT + itid, + ipid, + cpu, + CAST (SUM(dur) AS INT) AS dur, + CAST (MIN(freq) AS INT) AS min_freq, + CAST (MAX(freq) AS INT) AS max_freq, + CAST ( (SUM(dur * freq) / SUM(dur) ) AS INT) AS avg_frequency + FROM + result + GROUP BY + itid, cpu + ) + GROUP BY + ipid, itid + ORDER BY + sumNum + DESC + LIMIT 10 + ) AS cpu + ON + callstack.callid = cpu.tid + GROUP BY + callstack.name + ORDER BY + frequency + DESC + LIMIT 10`); + +export const getTabLiveProcessData = (leftNs: number, rightNs: number): Promise> => + query("getTabLiveProcessData", `SELECT + process.id as processId, + process.name as processName, + process.ppid as responsibleProcess, + process.uud as userName, + process.usag as cpu, + process.threadN as threads, + process.pss as memory, + process.cpu_time as cpuTime, + process.disk_reads as diskReads, + process.disk_writes as diskWrite + FROM + ( + SELECT + tt.process_id AS id, + tt.process_name AS name, + tt.parent_process_id AS ppid, + tt.uid as uud, + tt.cpu_usage as usag, + tt.thread_num AS threadN, + mt.maxTT - TR.start_ts as endTs, + tt.pss_info as pss, + tt.cpu_time, + tt.disk_reads, + tt.disk_writes + FROM + live_process tt + LEFT JOIN trace_range AS TR + LEFT JOIN (select re.process_id as idd, max(re.ts) as maxTT, min(re.ts) as minTT + from live_process re GROUP BY re.process_name, re.process_id ) mt + on mt.idd = tt.process_id where endTs >= $rightNS + GROUP BY + tt.process_name, + tt.process_id + ) process ;`, {$leftNS: leftNs, $rightNS: rightNs}) + +export const getTabProcessHistoryData = (leftNs: number, rightNs: number, + processId: number | undefined, threadId: number | undefined): Promise> => + query("getTabProcessHistoryData", `SELECT + process.id as processId, + process.isD as alive, + process.startTS as firstSeen, + process.endTs as lastSeen, + process.name as processName, + process.ppid as responsibleProcess, + process.uuid as userName, + process.cpu_time as cpuTime, + 0 as pss + FROM + ( + SELECT + tt.process_id AS id, + tt.process_name AS name, + tt.parent_process_id AS ppid, + tt.uid AS uuid, + tt.cpu_time, + (mt.minTT - TR.start_ts ) AS startTS, + mt.maxTT - TR.start_ts as endTs, + (mt.maxTT - TR.start_ts - $rightNS) > 0 as isD + FROM + live_process tt + LEFT JOIN trace_range AS TR + LEFT JOIN (select re.process_id as idd, max(re.ts) as maxTT, min(re.ts) as minTT + from live_process re GROUP BY re.process_name, re.process_id ) mt + on mt.idd = tt.process_id + GROUP BY + tt.process_name, + tt.process_id + ) process;` + , {$leftNS: leftNs, $rightNS: rightNs, $processID: processId, $threadID: threadId}) + +export const getTabCpuAbilityData = (leftNs: number, rightNs: number): Promise> => + query("getTabCpuAbilityData", `SELECT + ( n.ts - TR.start_ts ) AS startTime, + n.dur AS duration, + n.total_load AS totalLoad, + n.user_load AS userLoad, + n.system_load AS systemLoad, + n.process_num AS threads + FROM + cpu_usage AS n, + trace_range AS TR + WHERE + ( n.ts - TR.start_ts ) >= ifnull(( + SELECT + ( usage.ts - TR.start_ts ) + FROM + cpu_usage usage, + trace_range TR + WHERE + ( usage.ts - TR.start_ts ) <= $leftNS + ORDER BY + usage.ts DESC + LIMIT 1 + ),0) + AND ( n.ts - TR.start_ts ) <= $rightNS + ORDER BY + startTime ASC; + `, {$leftNS: leftNs, $rightNS: rightNs}) + +export const getTabMemoryAbilityData = (leftNs: number, rightNs: number): Promise> => + query("getTabMemoryAbilityData", `SELECT + m.ts AS startTime, + GROUP_CONCAT( IFNULL( m.value, 0 ) ) AS value, + GROUP_CONCAT( f.name ) AS name + FROM + sys_mem_measure AS m + INNER JOIN sys_event_filter AS f ON m.filter_id = f.id + AND (f.name = 'sys.mem.total' + or f.name = 'sys.mem.free' + or f.name = 'sys.mem.buffers' + or f.name = 'sys.mem.cached' + or f.name = 'sys.mem.shmem' + or f.name = 'sys.mem.slab' + or f.name = 'sys.mem.swap.total' + or f.name = 'sys.mem.swap.free' + or f.name = 'sys.mem.mapped' + or f.name = 'sys.mem.vmalloc.used' + or f.name = 'sys.mem.page.tables' + or f.name = 'sys.mem.kernel.stack' + or f.name = 'sys.mem.active' + or f.name = 'sys.mem.inactive' + or f.name = 'sys.mem.unevictable' + or f.name = 'sys.mem.vmalloc.total' + or f.name = 'sys.mem.slab.unreclaimable' + or f.name = 'sys.mem.cma.total' + or f.name = 'sys.mem.cma.free' + or f.name = 'sys.mem.kernel.reclaimable' + or f.name = 'sys.mem.zram' + ) + AND m.ts >= ifnull(( + SELECT + m.ts AS startTime + FROM + sys_mem_measure AS m + INNER JOIN sys_event_filter AS f ON m.filter_id = f.id + AND m.ts <= $leftNS + AND (f.name = 'sys.mem.total' + or f.name = 'sys.mem.free' + or f.name = 'sys.mem.buffers' + or f.name = 'sys.mem.cached' + or f.name = 'sys.mem.shmem' + or f.name = 'sys.mem.slab' + or f.name = 'sys.mem.swap.total' + or f.name = 'sys.mem.swap.free' + or f.name = 'sys.mem.mapped' + or f.name = 'sys.mem.vmalloc.used' + or f.name = 'sys.mem.page.tables' + or f.name = 'sys.mem.kernel.stack' + or f.name = 'sys.mem.active' + or f.name = 'sys.mem.inactive' + or f.name = 'sys.mem.unevictable' + or f.name = 'sys.mem.vmalloc.total' + or f.name = 'sys.mem.slab.unreclaimable' + or f.name = 'sys.mem.cma.total' + or f.name = 'sys.mem.cma.free' + or f.name = 'sys.mem.kernel.reclaimable' + or f.name = 'sys.mem.zram' + ) + ORDER BY + m.ts DESC + LIMIT 1 + ),0) + AND m.ts <= $rightNS GROUP BY m.ts;`, {$leftNS: leftNs, $rightNS: rightNs}) + +export const getTabNetworkAbilityData = (leftNs: number, rightNs: number): Promise> => + query("getTabNetworkAbilityData", `SELECT + ( n.ts - TR.start_ts ) AS startTime, + n.dur AS duration, + n.rx AS dataReceived, + n.tx_speed AS dataReceivedSec, + n.tx AS dataSend, + n.rx_speed AS dataSendSec, + n.packet_in AS packetsIn, + n.packet_in_sec AS packetsInSec, + n.packet_out AS packetsOut, + n.packet_out_sec AS packetsOutSec + FROM + network AS n, + trace_range AS TR + WHERE + ( n.ts - TR.start_ts ) >= ifnull(( + SELECT + ( nn.ts - T.start_ts ) AS startTime + FROM + network nn, + trace_range T + WHERE + ( nn.ts - T.start_ts ) <= $leftNS + ORDER BY + nn.ts DESC + LIMIT 1 + ),0) + AND ( n.ts - TR.start_ts ) <= $rightNS + ORDER BY + startTime ASC`, {$leftNS: leftNs, $rightNS: rightNs}) + +/*-------------------------------------------------------------------------------------*/ +export const getTabDiskAbilityData = (leftNs: number, rightNs: number): Promise> => + query("getTabDiskAbilityData", `SELECT + ( n.ts - TR.start_ts ) AS startTime, + n.dur AS duration, + n.rd AS dataRead, + n.rd_speed AS dataReadSec, + n.wr AS dataWrite, + n.wr_speed AS dataWriteSec, + n.rd_count AS readsIn, + n.rd_count_speed AS readsInSec, + n.wr_count AS writeOut, + n.wr_count_speed AS writeOutSec + FROM + diskio AS n, + trace_range AS TR + WHERE + ( n.ts - TR.start_ts ) >= ifnull(( + SELECT + ( nn.ts - T.start_ts ) AS startTime + FROM + diskio AS nn, + trace_range AS T + WHERE + ( nn.ts - T.start_ts ) <= $leftNS + ORDER BY + nn.ts DESC + LIMIT 1 + ),0) + AND ( n.ts - TR.start_ts ) <= $rightNS + ORDER BY + startTime ASC; + `, {$leftNS: leftNs, $rightNS: rightNs}) + +export const queryCpuAbilityData = (): Promise> => + query("queryCpuAbilityData", `select + (t.total_load) as value, + (t.ts - TR.start_ts) as startNS + from cpu_usage t, trace_range AS TR;`) + +export const queryCpuAbilityUserData = (): Promise> => + query("queryCpuAbilityUserData", `select + t.user_load as value, + (t.ts - TR.start_ts) as startNS + from cpu_usage t, trace_range AS TR;`) + +export const queryCpuAbilitySystemData = (): Promise> => + query("queryCpuAbilitySystemData", `select + t.system_load as value, + (t.ts - TR.start_ts) as startNS + from cpu_usage t, trace_range AS TR;`) + +export const queryMemoryUsedAbilityData = (id: string): Promise> => + query("queryMemoryUsedAbilityData", `select + t.value as value, + (t.ts - TR.start_ts) as startNS + from sys_mem_measure t, trace_range AS TR where t.filter_id = $id;`, {$id: id}) + +export const queryCachedFilesAbilityData = (id: string): Promise> => + query("queryCachedFilesAbilityData", `select + t.value as value, + (t.ts - TR.start_ts) as startNS + from sys_mem_measure t, trace_range AS TR where t.filter_id = $id;`, {$id: id}) + +export const queryCompressedAbilityData = (id: string): Promise> => + query("queryCompressedAbilityData", `select + t.value as value, + (t.ts - TR.start_ts) as startNS + from sys_mem_measure t, trace_range AS TR where t.filter_id = $id;`, {$id: id}) + +export const querySwapUsedAbilityData = (id: string): Promise> => + query("querySwapUsedAbilityData", `select + t.value as value, + (t.ts - TR.start_ts) as startNS + from sys_mem_measure t, trace_range AS TR where t.filter_id = $id;`, {$id: id}) + +export const queryBytesReadAbilityData = (): Promise> => + query("queryBytesReadAbilityData", `select + t.rd_speed as value, + (t.ts - TR.start_ts) as startNS + from diskio t, trace_range AS TR;`) + +export const queryBytesWrittenAbilityData = (): Promise> => + query("queryBytesWrittenAbilityData", `select + t.wr_speed as value, + (t.ts - TR.start_ts) as startNS + from diskio t, trace_range AS TR;`) + +export const queryReadAbilityData = (): Promise> => + query("queryReadAbilityData", `select + t.rd_count_speed as value, + (t.ts - TR.start_ts) as startNS + from diskio t, trace_range AS TR;`) + + +export const queryWrittenAbilityData = (): Promise> => + query("queryWrittenAbilityData", `select + t.wr_count_speed as value, + (t.ts - TR.start_ts) as startNS + from diskio t, trace_range AS TR;`) + +export const queryBytesInAbilityData = (): Promise> => + query("queryBytesInAbilityData", `select + t.tx_speed as value, + (t.ts - TR.start_ts) as startNS + from network t, trace_range AS TR;`) + +export const queryBytesOutAbilityData = (): Promise> => + query("queryBytesOutAbilityData", `select + t.rx_speed as value, + (t.ts - TR.start_ts) as startNS + from network t, trace_range AS TR;`,) + +export const queryPacketsInAbilityData = (): Promise> => + query("queryPacketsInAbilityData", `select + t.packet_in_sec as value, + (t.ts - TR.start_ts) as startNS + from network t, trace_range AS TR;`,) + +export const queryPacketsOutAbilityData = (): Promise> => + query("queryPacketsOutAbilityData", `select + t.packet_out_sec as value, + (t.ts - TR.start_ts) as startNS + from network t, trace_range AS TR;`) + +export const queryNetWorkMaxData = (): Promise> => + query("queryNetWorkMaxData", `select + ifnull(max(tx_speed),0) as maxIn, + ifnull(max(rx_speed),0) as maxOut, + ifnull(max(packet_in_sec),0) as maxPacketIn, + ifnull(max(packet_in_sec),0) as maxPacketOut + from network`) + +export const queryMemoryMaxData = (memoryName: string): Promise> => + query("queryMemoryMaxData", + `SELECT ifnull(max(m.value),0) as maxValue, + filter_id + from sys_mem_measure m + WHERE m.filter_id = + (SELECT id FROM sys_event_filter WHERE name = $memoryName) +`, {$memoryName: memoryName}) + +export const queryDiskIoMaxData = (): Promise> => + query("queryDiskIoMaxData", `select + ifnull(max(rd_speed),0) as bytesRead, + ifnull(max(wr_speed),0) as bytesWrite, + ifnull(max(rd_count_speed),0) as readOps, + ifnull(max(wr_count_speed),0) as writeOps + from diskio`) + +export const queryAbilityExits = (): Promise> => + query("queryAbilityExits", `select + event_name + from stat s + where s.event_name in ('trace_diskio','trace_network', 'trace_cpu_usage','sys_memory') + and s.stat_type ='received' and s.count > 0`) + +export const queryStartTime = (): Promise> => + query("queryStartTime", `SELECT start_ts FROM trace_range`) + +export const queryPerfFiles = (): Promise> => + query("queryPerfFiles", `select file_id as fileId,symbol,path from perf_files`, {}) + +export const queryPerfProcess = (): Promise> => + query("queryPerfThread", `select process_id as pid,thread_name as processName from perf_thread where process_id = thread_id`, {}) + +export const queryPerfThread = (): Promise> => + query("queryPerfThread", `select a.thread_id as tid,a.thread_name as threadName,a.process_id as pid,b.thread_name as processName from perf_thread a left join (select * from perf_thread where thread_id = process_id) b on a.process_id = b.thread_id`, {}) + +export const queryPerfSampleListByTimeRange = (leftNs: number, rightNs: number, cpus: Array, processes: Array, threads: Array): Promise> => { + let sql = ` +select A.callchain_id as sampleId, + A.thread_id as tid, + C.thread_name as threadName, + A.thread_state as state, + C.process_id as pid, + (timestamp_trace - R.start_ts) as time, + cpu_id as core +from perf_sample A,trace_range R +left join perf_thread C on A.thread_id = C.thread_id +where time >= $leftNs and time <= $rightNs and A.thread_id != 0 + ` + if (cpus.length != 0 || processes.length != 0 || threads.length != 0) { + let arg1 = cpus.length > 0 ? `or core in (${cpus.join(",")}) ` : ''; + let arg2 = processes.length > 0 ? `or pid in (${processes.join(",")}) ` : ''; + let arg3 = threads.length > 0 ? `or tid in (${threads.join(",")})` : ''; + let arg = `${arg1}${arg2}${arg3}`.substring(3); + sql = `${sql} and (${arg})` + } + return query("queryPerfSampleListByTimeRange", sql, {$leftNs: leftNs, $rightNs: rightNs}); +} + +export const queryPerfSampleIdsByTimeRange = (leftNs: number, rightNs: number, cpus: Array, processes: Array, threads: Array): Promise> => { + let sql = ` +select A.callchain_id as sampleId +from perf_sample A,trace_range R +left join perf_thread C on A.thread_id = C.thread_id +where (timestamp_trace - R.start_ts) >= $leftNs and (timestamp_trace - R.start_ts) <= $rightNs and A.thread_id != 0 + ` + if (cpus.length != 0 || processes.length != 0 || threads.length != 0) { + let arg1 = cpus.length > 0 ? `or A.cpu_id in (${cpus.join(",")}) ` : ''; + let arg2 = processes.length > 0 ? `or C.process_id in (${processes.join(",")}) ` : ''; + let arg3 = threads.length > 0 ? `or A.thread_id in (${threads.join(",")})` : ''; + let arg = `${arg1}${arg2}${arg3}`.substring(3); + sql = `${sql} and (${arg})` + } + return query("queryPerfSampleIdsByTimeRange", sql, {$leftNs: leftNs, $rightNs: rightNs}); +} + +export const queryPerfSampleCallChain = (sampleId: number): Promise> => + query("queryPerfSampleCallChain", ` + select + callchain_id as callChainId, + callchain_id as sampleId, + file_id as fileId, + symbol_id as symbolId, + vaddr_in_file as vaddrInFile, + name as symbol +from perf_callchain where callchain_id = $sampleId and symbol_id != -1 and vaddr_in_file != 0; + `, {$sampleId: sampleId}) + +export const queryPerfCmdline = ():Promise> => + query("queryPerfCmdline",` + select report_value from perf_report where report_type = 'cmdline' + `,{}) + +export const queryCPuAbilityMaxData = (): Promise> => + query("queryCPuAbilityMaxData", + `select ifnull(max(total_load),0) as totalLoad, + ifnull(max(user_load),0) as userLoad, + ifnull(max(system_load),0) as systemLoad + from cpu_usage`) + +export const querySearchFunc = (search:string):Promise> => + query("querySearchFunc",` + select c.cookie,c.id,c.name as funName,c.ts - r.start_ts as startTime,c.dur,c.depth,t.tid,t.name as threadName + ,p.pid ,'func' as type from callstack c left join thread t on c.callid = t.id left join process p on t.ipid = p.id + left join trace_range r + where c.name like '%${search}%' and startTime > 0; + `,{$search:search}) + +export const queryBinderBySliceId = (id:number): Promise> => + query("queryBinderBySliceId", + `select c.ts-D.start_ts as startTime, + c.dur, + t.tid,p.pid,c.depth + from callstack c,trace_range D + left join thread t on c.callid = t.id + left join process p on p.id = t.ipid +where cat = 'binder' and c.id = $id;`,{$id:id}) + +export const queryBinderByArgsId = (id:number,startTime:number,isNext:boolean): Promise> =>{ + let sql = `select c.ts - D.start_ts as startTime, + c.dur, + t.tid,p.pid,c.depth + from callstack c,trace_range D + left join thread t on c.callid = t.id + left join process p on p.id = t.ipid +where cat = 'binder' and c.argsetid = $id` + if(isNext){ + sql += " and c.ts > $startTime + D.start_ts" + }else { + sql += " and c.ts < $startTime + D.start_ts" + } + return query("queryBinderByArgsId",sql,{$id:id,$startTime:startTime}) +} + +export const getTabPaneFilesystemStatisticsFather = (leftNs: number, rightNs: number): Promise> => + query("getTabPaneFilesystemStatisticsFather", ` + select SUM(dur) as allDuration, + count(f.type) as count, + min(dur) as minDuration, + max(dur) as maxDuration, + round(avg(dur),2) as avgDuration, + p.name, + f.type, + p.pid, + sum(ifnull(size,0)) as size + from file_system_sample as f left join process as p on f.ipid=p.ipid + where f.start_ts >= $leftNs + and end_ts <= $rightNs + group by f.type; +`, {$leftNs:leftNs,$rightNs:rightNs}); + +export const getTabPaneFilesystemStatisticsChild = (leftNs: number, rightNs: number): Promise> => + query("getTabPaneFilesystemStatisticsChild", ` + select SUM(dur) as allDuration, + count(f.type) as count, + min(dur) as minDuration, + max(dur) as maxDuration, + round(avg(dur),2) as avgDuration, + p.name, + f.type, + p.pid, + sum(ifnull(size,0)) as size + from file_system_sample as f left join process as p on f.ipid=p.ipid + where f.start_ts >= $leftNs + and end_ts <= $rightNs + group by f.type, f.ipid; +`, {$leftNs:leftNs,$rightNs:rightNs}); + +export const getTabPaneFilesystemStatisticsAll = (leftNs: number, rightNs: number): Promise> => + query("getTabPaneFilesystemStatisticsAll", ` + select SUM(dur) as allDuration, + count(type) as count, + min(dur) as minDuration, + max(dur) as maxDuration, + round(avg(dur),2) as avgDuration, + type + from file_system_sample + where start_ts >= $leftNs + and end_ts <= $rightNs; +`, {$leftNs:leftNs,$rightNs:rightNs}); + +export const getTabPaneFilesystemStatistics = (leftNs: number, rightNs: number,types:number[]): Promise> => + query("getTabPaneFilesystemStatistics", ` + select p.pid, + ifnull(p.name,'Process') as name, + f.type, + count(f.ipid) as count, + sum(ifnull(size,0)) as size, + sum(case when f.type = 2 then ifnull(size,0) else 0 end) as logicalReads, + sum(case when f.type = 3 then ifnull(size,0) else 0 end) as logicalWrites, + sum(case when f.type != 2 and f.type != 3 then ifnull(size,0) else 0 end) as otherFile, + sum(dur) as allDuration, + min(dur) as minDuration, + max(dur) as maxDuration, + avg(dur) as avgDuration + from file_system_sample as f left join process as p on f.ipid=p.ipid + where end_ts >= $leftNs + and end_ts <= $rightNs + and f.type in (${types.join(",")}) + group by f.type,f.ipid + order by f.type; +`, {$leftNs:leftNs,$rightNs:rightNs}); + +export const getTabPaneVirtualMemoryStatisticsData = (leftNs: number, rightNs: number): Promise> => + query("getTabPaneVirtualMemoryStatisticsData", ` + select p.pid, + t.tid, + ifnull(p.name,'Process') as pname, + ifnull(t.name,'Thread') as tname, + f.type, + f.ipid, + f.itid, + count(f.ipid) as count, + sum(dur) as allDuration, + min(dur) as minDuration, + max(dur) as maxDuration, + avg(dur) as avgDuration + from paged_memory_sample as f left join process as p on f.ipid=p.ipid left join thread as t on f.itid=t.itid + where f.end_ts >= $leftNs + and f.end_ts <= $rightNs + group by f.type,f.ipid,f.itid + order by f.type; +`, {$leftNs:leftNs,$rightNs:rightNs}); + +export const getTabPaneIOTierStatisticsData = (leftNs: number, rightNs: number, diskIOipids:Array): Promise> =>{ + let str = ""; + if (diskIOipids.length > 0) { + str = ` and i.ipid in (${diskIOipids.join(",")})`; + } + return query("getTabPaneIOTierStatisticsData", ` + select p.pid, + ifnull(p.name,'Process') as pname, + i.tier, + i.ipid, + path_id as path, + count(i.ipid) as count, + sum(latency_dur) as allDuration, + min(latency_dur) as minDuration, + max(latency_dur) as maxDuration, + avg(latency_dur) as avgDuration + from bio_latency_sample as i left join process as p on i.ipid=p.ipid + where i.start_ts+latency_dur >= $leftNs + and i.start_ts+latency_dur <= $rightNs + ${str} + group by i.tier,i.ipid,i.path_id + order by i.tier; +`, {$leftNs:leftNs,$rightNs:rightNs}) +}; + +export const getTabPaneCounterSampleData = (leftNs: number, rightNs: number, cpuStateFilterIds: Array): Promise> =>{ + let str = ""; + if (cpuStateFilterIds.length > 0) { + str = ` and filter_id in (${cpuStateFilterIds.join(",")})`; + } + return query("getTabPaneCounterSampleData", ` + select value, filter_id as filterId, ts, f.cpu + from measure left join cpu_measure_filter as f on f.id=filter_id + where + ts <= $rightNs${str} order by ts asc; +`, {$leftNs:leftNs,$rightNs:rightNs}) +}; + +export const getTabPaneFrequencySampleData = (leftNs: number, rightNs: number, cpuFreqFilterIds: Array): Promise> =>{ + let str = ""; + if (cpuFreqFilterIds.length > 0) { + str = ` and filter_id in (${cpuFreqFilterIds.join(",")})`; + } + return query("getTabPaneFrequencySampleData", ` + select value, filter_id as filterId, ts, f.cpu + from measure left join cpu_measure_filter as f on f.id=filter_id + where + ts <= $rightNs${str} order by ts asc; +`, {$leftNs:leftNs,$rightNs:rightNs}) +}; + +export const hasFileSysData = () : Promise> => + query("hasFileSysData",` select - count(*) as count - from native_hook_frame `, - {}) - -export const queryNativeHookStatistics = (leftNs:number,rightNs:number): Promise> => - query("queryNativeHookStatistics",` - select event_type as eventType,sub_type as subType,max(all_heap_size) as max,sum(heap_size) as sumHeapSize,count(event_type) as count -from native_hook A,trace_range B -where (A.start_ts - B.start_ts) between ${leftNs} and ${rightNs} ---not ((A.start_ts - B.start_ts + ifnull(A.dur,0)) < ${leftNs} or (A.start_ts - B.start_ts) > ${rightNs}) -group by event_type, sub_type`,{$leftNs:leftNs,$rightNs:rightNs}) - -export const queryNativeHookStatisticsMalloc = (leftNs:number,rightNs:number):Promise> => - query('queryNativeHookStatisticsMalloc', - `select event_type as eventType, - heap_size as heapSize, - sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then heap_size else 0 end) as allocByte, - sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then 1 else 0 end) as allocCount, - sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then heap_size else 0 end) as freeByte, - sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then 1 else 0 end) as freeCount -from native_hook A,trace_range B -where ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs} - or (A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) - and (event_type = 'AllocEvent') -group by event_type,heap_size; - `,{$leftNs:leftNs,$rightNs:rightNs}) - -export const queryNativeHookStatisticsSubType = (leftNs:number,rightNs:number):Promise> => - query('queryNativeHookStatisticsSubType', - `select event_type as eventType, - sub_type as subType, - max(heap_size) as heapSize, - sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then heap_size else 0 end) as allocByte, - sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then 1 else 0 end) as allocCount, - sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then heap_size else 0 end) as freeByte, - sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then 1 else 0 end) as freeCount -from native_hook A,trace_range B -where ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs} - or (A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) - and (event_type = 'MmapEvent') -group by event_type,sub_type; - `,{$leftNs:leftNs,$rightNs:rightNs}) - -export const queryNativeHookEventId = (leftNs:number,rightNs:number,types:Array): Promise> => - query("queryNativeHookEventId",` - select eventId,event_type as eventType,sub_type as subType,heap_size as heapSize,addr,(A.start_ts - B.start_ts) as startTs,(A.end_ts - B.start_ts) as endTs -from native_hook A, trace_range B -where A.start_ts - B.start_ts between ${leftNs} and ${rightNs} and A.event_type in (${types.join(",")})`,{$leftNs:leftNs,$rightNs:rightNs,$types:types}) - -export const queryNativeHookEventTid = (leftNs:number,rightNs:number,types:Array): Promise> => - query("queryNativeHookEventTid",` - select eventId, - event_type as eventType, - sub_type as subType, - heap_size as heapSize, - addr, - (A.start_ts - B.start_ts) as startTs, - (A.end_ts - B.start_ts) as endTs, - tid -from native_hook A, trace_range B -left join thread t on A.itid = t.id -where A.start_ts - B.start_ts between ${leftNs} and ${rightNs} and A.event_type in (${types.join(",")})`,{$leftNs:leftNs,$rightNs:rightNs,$types:types}) - -export const queryNativeHookProcess = ():Promise> => - query("queryNativeHookProcess",`select distinct ipid,pid,name from native_hook left join process p on native_hook.ipid = p.id`,{}) - -export const queryNativeHookSnapshot = (rightNs:number):Promise> => - query("queryNativeHookSnapshot",`select event_type as eventType,sub_type as subType,sum(heap_size) as growth,count(*) as existing from native_hook n, trace_range t -where (event_type = 'AllocEvent' or event_type = 'MmapEvent') - and n.start_ts between 0 and ${rightNs} + t.start_ts - and n.end_ts > ${rightNs} + t.start_ts -group by event_type,sub_type`,{$rightNs:rightNs}) - -export const queryNativeHookSnapshotTypes = ():Promise> => - query("queryNativeHookSnapshotTypes",`select event_type as eventType,sub_type as subType from native_hook where (event_type = 'AllocEvent' or event_type = 'MmapEvent') group by event_type,sub_type;`,{}) - -export const queryAllHookData = (rightNs:number):Promise> => - query("queryAllHookData",`select eventId,event_type as eventType,sub_type as subType,addr,heap_size as growth,(n.start_ts - t.start_ts) as startTs,(n.end_ts - t.start_ts) as endTs from native_hook n, trace_range t -where (event_type = 'AllocEvent' or event_type = 'MmapEvent') - and n.start_ts between t.start_ts and ${rightNs} + t.start_ts`,{$rightNs:rightNs}) \ No newline at end of file + fsCount, + vmCount, + ioCount from + (select count(1) as fsCount from file_system_sample s,trace_range t where (s.start_ts between t.start_ts and t.end_ts) or (s.end_ts between t.start_ts and t.end_ts) ) + ,(select count(1) as vmCount from paged_memory_sample s,trace_range t where (s.start_ts between t.start_ts and t.end_ts) or (s.end_ts between t.start_ts and t.end_ts) ) + ,(select count(1) as ioCount from bio_latency_sample s,trace_range t where (s.start_ts between t.start_ts and t.end_ts) or (s.end_ts between t.start_ts and t.end_ts) ); + `,{}) + +export const getFileSysChartDataByType = (type:number) : Promise> => + query("getFileSysChartData",` + select + (A.start_ts -B.start_ts) as startNS, + (A.end_ts - B.start_ts) as endNS, + dur + from file_system_sample A,trace_range B + where type = $type and startNS > 0;`,{$type:type},"exec") + +export const getFileSysVirtualMemoryChartData = () : Promise> => + query("getFileSysVirtualMemoryChartData",` + select + (A.start_ts -B.start_ts) as startNS, + (A.end_ts - B.start_ts) as endNS, + dur as dur + from paged_memory_sample A,trace_range B + where startNS > 0 + order by A.start_ts;`,{},"exec") + +export const getDiskIOProcess = () : Promise> => + query("getDiskIOProcess",` + select name,B.ipid,pid + from (select distinct ipid from bio_latency_sample A,trace_range B where A.start_ts between B.start_ts and B.end_ts) A + left join process B on A.ipid = B.ipid;`,{}) + +export const getDiskIOLatencyChartDataByProcess = (all:boolean,ipid:number,typeArr:Array) : Promise> => + query("getDiskIOLatencyChartDataByProcess",` + select + (A.start_ts -B.start_ts) as startNS, + (A.start_ts - B.start_ts + A.latency_dur) as endNS, + latency_dur as dur + from bio_latency_sample A,trace_range B + where type in (${typeArr.join(",")}) and startNS > 0 + ${ all ? '' : 'and ipid = ' + ipid } + order by A.start_ts;`,{},"exec") + +export const querySdkCount = (sql:string, componentId:number, args?: any): Promise> => + query("querySdkCount", sql,args,"exec-sdk-" + componentId) + +export const querySdkCounterData = (sql:string, counter_id:number, componentId:number): Promise> => + query("querySdkCounterData", sql,{$counter_id:counter_id}, "exec-sdk-" + componentId) + +export const getTabSdkCounterData = (sqlStr: string, startTime: number, leftNs: number, rightNs: number, counters: Array, componentId: number): Promise> => + query("getTabSdkCounterData", sqlStr, { + $startTime:startTime, + $leftNs: leftNs, + $rightNs: rightNs, + $counters:counters + },"exec-sdk-" + componentId) + + +export const getTabSdkCounterLeftData = (sqlStr: string, leftNs: number, counters: Array, componentId: number): Promise> => + query("getTabSdkCounterLeftData", sqlStr, { + $leftNs: leftNs, + $counters:counters + },"exec-sdk-" + componentId) + +export const getTabSdkSliceData = (sqlStr: string, startTime:number, leftNs: number, rightNs: number, slices: Array,componentId: number): Promise> => + query("getTabSdkSliceData", sqlStr, { + $startTime:startTime, + $leftNs: leftNs, + $rightNs: rightNs, + $slices: slices + },"exec-sdk-" + componentId) + +export const querySdkSliceData = (sqlStr:string, column_id: number, startNS: number, endNS: number, componentId:number): Promise> => + query("querySdkSliceData", sqlStr, {$column_id: column_id, $startNS: startNS, $endNS: endNS},"exec-sdk-" + componentId) + +export const queryCounterMax = (sqlStr:string, counter_id:number, componentId:number): Promise> => + query("queryCounterMax", sqlStr,{$counter_id:counter_id}, "exec-sdk-" + componentId) + +export const queryAnomalyData = (): Promise> => + query("queryAnomalyData", `select + (S.ts - TR.start_ts) as startNS, + D.data as eventName, + D2.data as appKey, + (case when S.type==1 then group_concat(S.string_value,',') else group_concat(S.int_value,',') end) as Value + from trace_range AS TR,hisys_event_measure as S + left join data_dict as D on D.id=S.name_id + left join app_name as APP on APP.id=S.key_id + left join data_dict as D2 on D2.id=APP.app_key + where D.data in ('ANOMALY_SCREEN_OFF_ENERGY','ANOMALY_KERNEL_WAKELOCK','ANOMALY_CPU_HIGH_FREQUENCY','ANOMALY_WAKEUP') + or (D.data in ('ANOMALY_RUNNINGLOCK','ANORMALY_APP_ENERGY','ANOMALY_GNSS_ENERGY','ANOMALY_CPU_ENERGY','ANOMALY_ALARM_WAKEUP') and D2.data in ("APPNAME")) + group by S.serial,D.data`) + +export const querySystemLocationData = (): Promise> => + query("querySystemLocationData", `SELECT + ( S.ts - TR.start_ts ) AS ts, + D.data AS eventName, + D2.data AS appKey, + group_concat( ( CASE WHEN S.type == 1 THEN S.string_value ELSE S.int_value END ), ',' ) AS Value + FROM + trace_range AS TR, + hisys_event_measure AS S + LEFT JOIN data_dict AS D ON D.id = S.name_id + LEFT JOIN app_name AS APP ON APP.id = S.key_id + LEFT JOIN data_dict AS D2 ON D2.id = APP.app_key + WHERE + D.data = 'GNSS_STATE' AND D2.data = 'STATE' + GROUP BY + S.serial, + APP.app_key, + D.data, + D2.data;`) + + +export const querySystemLockData = (): Promise> => + query("querySystemLockData", `SELECT + ( S.ts - TR.start_ts ) AS ts, + D.data AS eventName, + D2.data AS appKey, + group_concat(( CASE WHEN S.type == 1 THEN S.string_value ELSE S.int_value END ), ',' ) AS Value + FROM + trace_range AS TR, + hisys_event_measure AS S + LEFT JOIN data_dict AS D ON D.id = S.name_id + LEFT JOIN app_name AS APP ON APP.id = S.key_id + LEFT JOIN data_dict AS D2 ON D2.id = APP.app_key + WHERE + ( D.data = 'POWER_RUNNINGLOCK' AND D2.data in ('TAG','MESSAGE')) + GROUP BY + S.serial;`) + +export const querySystemSchedulerData = (): Promise> => + query("querySystemSchedulerData", `SELECT + ( S.ts - TR.start_ts ) AS startNs, + D.data AS eventName, + group_concat(D2.data, ',') AS appKey, + group_concat( ( CASE WHEN S.type == 1 THEN S.string_value ELSE S.int_value END ), ',' ) AS Value + FROM + trace_range AS TR, + hisys_event_measure AS S + LEFT JOIN data_dict AS D ON D.id = S.name_id + LEFT JOIN app_name AS APP ON APP.id = S.key_id + LEFT JOIN data_dict AS D2 ON D2.id = APP.app_key + WHERE + D.data IN ( 'WORK_REMOVE', 'WORK_STOP', 'WORK_ADD' ) AND D2.data in ('NAME','TYPE','WORKID') + GROUP BY + S.serial;`) + +export const querySystemDetailsData = (rightNs: number, eventName: string): Promise> => + query("querySystemDetailsData", `SELECT + ( S.ts - TR.start_ts ) AS ts, + D.data AS eventName, + D2.data AS appKey, + group_concat( ( CASE WHEN S.type == 1 THEN S.string_value ELSE S.int_value END ), ',' ) AS appValue + FROM + trace_range AS TR, + hisys_event_measure AS S + LEFT JOIN data_dict AS D ON D.id = S.name_id + LEFT JOIN app_name AS APP ON APP.id = S.key_id + LEFT JOIN data_dict AS D2 ON D2.id = APP.app_key + WHERE + D.data in ($eventName) + and + D2.data in ('UID', 'TYPE', 'WORKID', 'NAME', 'INTERVAL', 'TAG', 'STATE', 'STACK', 'APPNAME', 'MESSAGE', 'PID', 'LOG_LEVEL') + and (S.ts - TR.start_ts) <= $rightNS + GROUP BY + S.serial, + APP.app_key, + D.data, + D2.data;`, {$rightNS: rightNs, $eventName: eventName}) + +export const querySystemWorkData = (rightNs: number): Promise> => + query("querySystemWorkData", `SELECT + ( S.ts - TR.start_ts ) AS ts, + D.data AS eventName, + D2.data AS appKey, + group_concat( ( CASE WHEN S.type == 1 THEN S.string_value ELSE S.int_value END ), ',' ) AS appValue + FROM + trace_range AS TR, + hisys_event_measure AS S + LEFT JOIN data_dict AS D ON D.id = S.name_id + LEFT JOIN app_name AS APP ON APP.id = S.key_id + LEFT JOIN data_dict AS D2 ON D2.id = APP.app_key + WHERE + D.data in ("WORK_REMOVE", "WORK_STOP", "WORK_ADD", "WORK_START") + and + D2.data in ('UID', 'TYPE', 'WORKID', 'NAME', 'INTERVAL', 'TAG', 'STATE', 'STACK', 'APPNAME', 'MESSAGE', 'PID', 'LOG_LEVEL') + and (S.ts - TR.start_ts) <= $rightNS + GROUP BY + S.serial, + APP.app_key, + D.data, + D2.data;`, {$rightNS: rightNs}) + +export const queryMaxPowerValue = (appName: string): Promise> => + query("queryMaxPowerValue", `SELECT + max( item ) AS maxValue + FROM + ( + SELECT + sum( energy + background_energy + screen_on_energy + screen_off_energy + foreground_energy ) AS item + FROM + energy + WHERE + app_name = $appName + GROUP BY + startNs);`, {$appName: appName}) + +export const queryPowerData = (): Promise> => + query("queryPowerData", `SELECT + ( S.ts - TR.start_ts ) AS startNS, + D.data AS eventName, + D2.data AS appKey, + group_concat( ( CASE WHEN S.type == 1 THEN S.string_value ELSE S.int_value END ), ',' ) AS eventValue + FROM + trace_range AS TR, + hisys_event_measure AS S + LEFT JOIN data_dict AS D ON D.id = S.name_id + LEFT JOIN app_name AS APP ON APP.id = S.key_id + LEFT JOIN data_dict AS D2 ON D2.id = APP.app_key + where + D.data in ('POWER_IDE_CPU','POWER_IDE_LOCATION','POWER_IDE_GPU','POWER_IDE_DISPLAY','POWER_IDE_CAMERA','POWER_IDE_BLUETOOTH','POWER_IDE_FLASHLIGHT','POWER_IDE_AUDIO','POWER_IDE_WIFISCAN') + and + D2.data in ('BACKGROUND_ENERGY','FOREGROUND_ENERGY','SCREEN_ON_ENERGY','SCREEN_OFF_ENERGY','ENERGY','APPNAME') + GROUP BY + S.serial, + APP.app_key, + D.data, + D2.data + ORDER BY + eventName;`,{}) + +export const getTabPowerDetailsData = (leftNs: number, rightNs: number): Promise> => + query("getTabPowerDetailsData", `SELECT + ( S.ts - TR.start_ts ) AS startNS, + D.data AS eventName, + D2.data AS appKey, + group_concat( ( CASE WHEN S.type == 1 THEN S.string_value ELSE S.int_value END ), ',' ) AS eventValue + FROM + trace_range AS TR, + hisys_event_measure AS S + LEFT JOIN data_dict AS D ON D.id = S.name_id + LEFT JOIN app_name AS APP ON APP.id = S.key_id + LEFT JOIN data_dict AS D2 ON D2.id = APP.app_key + where + D.data in ('POWER_IDE_CPU','POWER_IDE_LOCATION','POWER_IDE_GPU','POWER_IDE_DISPLAY','POWER_IDE_CAMERA','POWER_IDE_BLUETOOTH','POWER_IDE_FLASHLIGHT','POWER_IDE_AUDIO','POWER_IDE_WIFISCAN') + and + D2.data in ('APPNAME') + GROUP BY + S.serial, + APP.app_key, + D.data, + D2.data + UNION + SELECT + ( S.ts - TR.start_ts ) AS startNS, + D.data AS eventName, + D2.data AS appKey, + group_concat( ( CASE WHEN S.type == 1 THEN S.string_value ELSE S.int_value END ), ',' ) AS eventValue + FROM + trace_range AS TR, + hisys_event_measure AS S + LEFT JOIN data_dict AS D ON D.id = S.name_id + LEFT JOIN app_name AS APP ON APP.id = S.key_id + LEFT JOIN data_dict AS D2 ON D2.id = APP.app_key + where + D.data in ('POWER_IDE_CPU','POWER_IDE_LOCATION','POWER_IDE_GPU','POWER_IDE_DISPLAY','POWER_IDE_CAMERA','POWER_IDE_BLUETOOTH','POWER_IDE_FLASHLIGHT','POWER_IDE_AUDIO','POWER_IDE_WIFISCAN') + and + D2.data in ('CHARGE','BACKGROUND_TIME','SCREEN_ON_TIME','SCREEN_OFF_TIME','LOAD','USAGE','DURATION','CAMERA_ID', + 'FOREGROUND_COUNT','BACKGROUND_COUNT','SCREEN_ON_COUNT','SCREEN_OFF_COUNT','COUNT','UID','FOREGROUND_DURATION', + 'FOREGROUND_ENERGY','BACKGROUND_DURATION','BACKGROUND_ENERGY','SCREEN_ON_DURATION','SCREEN_ON_ENERGY', + 'SCREEN_OFF_DURATION','SCREEN_OFF_ENERGY','ENERGY') + and + (S.ts - TR.start_ts) >= $leftNS + and (S.ts - TR.start_ts) <= $rightNS + GROUP BY + S.serial, + APP.app_key, + D.data, + D2.data + ORDER BY + eventName;`, {$leftNS: leftNs, $rightNS: rightNs}) + +export const getTabPowerBatteryData = (rightNs: number): Promise> => + query("getTabPowerBatteryData", `select + MAX(S.ts) as ts, + D.data as eventName, + D2.data as appKey, + group_concat((case when S.type==1 then S.string_value else S.int_value end), ',') as eventValue + from + trace_range AS TR, + hisys_event_measure as S + left join + data_dict as D + on + D.id=S.name_id + left join + app_name as APP + on + APP.id=S.key_id + left join + data_dict as D2 + on + D2.id=APP.app_key + where + D.data = 'POWER_IDE_BATTERY' + and D2.data in ('GAS_GAUGE','CHARGE','SCREEN','LEVEL','CURRENT','CAPACITY','UID') + and (S.ts - TR.start_ts) >= 0 + and (S.ts - TR.start_ts) <= $rightNS + group by APP.app_key,D.data,D2.data;`, {$rightNS: rightNs}) + +export const queryMaxStateValue = (eventName: string): Promise> => + query("queryMaxStateValue", `select + D.data as type, + max(S.int_value) as maxValue + from trace_range AS TR,hisys_event_measure as S + left join data_dict as D on D.id=S.name_id + left join app_name as APP on APP.id=S.key_id + left join data_dict as D2 on D2.id=APP.app_key + where (case when 'SENSOR_STATE'==$eventName then D.data like '%SENSOR%' else D.data = $eventName end) + and D2.data in ('BRIGHTNESS','STATE','VALUE','LEVEL','VOLUME','OPER_TYPE','VOLUME') + group by APP.app_key,D.data,D2.data;`, {$eventName: eventName}) + +export const queryStateData = (eventName: string): Promise> => + query("queryStateData", `select + (S.ts-TR.start_ts) as startNs, + D.data as type, + D2.data as appKey, + S.int_value as value + from trace_range AS TR,hisys_event_measure as S + left join data_dict as D on D.id=S.name_id + left join app_name as APP on APP.id=S.key_id + left join data_dict as D2 on D2.id=APP.app_key + where (case when 'SENSOR_STATE'==$eventName then D.data like '%SENSOR%' else D.data = $eventName end) + and D2.data in ('BRIGHTNESS','STATE','VALUE','LEVEL','VOLUME','OPER_TYPE','VOLUME') + group by S.serial,APP.app_key,D.data,D2.data;`, {$eventName: eventName}) + +export const querySyseventAppName = (): Promise> => + query("querySyseventAppName", ` + SELECT + DISTINCT hisys_event_measure.string_value from data_dict + left join app_name on app_name.app_key=data_dict.id + left join hisys_event_measure on hisys_event_measure.key_id = app_name.id + where data_dict.data = "APPNAME"`) + +export const queryAnomalyDetailedData = (leftNs: number, rightNs: number): Promise> => + query("queryAnomalyDetailedData", `select + S.ts, + D.data as eventName, + D2.data as appKey, + group_concat((case when S.type==1 then S.string_value else S.int_value end), ',') as Value + from trace_range AS TR,hisys_event_measure as S + left join data_dict as D on D.id=S.name_id + left join app_name as APP on APP.id=S.key_id + left join data_dict as D2 on D2.id=APP.app_key + where D.data in ('ANOMALY_SCREEN_OFF_ENERGY','ANOMALY_ALARM_WAKEUP','ANOMALY_KERNEL_WAKELOCK', + 'ANOMALY_RUNNINGLOCK','ANORMALY_APP_ENERGY','ANOMALY_GNSS_ENERGY','ANOMALY_CPU_HIGH_FREQUENCY','ANOMALY_CPU_ENERGY','ANOMALY_WAKEUP') + and D2.data in ('APPNAME') + and (S.ts - TR.start_ts) >= $leftNS + and (S.ts - TR.start_ts) <= $rightNS + group by S.serial,APP.app_key,D.data,D2.data + union + select + S.ts, + D.data as eventName, + D2.data as appKey, + group_concat((case when S.type==1 then S.string_value else S.int_value end), ',') as Value + from trace_range AS TR,hisys_event_measure as S + left join data_dict as D on D.id=S.name_id + left join app_name as APP on APP.id=S.key_id + left join data_dict as D2 on D2.id=APP.app_key + where D.data in ('ANOMALY_SCREEN_OFF_ENERGY','ANOMALY_ALARM_WAKEUP','ANOMALY_KERNEL_WAKELOCK', + 'ANOMALY_RUNNINGLOCK','ANORMALY_APP_ENERGY','ANOMALY_GNSS_ENERGY','ANOMALY_CPU_HIGH_FREQUENCY','ANOMALY_CPU_ENERGY','ANOMALY_WAKEUP') + and D2.data not in ('pid_','tid_','type_','tz_','uid_','domain_', 'id_', 'level_', 'info_', 'tag_', 'APPNAME') + and (S.ts - TR.start_ts) >= $leftNS + and (S.ts - TR.start_ts) <= $rightNS + group by S.serial,APP.app_key,D.data,D2.data;`, {$leftNS: leftNs, $rightNS: rightNs}) + +export const querySmapsExits = (): Promise> => + query("querySmapsExits", `select + event_name + from stat s + where s.event_name = 'trace_smaps' + and s.stat_type ='received' and s.count > 0`) + +export const querySmapsData = (columnName: string): Promise> => + query("querySmapsCounterData", + `SELECT (A.timestamp - B.start_ts) as startNS, sum(${columnName}) as value FROM smaps A,trace_range B GROUP by A.timestamp;`) + +export const querySmapsDataMax = (columnName: string): Promise> => + query("querySmapsDataMax", ` + SELECT (A.timestamp - B.start_ts) as startNS,sum(${columnName}) as max_value FROM smaps A,trace_range B GROUP by A.timestamp order by max_value desc LIMIT 1`) + +export const getTabSmapsMaxRss = (leftNs: number, rightNs: number): Promise> => + query("getTabSmapsMaxRss", ` +SELECT (A.timestamp - B.start_ts) as startNS, sum(resident_size) as max_value FROM smaps A,trace_range B where startNS <= $rightNs`, {$rightNs:rightNs}) + +export const getTabSmapsData = (leftNs: number, rightNs: number): Promise> => + query("getTabSmapsData", ` + SELECT + (A.timestamp - t.start_ts) AS tsNS, + start_addr, + end_addr, + dirty, + swapper, + resident_size AS rss, + pss,virtaul_size AS size,reside,f.data AS permission,d.data AS path + FROM smaps A + LEFT JOIN data_dict d ON a.path_id = d.id LEFT + JOIN data_dict f ON a.protection_id = f.id, + trace_range AS t + WHERE tsNS <= $rightNs`, {$rightNs : rightNs},"exec") + +export const getTabVirtualMemoryType = (startTime: number, endTime: number): Promise> => + query("getTabVirtualMemoryType", ` + SELECT type from paged_memory_sample s,trace_range t + WHERE s.end_ts between $startTime + t.start_ts and $endTime + t.start_ts group by type`, {$startTime : startTime,$endTime:endTime},"exec") + +export const getTabIoCompletionTimesType = (startTime: number, endTime: number): Promise> => + query("getTabIoCompletionTimesType", ` + SELECT tier from bio_latency_sample s,trace_range t + WHERE s.start_ts + s.latency_dur between $startTime + t.start_ts and $endTime + t.start_ts group by tier`, {$startTime : startTime,$endTime:endTime},"exec") + +export const getCpuLimitFreqId = (): Promise> => + query("getCpuMaxMinFreqId", ` + select cpu,MAX(iif(name = 'cpu_frequency_limits_max',id,0)) as maxFilterId,MAX(iif(name = 'cpu_frequency_limits_min',id,0)) as minFilterId from cpu_measure_filter where name in ('cpu_frequency_limits_max','cpu_frequency_limits_min') group by cpu +`, {}) + +export const getCpuLimitFreqMax = (filterIds:string): Promise> =>{ + return query("getCpuLimitFreqMax", ` + select max(value) as maxValue,filter_id as filterId from measure where filter_id in (${filterIds}) group by filter_id +`, {}) +} + +export const getCpuLimitFreq = (maxId: number, minId: number,cpu:number): Promise> => + query("getCpuLimitFreq", ` + select ts - T.start_ts as startNs,max(value) as max,min(value) as min,$cpu as cpu from measure,trace_range T where filter_id in ($maxId,$minId) group by ts +`, {$maxId : maxId,$minId : minId,$cpu : cpu}) + +export const queryHisystemEventExits = (): Promise> => + query("queryHisystemEventExits", `select + event_name + from stat s + where s.event_name = 'trace_hisys_event' + and s.stat_type ='received' and s.count > 0`) + +export const queryEbpfSamplesCount = (startTime: number, endTime: number,ipids:number[]): Promise> => + query("queryEbpfSamplesCount", ` + select +fsCount, + vmCount from +(select count(1) as fsCount from file_system_sample s,trace_range t where s.end_ts between $startTime + t.start_ts and $endTime + t.start_ts ${ipids.length>0?`and s.ipid in (${ipids.join(",")})`:""}) +,(select count(1) as vmCount from paged_memory_sample s,trace_range t where s.end_ts between $startTime + t.start_ts and $endTime + t.start_ts ${ipids.length>0?`and s.ipid in (${ipids.join(",")})`:""}); +`, {$startTime : startTime,$endTime : endTime}); + +export const querySysLockDetailsData = (rightNs: number, eventName: string): Promise> => + query("querySysLockDetailsData", `SELECT + ( S.ts - TR.start_ts ) AS ts, + D.data AS eventName, + D2.data AS appKey, + group_concat( ( CASE WHEN S.type == 1 THEN S.string_value ELSE S.int_value END ), ',' ) AS appValue + FROM + trace_range AS TR, + hisys_event_measure AS S + LEFT JOIN data_dict AS D ON D.id = S.name_id + LEFT JOIN app_name AS APP ON APP.id = S.key_id + LEFT JOIN data_dict AS D2 ON D2.id = APP.app_key + WHERE + D.data in ($eventName) + and + D2.data in ('UID', 'TYPE', 'WORKID', 'NAME', 'INTERVAL', 'TAG', 'STATE', 'STACK', 'APPNAME', 'MESSAGE', 'PID', 'LOG_LEVEL') + and (S.ts - TR.start_ts) <= $rightNS + GROUP BY + S.serial, + APP.app_key, + D.data, + D2.data;`, {$rightNS: rightNs, $eventName: eventName}) + + +export const queryStateInitValue = (eventName: string, keyName: string): Promise> => + query("queryStateInitValue", `select + 0 as startNs, + $eventName as type, + '' as appKey, + (case $keyName + when 'brightness' then device_state.brightness + when 'wifi' then device_state.wifi + when 'bt_state' then device_state.bt_state + when 'location' then device_state.location + else 0 end) as value + from device_state;`, {$eventName: eventName, $keyName: keyName}) + +export const querySysLocationDetailsData = (rightNs: number, eventName: string): Promise> => + query("querySysLocationDetailsData", `SELECT + ( S.ts - TR.start_ts ) AS ts, + D.data AS eventName, + D2.data AS appKey, + group_concat( ( CASE WHEN S.type == 1 THEN S.string_value ELSE S.int_value END ), ',' ) AS appValue + FROM + trace_range AS TR, + hisys_event_measure AS S + LEFT JOIN data_dict AS D ON D.id = S.name_id + LEFT JOIN app_name AS APP ON APP.id = S.key_id + LEFT JOIN data_dict AS D2 ON D2.id = APP.app_key + WHERE + D.data in ($eventName) + and + D2.data in ('UID', 'TYPE', 'WORKID', 'NAME', 'INTERVAL', 'TAG', 'STATE', 'STACK', 'APPNAME', 'MESSAGE', 'PID', 'LOG_LEVEL') + and (S.ts - TR.start_ts) <= $rightNS + GROUP BY + S.serial, + APP.app_key, + D.data, + D2.data;`, {$rightNS: rightNs, $eventName: eventName}) +export const queryNativeMemoryRealTime = (): Promise> => + query("queryNativeMemoryRealTime",`select cs.ts,cs.clock_name from datasource_clockid dc left join clock_snapshot cs on dc.clock_id = cs.clock_id where data_source_name = 'memory-plugin' or data_source_name = 'nativehook' +`,{}) + +export const queryBootTime = (): Promise> => + query("queryBootTime",`select ts,clock_name from clock_snapshot where clock_name = 'boottime' +`,{}) + +export const queryConfigSysEventAppName = (): Promise> => + query("queryConfigSysEventAppName", ` + SELECT value from trace_config where trace_source = 'hisys_event' and key = 'process_name'`) diff --git a/host/ide/src/trace/database/SqlLiteWorker.ts b/host/ide/src/trace/database/SqlLiteWorker.ts index f39a1d2fcbb29c3acf4406c524f3c4383cac0be9..57ad8810a3d912688aaaee278a059a9201b32160 100644 --- a/host/ide/src/trace/database/SqlLiteWorker.ts +++ b/host/ide/src/trace/database/SqlLiteWorker.ts @@ -15,7 +15,7 @@ importScripts('sql-wasm.js', "TempSql.js"); let conn: any = null; - +let encoder = new TextEncoder(); function initIndexedDB() { return new Promise((resolve, reject) => { let request = indexedDB.open("systrace"); @@ -63,6 +63,20 @@ function deleteConnection(store: IDBObjectStore, id: number) { }) } +let mergedUnitArray = (bufferSlice:Array)=>{ + let length = 0; + bufferSlice.forEach(item => { + length += item.length; + }); + let mergedArray = new Uint8Array(length); + let offset = 0; + bufferSlice.forEach(item => { + mergedArray.set(item, offset); + offset += item.length; + }); + return mergedArray; +} + self.onerror = function (error) { } @@ -84,7 +98,7 @@ self.onmessage = async (e: any) => { self.postMessage({id: e.data.id, init: true}); }); } else if (e.data.action === "close") { - } else if (e.data.action === "exec") { + } else if (e.data.action === "exec"||e.data.action === "exec-buf") { try { let action = e.data.action; //: "exec" let sql = e.data.sql; diff --git a/host/ide/src/trace/database/TempSql.ts b/host/ide/src/trace/database/TempSql.ts index a04efb3e417a807ccc651392d55c947ccf305923..67a3cf419b1827c105d3a6b442be621ab2a00e45 100644 --- a/host/ide/src/trace/database/TempSql.ts +++ b/host/ide/src/trace/database/TempSql.ts @@ -13,28 +13,30 @@ * limitations under the License. */ -let temp_query_process = `create table temp_query_process as select - distinct process_view.pid as pid, - process_view.name as processName -from ( - select ipid, itid from sched_slice join thread_view using(itid) group by itid -) the_tracks -left join (select ipid, sum(dur) as total_dur - from sched_view join thread_view using(itid) - group by ipid -) using(ipid) -left join process_view using(ipid) -where pid is not null -order by - total_dur desc, - the_tracks.ipid, - processName, - the_tracks.itid; +let temp_query_process = `create table temp_query_process as + select + distinct process.pid as pid, + process.name as processName + from ( + select ipid,itid from sched_slice group by itid + ) the_tracks + left join + (select sched_slice.ipid, sum(dur) as total_dur from sched_slice group by ipid) using(ipid) + left join + process using(ipid) + where + pid is not null + order by + total_dur desc, + the_tracks.ipid, + processName, + the_tracks.itid; ` let temp_query_cpu_data = `create table temp_query_cpu_data as with list as (SELECT IP.name as processName, IP.name processCmdLine, - IP.pid as processId,B.cpu, + IP.pid as processId, + B.cpu, A.name, C.id as schedId, A.tid, @@ -47,7 +49,7 @@ let temp_query_cpu_data = `create table temp_query_cpu_data as with list as (SEL from thread_state AS B left join thread as A on B.itid = A.id left join sched_slice AS C on B.itid = C.itid and B.ts = C.ts - left join trace_section AS TR + left join trace_range AS TR left join process AS IP on A.ipid = IP.id where C.itid is not null order by B.id) @@ -56,18 +58,35 @@ create index temp_query_cpu_data_idx on temp_query_cpu_data(cpu,startTime); ` let temp_query_freq_data = `create table temp_query_freq_data as select cpu,value,ts-tb.start_ts as startNS -from measure c ,trace_section tb +from measure c ,trace_range tb inner join cpu_measure_filter t on c.filter_id = t.id where (name = 'cpufreq' or name='cpu_frequency') order by ts; create index temp_query_freq_data_idx on temp_query_freq_data(cpu); ` -let temp_query_process_data = `create table temp_query_process_data as select ta.id,type, ts, dur, ta.cpu, itid as utid, state - ,ts-tb.start_ts as startTime,tc.tid,tc.pid,tc.process,tc.thread -from thread_state ta,trace_section tb +let temp_query_process_data = `create table temp_query_process_data as +select ta.id, + type, + ts, + dur, + ta.cpu, + itid as utid, + state, + ts-tb.start_ts as startTime, + tc.tid, + tc.pid, + tc.process, + tc.thread +from thread_state ta,trace_range tb left join ( - select it.id,tid,pid,ip.name as process,it.name as thread from thread as it left join process ip on it.ipid = ip.id + select it.id, + tid, + pid, + ip.name as process, + it.name as thread + from thread as it + left join process ip on it.ipid = ip.id ) tc on ta.itid = tc.id where ta.cpu is not null order by startTime; @@ -84,7 +103,7 @@ let temp_query_thread_function = `create table temp_query_thread_function as sel c.id, c.depth, c.argsetid -from thread A,trace_section D +from thread A,trace_range D left join callstack C on A.id = C.callid where startTs not null and c.cookie is null; create index temp_query_thread_function_idx on temp_query_thread_function(tid); @@ -94,8 +113,8 @@ let temp_query_thread_data = `create table temp_query_thread_data as select A.id , B.cpu, B.ts-TR.start_ts AS startTime,B.dur,B.state,IP.pid,IP.name as processName from thread_state AS B left join thread as A on A.id=B.itid - left join trace_section AS TR - left join process AS IP on IP.id=ipid; + left join trace_range AS TR + left join process AS IP on IP.id=A.ipid; create index temp_query_thread_data_idx on temp_query_thread_data(tid);` let temp_view = `CREATE VIEW IF NOT EXISTS thread_view AS SELECT id as itid, * FROM thread; @@ -116,7 +135,7 @@ select IP.name as process,IP.pid as processId, Ip.id as id, (ts - B.start_ts + dur) as end_ts, (ts - B.start_ts) as start_ts -from thread_state as A,trace_section as B +from thread_state as A,trace_range as B left join thread as C on A.itid = C.id left join process AS IP on C.ipid = IP.id where A.dur > 0 and processId not null and (ts - B.start_ts)>0; @@ -138,7 +157,7 @@ let temp_get_process_thread_state_data = ` create table temp_get_process_thread_ from thread_state as B left join thread as A on B.itid = A.id left join process as IP on A.ipid = IP.id - left join trace_section as TR + left join trace_range as TR left join sched_slice as C on B.itid = C.itid and C.ts = B.ts where B.dur > 0 and IP.pid not null and (B.ts - TR.start_ts) >= 0; @@ -158,7 +177,7 @@ select IP.name as process, from thread_state AS B left join thread as A on B.itid = A.id left join process AS IP on A.ipid = IP.id - left join trace_section AS TR + left join trace_range AS TR where B.dur > 0 and IP.pid not null and (B.ts - TR.start_ts > 0); create index temp_get_tab_states_group_by_state_pid_tid_idx0 on temp_get_tab_states_group_by_state_pid_tid(process,processId,thread,threadId,state); @@ -176,7 +195,7 @@ select IP.name as process, from thread_state AS B left join thread as A on B.itid = A.id left join process AS IP on A.ipid = IP.id - left join trace_section AS TR + left join trace_range AS TR where pid not null and B.dur > 0 and (ts - TR.start_ts > 0); create index temp_get_tab_states_group_by_state_pid_idx0 on temp_get_tab_states_group_by_state_pid(process,processId,state); @@ -187,7 +206,7 @@ select state, dur, (ts - B.start_ts + dur) as end_ts, (ts - B.start_ts) as start_ts - from thread_state as A,trace_section as B + from thread_state as A,trace_range as B left join thread as C on A.itid = C.id left join process AS IP on C.ipid = IP.id where A.dur > 0 and IP.pid not null and (ts - B.start_ts > 0); @@ -195,63 +214,99 @@ select state, create index temp_get_tab_states_group_by_state_idx1 on temp_get_tab_states_group_by_state(start_ts,end_ts); ` let temp_get_tab_states_group_by_process_thread = `create table temp_get_tab_states_group_by_process_thread as -select IP.name as process, - IP.pid as processId, - A.name as thread, - a.tid as threadId, - B.dur as dur, - A.tid as tid, - (ts - TR.start_ts + dur) as end_ts, - (ts - TR.start_ts) as start_ts - from thread_state AS B - left join thread as A on B.itid = A.id - left join process AS IP on A.ipid = IP.id - left join trace_section AS TR - where pid not null and - B.dur > 0 and (ts - TR.start_ts)>0; + select + IP.name as process, + IP.pid as processId, + A.name as thread, + a.tid as threadId, + B.dur as dur, + A.tid as tid, + (ts - TR.start_ts + dur) as end_ts, + (ts - TR.start_ts) as start_ts + from + thread_state AS B + left join + thread as A on B.itid = A.id + left join + process AS IP on A.ipid = IP.id + left join + trace_range AS TR + where + pid not null + and + B.dur > 0 + and + (ts - TR.start_ts)>0; create index temp_get_tab_states_group_by_process_thread_idx0 on temp_get_tab_states_group_by_process_thread(process,processId,thread,threadId); create index temp_get_tab_states_group_by_process_thread_idx1 on temp_get_tab_states_group_by_process_thread(start_ts,end_ts); ` let temp_get_cpu_rate = `create table temp_get_cpu_rate as with cpu as ( - select cpu,ts,dur,(case when ro < 99 then ro else 99 end) as ro , - (case when ro < 99 then stime+ro*cell else stime + 99 * cell end) as st, - (case when ro < 99 then stime + (ro+1)*cell else etime end) as et + select + cpu, + ts, + dur, + (case when ro < 99 then ro else 99 end) as ro , + (case when ro < 99 then stime+ro*cell else stime + 99 * cell end) as st, + (case when ro < 99 then stime + (ro+1)*cell else etime end) as et from ( - select cpu,ts,A.dur,((ts+A.dur)-D.start_ts)/((D.end_ts-D.start_ts)/100) as ro,D.start_ts as stime,D.end_ts etime,(D.end_ts-D.start_ts)/100 as cell - from sched_slice A - left join trace_section D - left join thread B on A.itid = B.id - left join process C on B.ipid = C.id - where tid != 0 and (A.ts) between D.start_ts and D.end_ts)) -select cpu,ro, + select + cpu, + ts, + A.dur, + ((ts+A.dur)-D.start_ts)/((D.end_ts-D.start_ts)/100) as ro, + D.start_ts as stime, + D.end_ts etime, + (D.end_ts-D.start_ts)/100 as cell + from + sched_slice A + left join + trace_range D + left join + thread B on A.itid = B.id + left join + process C on B.ipid = C.id + where + tid != 0 + and (A.ts) + between D.start_ts and D.end_ts)) + select cpu,ro, sum(case when ts <= st and ts + dur <= et then (ts + dur - st) when ts <= st and ts + dur > et then et-st when ts > st and ts + dur <= et then dur when ts > st and ts + dur > et then et - ts end)/cast(et-st as float) as rate -from cpu -group by cpu,ro; + from cpu + group by cpu,ro; ` let temp_get_tab_thread_states = `create table temp_get_tab_thread_states as select - IP.name as process, - IP.pid as pid, - A.name as thread, - A.tid as tid, - B.state as state, - B.dur as dur, - (B.ts - TR.start_ts + ifnull(B.dur,0)) as end_ts, - (B.ts - TR.start_ts) as start_ts -from thread_state AS B -left join thread as A on A.id = B.itid -left join trace_section AS TR -left join process AS IP on IP.id=ipid -where (B.ts - TR.start_ts > 0); -create index temp_get_tab_thread_states_idx0 on temp_get_tab_thread_states(process,pid,thread,tid,state); -create index temp_get_tab_thread_states_idx1 on temp_get_tab_thread_states(start_ts,end_ts); + IP.name as process, + IP.pid as pid, + A.name as thread, + A.tid as tid, + B.state as state, + B.dur as dur, + (B.ts - TR.start_ts + ifnull(B.dur,0)) as end_ts, + (B.ts - TR.start_ts) as start_ts + from + thread_state AS B + left join + thread as A + on + A.id = B.itid + left join + trace_range AS TR + left join + process AS IP + on + IP.id=A.ipid + where + (B.ts - TR.start_ts > 0); + create index temp_get_tab_thread_states_idx0 on temp_get_tab_thread_states(process,pid,thread,tid,state); + create index temp_get_tab_thread_states_idx1 on temp_get_tab_thread_states(start_ts,end_ts); `; let temp_get_tab_slices = `create table temp_get_tab_slices as @@ -261,22 +316,63 @@ let temp_get_tab_slices = `create table temp_get_tab_slices as A.tid as tid, (C.ts - D.start_ts + C.dur) as end_ts, (C.ts - D.start_ts) as start_ts -from thread A,trace_section D -left join callstack C on A.id = C.callid -where C.ts not null + from + thread A, + trace_range D + left join + callstack C on A.id = C.callid + where + C.ts not null and c.dur >= 0 and (C.ts - D.start_ts > 0); -create index temp_get_tab_slices_idx0 on temp_get_tab_slices(name); + create index temp_get_tab_slices_idx0 on temp_get_tab_slices(name); +`; + +let createProcessNoId = ` + insert into process(id,ipid,type, pid, name, start_ts) SELECT null,null,'process' as type,tid as pid,t.name,t.start_ts from thread t where ipid is null and tid != 0; + update process set id = ROWID - 1,ipid = ROWID - 1 where id is null; + update thread set ipid = (select id from process where thread.tid = process.pid) where thread.ipid is null; +` +let temp_create_cpu_freq_view = `CREATE VIEW cpu_freq_view AS SELECT B.cpu, A.ts, LEAD(A.ts, 1, (SELECT end_ts FROM trace_range)) OVER (PARTITION BY A.filter_id ORDER BY ts) AS end_ts,LEAD(A.ts, 1, (SELECT end_ts FROM trace_range)) OVER (PARTITION BY A.filter_id ORDER BY ts) - ts AS dur,value AS freq FROM measure AS A, cpu_measure_filter AS B WHERE B.name = 'cpu_frequency' AND A.filter_id = B.id`; +let temp_create_virtual_table = `CREATE VIRTUAL table result USING SPAN_JOIN(cpu_freq_view partitioned cpu, sched_slice partitioned cpu)`; + +let queryThreadWakeUpFrom = ` + select TB.tid,TB.name as thread,TA.cpu,(TA.ts - TR.start_ts) as ts,TC.pid,TC.name as process + from + (select ts as wakeTs,wakeup_from as wakeupFromTid from instant,trace_range + where name = 'sched_wakeup' + and ref = $itid + and ts > start_ts + $startTime + and ts < start_ts + $startTime + $dur + order by ts) TW + left join thread_state TA on TW.wakeupFromTid = TA.itid and TA.ts < TW.wakeTs and TA.ts + TA.dur >= TW.wakeTs + left join thread TB on TA.itid = TB.id + left join process TC on TB.ipid = TC.id + left join trace_range TR + where TB.ipid not null + limit 1; `; -let delete_callstack_binder_data = `DELETE FROM callstack WHERE dur<0 or name like 'binder%';`; +let queryThreadWakeUp = ` + select TB.tid,TB.name as thread,min(TA.ts - TR.start_ts) as ts,TC.pid,TC.name as process + from + (select min(ts) as wakeTs,ref as itid from instant,trace_range + where name = 'sched_wakeup' + and wakeup_from = $itid + and ts > start_ts + $startTime + and ts < start_ts + $startTime + $dur + group by ref + ) TW + left join thread_state TA on TW.itid = TA.itid and TA.ts > TW.wakeTs + left join thread TB on TA.itid = TB.id + left join process TC on TB.ipid = TC.id + left join trace_range TR + where TB.ipid not null + group by TB.tid, TB.name,TC.pid, TC.name; +`; + +let delete_callstack_binder_data = `DELETE FROM callstack WHERE dur<-1 or name = 'binder transaction async' or name = 'binder async rcv';`; + let temp_init_sql_list = [ - temp_view, - delete_callstack_binder_data, temp_query_process, - temp_query_cpu_data, - temp_query_process_data, - temp_query_thread_function, - temp_query_thread_data, - temp_get_cpu_rate, ]; diff --git a/host/ide/src/trace/database/TraceWorker.ts b/host/ide/src/trace/database/TraceWorker.ts index 559550f62e06790b67669355d34972462b653df6..110d1b0605409b788fbf0c4964ec19bb3074b133 100644 --- a/host/ide/src/trace/database/TraceWorker.ts +++ b/host/ide/src/trace/database/TraceWorker.ts @@ -17,6 +17,18 @@ importScripts("trace_streamer_builtin.js", "TempSql.js"); self.onerror = function (error: any) { } let Module: any = null; +let enc = new TextEncoder(); +let dec = new TextDecoder(); +let arr: Uint8Array; +let start: number; +const REQ_BUF_SIZE = 4 * 1024 * 1024; +let reqBufferAddr:number = -1; +let bufferSlice:Array = [] +let json:string; + +let headUnitArray:Uint8Array; +let thirdWasmMap = new Map(); +let thirdJsonResult = new Map(); function initWASM() { return new Promise((resolve, reject) => { @@ -40,21 +52,165 @@ function initWASM() { }) } -const REQ_BUF_SIZE = 64 * 1024 * 1024; +function initThirdWASM(wasmFunctionName:string) { + function callModelFun(functionName: string) { + let func = eval(functionName); + return new func({ + locateFile: (s: any) => { + return s + }, + print: (line: any) => { + }, + printErr: (line: any) => { + }, + onRuntimeInitialized: () => { + }, + onAbort: () => { + } + }); + } + return callModelFun(wasmFunctionName) +} + +let merged = ()=>{ + let length = 0; + bufferSlice.forEach(item => { + length += item.length; + }); + let mergedArray = new Uint8Array(length); + let offset = 0; + bufferSlice.forEach(item => { + mergedArray.set(item, offset); + offset += item.length; + }); + return mergedArray; +} +let convertJSON = ()=>{ + let str = dec.decode(arr); + let jsonArray = []; + str = str.substring(str.indexOf("\n") + 1); + if (!str) { + }else{ + let parse = JSON.parse(str); + let columns = parse.columns; + let values = parse.values; + for (let i = 0; i < values.length; i++) { + let obj: any = {} + for (let j = 0; j < columns.length; j++) { + obj[columns[j]] = values[i][j] + } + jsonArray.push(obj) + } + } + return jsonArray; +} self.onmessage = async (e: MessageEvent) => { if (e.data.action === "open") { await initWASM(); // @ts-ignore - self.postMessage({id: e.data.id, action: "open", ready: true, index: 0}); + self.postMessage({id: e.data.id, action: e.data.action, ready: true, index: 0}); let uint8Array = new Uint8Array(e.data.buffer); - let p = Module._malloc(uint8Array.length); - Module.HEAPU8.set(uint8Array, p); - let r1 = Module._TraceStreamerParseData(p, uint8Array.length); - let r2 = Module._TraceStreamerParseDataOver(); - Module._free(p); - if (r1 == -1) { + let callback = (heapPtr: number, size: number, isEnd: number) => { + let out:Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); + bufferSlice.push(out); + if(isEnd == 1){ + arr = merged(); + bufferSlice.length = 0; + } + } + let fn = Module.addFunction(callback, "viii"); + reqBufferAddr = Module._Initialize(fn, REQ_BUF_SIZE); + let wasmConfigStr = e.data.wasmConfig + if (wasmConfigStr != "" && wasmConfigStr.indexOf("WasmFiles") != -1) { + let wasmConfig = JSON.parse(wasmConfigStr); + let wasmConfigs = wasmConfig.WasmFiles + let itemArray = wasmConfigs.map((item:any) => {return item.componentId + ";" + item.pluginName}) + let thirdWasmStr: string = itemArray.join(";") + let configUintArray = enc.encode(thirdWasmStr + ";"); + Module.HEAPU8.set(configUintArray, reqBufferAddr); + Module._TraceStreamer_Init_ThirdParty_Config(configUintArray.length); + let first = true; + let sendDataCallback = (heapPtr: number, size: number, componentID: number) => { + if (componentID == 100) { + if (first) { + first = false; + headUnitArray = Module.HEAPU8.slice(heapPtr, heapPtr + size); + } + return; + } + let configs = wasmConfigs.filter((wasmConfig: any) => { + return wasmConfig.componentId == componentID; + }) + if (configs.length > 0) { + let config = configs[0]; + let model = thirdWasmMap.get(componentID) + if (model == null && config.componentId == componentID) { + importScripts(config.wasmJsName) + let thirdMode = initThirdWASM(config.wasmName) + let configPluginName = config.pluginName + let pluginNamePtr = thirdMode._malloc(configPluginName.length); + let pluginNameUintArray = enc.encode(configPluginName); + thirdMode.HEAPU8.set(pluginNameUintArray, pluginNamePtr); + thirdMode._TraceStreamer_In_PluginName(pluginNamePtr, configPluginName.length) + let thirdQueryDataCallBack = (heapPtr: number, size: number, isEnd: number, isConfig: number) => { + if (isConfig == 1) { + let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size); + thirdJsonResult.set(componentID,{jsonConfig: dec.decode(out), disPlayName : config.disPlayName, pluginName: config.pluginName}) + } else { + let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size); + bufferSlice.push(out); + if (isEnd == 1) { + arr = merged(); + bufferSlice.length = 0; + } + } + } + let fn = thirdMode.addFunction(thirdQueryDataCallBack, "viiii"); + let thirdreqBufferAddr = thirdMode._Init(fn, REQ_BUF_SIZE) + let updateTraceTimeCallBack = (heapPtr: number, size: number) => { + let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size); + Module.HEAPU8.set(out, reqBufferAddr); + Module._UpdateTraceTime(out.length); + } + let traceRangeFn = thirdMode.addFunction(updateTraceTimeCallBack, "vii"); + let mm = thirdMode._InitTraceRange(traceRangeFn, 1024) + thirdMode._TraceStreamer_In_JsonConfig(); + thirdMode.HEAPU8.set(headUnitArray, thirdreqBufferAddr); + thirdMode._ParserData(headUnitArray.length, 100); + let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); + thirdMode.HEAPU8.set(out, thirdreqBufferAddr); + thirdMode._ParserData(out.length, componentID); + thirdWasmMap.set(componentID, {"model": thirdMode, "bufferAddr":thirdreqBufferAddr}) + } else { + let mm = model.model + let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); + mm.HEAPU8.set(out, model.bufferAddr); + mm._ParserData(out.length, componentID); + } + } + } + let fn1 = Module.addFunction(sendDataCallback, "viii"); + let reqBufferAddr1 = Module._TraceStreamer_Set_ThirdParty_DataDealer(fn1, REQ_BUF_SIZE); + } + let wrSize = 0; + let r2 = -1; + while (wrSize < uint8Array.length) { + const sliceLen = Math.min(uint8Array.length - wrSize, REQ_BUF_SIZE); + const dataSlice = uint8Array.subarray(wrSize, wrSize + sliceLen); + Module.HEAPU8.set(dataSlice, reqBufferAddr); + wrSize += sliceLen; + r2 = Module._TraceStreamerParseDataEx(sliceLen); + if (r2 == -1) { + break; + } + } + Module._TraceStreamerParseDataOver(); + for (let value of thirdWasmMap.values()) { + value.model._TraceStreamer_In_ParseDataOver(); + } + if (r2 == -1) { // @ts-ignore - self.postMessage({id: e.data.id, action: "open", init: false, msg: "parse data error"}); + self.postMessage({id: e.data.id, action: e.data.action, init: false, msg: "parse data error"}); return; } // @ts-ignore @@ -64,23 +220,44 @@ self.onmessage = async (e: MessageEvent) => { self.postMessage({id: e.data.id, ready: true, index: index + 1}); }); // @ts-ignore - self.postMessage({id: e.data.id, action: "open", init: true, msg: "ok"}); + self.postMessage({id: e.data.id, action: e.data.action, init: true, msg: "ok", configSqlMap:thirdJsonResult, buffer: e.data.buffer}, [e.data.buffer]); } else if (e.data.action === "exec") { - let arr = query(e.data.name, e.data.sql, e.data.params); + query(e.data.name, e.data.sql, e.data.params); + let jsonArray = convertJSON(); // @ts-ignore - self.postMessage({id: e.data.id, action: "exec", results: arr}); + self.postMessage({id: e.data.id, action: e.data.action, results: jsonArray}); + } else if (e.data.action == "exec-buf") { + query(e.data.name, e.data.sql, e.data.params); + // @ts-ignore + self.postMessage({id: e.data.id, action: e.data.action, results: arr.buffer}, [arr.buffer]); + } else if (e.data.action.startsWith("exec-sdk")) { + querySdk(e.data.name, e.data.sql, e.data.params, e.data.action); + let jsonArray = convertJSON(); + // @ts-ignore + self.postMessage({id: e.data.id, action: e.data.action, results: jsonArray}); + } else if(e.data.action == "init-port"){ + let port = e.ports[0]; + port.onmessage = (me)=>{ + query(me.data.action, me.data.sql, me.data.params); + let msg = {id: me.data.id,action:me.data.action, results: arr.buffer} + port.postMessage(msg, [arr.buffer]); + } } } function createView(sql: string) { let enc = new TextEncoder(); - let dec = new TextDecoder(); let sqlPtr = Module._malloc(sql.length); Module.HEAPU8.set(enc.encode(sql), sqlPtr); let res = Module._TraceStreamerSqlOperate(sqlPtr, sql.length); return res; } +function queryJSON(name: string, sql: string, params: any) { + query(name,sql,params); + return convertJSON(); +} + function query(name: string, sql: string, params: any) { if (params) { Reflect.ownKeys(params).forEach((key: any) => { @@ -91,28 +268,29 @@ function query(name: string, sql: string, params: any) { } }); } - let arr: Array = [] - let enc = new TextEncoder(); - let dec = new TextDecoder(); - let sqlPtr = Module._malloc(sql.length); - let outPtr = Module._malloc(REQ_BUF_SIZE); - Module.HEAPU8.set(enc.encode(sql), sqlPtr); - let a = new Date().getTime(); - let res = Module._TraceStreamerSqlQuery(sqlPtr, sql.length, outPtr, REQ_BUF_SIZE); - let out = Module.HEAPU8.subarray(outPtr, outPtr + res); - let str = dec.decode(out); - Module._free(sqlPtr); - Module._free(outPtr); - str = str.substring(str.indexOf("\n") + 1); - let parse = JSON.parse(str); - let columns = parse.columns; - let values = parse.values; - for (let i = 0; i < values.length; i++) { - let obj: any = {} - for (let j = 0; j < columns.length; j++) { - obj[columns[j]] = values[i][j] - } - arr.push(obj) + start = new Date().getTime(); + let sqlUintArray = enc.encode(sql); + Module.HEAPU8.set(sqlUintArray, reqBufferAddr); + Module._TraceStreamerSqlQueryEx(sqlUintArray.length); +} + +function querySdk(name: string, sql: string, params: any, action: string) { + if (params) { + Reflect.ownKeys(params).forEach((key: any) => { + if (typeof params[key] === "string") { + sql = sql.replace(new RegExp(`\\${key}`, "g"), `'${params[key]}'`); + } else { + sql = sql.replace(new RegExp(`\\${key}`, "g"), params[key]); + } + }); + } + let sqlUintArray = enc.encode(sql); + let commentId = action.substring(action.lastIndexOf("-") + 1) + let key = Number(commentId) + let wasm = thirdWasmMap.get(key); + if (wasm != undefined) { + let wasmModel = wasm.model + wasmModel.HEAPU8.set(sqlUintArray, wasm.bufferAddr); + wasmModel._TraceStreamerSqlQueryEx(sqlUintArray.length); } - return arr } \ No newline at end of file diff --git a/host/ide/src/trace/database/TraceWorkerRoot.ts b/host/ide/src/trace/database/TraceWorkerRoot.ts new file mode 100644 index 0000000000000000000000000000000000000000..cbde9ebed90bf834997a69f93fa8fcc6bac33cfa --- /dev/null +++ b/host/ide/src/trace/database/TraceWorkerRoot.ts @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +let worker:Worker; +self.onmessage = (e)=>{ + if (e.data.action === "open") { + worker = new Worker("TraceWorker.js") + worker.onmessage = (msg)=>{ + self.postMessage(msg.data); + } + worker.postMessage(e.data,[e.data.buffer]); + } else if (e.data.action === "exec") { + worker.postMessage(e.data); + } else if (e.data.action == "exec-buf") { + // @ts-ignore + worker.postMessage(e.data); + } +} +self.onerror = event => { + worker.terminate(); +} +self.onclose = () => { + worker.terminate(); +} \ No newline at end of file diff --git a/host/ide/src/trace/database/logic-worker/ProcedureLogicWorker.ts b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorker.ts new file mode 100644 index 0000000000000000000000000000000000000000..69029accdb299fd8c59f294b324f5149aaeb9842 --- /dev/null +++ b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorker.ts @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import {ProcedureLogicWorkerPerf} from "./ProcedureLogicWorkerPerf.js"; +import {ProcedureLogicWorkerNativeMemory} from "./ProcedureLogicWorkerNativeNemory.js"; +import {ProcedureLogicWorkerFileSystem} from "./ProcedureLogicWorkerFileSystem.js"; +import {ProcedureLogicWorkerSPT} from "./ProcedureLogicWorkerSPT.js"; +import {ProcedureLogicWorkerCpuState} from "./ProcedureLogicWorkerCpuState.js"; + + +let logicWorker: any = { + "perf":new ProcedureLogicWorkerPerf(), + "native-memory":new ProcedureLogicWorkerNativeMemory(), + "fileSystem":new ProcedureLogicWorkerFileSystem(), + "CpuState":new ProcedureLogicWorkerCpuState(), + "spt":new ProcedureLogicWorkerSPT(), +} + +function match(req:any) { + Reflect.ownKeys(logicWorker).filter((it) => { + if (req.type && req.type.startsWith(it as string)) { + logicWorker[it].handle(req); + } + }) +} + +self.onmessage = function (e: any) { + match(e.data); +} \ No newline at end of file diff --git a/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts new file mode 100644 index 0000000000000000000000000000000000000000..81c072c184d194d9c5c0b1a7a57904f858a88329 --- /dev/null +++ b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts @@ -0,0 +1,489 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SpNativeMemoryChart} from "../../component/chart/SpNativeMemoryChart.js"; + +export class ChartStruct { + depth: number = 0; + symbol: string = ''; + lib: string = ''; + addr: string = ''; + size: number = 0; + count: number = 0; + dur:number = 0; + parent: ChartStruct | undefined; + children: Array = []; +} + +export class Msg{ + tag:string = ""; + index:number = 0; + isSending:boolean = false; + data:Array = []; +} + +export class MerageBean extends ChartStruct{ + #parentNode: MerageBean | undefined = undefined + #total = 0 + currentTreeParentNode: MerageBean | undefined = undefined; + id: string = ""; + parentId: string = ""; + symbolName: string = ""; + symbol: string = "" + libName: string = "" + path: string = "" + self: string = "0s" + weight: string = "" + weightPercent: string = "" + selfDur: number = 0; + dur: number = 0; + pid: number = 0; + canCharge:boolean = true + isStore = 0; + isSelected: boolean = false; + searchShow: boolean = true; + children: MerageBean[] = [] + initChildren: MerageBean[] = [] + type:number = 0 + set parentNode(data: MerageBean | undefined) { + this.currentTreeParentNode = data; + this.#parentNode = data; + } + + get parentNode() { + return this.#parentNode + } + + set total(data: number) { + this.#total = data; + this.weight = `${getProbablyTime(this.dur)}` + this.weightPercent = `${(this.dur / data * 100).toFixed(1)}%` + } + + get total() { + return this.#total; + } +} + +class MerageBeanDataSplit{ + systmeRuleName = "/system/" + numRuleName = "/max/min/" + + //所有的操作都是针对整个树结构的 不区分特定的数据 + splitTree(splitMapData:any,data: MerageBean[], name: string, isCharge: boolean, isSymbol: boolean,currentTreeList:any[],searchValue:string) { + data.forEach((process) => { + process.children = [] + if (isCharge) { + this.recursionChargeInitTree(splitMapData,process, name, isSymbol) + } else { + this.recursionPruneInitTree(splitMapData,process, name, isSymbol) + } + }) + this.resetAllNode(data,currentTreeList,searchValue) + } + + recursionChargeInitTree(splitMapData:any,node: MerageBean, symbolName: string, isSymbol: boolean) { + if ((isSymbol && node.symbolName == symbolName) || (!isSymbol && node.libName == symbolName)) { + (splitMapData[symbolName] = splitMapData[symbolName] || []).push(node) + node.isStore++; + } + if (node.initChildren.length > 0) { + node.initChildren.forEach((child) => { + this.recursionChargeInitTree(splitMapData,child, symbolName, isSymbol) + }) + } + } + + //symbol lib charge + recursionChargeTree(node: MerageBean, symbolName: string, isSymbol: boolean) { + if ((isSymbol && node.symbolName == symbolName) || (!isSymbol && node.libName == symbolName)) { + node.currentTreeParentNode && node.currentTreeParentNode.children.splice(node.currentTreeParentNode.children.indexOf(node), 1, ...node.children); + node.children.forEach((child) => { + child.currentTreeParentNode = node.currentTreeParentNode + }) + } + if (node.children.length > 0) { + node.children.forEach((child) => { + this.recursionChargeTree(child, symbolName, isSymbol) + }) + } + } + + recursionPruneInitTree(splitMapData:any,node: MerageBean, symbolName: string, isSymbol: boolean) { + if (isSymbol && node.symbolName == symbolName || (!isSymbol && node.libName == symbolName)) { + (splitMapData[symbolName] = splitMapData[symbolName] || []).push(node) + node.isStore++; + this.pruneChildren(splitMapData,node, symbolName) + } else if (node.initChildren.length > 0) { + node.initChildren.forEach((child) => { + this.recursionPruneInitTree(splitMapData,child, symbolName, isSymbol) + }) + } + } + + //symbol lib prune + recursionPruneTree(node: MerageBean, symbolName: string, isSymbol: boolean) { + if (isSymbol && node.symbolName == symbolName || (!isSymbol && node.libName == symbolName)) { + node.currentTreeParentNode && node.currentTreeParentNode.children.splice(node.currentTreeParentNode.children.indexOf(node), 1); + } else { + node.children.forEach((child) => { + this.recursionPruneTree(child, symbolName, isSymbol) + }) + } + } + + recursionChargeByRule(splitMapData:any,node: MerageBean, ruleName: string, rule: (node: MerageBean) => boolean) { + if (node.initChildren.length > 0) { + node.initChildren.forEach((child) => { + if (rule(child)) { + (splitMapData[ruleName] = splitMapData[ruleName] || []).push(child) + child.isStore++; + } + this.recursionChargeByRule(splitMapData,child, ruleName, rule) + }) + } + } + + pruneChildren(splitMapData:any,node: MerageBean, symbolName: string) { + if (node.initChildren.length > 0) { + node.initChildren.forEach((child) => { + child.isStore++; + (splitMapData[symbolName] = splitMapData[symbolName] || []).push(child); + this.pruneChildren(splitMapData,child, symbolName) + }) + } + } + + hideSystemLibrary(allProcess:MerageBean[],splitMapData:any){ + allProcess.forEach((item)=>{ + item.children = [] + this.recursionChargeByRule(splitMapData,item,this.systmeRuleName,(node)=>{ + return node.path.startsWith(this.systmeRuleName) + }) + }) + } + + hideNumMaxAndMin(allProcess:MerageBean[],splitMapData:any,startNum:number,endNum:string){ + let max = endNum == "∞"?Number.POSITIVE_INFINITY :parseInt(endNum) + allProcess.forEach((item)=>{ + item.children = [] + this.recursionChargeByRule(splitMapData,item,this.numRuleName,(node)=>{ + return node.count < startNum || node.count > max + }) + }) + } + + resotreAllNode(splitMapData:any,symbols: string[]) { + symbols.forEach((symbol) => { + let list = splitMapData[symbol]; + if (list != undefined) { + list.forEach((item: any) => { + item.isStore-- + }) + } + }) + } + + resetAllNode(data: MerageBean[],currentTreeList:any[],searchValue:string) { + this.clearSearchNode(currentTreeList) + data.forEach((process) => { + process.searchShow = true + }) + this.resetNewAllNode(data,currentTreeList) + if (searchValue != "") { + this.findSearchNode(data, searchValue, false) + this.resetNewAllNode(data,currentTreeList) + } + } + + resetNewAllNode(data: MerageBean[],currentTreeList:any[]) { + data.forEach((process) => { + process.children = [] + }) + let values = currentTreeList.map((item: any) => { + item.children = [] + return item + }) + values.forEach((item: any) => { + if (item.parentNode != undefined) { + if (item.isStore == 0 && item.searchShow) { + let parentNode = item.parentNode + while (parentNode != undefined && !(parentNode.isStore == 0 && parentNode.searchShow)) { + parentNode = parentNode.parentNode + } + if (parentNode) { + item.currentTreeParentNode = parentNode + parentNode.children.push(item) + } + } + } + }) + } + + findSearchNode(data: MerageBean[], search: string, parentSearch: boolean) { + data.forEach((node) => { + if ((node.symbolName!=undefined&&node.symbolName.includes(search)) || parentSearch) { + node.searchShow = true + let parentNode = node.currentTreeParentNode + while (parentNode != undefined && !parentNode.searchShow) { + parentNode.searchShow = true + parentNode = parentNode.currentTreeParentNode + } + } else { + node.searchShow = false + } + if (node.children.length > 0) { + this.findSearchNode(node.children, search, node.searchShow) + } + }) + } + + clearSearchNode(currentTreeList:any[]) { + currentTreeList.forEach((node) => { + node.searchShow = true + }) + } + + splitAllProcess(allProcess:any[],splitMapData:any,list:any[]){ + list.forEach((item:any)=>{ + allProcess.forEach((process)=>{ + if(item.select == "0"){ + this.recursionChargeInitTree(splitMapData,process, item.name, item.type == "symbol") + }else { + this.recursionPruneInitTree(splitMapData,process, item.name, item.type == "symbol") + } + }) + if(!item.checked){ + this.resotreAllNode(splitMapData,[item.name]) + } + }) + } +} + +export let merageBeanDataSplit = new MerageBeanDataSplit() + +export abstract class LogicHandler { + abstract handle(data:any):void +} + +let dec = new TextDecoder(); + +export let setFileName = (path: string)=> { + let fileName = "" + if (path) { + let number = path.lastIndexOf("/"); + if (number > 0) { + fileName = path.substring(number + 1) + return fileName + } + } + return path +} + +let pagination = (page:number, pageSize:number, source:Array)=>{ + let offset = (page - 1) * pageSize; + return (offset + pageSize >= source.length) ? source.slice(offset, source.length) : source.slice(offset, offset + pageSize); +} + +const PAGE_SIZE:number = 50_0000; +export let postMessage = (id: any, action: string, results: Array) => { + if(results.length > PAGE_SIZE){ + let pageCount = Math.ceil( results.length / PAGE_SIZE) + for (let i = 1; i <= pageCount; i++) { + let tag = "start"; + if(i== 1){ + tag = "start" + }else if(i == pageCount){ + tag = "end" + }else{ + tag = "sending" + } + let msg = new Msg(); + msg.tag = tag; + msg.index = i; + msg.isSending = tag != "end"; + msg.data = pagination(i,PAGE_SIZE,results); + self.postMessage({id: id, action: action, isSending : msg.tag != "end",results: msg}) + } + results.length = 0; + }else{ + let msg = new Msg(); + msg.tag = "end"; + msg.index = 0; + msg.isSending = false; + msg.data = results; + self.postMessage({id: id, action: action,results: msg}) + results.length = 0; + } +} + +export let convertJSON = (arr:ArrayBuffer|Array)=>{ + if(arr instanceof ArrayBuffer) { + let str = dec.decode(arr); + let jsonArray = []; + str = str.substring(str.indexOf("\n") + 1); + if (!str) { + } else { + let parse = JSON.parse(str); + let columns = parse.columns; + let values = parse.values; + for (let i = 0; i < values.length; i++) { + let obj: any = {} + for (let j = 0; j < columns.length; j++) { + obj[columns[j]] = values[i][j] + } + jsonArray.push(obj) + } + } + return jsonArray; + } else { + return arr; + } +} + +export let getByteWithUnit = (bytes: number) : string => { + if (bytes < 0) { + return "-" + getByteWithUnit(Math.abs(bytes)) + } + let currentBytes = bytes + let kb1 = 1 << 10; + let mb1 = 1 << 10 << 10; + let gb1 = 1 << 10 << 10 << 10; // 1 gb + let res = "" + if (currentBytes > gb1) { + res += (currentBytes / gb1).toFixed(2) + " Gb"; + } else if (currentBytes > mb1) { + res += (currentBytes / mb1).toFixed(2) + " Mb"; + } else if (currentBytes > kb1) { + res += (currentBytes / kb1).toFixed(2) + " Kb"; + } else { + res += Math.round(currentBytes) + " byte"; + } + return res +} + +export let getTimeString = (ns: number): string =>{ + let currentNs = ns + let hour1 = 3600_000_000_000 + let minute1 = 60_000_000_000 + let second1 = 1_000_000_000; + let millisecond1 = 1_000_000; + let microsecond1 = 1_000; + let res = ""; + if (currentNs >= hour1) { + res += Math.floor(currentNs / hour1) + "h "; + currentNs = currentNs - Math.floor(currentNs / hour1) * hour1 + } + if (currentNs >= minute1) { + res += Math.floor(currentNs / minute1) + "m "; + currentNs = currentNs - Math.floor(ns / minute1) * minute1 + } + if (currentNs >= second1) { + res += Math.floor(currentNs / second1) + "s "; + currentNs = currentNs - Math.floor(currentNs / second1) * second1 + } + if (currentNs >= millisecond1) { + res += Math.floor(currentNs / millisecond1) + "ms "; + currentNs = currentNs - Math.floor(currentNs / millisecond1) * millisecond1 + } + if (currentNs >= microsecond1) { + res += Math.floor(currentNs / microsecond1) + "μs "; + currentNs = currentNs - Math.floor(currentNs / microsecond1) * microsecond1 + } + if (currentNs > 0) { + res += currentNs + "ns "; + } + if (res == "") { + res = ns + ""; + } + return res +} + +export function getProbablyTime(ns: number): string { + let currentNs = ns + let hour1 = 3600_000_000_000 + let minute1 = 60_000_000_000 + let second1 = 1_000_000_000; + let millisecond1 = 1_000_000; + let microsecond1 = 1_000; + let res = ""; + if (currentNs >= hour1) { + res += (currentNs / hour1).toFixed(2) + "h "; + }else if (currentNs >= minute1) { + res += (currentNs / minute1).toFixed(2) + "m "; + }else if (currentNs >= second1) { + res += (currentNs / second1).toFixed(2) + "s "; + }else if (currentNs >= millisecond1) { + res += (currentNs / millisecond1).toFixed(2) + "ms "; + }else if (currentNs >= microsecond1) { + res += (currentNs / microsecond1).toFixed(2) + "μs "; + }else if (currentNs > 0) { + res += currentNs + "ns "; + }else if (res == "") { + res = ns + ""; + } + return res +} + +export function timeMsFormat2p(ns: number) { + let currentNs = ns + let hour1 = 3600_000 + let minute1 = 60_000 + let second1 = 1_000; // 1 second + let res = "" + if (currentNs >= hour1) { + res += Math.floor(currentNs / hour1).toFixed(2) + "h" + return res + } + if (currentNs >= minute1) { + res += Math.floor(currentNs / minute1).toFixed(2) + "min" + return res + } + if (currentNs >= second1) { + res += Math.floor(currentNs / second1).toFixed(2) + "s" + return res + } + if (currentNs > 0) { + res += currentNs.toFixed(2) + "ms"; + return res + } + if (res == "") { + res = "0s"; + } + return res +} + +export function formatRealDate(date:Date,fmt:string) { + let obj = { + "M+": date.getMonth() + 1, + "d+": date.getDate(), + "h+": date.getHours(), + "m+": date.getMinutes(), + "s+": date.getSeconds(), + "q+": Math.floor((date.getMonth() + 3) / 3), + "S": date.getMilliseconds() + }; + if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length)); + for (let key in obj){ + if (new RegExp("(" + key + ")").test(fmt)) { // @ts-ignore + fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (obj[key]) : (("00" + obj[key]).substr(("" + obj[key]).length))); + } + } + return fmt; +} + +export function formatRealDateMs(timeNs:number){ + return formatRealDate(new Date((timeNs)/1000000),"MM-dd hh:mm:ss.S") +} \ No newline at end of file diff --git a/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCpuState.ts b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCpuState.ts new file mode 100644 index 0000000000000000000000000000000000000000..9cbd76665f02bd1599df6d092d02218d917cd172 --- /dev/null +++ b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCpuState.ts @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {convertJSON, LogicHandler} from "./ProcedureLogicWorkerCommon.js"; + +export class ProcedureLogicWorkerCpuState extends LogicHandler { + + currentEventId: string = "" + + handle(data: any): void { + this.currentEventId = data.id + if (data && data.type) { + switch (data.type) { + case "CpuState-getCpuState": + if(data.params.list){ + let arr = convertJSON(data.params.list) || [] + self.postMessage({id: data.id, action: data.action, results: this.supplementCpuState(arr)}) + arr = []; + }else{ + this.getCpuState(data.params.cpu); + } + break; + } + } + } + + queryData(queryName: string, sql: string, args: any) { + self.postMessage({ + id: this.currentEventId, + type: queryName, + isQuery: true, + args: args, + sql: sql + }) + } + + getCpuState(cpu:number){ + this.queryData("CpuState-getCpuState", ` + select (A.ts - B.start_ts) as startTs, + A.dur, + (A.ts - B.start_ts + A.dur) as endTs, + (case + when state = 'Running' then 0 + when state = 'S' then 1 + when state = 'R' or state = 'R+' then 2 + else 3 end) as value + from thread_state A,trace_range B + where cpu = $cpu and startTs >= 0; + `, {$cpu:cpu}); + } + + supplementCpuState(arr:Array):Array{ + let source:Array = []; + if(arr.length > 0){ + let first = arr[0]; + if(first.startTs > 0){ + let cs:CpuState = new CpuState(); + cs.startTs = 0; + cs.value = 3; + cs.dur = first.startTs; + cs.endTs = first.startTs; + source.push(cs); + } + source.push(first); + for (let i = 1,len = arr.length; i < len; i++) { + let last = arr[i-1]; + let current = arr[i]; + if(current.startTs > last.endTs){ + let cs:CpuState = new CpuState(); + cs.startTs = last.endTs; + cs.value = 3; + cs.dur = current.startTs - last.endTs; + cs.endTs = current.startTs; + source.push(cs); + } + source.push(current); + } + } + return source; + } + +} + +export class CpuState{ + startTs:number = 0 + endTs:number = 0 + dur:number = 0 + value:number = 0 +} + diff --git a/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerFileSystem.ts b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerFileSystem.ts new file mode 100644 index 0000000000000000000000000000000000000000..38116d3a154952cabb979a191dfced4fed05c4f2 --- /dev/null +++ b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerFileSystem.ts @@ -0,0 +1,779 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + convertJSON, getByteWithUnit, + getProbablyTime, + getTimeString, + LogicHandler, + MerageBean, + merageBeanDataSplit, + postMessage, + setFileName +} from "./ProcedureLogicWorkerCommon.js"; + +export let FILE_TYPE_MAP = { + '0': 'OPEN', + '1': 'CLOSE', + '2': 'READ', + '3': 'WRITE', +}; + +export let DISKIO_TYPE_MAP = { + '1': 'DATA_READ', + '2': 'DATA_WRITE', + '3': 'METADATA_READ', + '4': 'METADATA_WRITE', + '5': 'PAGE_IN', + '6': 'PAGE_OUT', +}; + +export let VM_TYPE_MAP = { + '1': 'File Backed In', + '2': 'Page Cache Hit', + '3': 'Swap From Zram', + '4': 'Swap From Disk', + '5': 'Zero Fill Page', + '6': 'Zero FAKE Page', + '7': 'Copy On Write', +}; + +export class ProcedureLogicWorkerFileSystem extends LogicHandler { + static data_dict: Map = new Map(); + static callChainsMap: Map = new Map() + handlerMap:Map = new Map(); + currentEventId: string = "" + tab:string = ""; + + handle(data: any): void { + if(data.id){ + this.currentEventId = data.id + } + if (data && data.type) { + switch (data.type) { + case "fileSystem-init": + ProcedureLogicWorkerFileSystem.data_dict = data.params as Map + this.initCallchains(); + break + case "fileSystem-queryCallchains": + let callChains = convertJSON(data.params.list) || []; + this.initCallChainTopDown(callChains) + // @ts-ignore + self.postMessage({id: data.id, action: data.action, results: []}); + break; + case "fileSystem-queryFileSamples": + this.handlerMap.get("fileSystem").samplesList = convertJSON(data.params.list) || [] + self.postMessage({ + id: this.currentEventId, action: data.action, results: this.handlerMap.get("fileSystem").resolvingAction([{ + funcName: "getCallChainsBySampleIds", + funcArgs: [true] + }]) + }); + break; + case "fileSystem-queryIoSamples": + this.handlerMap.get("io").samplesList = convertJSON(data.params.list) || [] + self.postMessage({ + id: this.currentEventId, action: data.action, results: this.handlerMap.get("io").resolvingAction([{ + funcName: "getCallChainsBySampleIds", + funcArgs: [true] + }]) + }); + break; + case "fileSystem-queryVirtualMemorySamples": + this.handlerMap.get("virtualMemory").samplesList = convertJSON(data.params.list) || [] + self.postMessage({ + id: this.currentEventId, action: data.action, results: this.handlerMap.get("virtualMemory").resolvingAction([{ + funcName: "getCallChainsBySampleIds", + funcArgs: [true] + }]) + }); + break; + case "fileSystem-action": + if (data.params) { + let filter = data.params.args.filter((item: any) => item.funcName == "getCurrentDataFromDb"); + if (filter.length == 0) { + // @ts-ignore + self.postMessage({ + id: data.id, + action: data.action, + results: this.handlerMap.get(data.params.callType).resolvingAction(data.params.args) + }); + } else { + this.handlerMap.get(data.params.callType).resolvingAction(data.params.args) + } + } + break; + case "fileSystem-queryStack": + let res = this.getStacksByCallchainId(data.params.callchainId) + self.postMessage({id: data.id, action: data.action, results: res}) + break; + case "fileSystem-queryFileSysEvents": + if (data.params.list) { + let res = convertJSON(data.params.list) || [] + postMessage(data.id, data.action, this.supplementFileSysEvents(res, this.tab)); + } else { + this.tab = data.params.tab; + this.queryFileSysEvents(data.params.leftNs, data.params.rightNs, data.params.typeArr, data.params.tab) + } + break; + case "fileSystem-queryVMEvents": + if (data.params.list) { + let res = convertJSON(data.params.list) || [] + postMessage(data.id, data.action, this.supplementVMEvents(res)); + } else { + this.queryVMEvents(data.params.leftNs, data.params.rightNs, data.params.typeArr) + } + break + case "fileSystem-queryIOEvents": + if (data.params.list) { + let res = convertJSON(data.params.list) || [] + postMessage(data.id, data.action, this.supplementIoEvents(res)); + } else { + this.queryIOEvents(data.params.leftNs, data.params.rightNs, data.params.diskIOipids) + } + break + } + } + } + + queryFileSysEvents(leftNs: number, rightNs: number, typeArr: Array, tab: string) { + let types = Array.from(typeArr).join(","); + let sql = ""; + if (tab == "events") { + sql = ` + select + A.callchain_id as callchainId, + (A.start_ts - B.start_ts) as startTs, + dur, + A.type, + ifnull(C.name,'Process') || '[' || C.pid || ']' as process, + ifnull(D.name,'Thread') || '[' || D.tid || ']' as thread, + first_argument as firstArg, + second_argument as secondArg, + third_argument as thirdArg, + fourth_argument as fourthArg, + return_value as returnValue, + fd, + file_id as fileId, + error_code as error + from file_system_sample A,trace_range B + left join process C on A.ipid = C.id + left join thread D on A.itid = D.id + where A.type in (${types}) + and( + (A.end_ts - B.start_ts) between $leftNS and $rightNS + ) + order by A.end_ts; + ` + } else if (tab == "history") { + sql = ` + select + A.callchain_id as callchainId, + (A.start_ts - B.start_ts) as startTs, + dur, + fd, + A.type, + A.file_id as fileId, + ifnull(C.name,'Process') || '[' || C.pid || ']' as process + from file_system_sample A,trace_range B + left join process C on A.ipid = C.id + where A.type in (${types}) + and fd not null + and( + (A.start_ts - B.start_ts) between $leftNS and $rightNS + ) + order by A.end_ts; + ` + } else { + sql = ` + select TB.callchain_id as callchainId, + (TB.start_ts - TR.start_ts) as startTs, + (${rightNs} - TB.start_ts) as dur, + TB.fd, + TB.type, + TB.file_id as fileId, + ifnull(TC.name, 'Process') || '[' || TC.pid || ']' as process + from ( + select fd,ipid, + max(case when type = 0 then A.end_ts else 0 end) as openTs, + max(case when type = 1 then A.end_ts else 0 end) as closeTs + from file_system_sample A + where type in (0, 1) and A.end_ts between $leftNS and $rightNS group by fd,ipid + ) TA + left join file_system_sample TB on TA.fd = TB.fd and TA.ipid = TB.ipid and TA.openTs = TB.end_ts + left join process TC on TB.ipid = TC.ipid + left join trace_range TR + where startTs not null and TB.fd not null and TA.closeTs < TA.openTs + order by TB.end_ts; ` + } + this.queryData("fileSystem-queryFileSysEvents", sql, {$leftNS: leftNs, $rightNS: rightNs}) + } + + queryVMEvents(leftNs: number, rightNs: number, typeArr: Array){ + let types = Array.from(typeArr).join(","); + let sql = `select + A.callchain_id as callchainId, + (A.start_ts - B.start_ts) as startTs, + dur, + addr as address, + C.pid, + T.tid, + size, + A.type, + ifnull(T.name,'Thread') || '[' || T.tid || ']' as thread, + ifnull(C.name,'Process') || '[' || C.pid || ']' as process + from paged_memory_sample A,trace_range B + left join process C on A.ipid = C.id + left join thread T on T.id = A.itid + where ( + (A.end_ts - B.start_ts) between $leftNS and $rightNS + );`; + this.queryData("fileSystem-queryVMEvents", sql, {$leftNS: leftNs, $rightNS: rightNs}) + } + + queryIOEvents(leftNs: number, rightNs: number, diskIOipids: Array){ + let ipidsSql = ''; + if(diskIOipids.length > 0){ + ipidsSql += `and A.ipid in (${diskIOipids.join(",")})` + } + let sql = `select + A.callchain_id as callchainId, + (A.start_ts - B.start_ts) as startTs, + latency_dur as dur, + path_id as pathId, + dur_per_4k as durPer4k, + tier, + size, + A.type, + block_number as blockNumber, + T.tid, + C.pid, + ifnull(T.name,'Thread') || '[' || T.tid || ']' as thread, + ifnull(C.name,'Process') || '[' || C.pid || ']' as process + from bio_latency_sample A,trace_range B + left join process C on A.ipid = C.id + left join thread T on T.id = A.itid + where ( + (A.end_ts - B.start_ts) between $leftNS and $rightNS + ) ${ipidsSql};`; + this.queryData("fileSystem-queryIOEvents", sql, {$leftNS: leftNs, $rightNS: rightNs}) + } + + getStacksByCallchainId(id: number) { + let stacks = ProcedureLogicWorkerFileSystem.callChainsMap.get(id) ?? []; + let arr: Array = []; + for (let s of stacks) { + let st: Stack = new Stack() + st.path = (ProcedureLogicWorkerFileSystem.data_dict.get(s.pathId) ?? "Unknown Path").split("/").reverse()[0]; + st.symbol = `${s.symbolsId == null ? s.ip : ProcedureLogicWorkerFileSystem.data_dict.get(s.symbolsId) ?? ''} (${st.path})`; + st.type = (st.path.endsWith(".so.1") || st.path.endsWith(".dll") || st.path.endsWith(".so")) ? 0 : 1; + arr.push(st); + } + return arr; + } + + supplementIoEvents(res: Array){ + return res.map((event) => { + if(typeof event.pathId == 'string'){ + event.pathId = parseInt(event.pathId) + } + event.startTsStr = getTimeString(event.startTs) + event.durPer4kStr = event.durPer4k==0?"-":getProbablyTime(event.durPer4k) + event.sizeStr = getByteWithUnit(event.size) + event.durStr = getProbablyTime(event.dur) + event.path = event.pathId?ProcedureLogicWorkerFileSystem.data_dict.get(event.pathId) ?? '-':"-" + // @ts-ignore + event.operation = DISKIO_TYPE_MAP[`${event.type}`]||"UNKNOW" + let stacks = ProcedureLogicWorkerFileSystem.callChainsMap.get(event.callchainId)||[]; + if(stacks.length > 0){ + let stack = stacks[0] + event.backtrace = [stack.symbolsId == null ? stack.ip : ProcedureLogicWorkerFileSystem.data_dict.get(stack.symbolsId) ?? "", `(${stacks.length} other frames)`]; + }else { + event.backtrace = []; + } + return event + }) + } + + supplementVMEvents(res: Array){ + return res.map((event) => { + event.startTsStr = getTimeString(event.startTs) + event.sizeStr = getByteWithUnit(event.size*4096) + event.durStr = getProbablyTime(event.dur) + // @ts-ignore + event.operation = VM_TYPE_MAP[`${event.type}`]||"UNKNOW" + return event + }) + } + + + supplementFileSysEvents(res: Array, tab: string) { + res.map((r) => { + let stacks = ProcedureLogicWorkerFileSystem.callChainsMap.get(r.callchainId); + r.startTsStr = getTimeString(r.startTs); + r.durStr = getProbablyTime(r.dur); + if (tab == "events") { + r.firstArg = r.firstArg ?? "0x0" + r.secondArg = r.secondArg ?? "0x0" + r.thirdArg = r.thirdArg ?? "0x0" + r.fourthArg = r.fourthArg ?? "0x0" + r.returnValue = r.returnValue ?? "0x0" + r.error = r.error ?? "0x0" + r.path = ProcedureLogicWorkerFileSystem.data_dict.get(r.fileId) ?? "-"; + } + // @ts-ignore + r.typeStr = FILE_TYPE_MAP[`${r.type}`] ?? ""; + if (stacks && stacks.length > 0) { + let stack = stacks[0] + r.depth = stacks.length; + r.symbol = stack.symbolsId == null ? stack.ip : ProcedureLogicWorkerFileSystem.data_dict.get(stack.symbolsId) ?? "" + if (tab != "events") { + r.path = ProcedureLogicWorkerFileSystem.data_dict.get(r.fileId) ?? "-"; + } + r.backtrace = [r.symbol, `(${r.depth} other frames)`]; + } else { + r.depth = 0; + r.symbol = ""; + r.path = ""; + r.backtrace = []; + } + }) + return res; + } + + initCallchains() { + if (this.handlerMap.size > 0) { + this.handlerMap.forEach((value)=>{ + value.clearAll(); + }) + this.handlerMap.clear(); + } + this.handlerMap.set("fileSystem",new FileSystemCallTreeHandler("fileSystem",this.queryData)) + this.handlerMap.set("io",new FileSystemCallTreeHandler("io",this.queryData)) + this.handlerMap.set("virtualMemory",new FileSystemCallTreeHandler("virtualMemory",this.queryData)) + ProcedureLogicWorkerFileSystem.callChainsMap.clear(); + this.queryData("fileSystem-queryCallchains", `select callchain_id as callChainId,depth,symbols_id as symbolsId,file_path_id as pathId,ip from ebpf_callstack`, {}) + } + + + initCallChainTopDown(list: any[]) { + list.forEach((callchain: FileCallChain) => { + if (ProcedureLogicWorkerFileSystem.callChainsMap.has(callchain.callChainId)) { + ProcedureLogicWorkerFileSystem.callChainsMap.get(callchain.callChainId)!.push(callchain) + } else { + ProcedureLogicWorkerFileSystem.callChainsMap.set(callchain.callChainId, [callchain]) + } + }) + } + + queryData(queryName: string, sql: string, args: any) { + self.postMessage({ + id: this.currentEventId, + type: queryName, + isQuery: true, + args: args, + sql: sql + }) + } + +} + +class FileSystemCallTreeHandler { + currentTreeMapData: any = {} + allProcess: FileMerageBean[] = [] + dataSource: FileMerageBean[] = [] + currentDataType:string = "" + currentTreeList: any[] = [] + samplesList:FileSample[] = []; + splitMapData: any = {} + searchValue: string = "" + queryData = (action: string,sql: string,args: any) =>{} + + constructor(type:string,queryData:any) { + this.currentDataType = type; + this.queryData = queryData + } + + queryCallchainsSamples(selectionParam: any){ + switch (this.currentDataType) { + case "fileSystem": + this.queryFileSamples(selectionParam) + break; + case "io": + this.queryIOSamples(selectionParam) + break; + case "virtualMemory": + this.queryEpbfSamples(selectionParam) + break; + } + } + + queryFileSamples(selectionParam: any) { + let sql = ''; + if (selectionParam.fileSystemType != undefined && selectionParam.fileSystemType.length > 0) { + sql += " and s.type in (" + sql += selectionParam.fileSystemType.join(",") + sql += ")" + } + if(selectionParam.diskIOipids.length > 0&&!selectionParam.diskIOLatency&&selectionParam.fileSystemType.length == 0){ + sql += ` and s.ipid in (${selectionParam.diskIOipids.join(",")})` + } + this.queryData("fileSystem-queryFileSamples", `select s.callchain_id as callChainId,h.tid,h.name as threadName,s.dur,s.type,p.pid,p.name as processName from file_system_sample s,trace_range t +left join process p on p.id = s.ipid +left join thread h on h.id = s.itid +where s.end_ts between $startTime + t.start_ts and $endTime + t.start_ts ${sql} and callchain_id != -1;` + , {$startTime: selectionParam.leftNs, $endTime: selectionParam.rightNs}) + + } + + queryIOSamples(selectionParam: any){ + let sql = ''; + if(selectionParam.diskIOipids.length > 0){ + sql += `and (s.ipid in (${selectionParam.diskIOipids.join(",")}) and s.type in (5,6)) ` + } + if(selectionParam.diskIOReadIds.length > 0){ + sql += `or (s.ipid in (${selectionParam.diskIOReadIds.join(",")}) and s.type in (1,3)) ` + } + if(selectionParam.diskIOWriteIds.length > 0){ + sql += `or (s.ipid in (${selectionParam.diskIOWriteIds.join(",")}) and s.type in (2,4)) ` + } + this.queryData("fileSystem-queryIoSamples", `select s.callchain_id as callChainId,h.tid,h.name as threadName,s.latency_dur as dur,s.type,p.pid,p.name as processName from bio_latency_sample s,trace_range t +left join process p on p.id = s.ipid +left join thread h on h.id = s.itid +where s.end_ts between $startTime + t.start_ts and $endTime + t.start_ts ${sql} and callchain_id != -1;` + , {$startTime: selectionParam.leftNs, $endTime: selectionParam.rightNs}) + } + + queryEpbfSamples(selectionParam: any){ + let sql = ''; + if(selectionParam.diskIOipids.length > 0&&!selectionParam.diskIOLatency&&!selectionParam.fileSysVirtualMemory){ + sql += ` and s.ipid in (${selectionParam.diskIOipids.join(",")})` + } + this.queryData("fileSystem-queryVirtualMemorySamples", `select s.callchain_id as callChainId,h.tid,h.name as threadName,s.dur,s.type,p.pid,p.name as processName from paged_memory_sample s,trace_range t +left join process p on p.id = s.ipid +left join thread h on h.id = s.itid +where s.end_ts between $startTime + t.start_ts and $endTime + t.start_ts ${sql} and callchain_id != -1;` + , {$startTime: selectionParam.leftNs, $endTime: selectionParam.rightNs}) + } + + freshCurrentCallchains(samples: FileSample[], isTopDown: boolean) { + this.currentTreeMapData = {} + this.currentTreeList = [] + this.allProcess = []; + this.dataSource = [] + let totalCount = 0 + + samples.forEach((sample) => { + totalCount += sample.dur; + let callChains = this.createThreadAndType(sample) + if(callChains.length == 2){ + return + } + let topIndex = isTopDown ? 0 : (callChains.length - 1); + if (callChains.length > 1) { + let root = this.currentTreeMapData[callChains[topIndex].symbolsId + "" + callChains[topIndex].pathId + sample.pid]; + if (root == undefined) { + root = new FileMerageBean(); + this.currentTreeMapData[callChains[topIndex].symbolsId + "" + callChains[topIndex].pathId + sample.pid] = root; + this.currentTreeList.push(root) + } + FileMerageBean.merageCallChainSample(root, callChains[topIndex], sample, false); + this.merageChildrenByIndex(root, callChains, topIndex, sample, isTopDown); + } + }) + let rootMerageMap: any = {} + Object.values(this.currentTreeMapData).forEach((merageData: any) => { + if (rootMerageMap[merageData.pid] == undefined) { + let processMerageData = new FileMerageBean()//新增进程的节点数据 + processMerageData.canCharge = false + processMerageData.symbolName = merageData.processName + processMerageData.symbol = processMerageData.symbolName + processMerageData.children.push(merageData) + processMerageData.initChildren.push(merageData) + processMerageData.dur = merageData.dur; + processMerageData.count = merageData.count; + processMerageData.total = totalCount; + rootMerageMap[merageData.pid] = processMerageData + } else { + rootMerageMap[merageData.pid].children.push(merageData) + rootMerageMap[merageData.pid].initChildren.push(merageData) + rootMerageMap[merageData.pid].dur += merageData.dur; + rootMerageMap[merageData.pid].count += merageData.count; + rootMerageMap[merageData.pid].total = totalCount; + } + merageData.parentNode = rootMerageMap[merageData.pid]//子节点添加父节点的引用 + }) + let id = 0; + this.currentTreeList.forEach((node) => { + node.total = totalCount; + this.setMerageName(node) + if (node.id == "") { + node.id = id + "" + id++ + } + if (node.parentNode) { + if (node.parentNode.id == "") { + node.parentNode.id = id + "" + id++ + } + node.parentId = node.parentNode.id + } + }) + this.allProcess = Object.values(rootMerageMap) + } + + createThreadAndType(sample: FileSample){ + let typeCallchain = new FileCallChain(); + typeCallchain.callChainId = sample.callChainId + let map:any = {} + if(this.currentDataType == "fileSystem"){ + map = FILE_TYPE_MAP + }else if(this.currentDataType == "io"){ + map = DISKIO_TYPE_MAP + }else if(this.currentDataType == "virtualMemory"){ + map = VM_TYPE_MAP + } + // @ts-ignore + typeCallchain.ip = map[sample.type.toString()]||"UNKNOW"; + typeCallchain.symbolsId = sample.type + typeCallchain.pathId = -1; + let threadCallChain = new FileCallChain(); + threadCallChain.callChainId = sample.callChainId + threadCallChain.ip = (sample.threadName||"Thread")+`-${sample.tid}` + threadCallChain.symbolsId = sample.tid; + threadCallChain.pathId = -1; + return [typeCallchain,threadCallChain,...(ProcedureLogicWorkerFileSystem.callChainsMap.get(sample.callChainId)||[])] + } + + + merageChildrenByIndex(currentNode: FileMerageBean, callChainDataList: any[], index: number, sample: FileSample, isTopDown: boolean) { + isTopDown ? index++ : index--; + let isEnd = isTopDown ? (callChainDataList.length == index + 1) : (index == 0) + let node; + if (currentNode.initChildren.filter((child: any) => { + if (child.ip == callChainDataList[index]?.ip + ||((child.symbolsId!=null) + &&child.symbolsId == callChainDataList[index]?.symbolsId + &&child.pathId == callChainDataList[index]?.pathId)) { + node = child; + FileMerageBean.merageCallChainSample(child, callChainDataList[index], sample, isEnd) + return true; + } + return false; + }).length == 0) { + node = new FileMerageBean() + FileMerageBean.merageCallChainSample(node, callChainDataList[index], sample, isEnd) + currentNode.children.push(node) + currentNode.initChildren.push(node) + this.currentTreeList.push(node) + node.parentNode = currentNode + } + if (node && !isEnd) this.merageChildrenByIndex(node, callChainDataList, index, sample, isTopDown) + } + + setMerageName(currentNode: FileMerageBean) { + if (currentNode.pathId == -1) { + currentNode.canCharge = false; + currentNode.symbol = currentNode.ip; + currentNode.symbolName = currentNode.symbol; + currentNode.libName = ""; + currentNode.path = ""; + } else { + currentNode.symbol = ProcedureLogicWorkerFileSystem.data_dict.get(currentNode.symbolsId) || currentNode.ip || 'unkown' + currentNode.path = ProcedureLogicWorkerFileSystem.data_dict.get(currentNode.pathId) || 'unkown' + currentNode.libName = setFileName(currentNode.path) + currentNode.symbolName = `${currentNode.symbol} (${currentNode.libName})` + } + } + + resolvingAction(params: any[]) { + if (params.length > 0) { + params.forEach((item) => { + if (item.funcName && item.funcArgs) { + switch (item.funcName) { + case "getCallChainsBySampleIds": + this.freshCurrentCallchains(this.samplesList, item.funcArgs[0]) + break + case "getCurrentDataFromDb": + this.queryCallchainsSamples(item.funcArgs[0]); + break + case "hideSystemLibrary": + merageBeanDataSplit.hideSystemLibrary(this.allProcess, this.splitMapData); + break + case "hideNumMaxAndMin": + merageBeanDataSplit.hideNumMaxAndMin(this.allProcess, this.splitMapData, item.funcArgs[0], item.funcArgs[1]) + break + case "splitAllProcess": + merageBeanDataSplit.splitAllProcess(this.allProcess, this.splitMapData, item.funcArgs[0]) + break + case "resetAllNode": + merageBeanDataSplit.resetAllNode(this.allProcess, this.currentTreeList, this.searchValue) + break + case "resotreAllNode": + merageBeanDataSplit.resotreAllNode(this.splitMapData, item.funcArgs[0]) + break + case "clearSplitMapData": + this.clearSplitMapData(item.funcArgs[0]) + break + case "splitTree": + merageBeanDataSplit.splitTree(this.splitMapData, this.allProcess, item.funcArgs[0], item.funcArgs[1], item.funcArgs[2], this.currentTreeList, this.searchValue); + break + case "setSearchValue": + this.searchValue = item.funcArgs[0] + break + } + } + }) + this.dataSource = this.allProcess.filter((process) => { + return process.children && process.children.length > 0 + }) + } + return this.dataSource + } + + clearAll() { + this.samplesList = [] + this.splitMapData = {} + this.currentTreeMapData = {} + this.currentTreeList = [] + this.searchValue = "" + this.allProcess = [] + this.dataSource = [] + this.splitMapData = {} + this.currentDataType = "" + } + + clearSplitMapData(symbolName: string) { + delete this.splitMapData[symbolName] + } +} + +class FileCallChain { + callChainId: number = 0; + depth: number = 0; + symbolsId: number = 0; + pathId: number = 0; + ip: string = "" +} + +class FileSample { + type:number = 0 + callChainId:number = 0; + dur:number = 0; + pid:number = 0; + tid:number = 0; + threadName:string = ""; + processName:string = "" +} + +export class FileMerageBean extends MerageBean { + ip: string = "" + symbolsId: number = 0; + pathId: number = 0; + processName: string = ""; + type: number = 0 + + static merageCallChainSample(currentNode: FileMerageBean, callChain: FileCallChain, sample: FileSample, isEnd: boolean) { + if (currentNode.processName == "") { + currentNode.ip = callChain.ip + currentNode.pid = sample.pid + currentNode.canCharge = true + currentNode.pathId = callChain.pathId; + currentNode.symbolsId = callChain.symbolsId; + currentNode.processName = sample.processName || `Process(${sample.pid})` + } + if (isEnd) { + currentNode.selfDur += sample.dur; + currentNode.self = getProbablyTime(currentNode.selfDur) + } + currentNode.dur += sample.dur; + currentNode.count++; + } +} + +export class Stack { + type: number = 0; + symbol: string = ""; + path: string = ""; +} + +export class FileSysEvent { + isSelected:boolean = false; + id: number = 0; + callchainId: number = 0; + startTs: number = 0; + startTsStr: string = ""; + durStr: string = ""; + dur: number = 0; + process: string = ""; + thread: string = ""; + type: number = 0; + typeStr: string = ""; + fd: number = 0; + size: number = 0; + depth: number = 0; + firstArg: string = ""; + secondArg: string = ""; + thirdArg: string = ""; + fourthArg: string = ""; + returnValue: string = ""; + error: string = ""; + path: string = ""; + symbol: string = ""; + backtrace: Array = []; + fileId: number = 0; +} + +export class IoCompletionTimes{ + isSelected:boolean = false; + type:number = 0; + callchainId: number = 0; + startTs: number = 0; + startTsStr: string = ""; + durStr: string = ""; + dur: number = 0; + tid: number = 0; + pid: number = 0; + process: string = ""; + thread: string = ""; + path: string = ""; + pathId:number = 0; + operation: string = ""; + size: number = 0; + sizeStr:string = ""; + blockNumber:string = ""; + tier:number = 0; + backtrace: Array = []; + durPer4kStr: string = "" + durPer4k: number = 0; +} + +export class VirtualMemoryEvent{ + isSelected:boolean = false; + callchainId: number = 0; + startTs: number = 0; + startTsStr: string = ""; + durStr: string = ""; + dur: number = 0; + process: string = ""; + thread: string = ""; + address:string = ""; + size:number = 0; + sizeStr:string = ""; + type:number = 0; + tid:number = 0; + pid:number = 0; + operation: string = ""; +} diff --git a/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerNativeNemory.ts b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerNativeNemory.ts new file mode 100644 index 0000000000000000000000000000000000000000..46b3921a390360c00f4f8b6fe3042a06c5f08b49 --- /dev/null +++ b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerNativeNemory.ts @@ -0,0 +1,937 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + convertJSON, formatRealDateMs, + getByteWithUnit, + getTimeString, + LogicHandler, + MerageBean, merageBeanDataSplit, postMessage, setFileName +} from "./ProcedureLogicWorkerCommon.js"; + +export class ProcedureLogicWorkerNativeMemory extends LogicHandler { + selectTotalSize = 0; + selectTotalCount = 0; + stackCount = 0; + DATA_DICT: Map = new Map(); + FILE_DICT: Map = new Map(); + HEAP_FRAME_MAP: Map> = new Map>(); + NATIVE_MEMORY_DATA: Array = []; + currentTreeMapData: any = {} + currentTreeList: any[] = [] + queryAllCallchainsSamples:NativeHookStatistics[] = []; + currentSamples:NativeHookStatistics[] = [] + allThreads:NativeHookCallInfo[] = [] + splitMapData: any = {} + searchValue: string = "" + currentEventId: string = "" + chartComplete:Map = new Map(); + realTimeDif:number = 0; + responseTypes:{key:number, value:string}[] = [] + + handle(data: any): void { + this.currentEventId = data.id + if (data && data.type) { + switch (data.type) { + case "native-memory-init": + this.clearAll(); + if(data.params.isRealtime) { + this.realTimeDif = data.params.realTimeDif + } + this.initDataDict(); + break + case "native-memory-queryDataDICT": + let dict = convertJSON(data.params.list) || [] + dict.map((d: any) => this.DATA_DICT.set(d['id'], d['data'])); + this.initNMChartData(); + break; + case "native-memory-queryNMChartData": + this.NATIVE_MEMORY_DATA = convertJSON(data.params.list) || []; + this.initNMFrameData(); + break; + case "native-memory-queryNMFrameData": + let arr = convertJSON(data.params.list) || []; + this.initNMStack(arr); + arr = []; + self.postMessage({ + id: data.id, + action: "native-memory-init", + results: [] + }); + break; + case "native-memory-queryCallchainsSamples": + if (data.params.list) { + let callchainsSamples = convertJSON(data.params.list) || []; + this.queryAllCallchainsSamples = callchainsSamples; + this.freshCurrentCallchains(callchainsSamples,true) + // @ts-ignore + self.postMessage({ + id: data.id, + action: data.action, + results: this.allThreads + }); + }else { + this.queryCallchainsSamples(data.params.leftNs, data.params.rightNs,data.params.types) + } + break; + case "native-memory-action": + if (data.params) { + // @ts-ignore + + self.postMessage({ + id: data.id, + action: data.action, + results: this.resolvingAction(data.params) + }); + } + break; + case "native-memory-chart-action": + if (data.params) { + postMessage(data.id, data.action, this.resolvingActionNativeMemoryChartData(data.params)); + } + break; + case "native-memory-calltree-action": + if (data.params) { + self.postMessage({id: data.id, action: data.action, results: this.resolvingNMCallAction(data.params)}); + } + break; + case "native-memory-init-responseType": + this.initResponseTypeList(data.params); + self.postMessage({ + id: data.id, + action: data.action, + results: [] + }); + break; + case "native-memory-get-responseType": + self.postMessage({id: data.id, action: data.action, results: this.responseTypes}); + break; + } + } + } + + queryData(queryName: string, sql: string, args: any) { + self.postMessage({ + id: this.currentEventId, + type: queryName, + isQuery: true, + args: args, + sql: sql + }) + } + + initDataDict() { + this.queryData("native-memory-queryDataDICT", `select * from data_dict;`, {}) + } + + initNMChartData() { + this.queryData("native-memory-queryNMChartData", ` + select * from ( + select + h.start_ts - t.start_ts as startTime, + h.heap_size as heapSize, + (case when h.event_type = 'AllocEvent' then 0 else 1 end) as eventType + from native_hook h ,trace_range t + where h.start_ts >= t.start_ts + and h.start_ts <= t.end_ts + and (h.event_type = 'AllocEvent' or h.event_type = 'MmapEvent') + union + select + h.end_ts - t.start_ts as startTime, + h.heap_size as heapSize, + (case when h.event_type = 'AllocEvent' then 2 else 3 end) as eventType + from native_hook h ,trace_range t + where h.start_ts >= t.start_ts + and h.start_ts <= t.end_ts + and h.end_ts not null + and (h.event_type = 'AllocEvent' or h.event_type = 'MmapEvent') + ) + order by startTime; + `, {}) + } + + initResponseTypeList(list:any[]){ + this.responseTypes = [{ + key:-1, + value:"ALL" + }] + list.forEach((item)=>{ + if(item.lastLibId == null){ + this.responseTypes.push({ + key:0, + value:"-" + }) + }else { + this.responseTypes.push({ + key:item.lastLibId, + value:this.groupCutFilePath(item.lastLibId,item.value)||"-" + }) + } + }) + } + + initNMFrameData() { + this.queryData("native-memory-queryNMFrameData", ` + select h.symbol_id as symbolId, h.file_id as fileId, h.depth, h.callchain_id as eventId, h.vaddr as addr + from native_hook_frame h + `, {}) + } + + initNMStack(frameArr:Array){ + frameArr.map((frame) => { + let frameEventId = frame.eventId; + if(this.HEAP_FRAME_MAP.has(frameEventId)){ + this.HEAP_FRAME_MAP.get(frameEventId)!.push(frame); + }else{ + this.HEAP_FRAME_MAP.set(frameEventId,[frame]) + } + }) + } + + resolvingAction(paramMap: Map): Array { + let actionType = paramMap.get("actionType"); + if (actionType == "call-info") { + return this.resolvingActionCallInfo(paramMap); + } else if (actionType == "native-memory") { + return this.resolvingActionNativeMemory(paramMap); + } else if (actionType == "memory-stack") { + return this.resolvingActionNativeMemoryStack(paramMap); + } else { + return [] + } + } + + resolvingActionNativeMemoryChartData(paramMap: Map): Array { + let nativeMemoryType: number = paramMap.get("nativeMemoryType") as number; + let totalNS: number = paramMap.get("totalNS") as number; + let arr: Array = []; + let maxSize = 0,maxDensity = 0,minSize = 0,minDensity = 0; + let tempSize = 0,tempDensity = 0; + let filterLen = 0,filterLevel = 0; + let putArr = (ne:NativeEvent,filterLevel:number)=>{ + let heap = new HeapStruct(); + heap.startTime = ne.startTime; + if(arr.length == 0){ + if (ne.eventType == 0 || ne.eventType == 1) { + heap.density = 1; + heap.heapsize = ne.heapSize; + } else { + heap.density = -1; + heap.heapsize = (0 - ne.heapSize); + } + maxSize = heap.heapsize; + maxDensity = heap.density; + minSize = heap.heapsize; + minDensity = heap.density; + arr.push(heap); + }else{ + let last = arr[arr.length -1]; + last.dur = heap.startTime! - last.startTime!; + if(last.dur > filterLevel){ + if (ne.eventType == 0 || ne.eventType == 1) { + heap.density = last.density! + tempDensity + 1 + heap.heapsize = last.heapsize! + tempSize + ne.heapSize; + } else { + heap.density = last.density! + tempDensity - 1 + heap.heapsize = last.heapsize! + tempSize - ne.heapSize; + } + tempDensity = 0; + tempSize = 0; + if(heap.density > maxDensity){ + maxDensity = heap.density + } + if(heap.density < minDensity){ + minDensity = heap.density + } + if (heap.heapsize > maxSize) { + maxSize = heap.heapsize; + } + if (heap.heapsize < minSize) { + minSize = heap.heapsize; + } + arr.push(heap) + }else{ + if (ne.eventType == 0 || ne.eventType == 1) { + tempDensity = tempDensity +1 + tempSize = tempSize + ne.heapSize; + } else { + tempDensity = tempDensity - 1 + tempSize = tempSize - ne.heapSize; + } + } + } + } + if(nativeMemoryType == 1){ + let temp = this.NATIVE_MEMORY_DATA.filter((ne) => ne.eventType == 0 || ne.eventType == 2); + filterLen = temp.length; + filterLevel = this.getFilterLevel(filterLen); + temp.map((ne) => putArr(ne,filterLevel)) + temp.length = 0; + }else if(nativeMemoryType == 2){ + let temp = this.NATIVE_MEMORY_DATA.filter((ne) => ne.eventType == 1 || ne.eventType == 3); + filterLen = temp.length; + filterLevel = this.getFilterLevel(filterLen); + temp.map((ne) => putArr(ne,filterLevel)); + temp.length = 0; + }else{ + filterLen = this.NATIVE_MEMORY_DATA.length; + let filterLevel = this.getFilterLevel(filterLen); + this.NATIVE_MEMORY_DATA.map((ne) => putArr(ne,filterLevel)) + } + if(arr.length > 0){ + arr[arr.length -1].dur = totalNS - arr[arr.length -1].startTime! + } + arr.map((heap)=>{ + heap.maxHeapSize = maxSize; + heap.maxDensity = maxDensity; + heap.minHeapSize = minSize; + heap.minDensity = minDensity; + }) + this.chartComplete.set(nativeMemoryType,true); + if(this.chartComplete.has(0) && this.chartComplete.has(1) && this.chartComplete.has(2)){ + this.NATIVE_MEMORY_DATA = []; + } + return arr; + } + + resolvingActionNativeMemoryStack(paramMap: Map) { + let eventId = paramMap.get("eventId"); + let frameArr = this.HEAP_FRAME_MAP.get(eventId) || []; + let arr: Array = []; + frameArr.map((frame) => { + let target = new NativeHookCallInfo(); + target.eventId = frame.eventId; + target.depth = frame.depth; + target.addr = frame.addr; + target.symbol = this.groupCutFilePath(frame.symbolId,this.DATA_DICT.get(frame.symbolId)||"" )??""; + target.library = this.groupCutFilePath(frame.fileId,this.DATA_DICT.get(frame.fileId)||"") ?? ""; + target.title = `[ ${target.symbol} ] ${target.library}`; + target.type = (target.library.endsWith(".so.1") || target.library.endsWith(".dll") || target.library.endsWith(".so")) ? 0 : 1; + arr.push(target); + }) + return arr; + } + + resolvingActionNativeMemory(paramMap: Map): Array { + let dataSource = paramMap.get("data") as Array; + let filterAllocType = paramMap.get("filterAllocType"); + let filterEventType = paramMap.get("filterEventType"); + let filterResponseType = paramMap.get("filterResponseType"); + let leftNs = paramMap.get("leftNs"); + let rightNs = paramMap.get("rightNs"); + let statisticsSelection = paramMap.get("statisticsSelection"); + let filter = dataSource.filter((item) => { + if (item.subTypeId != null && item.subType == undefined) { + item.subType = this.DATA_DICT.get(item.subTypeId)||"-" + } + let filterAllocation = true + if (filterAllocType == "1") { + filterAllocation = item.startTs >= leftNs && item.startTs <= rightNs + && (item.endTs > rightNs || item.endTs == 0 || item.endTs == null) + } else if (filterAllocType == "2") { + filterAllocation = item.startTs >= leftNs && item.startTs <= rightNs + && item.endTs <= rightNs && item.endTs != 0 && item.endTs != null; + } + let filterNative = this.getTypeFromIndex(parseInt(filterEventType), item, statisticsSelection) + let filterLastLib = filterResponseType == -1?true:(filterResponseType == item.lastLibId) + return filterAllocation && filterNative && filterLastLib + }) + let data: Array = []; + for (let i = 0, len = filter.length; i < len; i++) { + let hook = filter[i]; + let memory = new NativeMemory(); + memory.index = i; + memory.eventId = hook.eventId; + memory.eventType = hook.eventType; + memory.subType = hook.subType; + memory.heapSize = hook.heapSize; + memory.endTs = hook.endTs; + memory.heapSizeUnit = getByteWithUnit(hook.heapSize); + memory.addr = "0x" + hook.addr; + memory.startTs = hook.startTs; + memory.timestamp = this.realTimeDif == 0?getTimeString(hook.startTs):formatRealDateMs(hook.startTs + this.realTimeDif); + memory.state = (hook.endTs > leftNs && hook.endTs <= rightNs) ? "Freed" : "Existing"; + memory.threadId = hook.tid; + memory.threadName = hook.threadName; + memory.lastLibId = hook.lastLibId; + (memory as any).isSelected = hook.isSelected; + let arr = this.HEAP_FRAME_MAP.get(hook.eventId) || [] + let frame = Array.from(arr).reverse().find((item) => { + let fileName = this.DATA_DICT.get(item.fileId); + return !(( fileName?? "").includes("libc++") || (fileName ?? "").includes("musl")); + }) + if(frame == null || frame == undefined){ + if(arr.length > 0){ + frame = arr[0]; + } + } + if (frame != null && frame != undefined) { + memory.symbol = this.groupCutFilePath(frame.symbolId,this.DATA_DICT.get(frame.symbolId)||"" ) ; + memory.library = this.groupCutFilePath(frame.fileId,this.DATA_DICT.get(frame.fileId)||"Unknown Path"); + }else{ + memory.symbol = "-"; + memory.library = "-"; + } + data.push(memory); + } + return data + } + + resolvingActionCallInfo(paramMap: Map): Array { + let dataSource = paramMap.get("data") as Array; + let filterAllocType = paramMap.get("filterAllocType"); + let filterEventType = paramMap.get("filterEventType"); + let leftNs = paramMap.get("leftNs"); + let rightNs = paramMap.get("rightNs"); + let filter: Array = []; + dataSource.map((item) => { + let filterAllocation = true; + let filterNative = true; + if (filterAllocType == "1") { + filterAllocation = item.startTs >= leftNs && item.startTs <= rightNs + && (item.endTs > rightNs || item.endTs == 0 || item.endTs == null) + } else if (filterAllocType == "2") { + filterAllocation = item.startTs >= leftNs && item.startTs <= rightNs + && item.endTs <= rightNs && item.endTs != 0 && item.endTs != null; + } + if (filterEventType == "1") { + filterNative = item.eventType == "AllocEvent" + } else if (filterEventType == "2") { + filterNative = item.eventType == "MmapEvent" + } + if (filterAllocation && filterNative) { + filter.push(item); + } + }) + this.freshCurrentCallchains(filter,true) + return this.allThreads; + } + + groupCutFilePath(fileId:number,path:string):string{ + let name = ""; + if(this.FILE_DICT.has(fileId)){ + name = this.FILE_DICT.get(fileId) ?? ""; + }else { + let currentPath = path.substring(path.lastIndexOf("/")+1); + this.FILE_DICT.set(fileId,currentPath) + name = currentPath; + } + return name == "" ? "-" : name + } + + groupByWithTid(data: Array): Array { + let tidMap = new Map(); + for (let call of data) { + if (tidMap.has(call.tid)) { + let tidCall = tidMap.get(call.tid); + tidCall!.size += call.size; + tidCall!.heapSizeStr = `${getByteWithUnit(tidCall!.size)}`; + tidCall!.heapPercent = `${(tidCall!.size / this.selectTotalSize * 100).toFixed(1)}%` + tidCall!.count += call.count; + tidCall!.countValue = `${tidCall!.count}` + tidCall!.countPercent = `${(tidCall!.count / this.selectTotalCount * 100).toFixed(1)}%` + tidCall!.children.push(call); + } else { + let tidCall = new NativeHookCallInfo(); + tidCall.id = "tid_" + call.tid; + tidCall.count = call.count; + tidCall!.countValue = `${call.count}` + tidCall!.countPercent = `${(tidCall!.count / this.selectTotalCount * 100).toFixed(1)}%` + tidCall.size = call.size; + tidCall.heapSizeStr = `${getByteWithUnit(tidCall!.size)}`; + tidCall!.heapPercent = `${(tidCall!.size / this.selectTotalSize * 100).toFixed(1)}%` + tidCall.title = (call.threadName == null ? 'Thread' : call.threadName) + " [ " + call.tid + " ]"; + tidCall.symbol = tidCall.title; + tidCall.addr = tidCall.addr; + tidCall.type = -1; + tidCall.children.push(call); + tidMap.set(call.tid, tidCall); + } + } + let showData = Array.from(tidMap.values()) + return showData; + } + + mergeTree(target: NativeHookCallInfo, src: NativeHookCallInfo) { + let len = src.children.length; + src.size += target.size; + src.heapSizeStr = `${getByteWithUnit(src!.size)}`; + src.heapPercent = `${(src!.size / this.selectTotalSize * 100).toFixed(1)}%` + if (len == 0) { + src.children.push(target); + } else { + let index = src.children.findIndex((hook) => hook.symbol == target.symbol && hook.depth == target.depth); + if (index != -1) { + let srcChild = src.children[index]; + srcChild.count += target.count; + srcChild!.countValue = `${srcChild.count}` + srcChild!.countPercent = `${(srcChild!.count / this.selectTotalCount * 100).toFixed(1)}%` + if (target.children.length > 0) { + this.mergeTree(target.children[0], srcChild) + } else { + srcChild.size += target.size; + srcChild.heapSizeStr = `${getByteWithUnit(src!.size)}`; + srcChild.heapPercent = `${(srcChild!.size / this.selectTotalSize * 100).toFixed(1)}%` + } + } else { + src.children.push(target) + } + } + } + + traverseSampleTree(stack: NativeHookCallInfo, hook: NativeHookStatistics) { + stack.count += 1; + stack.countValue = `${stack.count}` + stack.countPercent = `${(stack.count / this.selectTotalCount * 100).toFixed(1)}%` + stack.size += hook.heapSize; + stack.tid = hook.tid; + stack.threadName = hook.threadName; + stack.heapSizeStr = `${getByteWithUnit(stack.size)}`; + stack.heapPercent = `${(stack.size / this.selectTotalSize * 100).toFixed(1)}%`; + if (stack.children.length > 0) { + stack.children.map((child) => { + this.traverseSampleTree(child as NativeHookCallInfo, hook); + }) + } + } + + traverseTree(stack: NativeHookCallInfo, hook: NativeHookStatistics) { + stack.count = 1; + stack.countValue = `${stack.count}` + stack.countPercent = `${(stack!.count / this.selectTotalCount * 100).toFixed(1)}%` + stack.size = hook.heapSize; + stack.tid = hook.tid; + stack.threadName = hook.threadName; + stack.heapSizeStr = `${getByteWithUnit(stack!.size)}`; + stack.heapPercent = `${(stack!.size / this.selectTotalSize * 100).toFixed(1)}%`; + if (stack.children.length > 0) { + stack.children.map((child) => { + this.traverseTree(child as NativeHookCallInfo, hook); + }) + } + } + + getTypeFromIndex(indexOf: number, item: NativeHookStatistics, statisticsSelection: Array): boolean { + if (indexOf == -1) { + return false; + } + if (indexOf < 3) { + if (indexOf == 0) { + return true + } else if (indexOf == 1) { + return item.eventType == "AllocEvent" + } else if (indexOf == 2) { + return item.eventType == "MmapEvent" + } + } else if (indexOf - 3 < statisticsSelection.length) { + let selectionElement = statisticsSelection[indexOf - 3]; + + if (selectionElement.memoryTap != undefined && selectionElement.max != undefined) { + if (selectionElement.memoryTap.indexOf("Malloc") != -1) { + return item.eventType == "AllocEvent" && item.heapSize == selectionElement.max + } else if (selectionElement.memoryTap.indexOf("Mmap") != -1) { + return item.eventType == "MmapEvent" && item.heapSize == selectionElement.max + } else { + return item.subType == selectionElement.memoryTap && item.heapSize == selectionElement.max + } + } + } + return false; + } + + clearAll() { + this.DATA_DICT.clear(); + this.FILE_DICT.clear(); + this.splitMapData = {}; + this.currentSamples = []; + this.allThreads = []; + this.queryAllCallchainsSamples = []; + this.HEAP_FRAME_MAP.clear(); + this.NATIVE_MEMORY_DATA = []; + this.chartComplete.clear(); + this.realTimeDif = 0; + } + + listToTree(target: NativeHookCallInfo, src: NativeHookCallInfo) { + if (target.depth == src.depth + 1) { + src.children.push(target) + } else { + if (src.children.length > 0) { + this.listToTree(target, src.children[0]); + } + } + } + + queryCallchainsSamples(leftNs: number, rightNs: number, types: Array){ + this.queryData("native-memory-queryCallchainsSamples", ` + select + callchain_id as eventId, + event_type as eventType, + heap_size as heapSize, + (A.start_ts - B.start_ts) as startTs, + (A.end_ts - B.start_ts) as endTs, + tid, + ifnull(last_lib_id,0) as lastLibId, + t.name as threadName + from + native_hook A, + trace_range B + left join + thread t + on + A.itid = t.id + where + A.start_ts - B.start_ts + between ${leftNs} and ${rightNs} and A.event_type in (${types.join(",")}) + `, {}) + } + + freshCurrentCallchains(samples: NativeHookStatistics[], isTopDown: boolean){ + this.currentTreeMapData = {}; + this.currentTreeList = []; + let totalSize = 0; + let totalCount = 0; + samples.forEach((sample) => { + if(sample.eventId == -1){ + return + } + totalSize += sample.heapSize; + totalCount += sample.count||1 + let callChains = this.createThreadSample(sample) + let topIndex = isTopDown ? 0 : (callChains.length - 1); + let root = this.currentTreeMapData[sample.tid + "-" + (callChains[topIndex].symbolId||"")+"-"+(callChains[topIndex].fileId||"")]; + if (root == undefined) { + root = new NativeHookCallInfo() + this.currentTreeMapData[sample.tid + "-" + (callChains[topIndex].symbolId||"")+"-"+(callChains[topIndex].fileId||"")] = root + this.currentTreeList.push(root) + } + NativeHookCallInfo.merageCallChainSample(root,callChains[topIndex],sample) + if(callChains.length > 1){ + this.merageChildrenByIndex(root,callChains,topIndex,sample,isTopDown) + } + }) + let rootMerageMap: any = {} + let threads = Object.values(this.currentTreeMapData); + threads.forEach((merageData: any) => { + if (rootMerageMap[merageData.tid] == undefined) { + let threadMerageData = new NativeHookCallInfo()//新增进程的节点数据 + threadMerageData.canCharge = false + threadMerageData.type = -1; + threadMerageData.symbolName = `${merageData.threadName||"Thread"} [${merageData.tid}]` + threadMerageData.symbol = threadMerageData.symbolName + threadMerageData.children.push(merageData) + threadMerageData.initChildren.push(merageData) + threadMerageData.count = merageData.count||1; + threadMerageData.heapSize = merageData.heapSize + threadMerageData.totalCount = totalCount; + threadMerageData.totalSize = totalSize; + rootMerageMap[merageData.tid] = threadMerageData + } else { + rootMerageMap[merageData.tid].children.push(merageData) + rootMerageMap[merageData.tid].initChildren.push(merageData) + rootMerageMap[merageData.tid].count += merageData.count||1; + rootMerageMap[merageData.tid].heapSize += merageData.heapSize + rootMerageMap[merageData.tid].totalCount = totalCount; + rootMerageMap[merageData.tid].totalSize = totalSize; + } + merageData.parentNode = rootMerageMap[merageData.tid]//子节点添加父节点的引用 + }) + let id = 0; + this.currentTreeList.forEach((node) => { + node.totalCount = totalCount; + node.totalSize = totalSize; + this.setMerageName(node) + if (node.id == "") { + node.id = id + "" + id++ + } + if (node.parentNode) { + if (node.parentNode.id == "") { + node.parentNode.id = id + "" + id++ + } + node.parentId = node.parentNode.id + } + }) + this.allThreads = Object.values(rootMerageMap) as NativeHookCallInfo[] + } + + groupCallchainSample(paramMap: Map){ + let groupMap:any = {} + let filterAllocType = paramMap.get("filterAllocType"); + let filterEventType = paramMap.get("filterEventType"); + let filterResponseType = paramMap.get("filterResponseType"); + let leftNs = paramMap.get("leftNs"); + let rightNs = paramMap.get("rightNs"); + if(filterAllocType == "0"&&filterEventType == "0" && filterResponseType == -1){ + this.currentSamples = this.queryAllCallchainsSamples + return + } + let filter = this.queryAllCallchainsSamples.filter((item) => { + let filterAllocation = true + if (filterAllocType == "1") { + filterAllocation = item.startTs >= leftNs && item.startTs <= rightNs + && (item.endTs > rightNs || item.endTs == 0 || item.endTs == null) + } else if (filterAllocType == "2") { + filterAllocation = item.startTs >= leftNs && item.startTs <= rightNs + && item.endTs <= rightNs && item.endTs != 0 && item.endTs != null; + } + let filterLastLib = filterResponseType == -1?true:(filterResponseType == item.lastLibId) + let filterNative = this.getTypeFromIndex(parseInt(filterEventType), item, []) + return filterAllocation && filterNative && filterLastLib + }) + filter.forEach((sample)=>{ + let currentNode = groupMap[sample.tid + "-" + sample.eventId]||new NativeHookStatistics() + if(currentNode.count == 0){ + Object.assign(currentNode,sample) + currentNode.count++ + }else { + currentNode.count++ + currentNode.heapSize += sample.heapSize + } + groupMap[sample.tid + "-" + sample.eventId] = currentNode + }) + this.currentSamples = Object.values(groupMap) + } + + createThreadSample(sample:NativeHookStatistics){ + return this.HEAP_FRAME_MAP.get(sample.eventId)||[] + } + + merageChildrenByIndex(currentNode:NativeHookCallInfo,callChainDataList: any[], index: number, sample: NativeHookStatistics, isTopDown: boolean){ + isTopDown ? index++ : index--; + let isEnd = isTopDown ? (callChainDataList.length == index + 1) : (index == 0) + let node; + if (currentNode.initChildren.filter((child: any) => { + if ((child.symbolId == callChainDataList[index]?.symbolId&&child.fileId == callChainDataList[index]?.fileId)) { + node = child; + NativeHookCallInfo.merageCallChainSample(child, callChainDataList[index], sample) + return true; + } + return false; + }).length == 0) { + node = new NativeHookCallInfo() + NativeHookCallInfo.merageCallChainSample(node, callChainDataList[index], sample) + currentNode.children.push(node) + currentNode.initChildren.push(node) + this.currentTreeList.push(node) + node.parentNode = currentNode + } + if (node && !isEnd) this.merageChildrenByIndex(node, callChainDataList, index, sample, isTopDown) + } + + setMerageName(currentNode: NativeHookCallInfo){ + currentNode.symbol = this.groupCutFilePath(currentNode.symbolId,this.DATA_DICT.get(currentNode.symbolId)||"" )??"unkown"; + currentNode.path = this.DATA_DICT.get(currentNode.fileId)||"unkown" + currentNode.libName = setFileName(currentNode.path) + currentNode.lib = currentNode.path + currentNode.symbolName = `[${currentNode.symbol}] ${currentNode.libName}` + currentNode.type = (currentNode.libName.endsWith(".so.1") || currentNode.libName.endsWith(".dll") || currentNode.libName.endsWith(".so")) ? 0 : 1; + } + + clearSplitMapData(symbolName: string) { + delete this.splitMapData[symbolName] + } + + resolvingNMCallAction(params: any[]){ + if (params.length > 0) { + params.forEach((item) => { + if (item.funcName && item.funcArgs) { + switch (item.funcName) { + case "groupCallchainSample": + this.groupCallchainSample(item.funcArgs[0] as Map) + break + case "getCallChainsBySampleIds": + this.freshCurrentCallchains(this.currentSamples, item.funcArgs[0]) + break + case "hideSystemLibrary": + merageBeanDataSplit.hideSystemLibrary(this.allThreads, this.splitMapData); + break + case "hideNumMaxAndMin": + merageBeanDataSplit.hideNumMaxAndMin(this.allThreads, this.splitMapData, item.funcArgs[0], item.funcArgs[1]) + break + case "splitAllProcess": + merageBeanDataSplit.splitAllProcess(this.allThreads, this.splitMapData, item.funcArgs[0]) + break + case "resetAllNode": + merageBeanDataSplit.resetAllNode(this.allThreads, this.currentTreeList, this.searchValue) + break + case "resotreAllNode": + merageBeanDataSplit.resotreAllNode(this.splitMapData, item.funcArgs[0]) + break + case "splitTree": + merageBeanDataSplit.splitTree(this.splitMapData, this.allThreads, item.funcArgs[0], item.funcArgs[1], item.funcArgs[2], this.currentTreeList, this.searchValue); + break + case "setSearchValue": + this.searchValue = item.funcArgs[0] + break + case "clearSplitMapData": + this.clearSplitMapData(item.funcArgs[0]) + break + } + } + }) + } + return this.allThreads.filter((thread) => { + return thread.children && thread.children.length > 0 + }) + } + + getFilterLevel(len:number):number{ + if(len > 100_0000){ + return 10_0000; + }else if(len > 50_0000){ + return 5_0000; + }else if(len > 30_0000){ + return 3_5000 + }else if(len > 15_0000){ + return 1_5000 + }else{ + return 0 + } + } +} + +export class HeapTreeDataBean { + MoudleName: string | undefined + AllocationFunction: string | undefined + symbolId: number = 0 + fileId: number = 0 + startTs: number = 0 + endTs: number = 0 + eventType: string | undefined + depth: number = 0 + heapSize: number = 0 + eventId: number = 0 + addr : string = '' +} + +export class NativeHookStatistics { + eventId: number = 0; + eventType: string = ""; + subType: string = ""; + subTypeId: number = 0; + heapSize: number = 0; + addr: string = ""; + startTs: number = 0; + endTs: number = 0; + sumHeapSize: number = 0; + max: number = 0; + count: number = 0; + tid: number = 0; + threadName: string = ""; + lastLibId:number = 0; + isSelected: boolean = false; +} + +export class NativeHookCallInfo extends MerageBean { + #totalCount: number = 0 + #totalSize:number = 0; + library: string = ""; + symbolId: number = 0 + fileId: number = 0 + title: string = ""; + count: number = 0; + countValue: string = "" + countPercent: string = ""; + type: number = 0; + heapSize: number = 0; + heapPercent: string = ""; + heapSizeStr: string = ""; + eventId: number = 0; + tid: number = 0; + threadName: string = ""; + eventType:string = ""; + isSelected: boolean = false; + + set totalCount(total:number){ + this.#totalCount = total; + this.countValue = this.count + ""; + this.size = this.heapSize; + this.countPercent = `${(this.count / total * 100).toFixed(1)}%`; + } + + get totalCount(){ + return this.#totalCount + } + + set totalSize(total:number){ + this.#totalSize = total; + this.heapSizeStr = `${getByteWithUnit(this.heapSize)}` + this.heapPercent = `${(this.heapSize / total * 100).toFixed(1)}%`; + } + + get totalSize(){ + return this.#totalSize + } + + static merageCallChainSample(currentNode: NativeHookCallInfo, callChain: HeapTreeDataBean, sample: NativeHookStatistics){ + if(currentNode.symbol == undefined||currentNode.symbol == ""){ + currentNode.symbol = callChain.AllocationFunction||""; + currentNode.addr = callChain.addr; + currentNode.eventId = sample.eventId; + currentNode.eventType = sample.eventType; + currentNode.symbolId = callChain.symbolId; + currentNode.fileId = callChain.fileId; + currentNode.tid = sample.tid + } + currentNode.count += sample.count||1; + currentNode.heapSize += sample.heapSize; + } + +} + +export class NativeMemory { + index: number = 0; + eventId: number = 0; + eventType: string = ""; + subType: string = ""; + addr: string = ""; + startTs: number = 0; + endTs: number = 0; + timestamp: string = "" + heapSize: number = 0; + heapSizeUnit: string = ""; + symbol: string = ""; + library: string = ""; + lastLibId:number = 0; + isSelected: boolean = false; + state: string = ""; + threadId: number = 0; + threadName: string = ""; +} + +export class HeapStruct { + startTime: number | undefined + endTime: number | undefined + dur: number | undefined + density: number | undefined + heapsize: number | undefined + maxHeapSize: number = 0 + maxDensity: number = 0 + minHeapSize: number = 0 + minDensity: number = 0 +} + +export class NativeEvent { + startTime: number = 0; + heapSize: number = 0; + eventType: number = 0; +} + +export class StatisticsSelection { + memoryTap: string = ""; + max: number = 0; +} \ No newline at end of file diff --git a/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts new file mode 100644 index 0000000000000000000000000000000000000000..f06b7bd8ed20c7614018339c46ec36f6da5fa718 --- /dev/null +++ b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts @@ -0,0 +1,893 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {LogicHandler,ChartStruct,convertJSON} from "./ProcedureLogicWorkerCommon.js"; + + +export class ProcedureLogicWorkerPerf extends LogicHandler{ + systmeRuleName = "/system/" + numRuleName = "/max/min/" + filesData: any = {} + samplesData: any = {} + threadData: any = {} + callChainData: any = {} + splitMapData: any = {} + currentTreeMapData: any = {} + currentTreeList: any[] = [] + searchValue: string = "" + dataSource:PerfCallChainMerageData[] = [] + allProcess:PerfCallChainMerageData[] = [] + callChainMap: Map = new Map() + queryFunc:Function|undefined = undefined + isActualQuery:boolean = false; + static cmdLineResult:any = undefined + currentEventId:string = "" + + handle(data:any): void { + this.currentEventId = data.id + if (data&&data.type) { + switch(data.type){ + case "perf-init": + ProcedureLogicWorkerPerf.cmdLineResult = data.params; + this.initPerfFiles() + break + case "perf-queryPerfFiles": + let files = convertJSON(data.params.list)||[] + files.forEach((file:any) => { + this.filesData[file.fileId] = this.filesData[file.fileId] || [] + PerfFile.setFileName(file) + this.filesData[file.fileId].push(file) + }) + this.initPerfThreads() + break; + case "perf-queryPerfThread": + let threads = convertJSON(data.params.list)||[] + threads.forEach((thread:any) => { + this.threadData[thread.tid] = thread + }) + this.initPerfCalls() + break; + case "perf-queryPerfCalls": + let perfCalls = convertJSON(data.params.list)||[] + if (perfCalls.length != 0) { + perfCalls.forEach((perfCall:any)=>{ + this.callChainMap.set(perfCall.sampleId,perfCall) + }) + } + this.initPerfCallchains() + break; + case "perf-queryPerfCallchains": + let arr = convertJSON(data.params.list)||[] + this.initCallChainTopDown(arr) + // @ts-ignore + self.postMessage({id: data.id, action: data.action, results: this.callChainMap}); + break; + case "perf-queryCallchainsGroupSample": + this.samplesData = convertJSON(data.params.list)||[] + self.postMessage({id: data.id, action: data.action, results: this.resolvingAction([{ + funcName:"getCallChainsBySampleIds", + funcArgs:[true] + }])}); + break; + case "perf-action": + if(data.params){ + let filter = data.params.filter((item:any) => item.funcName == "getCurrentDataFromDb"); + if (filter.length == 0) { + // @ts-ignore + self.postMessage({id: data.id, action: data.action, results: this.resolvingAction(data.params)}); + }else { + this.resolvingAction(data.params) + } + } + break; + } + } + } + + queryData(queryName:string,sql:string,args:any){ + self.postMessage({ + id:this.currentEventId, + type:queryName, + isQuery:true, + args:args, + sql:sql + }) + } + + initPerfFiles() { + this.clearAll() + this.queryData("perf-queryPerfFiles", `select file_id as fileId,symbol,path from perf_files`, {}) + } + + initPerfThreads(){ + this.queryData("perf-queryPerfThread", `select a.thread_id as tid,a.thread_name as threadName,a.process_id as pid,b.thread_name as processName from perf_thread a left join (select * from perf_thread where thread_id = process_id) b on a.process_id = b.thread_id`, {}) + } + + initPerfCalls(){ + this.queryData("perf-queryPerfCalls",`select count(callchain_id) as depth,callchain_id as sampleId,name from perf_callchain group by callchain_id`,{}) + } + + initPerfCallchains(){ + this.queryData("perf-queryPerfCallchains",`select c.name,c.callchain_id as sampleId,c.vaddr_in_file as vaddrInFile,c.file_id as fileId,c.symbol_id as symbolId from perf_callchain c`, + {}) + } + + getCurrentDataFromDb(selectionParam:any){ + let cpus = selectionParam.perfAll ? [] : selectionParam.perfCpus + let processes = selectionParam.perfAll ? [] : selectionParam.perfProcess + let threads = selectionParam.perfAll ? [] : selectionParam.perfThread + let sql = '' + if (cpus.length != 0 || processes.length != 0 || threads.length != 0) { + let arg1 = cpus.length > 0 ? `or s.cpu_id in (${cpus.join(",")}) ` : ''; + let arg2 = processes.length > 0 ? `or thread.process_id in (${processes.join(",")}) ` : ''; + let arg3 = threads.length > 0 ? `or s.thread_id in (${threads.join(",")})` : ''; + let arg = `${arg1}${arg2}${arg3}`.substring(3); + sql = ` and (${arg})` + } + this.queryData("perf-queryCallchainsGroupSample",` +select p.callchain_id as sampleId,p.thread_state as threadState,p.thread_id as tid,p.count,p.process_id as pid from (select callchain_id,s.thread_id,thread_state,process_id,count(callchain_id) as count +from perf_sample s,trace_range t left join perf_thread thread on s.thread_id = thread.thread_id +where timestamp_trace between $startTime + t.start_ts and $endTime + t.start_ts and callchain_id != -1 and s.thread_id != 0 ${sql} +group by callchain_id,s.thread_id,thread_state,process_id) p` + ,{$startTime:selectionParam.leftNs,$endTime:selectionParam.rightNs,$sql:sql}) + } + + clearAll(){ + this.filesData = {} + this.samplesData = {} + this.threadData= {} + this.callChainData = {} + this.splitMapData = {} + this.currentTreeMapData = {} + this.currentTreeList = [] + this.searchValue = "" + this.dataSource = [] + this.allProcess = [] + this.callChainMap = new Map() + } + + initCallChainBottomUp(callChains: PerfCallChain[]) { + callChains.forEach((callChain, index) => { + if (this.threadData[callChain.tid] == undefined) { + return + } + this.setCallChainName(callChain); + this.addGroupData(callChain) + if (index + 1 < callChains.length && callChains[index + 1].sampleId == callChain.sampleId) { + PerfCallChain.setPreviousNode(callChain, callChains[index + 1]) + } + if (callChains.length == index + 1 || callChains[index + 1].sampleId != callChain.sampleId) { + this.addProcessThreadStateData(callChain) + } + }) + } + + initCallChainTopDown(callChains: PerfCallChain[]) { + this.callChainData = {} + callChains.forEach((callChain, index) => { + this.setCallChainName(callChain); + this.addGroupData(callChain) + let callChainDatum = this.callChainData[callChain.sampleId]; + if(callChainDatum.length > 1){ + PerfCallChain.setNextNode(callChainDatum[callChainDatum.length - 2], callChainDatum[callChainDatum.length - 1]) + } + }) + } + + setCallChainName(callChain: PerfCallChain) {//设置调用栈的名称 + callChain.canCharge = true; + if (callChain.symbolId == -1) { + if (this.filesData[callChain.fileId] && this.filesData[callChain.fileId].length > 0) { + callChain.fileName = this.filesData[callChain.fileId][0].fileName + callChain.path = this.filesData[callChain.fileId][0].path + } else { + callChain.fileName = "unkown" + } + } else { + if (this.filesData[callChain.fileId] && this.filesData[callChain.fileId].length > callChain.symbolId) { + callChain.fileName = this.filesData[callChain.fileId][callChain.symbolId].fileName + callChain.path = this.filesData[callChain.fileId][callChain.symbolId].path + } else { + callChain.fileName = "unkown" + } + } + } + + addProcessThreadStateData(callChain: PerfCallChain) {//当调用栈为调用的根节点时 + this.addPerfCallData(callChain) + let threadCallChain = new PerfCallChain()//新增的线程数据 + threadCallChain.depth = 0 + PerfCallChain.merageCallChain(threadCallChain, callChain) + threadCallChain.canCharge = false + threadCallChain.name = this.threadData[callChain.tid].threadName||"Thead" + "(" + callChain.tid + ")" + let threadStateCallChain = new PerfCallChain()//新增的线程状态数据 + PerfCallChain.merageCallChain(threadStateCallChain, callChain) + threadStateCallChain.name = callChain.threadState || "Unkown State" + threadStateCallChain.fileName = threadStateCallChain.name == "-" ? "Unkown Thead State" : "" + threadStateCallChain.canCharge = false + this.addGroupData(threadCallChain) + this.addGroupData(threadStateCallChain) + PerfCallChain.setNextNode(threadCallChain, threadStateCallChain) + PerfCallChain.setNextNode(threadStateCallChain, callChain) + } + + addPerfCallData(callChain: PerfCallChain){ + let perfCall = new PerfCall() + perfCall.depth = this.callChainData[callChain.sampleId]?.length||0 + perfCall.sampleId = callChain.sampleId + perfCall.name = callChain.name + this.callChainMap.set(callChain.sampleId,perfCall) + } + + addGroupData(callChain: PerfCallChain) { + this.callChainData[callChain.sampleId] = this.callChainData[callChain.sampleId] || [] + this.callChainData[callChain.sampleId].push(callChain) + } + + getCallChainsBySampleIds(sampleIds: string[], isTopDown: boolean) { + this.allProcess = this.groupNewTreeNoId(sampleIds, isTopDown) + return this.allProcess + } + + addOtherCallchainData(countSample: PerfCountSample,list:any[]) { + let threadCallChain = new PerfCallChain()//新增的线程数据 + threadCallChain.tid = countSample.tid + threadCallChain.canCharge = false + threadCallChain.name = this.threadData[countSample.tid].threadName||"Thead" + "(" + countSample.tid + ")" + let threadStateCallChain = new PerfCallChain()//新增的线程状态数据 + threadStateCallChain.tid = countSample.tid + threadStateCallChain.name = countSample.threadState || "Unkown State" + threadStateCallChain.fileName = threadStateCallChain.name == "-" ? "Unkown Thead State" : "" + threadStateCallChain.canCharge = false + list.unshift(threadCallChain,threadStateCallChain) + + } + + freshCurrentCallchains(samples: PerfCountSample[] , isTopDown: boolean){ + this.currentTreeMapData = {} + this.currentTreeList = [] + let totalCount = 0 + samples.forEach((sample) => { + totalCount+=sample.count + let callChains = [...this.callChainData[sample.sampleId]] + this.addOtherCallchainData(sample,callChains) + let topIndex = isTopDown ? 0 : (callChains.length - 1); + if (callChains.length > 0) { + let root = this.currentTreeMapData[callChains[topIndex].name +sample.pid]; + if (root == undefined) { + root = new PerfCallChainMerageData(); + this.currentTreeMapData[callChains[topIndex].name + sample.pid] = root; + this.currentTreeList.push(root) + } + PerfCallChainMerageData.merageCallChainSample(root, callChains[topIndex],sample, false); + this.merageChildrenByIndex(root, callChains,topIndex,sample , isTopDown); + } + }) + let rootMerageMap: any = {} + Object.values(this.currentTreeMapData).forEach((merageData: any) => { + if (rootMerageMap[merageData.pid] == undefined) { + let processMerageData = new PerfCallChainMerageData()//新增进程的节点数据 + processMerageData.canCharge = false + processMerageData.symbolName = this.threadData[merageData.tid].processName||`Process(${merageData.pid})` + processMerageData.symbol = processMerageData.symbolName + processMerageData.tid = merageData.tid + processMerageData.children.push(merageData) + processMerageData.initChildren.push(merageData) + processMerageData.dur = merageData.dur; + processMerageData.count = merageData.dur; + processMerageData.total = totalCount; + rootMerageMap[merageData.pid] = processMerageData + } else { + rootMerageMap[merageData.pid].children.push(merageData) + rootMerageMap[merageData.pid].initChildren.push(merageData) + rootMerageMap[merageData.pid].dur += merageData.dur; + rootMerageMap[merageData.pid].count += merageData.dur; + rootMerageMap[merageData.pid].total = totalCount; + } + merageData.parentNode = rootMerageMap[merageData.pid]//子节点添加父节点的引用 + }) + let id = 0; + this.currentTreeList.forEach((node) => { + node.total = totalCount; + if (node.id == "") { + node.id = id + "" + id++ + } + if(node.parentNode){ + if (node.parentNode.id == "") { + node.parentNode.id = id + "" + id++ + } + node.parentId = node.parentNode.id + } + }) + this.allProcess = Object.values(rootMerageMap) + } + + merageChildrenByIndex(currentNode:PerfCallChainMerageData, callChainDataList:any[],index:number,sample: PerfCountSample , isTopDown:boolean){ + isTopDown?index++:index--; + let isEnd = isTopDown?(callChainDataList.length == index + 1):(index == 0) + let node; + if (currentNode.initChildren.filter((child: PerfCallChainMerageData) => { + if (child.symbolName == callChainDataList[index]?.name) { + node = child; + PerfCallChainMerageData.merageCallChainSample(child, callChainDataList[index],sample, isEnd) + return true; + } + return false; + }).length == 0) { + node = new PerfCallChainMerageData() + PerfCallChainMerageData.merageCallChainSample(node, callChainDataList[index],sample, isEnd) + currentNode.children.push(node) + currentNode.initChildren.push(node) + this.currentTreeList.push(node) + node.parentNode = currentNode + } + if (node&&!isEnd) this.merageChildrenByIndex(node, callChainDataList,index,sample, isTopDown) + } + + + + + + + groupNewTreeNoId(sampleIds: string[], isTopDown: boolean):any[] { + this.currentTreeMapData = {} + this.currentTreeList = [] + for (let i = 0; i < sampleIds.length; i++) { + let callChains = this.callChainData[sampleIds[i]] + if (callChains == undefined) continue + let topIndex = isTopDown ? 0 : (callChains.length - 1); + if (callChains.length > 0) { + let root = this.currentTreeMapData[callChains[topIndex].name + callChains[topIndex].pid]; + if (root == undefined) { + root = new PerfCallChainMerageData(); + this.currentTreeMapData[callChains[topIndex].name + callChains[topIndex].pid] = root; + this.currentTreeList.push(root) + } + PerfCallChainMerageData.merageCallChain(root, callChains[topIndex], isTopDown); + this.merageChildren(root, callChains[topIndex], isTopDown); + } + } + let rootMerageMap: any = {} + Object.values(this.currentTreeMapData).forEach((merageData: any) => { + if (rootMerageMap[merageData.pid] == undefined) { + let processMerageData = new PerfCallChainMerageData()//新增进程的节点数据 + processMerageData.canCharge = false + processMerageData.symbolName = this.threadData[merageData.tid].processName||`Process(${merageData.pid})` + processMerageData.symbol = processMerageData.symbolName + processMerageData.tid = merageData.tid + processMerageData.children.push(merageData) + processMerageData.initChildren.push(merageData) + processMerageData.dur = merageData.dur; + processMerageData.count = merageData.dur; + processMerageData.total = sampleIds.length; + rootMerageMap[merageData.pid] = processMerageData + } else { + rootMerageMap[merageData.pid].children.push(merageData) + rootMerageMap[merageData.pid].initChildren.push(merageData) + rootMerageMap[merageData.pid].dur += merageData.dur; + rootMerageMap[merageData.pid].count += merageData.dur; + rootMerageMap[merageData.pid].total = sampleIds.length; + } + merageData.parentNode = rootMerageMap[merageData.pid]//子节点添加父节点的引用 + }) + let id = 0; + this.currentTreeList.forEach((node) => { + node.total = sampleIds.length; + if (node.id == "") { + node.id = id + "" + id++ + } + if(node.parentNode){ + if (node.parentNode.id == "") { + node.parentNode.id = id + "" + id++ + } + node.parentId = node.parentNode.id + } + }) + return Object.values(rootMerageMap) + } + + merageChildren(currentNode: PerfCallChainMerageData, callChain: any, isTopDown: boolean) { + let nextNodeKey = isTopDown ? "nextNode" : "previousNode" + if (callChain[nextNodeKey] == undefined) return + let node; + if (currentNode.initChildren.filter((child: PerfCallChainMerageData) => { + if (child.symbolName == callChain[nextNodeKey]?.name) { + node = child; + PerfCallChainMerageData.merageCallChain(child, callChain[nextNodeKey], isTopDown) + return true; + } + return false; + }).length == 0) { + node = new PerfCallChainMerageData() + PerfCallChainMerageData.merageCallChain(node, callChain[nextNodeKey], isTopDown) + currentNode.children.push(node) + currentNode.initChildren.push(node) + this.currentTreeList.push(node) + node.parentNode = currentNode + } + if (node) this.merageChildren(node, callChain[nextNodeKey], isTopDown) + } + + //所有的操作都是针对整个树结构的 不区分特定的数据 + splitTree(data: PerfCallChainMerageData[], name: string, isCharge: boolean, isSymbol: boolean) { + data.forEach((process) => { + process.children = [] + if (isCharge) { + this.recursionChargeInitTree(process, name, isSymbol) + } else { + this.recursionPruneInitTree(process, name, isSymbol) + } + }) + this.resetAllNode(data) + } + + recursionChargeInitTree(node: PerfCallChainMerageData, symbolName: string, isSymbol: boolean) { + if ((isSymbol && node.symbolName == symbolName) || (!isSymbol && node.libName == symbolName)) { + (this.splitMapData[symbolName] = this.splitMapData[symbolName] || []).push(node) + node.isStore++; + } + if (node.initChildren.length > 0) { + node.initChildren.forEach((child) => { + this.recursionChargeInitTree(child, symbolName, isSymbol) + }) + } + } + + //symbol lib charge + recursionChargeTree(node: PerfCallChainMerageData, symbolName: string, isSymbol: boolean) { + if ((isSymbol && node.symbolName == symbolName) || (!isSymbol && node.libName == symbolName)) { + node.currentTreeParentNode && node.currentTreeParentNode.children.splice(node.currentTreeParentNode.children.indexOf(node), 1, ...node.children); + node.children.forEach((child) => { + child.currentTreeParentNode = node.currentTreeParentNode + }) + } + if (node.children.length > 0) { + node.children.forEach((child) => { + this.recursionChargeTree(child, symbolName, isSymbol) + }) + } + } + + recursionPruneInitTree(node: PerfCallChainMerageData, symbolName: string, isSymbol: boolean) { + if (isSymbol && node.symbolName == symbolName || (!isSymbol && node.libName == symbolName)) { + (this.splitMapData[symbolName] = this.splitMapData[symbolName] || []).push(node) + node.isStore++; + this.pruneChildren(node, symbolName) + } else if (node.initChildren.length > 0) { + node.initChildren.forEach((child) => { + this.recursionPruneInitTree(child, symbolName, isSymbol) + }) + } + } + + //symbol lib prune + recursionPruneTree(node: PerfCallChainMerageData, symbolName: string, isSymbol: boolean) { + if (isSymbol && node.symbolName == symbolName || (!isSymbol && node.libName == symbolName)) { + node.currentTreeParentNode && node.currentTreeParentNode.children.splice(node.currentTreeParentNode.children.indexOf(node), 1); + } else { + node.children.forEach((child) => { + this.recursionPruneTree(child, symbolName, isSymbol) + }) + } + } + + recursionChargeByRule(node: PerfCallChainMerageData, ruleName: string, rule: (node: PerfCallChainMerageData) => boolean) { + if (node.initChildren.length > 0) { + node.initChildren.forEach((child) => { + if (rule(child)) { + (this.splitMapData[ruleName] = this.splitMapData[ruleName] || []).push(child) + child.isStore++; + } + this.recursionChargeByRule(child, ruleName, rule) + }) + } + } + + pruneChildren(node: PerfCallChainMerageData, symbolName: string) { + if (node.initChildren.length > 0) { + node.initChildren.forEach((child) => { + child.isStore++; + (this.splitMapData[symbolName] = this.splitMapData[symbolName] || []).push(child); + this.pruneChildren(child, symbolName) + }) + } + } + + hideSystemLibrary(){ + this.allProcess.forEach((item)=>{ + item.children = [] + this.recursionChargeByRule(item,this.systmeRuleName,(node)=>{ + return node.path.startsWith(this.systmeRuleName) + }) + }) + } + + hideNumMaxAndMin(startNum:number,endNum:string){ + let max = endNum == "∞"?Number.POSITIVE_INFINITY :parseInt(endNum) + this.allProcess.forEach((item)=>{ + item.children = [] + this.recursionChargeByRule(item,this.numRuleName,(node)=>{ + return node.dur < startNum || node.dur > max + }) + }) + } + + clearSplitMapData(symbolName: string) { + delete this.splitMapData[symbolName] + } + + resotreAllNode(symbols: string[]) { + symbols.forEach((symbol) => { + let list = this.splitMapData[symbol]; + if (list != undefined) { + list.forEach((item: any) => { + item.isStore-- + }) + } + }) + } + + resetAllNode(data: PerfCallChainMerageData[]) { + this.clearSearchNode() + data.forEach((process) => { + process.searchShow = true + }) + this.resetNewAllNode(data) + if (this.searchValue != "") { + this.findSearchNode(data, this.searchValue, false) + this.resetNewAllNode(data) + } + } + + resetNewAllNode(data: PerfCallChainMerageData[]) { + data.forEach((process) => { + process.children = [] + }) + let values = this.currentTreeList.map((item: any) => { + item.children = [] + return item + }) + values.forEach((item: any) => { + if (item.parentNode != undefined) { + if (item.isStore == 0 && item.searchShow) { + let parentNode = item.parentNode + while (parentNode != undefined && !(parentNode.isStore == 0 && parentNode.searchShow)) { + parentNode = parentNode.parentNode + } + if (parentNode) { + item.currentTreeParentNode = parentNode + parentNode.children.push(item) + } + } + } + }) + } + + findSearchNode(data: PerfCallChainMerageData[], search: string, parentSearch: boolean) { + data.forEach((node) => { + if ((node.symbol&&node.symbol.includes(search)) || parentSearch) { + node.searchShow = true + let parentNode = node.currentTreeParentNode + while (parentNode != undefined && !parentNode.searchShow) { + parentNode.searchShow = true + parentNode = parentNode.currentTreeParentNode + } + } else { + node.searchShow = false + } + if (node.children.length > 0) { + this.findSearchNode(node.children, search, node.searchShow) + } + }) + } + + clearSearchNode() { + this.currentTreeList.forEach((node) => { + node.searchShow = true + }) + } + + splitAllProcess(list:any[]){ + list.forEach((item:any)=>{ + this.allProcess.forEach((process)=>{ + if(item.select == "0"){ + this.recursionChargeInitTree(process, item.name, item.type == "symbol") + }else { + this.recursionPruneInitTree(process, item.name, item.type == "symbol") + } + }) + if(!item.checked){ + this.resotreAllNode([item.name]) + } + }) + } + + resolvingAction(params:any[]) { + if (params.length > 0) { + params.forEach((item) => { + if (item.funcName && item.funcArgs) { + switch (item.funcName) { + case "getCallChainsBySampleIds": + this.freshCurrentCallchains(this.samplesData,item.funcArgs[0]) + break + case "getCurrentDataFromDb": + this.getCurrentDataFromDb(item.funcArgs[0]); + break + case "hideSystemLibrary": + this.hideSystemLibrary(); + break + case "hideNumMaxAndMin": + this.hideNumMaxAndMin(item.funcArgs[0], item.funcArgs[1]) + break + case "splitAllProcess": + this.splitAllProcess(item.funcArgs[0]) + break + case "resetAllNode": + this.resetAllNode(this.allProcess) + break + case "resotreAllNode": + this.resotreAllNode(item.funcArgs[0]) + break + case "clearSplitMapData": + this.clearSplitMapData(item.funcArgs[0]) + break + case "splitTree": + this.splitTree(this.allProcess, item.funcArgs[0], item.funcArgs[1], item.funcArgs[2]); + break + case "setSearchValue": + this.searchValue = item.funcArgs[0] + break + } + } + }) + this.dataSource = this.allProcess.filter((process) => { + return process.children && process.children.length > 0 + }) + } + return this.dataSource + } +} + + +export class PerfFile { + fileId: number = 0; + symbol: string = "" + path: string = "" + fileName: string = "" + + static setFileName(data: PerfFile) { + if (data.path) { + let number = data.path.lastIndexOf("/"); + if (number > 0) { + data.fileName = data.path.substring(number + 1) + return + } + } + data.fileName = data.path + } + + setFileName() { + if (this.path) { + let number = this.path.lastIndexOf("/"); + if (number > 0) { + this.fileName = this.path.substring(number + 1) + return + } + } + this.fileName = this.path + } +} + +export class PerfThread { + tid: number = 0; + pid: number = 0; + threadName: string = ""; + processName: string = ""; +} + +export class PerfCallChain { + tid: number = 0; + pid: number = 0; + name: string = "" + fileName: string = ""; + threadState: string = ""; + startNS: number = 0; + dur: number = 0; + sampleId: number = 0; + callChainId: number = 0; + vaddrInFile: number = 0; + fileId: number = 0; + symbolId: number = 0; + path: string = ""; + count:number = 0; + parentId: string = ""//合并之后区分的id + id: string = "" + topDownMerageId: string = ""//top down合并使用的id + topDownMerageParentId: string = ""//top down合并使用的id + bottomUpMerageId: string = ""//bottom up合并使用的id + bottomUpMerageParentId: string = ""//bottom up合并使用的id + depth: number = 0; + canCharge:boolean = true + previousNode: PerfCallChain | undefined = undefined;//将list转换为一个链表结构 + nextNode: PerfCallChain | undefined = undefined; + + static setNextNode(currentNode: PerfCallChain, nextNode: PerfCallChain) { + currentNode.nextNode = nextNode + nextNode.previousNode = currentNode + } + + static setPreviousNode(currentNode: PerfCallChain, prevNode: PerfCallChain) { + currentNode.previousNode = prevNode + prevNode.nextNode = currentNode + } + + static merageCallChain(currentNode: PerfCallChain, callChain: PerfCallChain) { + currentNode.startNS = callChain.startNS + currentNode.tid = callChain.tid + currentNode.pid = callChain.pid + currentNode.sampleId = callChain.sampleId + currentNode.dur = callChain.dur + currentNode.count = callChain.count + } + +} + + + +export class PerfCallChainMerageData extends ChartStruct { + #parentNode: PerfCallChainMerageData | undefined = undefined + #total = 0 + id: string = ""; + parentId: string = ""; + currentTreeParentNode: PerfCallChainMerageData | undefined = undefined; + symbolName: string = ""; + symbol: string = "" + libName: string = "" + path: string = "" + self: string = "0s" + weight: string = "" + weightPercent: string = "" + selfDur: number = 0; + dur: number = 0; + tid: number = 0; + pid: number = 0; + isStore = 0; + canCharge:boolean = true + children: PerfCallChainMerageData[] = [] + initChildren: PerfCallChainMerageData[] = [] + type: number = 0; + vaddrInFile: number = 0; + isSelected: boolean = false; + searchShow: boolean = true; + + set parentNode(data: PerfCallChainMerageData | undefined) { + this.currentTreeParentNode = data; + this.#parentNode = data; + } + + get parentNode() { + return this.#parentNode + } + + set total(data: number) { + this.#total = data; + this.weight = `${timeMsFormat2p(this.dur * (ProcedureLogicWorkerPerf.cmdLineResult?.fValue || 1))}` + this.weightPercent = `${(this.dur / data * 100).toFixed(1)}%` + } + + get total() { + return this.#total; + } + + static merageCallChain(currentNode: PerfCallChainMerageData, callChain: PerfCallChain, isTopDown: boolean) { + if (currentNode.symbolName == "") { + currentNode.symbol = `${callChain.name} ${callChain.fileName ? `(${callChain.fileName})` : ""}` + currentNode.symbolName = callChain.name + currentNode.pid = callChain.pid + currentNode.tid = callChain.tid + currentNode.libName = callChain.fileName + currentNode.vaddrInFile = callChain.vaddrInFile; + currentNode.canCharge = callChain.canCharge + if (callChain.path) { + currentNode.path = callChain.path + } + } + if (callChain[isTopDown ? "nextNode" : "previousNode"] == undefined) { + currentNode.selfDur+=callChain.count; + currentNode.self = timeMsFormat2p(currentNode.selfDur * (ProcedureLogicWorkerPerf.cmdLineResult?.fValue || 1)) + } + currentNode.dur+=callChain.count; + currentNode.count+=callChain.count; + } + + static merageCallChainSample(currentNode: PerfCallChainMerageData, callChain: PerfCallChain,sample: PerfCountSample, isEnd: boolean) { + if (currentNode.symbolName == "") { + currentNode.symbol = `${callChain.name} ${callChain.fileName ? `(${callChain.fileName})` : ""}` + currentNode.symbolName = callChain.name + currentNode.pid = sample.pid + currentNode.tid = sample.tid + currentNode.libName = callChain.fileName + currentNode.vaddrInFile = callChain.vaddrInFile; + currentNode.canCharge = callChain.canCharge + if (callChain.path) { + currentNode.path = callChain.path + } + } + if (isEnd) { + currentNode.selfDur+=sample.count; + currentNode.self = timeMsFormat2p(currentNode.selfDur * (ProcedureLogicWorkerPerf.cmdLineResult?.fValue || 1)) + } + currentNode.dur+=sample.count; + currentNode.count+=sample.count; + } +} + +export class PerfCountSample { + sampleId: number = 0; + tid: number = 0; + count:number = 0; + threadState:string = ''; + pid: number = 0 +} + +export class PerfStack { + symbol: string = ""; + path: string = ""; + fileId: number = 0; + type: number = 0; + vaddrInFile: number = 0; +} + +export class PerfCmdLine { + report_value: string = ""; +} + +export class PerfCall{ + sampleId: number = 0; + depth: number = 0; + name: string = ""; +} + +export function timeMsFormat2p(ns: number) { + let currentNs = ns + let hour1 = 3600_000 + let minute1 = 60_000 + let second1 = 1_000; // 1 second + let res = "" + if (currentNs >= hour1) { + res += Math.floor(currentNs / hour1).toFixed(2) + "h" + return res + } + if (currentNs >= minute1) { + res += Math.floor(currentNs / minute1).toFixed(2) + "min" + return res + } + if (currentNs >= second1) { + res += Math.floor(currentNs / second1).toFixed(2) + "s" + return res + } + if (currentNs > 0) { + res += currentNs.toFixed(2) + "ms"; + return res + } + if (res == "") { + res = "0s"; + } + return res +} \ No newline at end of file diff --git a/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerSPT.ts b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerSPT.ts new file mode 100644 index 0000000000000000000000000000000000000000..febe826bb3510aa80f290d9d6d199a442b434d46 --- /dev/null +++ b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerSPT.ts @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {convertJSON, LogicHandler} from "./ProcedureLogicWorkerCommon.js"; + +export class ProcedureLogicWorkerSPT extends LogicHandler { + arrTs: Array = []; + arrTp: Array = []; + currentEventId: string = "" + + handle(data: any): void { + this.currentEventId = data.id + if (data && data.type) { + switch (data.type) { + case "spt-init": + this.getThreadState(); + break; + case "spt-getThreadStateData": + this.arrTs = convertJSON(data.params.list) || []; + this.getThreadProcessData() + break; + case "spt-getThreadProcessData": + this.arrTp = convertJSON(data.params.list) || []; + this.initProcessThreadStateData(); + break; + } + } + } + + queryData(queryName: string, sql: string, args: any) { + self.postMessage({ + id: this.currentEventId, + type: queryName, + isQuery: true, + args: args, + sql: sql + }) + } + + getThreadState(){ + this.queryData("spt-getThreadStateData", ` + select itid, + state, + dur, + ts, + (ts - start_ts + dur) as end_ts, + (ts - start_ts) as start_ts, + cpu +from thread_state,trace_range where dur > 0 and (ts - start_ts) >= 0; +`, {}); + } + + getThreadProcessData(){ + this.queryData("spt-getThreadProcessData", ` + select A.id, + A.tid as threadId, + A.name as thread, + IP.pid as processId, + IP.name as process +from thread as A left join process as IP on A.ipid = IP.id +where IP.pid not null; +`, {}); + } + + getSPT(){ + this.queryData("spt-getStatesProcessThreadData", ` + select + IP.name as process, + IP.pid as processId, + A.name as thread, + B.state as state, + A.tid as threadId, + B.dur, + (B.ts - TR.start_ts + B.dur) as end_ts, + (B.ts - TR.start_ts) as start_ts, + B.cpu + from + thread_state as B + left join + thread as A + on + B.itid = A.id + left join + process as IP + on + A.ipid = IP.id + left join + trace_range as TR + where + B.dur > 0 + and + IP.pid not null + and (B.ts - TR.start_ts) >= 0; +`, {}); + } + + initProcessThreadStateData() { + let mapTp: Map = new Map(); + for (let tp of this.arrTp) { + mapTp.set(tp.id, tp); + } + let sptArr:Array = []; + for (let tr of this.arrTs) { + if (mapTp.has(tr.itid)) { + let tp = mapTp.get(tr.itid); + let spt = new SPT(); + spt.processId = tp!.processId + spt.process = tp!.process + spt.thread = tp!.thread + spt.threadId = tp!.threadId + spt.state = tr.state; + spt.dur = tr.dur; + spt.end_ts = tr.end_ts; + spt.start_ts = tr.start_ts; + spt.cpu = tr.cpu; + sptArr.push(spt); + } + } + this.arrTp = []; + this.arrTs = []; + self.postMessage({ + id: this.currentEventId, + action: "spt-init", + results: sptArr + }); + } + + +} + +export class ThreadState{ + itid:number = 0 + state:string = "" + dur:number = 0 + ts:number = 0 + end_ts:number = 0 + start_ts:number = 0 + cpu:number = 0 +} + +export class ThreadProcess{ + id:number = 0 + threadId :number = 0 + thread :string = "" + processId : number = 0 + process : string = "" +} + +export class SPT { + process: string = "" + processId: number = 0 + thread: string = "" + threadId: number = 0 + state: string = "" + dur: number = 0 + start_ts: number = 0 + end_ts: number = 0 + cpu: number = 0; + priority: string = "-" + note: string = "-" +} diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorker.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorker.ts new file mode 100644 index 0000000000000000000000000000000000000000..98ec37004a3a7ffa23d32f10332994358df53244 --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorker.ts @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {CpuRender, EmptyRender} from "./ProcedureWorkerCPU.js"; +import { + RequestMessage, +} from "./ProcedureWorkerCommon.js"; +import {FreqRender} from "./ProcedureWorkerFreq.js"; +import {ProcessRender} from "./ProcedureWorkerProcess.js"; +import {MemRender} from "./ProcedureWorkerMem.js"; +import {ThreadRender} from "./ProcedureWorkerThread.js"; +import {FuncRender} from "./ProcedureWorkerFunc.js"; +import {FpsRender} from "./ProcedureWorkerFPS.js"; +import {HeapRender, NativeMemoryRender} from "./ProcedureWorkerHeap.js"; +import {CpuAbilityRender} from "./ProcedureWorkerCpuAbility.js"; +import {MemoryAbilityRender} from "./ProcedureWorkerMemoryAbility.js"; +import {DiskIoAbilityRender} from "./ProcedureWorkerDiskIoAbility.js"; +import {NetworkAbilityRender} from "./ProcedureWorkerNetworkAbility.js"; +import {HiperfCpuRender} from "./ProcedureWorkerHiPerfCPU.js"; +import {HiperfProcessRender} from "./ProcedureWorkerHiPerfProcess.js"; +import {HiperfThreadRender} from "./ProcedureWorkerHiPerfThread.js"; +import {HiperfEventRender} from "./ProcedureWorkerHiPerfEvent.js"; +import {HiperfReportRender} from "./ProcedureWorkerHiPerfReport.js"; +import {VirtualMemoryRender} from "./ProcedureWorkerVirtualMemory.js"; +import {FileSystemRender} from "./ProcedureWorkerFileSystem.js"; +import {info} from "../../../log/Log.js"; +import {SdkSliceRender} from "./ProduceWorkerSdkSlice.js"; +import {SdkCounterRender} from "./ProduceWorkerSdkCounter.js"; +import {CpuStateRender} from "./ProcedureWorkerCpuState.js"; +import {EnergyAnomalyRender} from "./ProcedureWorkerEnergyAnomaly.js"; +import {EnergySystemRender} from "./ProcedureWorkerEnergySystem.js"; +import {EnergyPowerRender} from "./ProcedureWorkerEnergyPower.js"; +import {EnergyStateRender} from "./ProcedureWorkerEnergyState.js"; +import {SmapsRender} from "./ProcedureWorkerSmaps.js"; +import {CpuFreqLimitRender} from "./ProcedureWorkerCpuFreqLimits.js"; + +let dataList: any = {} +let dataList2: any = {} +let dataFilter: any = {} +let canvasList: any = {} +let contextList: any = {} +export let renders: any = { + // "timeline": new TimelineRender(), + "cpu-data": new CpuRender(), + "cpu-state": new CpuStateRender(), + "cpu-limit-freq": new CpuFreqLimitRender(), + "fps": new FpsRender(), + "freq": new FreqRender(), + "empty": new EmptyRender(), + "virtual-memory-folder": new EmptyRender(), + "virtual-memory-cell": new VirtualMemoryRender(), + "file-system-group": new EmptyRender(), + "file-system-cell": new FileSystemRender(), + "process": new ProcessRender(), + "heap": new HeapRender(), + "mem": new MemRender(), + "thread": new ThreadRender(), + "func": new FuncRender(), + "native": new NativeMemoryRender(), + "HiPerf-Group": new EmptyRender(), + "monitorGroup": new EmptyRender(), + "HiPerf-Cpu": new HiperfCpuRender(), + "HiPerf-Process": new HiperfProcessRender(), + "HiPerf-Thread": new HiperfThreadRender(), + "HiPerf-Report-Event": new HiperfEventRender(), + "HiPerf-Report-Fold": new HiperfReportRender(), + "monitorCpu": new CpuAbilityRender(), + "monitorMemory": new MemoryAbilityRender(), + "monitorDiskIo": new DiskIoAbilityRender(), + "monitorNetwork": new NetworkAbilityRender(), + "sdk-slice": new SdkSliceRender(), + "sdk-counter": new SdkCounterRender(), + "energyAnomaly": new EnergyAnomalyRender(), + "energySystem": new EnergySystemRender(), + "energyPower": new EnergyPowerRender(), + "energyState": new EnergyStateRender(), + "smaps": new SmapsRender(), +}; + +function match(type: string, req: RequestMessage) { + Reflect.ownKeys(renders).filter((it) => { + if (type.startsWith(it as string)) { + if (dataList[type]) { + req.lazyRefresh = dataList[type].length > 20000; + } + renders[it].render(req, dataList[type], dataFilter[type], dataList2); + } + }) +} + +let dec = new TextDecoder(); +let convertJSON = (arr: any) => { + if (arr instanceof ArrayBuffer) { + let jsonArray = []; + let str = dec.decode(new Uint8Array(arr)); + str = str.substring(str.indexOf("\n") + 1); + if (!str) { + } else { + let parse = JSON.parse(str); + let columns = parse.columns; + let values = parse.values; + for (let i = 0; i < values.length; i++) { + let obj: any = {} + for (let j = 0; j < columns.length; j++) { + obj[columns[j]] = values[i][j] + } + jsonArray.push(obj) + } + } + return jsonArray; + } else { + return arr; + } +} +self.onmessage = function (e: any) { + if ((e.data.type as string).startsWith("clear")) { + dataList = {}; + dataList2 = {}; + dataFilter = {}; + canvasList = {}; + contextList = {}; + // @ts-ignore + self.postMessage({ + id: e.data.id, + type: e.data.type, + results: null, + }); + return; + } + if (e.data.params.list) { + dataList[e.data.type] = convertJSON(e.data.params.list); + if (e.data.params.offscreen) { + canvasList[e.data.type] = e.data.params.offscreen; + contextList[e.data.type] = e.data.params.offscreen!.getContext('2d'); + contextList[e.data.type].scale(e.data.params.dpr, e.data.params.dpr); + } + } + if (!dataFilter[e.data.type]) { + dataFilter[e.data.type] = [] + } + let req = new RequestMessage(); + req.canvas = canvasList[e.data.type]; + req.context = contextList[e.data.type]; + req.type = e.data.type as string; + req.params = e.data.params; + req.online = e.data.params.online; + req.buf = e.data.params.buf; + req.isRangeSelect = e.data.params.isRangeSelect; + req.isHover = e.data.params.isHover; + req.xs = e.data.params.xs; + req.frame = e.data.params.frame; + req.flagMoveInfo = e.data.params.flagMoveInfo; + req.flagSelectedInfo = e.data.params.flagSelectedInfo; + req.hoverX = e.data.params.hoverX; + req.hoverY = e.data.params.hoverY; + req.startNS = e.data.params.startNS; + req.endNS = e.data.params.endNS; + req.totalNS = e.data.params.totalNS; + req.slicesTime = e.data.params.slicesTime; + req.range = e.data.params.range; + req.scale = e.data.params.scale; + req.canvasWidth = e.data.params.canvasWidth; + req.canvasHeight = e.data.params.canvasHeight; + req.useCache = e.data.params.useCache; + req.lineColor = e.data.params.lineColor; + req.chartColor = e.data.params.chartColor; + req.wakeupBean = e.data.params.wakeupBean; + req.intervalPerf = e.data.params.intervalPerf; + req.id = e.data.id; + if (!req.frame) { + info(req.frame); + return; + } + if (req.canvas) { + if (req.canvas.width !== req.canvasWidth || req.canvas.height !== req.canvasHeight) { + req.canvas.width = req.canvasWidth; + req.canvas.height = req.canvasHeight; + req.context.scale(e.data.params.dpr, e.data.params.dpr); + } + } + match(req.type, req); +}; +self.onmessageerror = function (e: any) { +} + diff --git a/host/ide/src/trace/database/ProcedureWorkerCPU.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerCPU.ts similarity index 38% rename from host/ide/src/trace/database/ProcedureWorkerCPU.ts rename to host/ide/src/trace/database/ui-worker/ProcedureWorkerCPU.ts index a0f22b246d0b4efc6767bcd1d2414c6f6e0a26ca..b4e312c151037581ff153247b98fc2f2bf43efc4 100644 --- a/host/ide/src/trace/database/ProcedureWorkerCPU.ts +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerCPU.ts @@ -13,30 +13,181 @@ * limitations under the License. */ -import {BaseStruct, ColorUtils} from "./ProcedureWorkerCommon.js"; +import {ColorUtils} from "../../component/trace/base/ColorUtils.js"; +import { + BaseStruct, dataFilterHandler, + drawFlagLine, + drawLines, + drawLoading, + drawSelection, drawWakeUp, Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; -export function cpu(list: Array, res: Set, startNS: number, endNS: number, totalNS: number, frame: any) { - res.clear(); - if (list) { - let pns = (endNS - startNS) / frame.width; - let y = frame.y + 5; - let height = frame.height - 10; - for (let i = 0, len = list.length; i < len; i++) { - let it = list[i]; - if ((it.startTime || 0) + (it.dur || 0) > startNS && (it.startTime || 0) < endNS) { - // setCpuFrame(list[i], 5, startNS, endNS, totalNS, frame) - if (!list[i].frame) { - list[i].frame = {}; - list[i].frame.y = y; - list[i].frame.height = height; +export class EmptyRender extends Render { + renderMainThread(req: any, row: TraceRow) { + req.context.beginPath(); + req.context.closePath(); + } + render(req: RequestMessage, list: Array, filter: Array) { + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + req.context.beginPath(); + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + drawSelection(req.context, req.params); + req.context.closePath(); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: null + }); + } +} + +export class CpuRender { + renderMainThread(req: { + context: CanvasRenderingContext2D, + useCache: boolean, + type: string, + }, row: TraceRow) { + let list = row.dataList; + let filter = row.dataListCache; + dataFilterHandler(list,filter,{ + startKey: "startTime", + durKey: "dur", + startNS: TraceRow.range?.startNS ?? 0, + endNS: TraceRow.range?.endNS ?? 0, + totalNS: TraceRow.range?.totalNS ?? 0, + frame: row.frame, + paddingTop: 5, + useCache: req.useCache || !(TraceRow.range?.refresh ?? false) + }) + req.context.beginPath(); + req.context.font = "11px sans-serif"; + filter.forEach((re)=>{ + CpuStruct.draw(req.context, re); + }) + req.context.closePath(); + let currentCpu = parseInt(req.type!.replace("cpu-data-", "")); + drawWakeUp(req.context, CpuStruct.wakeupBean, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, row.frame, req.type == `cpu-data-${CpuStruct.selectCpuStruct?.cpu || 0}` ? CpuStruct.selectCpuStruct : undefined, currentCpu); + } + + render(req: RequestMessage, list: Array, filter: Array) { + if (req.lazyRefresh) { + this.cpu(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + this.cpu(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startTime, arr[arr.length - 1].startTime + arr[arr.length - 1].dur) + } + req.context.beginPath(); + drawLines(req.context, req.xs, req.frame.height, req.lineColor); + CpuStruct.hoverCpuStruct = undefined; + if (req.isHover) { + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x && req.hoverX <= re.frame.x + re.frame.width && req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height) { + CpuStruct.hoverCpuStruct = re; + break; + } } - CpuStruct.setCpuFrame(list[i], pns, startNS, endNS, frame) - if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && ((list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0)))) { + } else { + CpuStruct.hoverCpuStruct = req.params.hoverCpuStruct; + } + CpuStruct.selectCpuStruct = req.params.selectCpuStruct; + req.context.font = "11px sans-serif"; + for (let re of filter) { + CpuStruct.draw(req.context, re); + } + drawSelection(req.context, req.params); + req.context.closePath(); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + let currentCpu = parseInt(req.type!.replace("cpu-data-", "")); + drawWakeUp(req.context, req.wakeupBean, req.startNS, req.endNS, req.totalNS, req.frame, req.type == `cpu-data-${CpuStruct.selectCpuStruct?.cpu || 0}` ? CpuStruct.selectCpuStruct : undefined, currentCpu); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: CpuStruct.hoverCpuStruct + }); + } + cpu(list: Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, use: boolean) { + if (use && res.length > 0) { + let pns = (endNS - startNS) / frame.width; + let y = frame.y + 5; + let height = frame.height - 10; + for (let i = 0, len = res.length; i < len; i++) { + let it = res[i]; + if ((it.startTime || 0) + (it.dur || 0) > startNS && (it.startTime || 0) < endNS) { + if (!res[i].frame) { + res[i].frame = {}; + res[i].frame.y = y; + res[i].frame.height = height; + } + CpuStruct.setCpuFrame(res[i], pns, startNS, endNS, frame) } else { - res.add(list[i]) + res[i].frame = null; } } + return; + } + if (list) { + res.length = 0; + let pns = (endNS - startNS) / frame.width;//每个像素多少ns + let y = frame.y + 5; + let height = frame.height - 10; + let left = 0, right = 0; + for (let i = 0, j = list.length - 1, ib = true, jb = true; i < list.length, j >= 0; i++, j--) { + if (list[j].startTime <= endNS && jb) { + right = j; + jb = false; + } + if (list[i].startTime + list[i].dur >= startNS && ib) { + left = i; + ib = false; + } + if (!ib && !jb) { + break; + } + } + let slice = list.slice(left, right + 1); + let sum = 0; + for (let i = 0; i < slice.length; i++) { + if (!slice[i].frame) { + slice[i].frame = {}; + slice[i].frame.y = y; + slice[i].frame.height = height; + } + if (slice[i].dur >= pns) { + slice[i].v = true; + CpuStruct.setCpuFrame(slice[i], pns, startNS, endNS, frame) + } else { + if (i > 0) { + let c = slice[i].startTime - slice[i - 1].startTime - slice[i - 1].dur + if (c < pns && sum < pns) { + sum += c + slice[i - 1].dur; + slice[i].v = false; + } else { + slice[i].v = true; + CpuStruct.setCpuFrame(slice[i], pns, startNS, endNS, frame) + sum = 0; + } + } + } + } + res.push(...slice.filter(it => it.v)); } } } @@ -45,6 +196,7 @@ export class CpuStruct extends BaseStruct { static cpuCount: number = 1 //最大cpu数量 static hoverCpuStruct: CpuStruct | undefined; static selectCpuStruct: CpuStruct | undefined; + static wakeupBean: WakeupBean | null | undefined = null; cpu: number | undefined dur: number | undefined end_state: string | undefined @@ -58,38 +210,26 @@ export class CpuStruct extends BaseStruct { startTime: number | undefined tid: number | undefined type: string | undefined - - // static setFrame(node: CpuStruct, padding: number, startNS: number, endNS: number, totalNS: number, frame: Rect) { - // let x1: number; - // let x2: number; - // if ((node.startTime || 0) < startNS) { - // x1 = 0; - // } else { - // x1 = ns2x((node.startTime || 0), startNS, endNS, totalNS, frame); - // } - // if ((node.startTime || 0) + (node.dur || 0) > endNS) { - // x2 = frame.width; - // } else { - // x2 = ns2x((node.startTime || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); - // } - // let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1; - // let rectangle: Rect = new Rect(Math.floor(x1), frame.y + padding, Math.ceil(getV), frame.height - padding * 2); - // node.frame = rectangle; - // node.isHover = false; - // } + v: boolean = false static draw(ctx: CanvasRenderingContext2D, data: CpuStruct) { if (data.frame) { let width = data.frame.width || 0; - if (data.processId === CpuStruct.hoverCpuStruct?.processId || !CpuStruct.hoverCpuStruct) { + if (data.tid === CpuStruct.hoverCpuStruct?.tid || !CpuStruct.hoverCpuStruct) { + ctx.globalAlpha = 1 + ctx.fillStyle = ColorUtils.colorForTid((data.processId || 0) > 0 ? (data.processId || 0) : (data.tid || 0)) + } else if (data.processId === CpuStruct.hoverCpuStruct?.processId) { + ctx.globalAlpha = 0.6 ctx.fillStyle = ColorUtils.colorForTid((data.processId || 0) > 0 ? (data.processId || 0) : (data.tid || 0)) } else { + ctx.globalAlpha = 1 ctx.fillStyle = "#e0e0e0" } ctx.fillRect(data.frame.x, data.frame.y, width, data.frame.height) + ctx.globalAlpha = 1 if (width > textPadding * 2) { let process = `${(data.processName || "Process")} [${data.processId}]` - let thread = `${data.name || "Thread"} [${data.tid}]` + let thread = `${data.name || "Thread"} [${data.tid}] [Prio:${data.priority || 0}]` let processMeasure = ctx.measureText(process); let threadMeasure = ctx.measureText(thread); let processCharWidth = Math.round(processMeasure.width / process.length) @@ -106,6 +246,8 @@ export class CpuStruct extends BaseStruct { ctx.textBaseline = "bottom"; ctx.fillText(process.substring(0, chatNum - 4) + '...', x1, y, width - textPadding * 2) } + ctx.fillStyle = "#ffffff" + ctx.font = "9px sans-serif"; if (threadMeasure.width < width - textPadding * 2) { ctx.textBaseline = "top"; let x2 = Math.floor(width / 2 - threadMeasure.width / 2 + data.frame.x + textPadding) @@ -142,15 +284,11 @@ export class CpuStruct extends BaseStruct { } static equals(d1: CpuStruct, d2: CpuStruct): boolean { - if (d1 && d2 && d1.cpu == d2.cpu && + return d1 && d2 && d1.cpu == d2.cpu && d1.tid == d2.tid && d1.processId == d2.processId && d1.startTime == d2.startTime && - d1.dur == d2.dur) { - return true; - } else { - return false; - } + d1.dur == d2.dur; } } diff --git a/host/ide/src/trace/database/ProcedureWorkerCommon.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts similarity index 31% rename from host/ide/src/trace/database/ProcedureWorkerCommon.ts rename to host/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts index 2672f456510da3415e74d4ebdd4dc8e61d7e84d9..ff7715df875b68c578d0d98e36219ecb6a97a8df 100644 --- a/host/ide/src/trace/database/ProcedureWorkerCommon.ts +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts @@ -13,6 +13,50 @@ * limitations under the License. */ +import {CpuStruct, WakeupBean} from "./ProcedureWorkerCPU.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; + +export abstract class Render { + abstract renderMainThread(req: any, row: TraceRow): void; +} + +export abstract class PerfRender { + abstract render(req: RequestMessage, list: Array, filter: Array, dataList2: Array): void; +} + +export class RequestMessage { + type: string | undefined | null + lazyRefresh: boolean | undefined; + intervalPerf: any; + canvas: any; + context: any; + params: any; + online: any; + buf: any; + isRangeSelect: any; + isHover: any; + xs: any; + frame: any; + flagMoveInfo: any; + flagSelectedInfo: any; + hoverX: any; + hoverY: any; + startNS: any; + endNS: any; + totalNS: any; + slicesTime: { startTime: number | null, endTime: number | null, color: string | null } | undefined; + range: any; + scale: any; + chartColor: any; + canvasWidth: any; + canvasHeight: any; + useCache: any; + lineColor: any; + wakeupBean: WakeupBean | undefined | null; + id: any; + postMessage: { (message: any, targetOrigin: string, transfer?: Transferable[]): void; (message: any, options?: WindowPostMessageOptions): void } | undefined; +} + export function ns2s(ns: number): string { let second1 = 1_000_000_000; // 1 second let millisecond1 = 1_000_000; // 1 millisecond @@ -33,9 +77,126 @@ export function ns2s(ns: number): string { return res; } +export function isFrameContainPoint(frame: Rect, x: number, y: number): boolean { + return x >= frame.x && x <= frame.x + frame.width && y >= frame.y && y <= frame.y + frame.height +} + +class FilterConfig { + startNS: number = 0; + endNS: number = 0; + totalNS: number = 0; + frame: any = null; + useCache: boolean = false; + startKey: string = "startNS"; + durKey: string = "dur"; + paddingTop: number = 0; +} + +export function fillCacheData(filterData: Array, condition: FilterConfig): boolean { + if (condition.useCache && filterData.length > 0) { + let pns = (condition.endNS - condition.startNS) / condition.frame.width; + let y = condition.frame.y + condition.paddingTop; + let height = condition.frame.height - condition.paddingTop * 2; + for (let i = 0, len = filterData.length; i < len; i++) { + let it = filterData[i]; + if ((it[condition.startKey] || 0) + (it[condition.durKey] || 0) > condition.startNS && (it[condition.startKey] || 0) < condition.endNS) { + if (!filterData[i].frame) { + filterData[i].frame = {}; + filterData[i].frame.y = y; + filterData[i].frame.height = height; + } + setNodeFrame(filterData[i], pns, condition.startNS, condition.endNS, condition.frame, condition.startKey, condition.durKey) + } else { + filterData[i].frame = null; + } + } + return true; + } + return false; +} + +export function findRange(fullData: Array, condition: FilterConfig): Array { + let left = 0, right = 0; + for (let i = 0, j = fullData.length - 1, ib = true, jb = true; i < fullData.length, j >= 0; i++, j--) { + if (fullData[j][condition.startKey] <= condition.endNS && jb) { + right = j; + jb = false; + } + if (fullData[i][condition.startKey] + fullData[i][condition.durKey] >= condition.startNS && ib) { + left = i; + ib = false; + } + if (!ib && !jb) { + break; + } + } + let slice = fullData.slice(left, right + 1); + return slice; +} + +export function dataFilterHandler(fullData: Array, filterData: Array, condition: FilterConfig) { + if (fillCacheData(filterData, condition)) return; + if (fullData) { + filterData.length = 0; + let pns = (condition.endNS - condition.startNS) / condition.frame.width;//每个像素多少ns + let y = condition.frame.y + condition.paddingTop; + let height = condition.frame.height - condition.paddingTop * 2; + let slice = findRange(fullData, condition); + let sum = 0; + for (let i = 0; i < slice.length; i++) { + if (!slice[i].frame) { + slice[i].frame = {}; + slice[i].frame.y = y; + slice[i].frame.height = height; + } + if (i === slice.length - 1) { + if (!(slice[i][condition.durKey])) { + slice[i][condition.durKey] = (condition.endNS || 0) - (slice[i][condition.startKey] || 0) + } + } else { + if (!(slice[i][condition.durKey])) { + slice[i][condition.durKey] = (slice[i + 1][condition.startKey] || 0) - (slice[i][condition.startKey] || 0) + } + } + if (slice[i][condition.durKey] >= pns || slice.length < 100) { + slice[i].v = true; + setNodeFrame(slice[i], pns, condition.startNS, condition.endNS, condition.frame, condition.startKey, condition.durKey) + } else { + if (i > 0) { + let c = slice[i][condition.startKey] - slice[i - 1][condition.startKey] - slice[i - 1][condition.durKey] + if (c < pns && sum < pns) { + sum += c + slice[i - 1][condition.durKey]; + slice[i].v = false; + } else { + slice[i].v = true; + setNodeFrame(slice[i], pns, condition.startNS, condition.endNS, condition.frame, condition.startKey, condition.durKey) + sum = 0; + } + } + } + } + filterData.push(...slice.filter(it => it.v)); + } +} + +function setNodeFrame(node: any, pns: number, startNS: number, endNS: number, frame: any, startKey: string, durKey: string) { + if ((node[startKey] || 0) < startNS) { + node.frame.x = 0; + } else { + node.frame.x = Math.floor(((node[startKey] || 0) - startNS) / pns); + } + if ((node[startKey] || 0) + (node[durKey] || 0) > endNS) { + node.frame.width = frame.width - node.frame.x; + } else { + node.frame.width = Math.ceil(((node[startKey] || 0) + (node[durKey] || 0) - startNS) / pns - node.frame.x); + } + if (node.frame.width < 1) { + node.frame.width = 1; + } +} + export function ns2x(ns: number, startNS: number, endNS: number, duration: number, rect: any) { // @ts-ignore - // return _ns2x(ns,startNS,endNS,duration,rect.width); if (endNS == 0) { endNS = duration; } @@ -141,89 +302,9 @@ export class BaseStruct { isHover: boolean = false; } - -export class ColorUtils { - // public static GREY_COLOR:string = Color.getHSBColor(0, 0, 62); // grey - public static GREY_COLOR: string = "#f0f0f0" - /** - * Color array of all current columns - */ - public static MD_PALETTE: Array = [ - "#3391ff",// red - "#0076ff",// pink - "#66adff",// purple - "#2db3aa",// deep purple - "#008078",// indigo - "#73e6de",// blue - "#535da6",// light blue - "#38428c", // cyan - "#7a84cc",// teal - "#ff9201",// green - "#ff7500",// light green - "#ffab40",// lime - "#2db4e2",// amber 0xffc105 - "#0094c6", // orange - "#7cdeff",// deep orange - "#ffd44a", // brown - "#fbbf00",// blue gray - "#ffe593",// yellow 0xffec3d - ]; - public static FUNC_COLOR: Array = [ - "#3391ff", // purple - "#2db4e2", - "#2db3aa", // deep purple - "#ffd44a", - "#535da6", // indigo - "#008078", // blue - "#ff9201", - "#38428c"]; - - /** - * Get the color value according to the length of the string - * - * @param str str - * @param max max - * @return int - */ - public static hash(str: string, max: number): number { - let colorA: number = 0x811c9dc5; - let colorB: number = 0xfffffff; - let colorC: number = 16777619; - let colorD: number = 0xffffffff; - let hash: number = colorA & colorB; - - for (let index: number = 0; index < str.length; index++) { - hash ^= str.charCodeAt(index); - hash = (hash * colorC) & colorD; - } - return Math.abs(hash) % max; - } - - /** - * Get color according to tid - * - * @param tid tid - * @return Color - */ - public static colorForTid(tid: number): string { - let colorIdx: number = ColorUtils.hash(`${tid}`, ColorUtils.MD_PALETTE.length); - return ColorUtils.MD_PALETTE[colorIdx]; - } - - public static formatNumberComma(str: number): string { - let l = str.toString().split("").reverse(); - let t: string = ""; - for (let i = 0; i < l.length; i++) { - t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? "," : ""); - } - return t.split("").reverse().join("") - } -} - -export function drawLines(ctx: any, xs: Array, height: number, lineColor: string) { +export function drawLines(ctx: CanvasRenderingContext2D, xs: Array, height: number, lineColor: string) { if (ctx) { ctx.lineWidth = 1; - // ctx.strokeStyle = window.getComputedStyle(this.rootEL!, null).getPropertyValue("border-bottom-color");//"#dadada" "#474e59";// ctx.strokeStyle = lineColor || "#dadada"; xs?.forEach(it => { ctx.moveTo(Math.floor(it), 0) @@ -233,7 +314,7 @@ export function drawLines(ctx: any, xs: Array, height: number, lineColor: s } } -export function drawFlagLine(ctx: any, hoverFlag: any, selectFlag: any, startNS: number, endNS: number, totalNS: number, frame: any) { +export function drawFlagLine(ctx: any, hoverFlag: any, selectFlag: any, startNS: number, endNS: number, totalNS: number, frame: any, slicesTime: { startTime: number | null | undefined, endTime: number | null | undefined, color: string | null | undefined } | undefined) { if (ctx) { if (hoverFlag) { ctx.beginPath(); @@ -254,6 +335,141 @@ export function drawFlagLine(ctx: any, hoverFlag: any, selectFlag: any, startNS: ctx.stroke(); ctx.closePath(); } + if (slicesTime && slicesTime.startTime && slicesTime.endTime) { + ctx.beginPath(); + ctx.lineWidth = 1; + ctx.strokeStyle = slicesTime.color || "#dadada"; + let x1 = ns2x(slicesTime.startTime, startNS, endNS, totalNS, frame); + let x2 = ns2x(slicesTime.endTime, startNS, endNS, totalNS, frame); + ctx.moveTo(Math.floor(x1), 0) + ctx.lineTo(Math.floor(x1), frame.height) + ctx.moveTo(Math.floor(x2), 0) + ctx.lineTo(Math.floor(x2), frame.height) + ctx.stroke(); + ctx.closePath(); + } } } +export function drawFlagLineSegment(ctx: any, hoverFlag: any, selectFlag: any, frame: any) { + if (ctx) { + if (hoverFlag) { + ctx.beginPath(); + ctx.lineWidth = 2; + ctx.strokeStyle = hoverFlag?.color || "#dadada"; + ctx.moveTo(Math.floor(hoverFlag.x), 0) + ctx.lineTo(Math.floor(hoverFlag.x), frame.height) + ctx.stroke(); + ctx.closePath(); + } + if (selectFlag) { + ctx.beginPath(); + ctx.lineWidth = 2; + ctx.strokeStyle = selectFlag?.color || "#dadada"; + selectFlag.x = ns2x(selectFlag.time, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, frame); + ctx.moveTo(Math.floor(selectFlag.x), 0) + ctx.lineTo(Math.floor(selectFlag.x), frame.height) + ctx.stroke(); + ctx.closePath(); + } + if (TraceRow.range!.slicesTime && TraceRow.range!.slicesTime.startTime && TraceRow.range!.slicesTime.endTime) { + ctx.beginPath(); + ctx.lineWidth = 1; + ctx.strokeStyle = TraceRow.range!.slicesTime.color || "#dadada"; + let x1 = ns2x(TraceRow.range!.slicesTime.startTime, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, frame); + let x2 = ns2x(TraceRow.range!.slicesTime.endTime, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, frame); + ctx.moveTo(Math.floor(x1), 0) + ctx.lineTo(Math.floor(x1), frame.height) + ctx.moveTo(Math.floor(x2), 0) + ctx.lineTo(Math.floor(x2), frame.height) + ctx.stroke(); + ctx.closePath(); + } + } +} + +export function drawSelection(context: any, params: any) { + if (params.isRangeSelect && params.rangeSelectObject) { + params.rangeSelectObject!.startX = Math.floor(ns2x(params.rangeSelectObject!.startNS!, params.startNS, params.endNS, params.totalNS, params.frame)); + params.rangeSelectObject!.endX = Math.floor(ns2x(params.rangeSelectObject!.endNS!, params.startNS, params.endNS, params.totalNS, params.frame)); + if (context) { + context.globalAlpha = 0.5 + context.fillStyle = "#666666" + context.fillRect(params.rangeSelectObject!.startX!, params.frame.y, params.rangeSelectObject!.endX! - params.rangeSelectObject!.startX!, params.frame.height) + context.globalAlpha = 1 + } + } +} + +// draw range select +export function drawSelectionRange(context: any, params: TraceRow) { + if (params.rangeSelect && TraceRow.rangeSelectObject) { + TraceRow.rangeSelectObject!.startX = Math.floor(ns2x(TraceRow.rangeSelectObject!.startNS!, TraceRow.range?.startNS ?? 0, TraceRow.range?.endNS ?? 0, TraceRow.range?.totalNS ?? 0, params.frame)); + TraceRow.rangeSelectObject!.endX = Math.floor(ns2x(TraceRow.rangeSelectObject!.endNS!, TraceRow.range?.startNS ?? 0, TraceRow.range?.endNS ?? 0, TraceRow.range?.totalNS ?? 0, params.frame)); + if (context) { + context.globalAlpha = 0.5 + context.fillStyle = "#666666" + context.fillRect(TraceRow.rangeSelectObject!.startX!, params.frame.y, TraceRow.rangeSelectObject!.endX! - TraceRow.rangeSelectObject!.startX!, params.frame.height) + context.globalAlpha = 1 + } + } +} + +export function drawWakeUp(context: CanvasRenderingContext2D | any, wake: WakeupBean | undefined | null, startNS: number, endNS: number, totalNS: number, frame: Rect, selectCpuStruct: CpuStruct | undefined = undefined, currentCpu: number | undefined = undefined) { + if (wake) { + let x1 = Math.floor(ns2x((wake.wakeupTime || 0), startNS, endNS, totalNS, frame)); + context.beginPath(); + context.lineWidth = 2; + context.fillStyle = "#000000"; + if (x1 > 0 && x1 < frame.x + frame.width) { + context.moveTo(x1, frame.y); + context.lineTo(x1, frame.y + frame.height); + if (currentCpu == wake.cpu) { + let centerY = Math.floor(frame.y + frame.height / 2); + context.moveTo(x1, centerY - 6); + context.lineTo(x1 + 4, centerY); + context.lineTo(x1, centerY + 6); + context.lineTo(x1 - 4, centerY); + context.lineTo(x1, centerY - 6); + context.fill(); + } + } + if (selectCpuStruct) { + let x2 = Math.floor(ns2x((selectCpuStruct.startTime || 0), startNS, endNS, totalNS, frame)); + let y = frame.y + frame.height - 10; + context.moveTo(x1, y); + context.lineTo(x2, y); + + let s = ns2s((selectCpuStruct.startTime || 0) - (wake.wakeupTime || 0)); + let distance = x2 - x1; + if (distance > 12) { + context.moveTo(x1, y); + context.lineTo(x1 + 6, y - 3); + context.moveTo(x1, y); + context.lineTo(x1 + 6, y + 3); + context.moveTo(x2, y); + context.lineTo(x2 - 6, y - 3); + context.moveTo(x2, y); + context.lineTo(x2 - 6, y + 3); + let measure = context.measureText(s); + let tHeight = measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent + let xStart = x1 + Math.floor(distance / 2 - measure.width / 2); + if (distance > measure.width + 4) { + context.fillStyle = "#ffffff" + context.fillRect(xStart - 2, y - 4 - tHeight, measure.width + 4, tHeight + 4); + context.font = "10px solid"; + context.fillStyle = "#000000"; + context.textBaseline = "bottom"; + context.fillText(s, xStart, y - 2); + } + + } + } + context.strokeStyle = "#000000"; + context.stroke(); + context.closePath(); + } +} + +export function drawLoading(ctx: CanvasRenderingContext2D, startNS: number, endNS: number, totalNS: number, frame: any, left: number, right: number) { +} diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerCpuAbility.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerCpuAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..94fb5ac7465ec83d547fa062605233ee40cf114c --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerCpuAbility.ts @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ColorUtils } from "../../component/trace/base/ColorUtils.js"; +import { + BaseStruct, dataFilterHandler, + drawFlagLine, + drawLines, drawLoading, + drawSelection, drawWakeUp, isFrameContainPoint, + ns2x, Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; +import {DiskAbilityMonitorStruct} from "./ProcedureWorkerDiskIoAbility.js"; + +export class CpuAbilityRender extends Render { + renderMainThread(req: { + context: CanvasRenderingContext2D, + useCache: boolean, + type: string, + maxCpuUtilization:number, + maxCpuUtilizationName:string + }, row: TraceRow) { + let list = row.dataList; + let filter = row.dataListCache; + dataFilterHandler(list,filter,{ + startKey: "startNS", + durKey: "dur", + startNS: TraceRow.range?.startNS ?? 0, + endNS: TraceRow.range?.endNS ?? 0, + totalNS: TraceRow.range?.totalNS ?? 0, + frame: row.frame, + paddingTop: 5, + useCache: req.useCache || !(TraceRow.range?.refresh ?? false) + }) + req.context.beginPath(); + let find = false; + for (let re of filter) { + CpuAbilityMonitorStruct.draw(req.context, re,req.maxCpuUtilization,row.isHover) + if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { + CpuAbilityMonitorStruct.hoverCpuAbilityStruct = re; + find = true; + } + } + if (!find && row.isHover) CpuAbilityMonitorStruct.hoverCpuAbilityStruct = undefined; + req.context.closePath(); + let textMetrics = req.context.measureText(req.maxCpuUtilizationName); + req.context.globalAlpha = 0.8 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(req.maxCpuUtilizationName, 4, 5 + 9) + } + + render(req: RequestMessage, list: Array, filter: Array) { + + } +} + +export function cpuAbility(list: Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, use: boolean) { + if (use && res.length > 0) { + for (let index = 0; index < res.length; index++) { + let item = res[index]; + if ((item.startNS || 0) + (item.dur || 0) > (startNS || 0) && (item.startNS || 0) < (endNS || 0)) { + CpuAbilityMonitorStruct.setCpuAbilityFrame(res[index], 5, startNS || 0, endNS || 0, totalNS || 0, frame) + } else { + res[index].frame = null; + } + } + return; + } + res.length = 0; + if (list) { + for (let index = 0; index < list.length; index++) { + let item = list[index]; + if (index === list.length - 1) { + item.dur = (endNS || 0) - (item.startNS || 0) + } else { + item.dur = (list[index + 1].startNS || 0) - (item.startNS || 0) + } + if ((item.startNS || 0) + (item.dur || 0) > (startNS || 0) && (item.startNS || 0) < (endNS || 0)) { + CpuAbilityMonitorStruct.setCpuAbilityFrame(list[index], 5, startNS || 0, endNS || 0, totalNS || 0, frame) + if (index > 0 && ((list[index - 1].frame?.x || 0) == (list[index].frame?.x || 0) && (list[index - 1].frame?.width || 0) == (list[index].frame?.width || 0))) { + + } else { + res.push(item) + } + } + } + } +} + +export class CpuAbilityMonitorStruct extends BaseStruct { + static maxCpuUtilization: number = 0 + static maxCpuUtilizationName: string = "0 %" + static hoverCpuAbilityStruct: CpuAbilityMonitorStruct | undefined; + static selectCpuAbilityStruct: CpuAbilityMonitorStruct | undefined; + + type: number | undefined + value: number | undefined + startNS: number | undefined + dur: number | undefined //自补充,数据库没有返回 + + static draw(context2D: CanvasRenderingContext2D, data: CpuAbilityMonitorStruct ,maxCpuUtilization:number,isHover:boolean) { + if (data.frame) { + let width = data.frame.width || 0; + let index = 2; + context2D.fillStyle = ColorUtils.colorForTid(index) + context2D.strokeStyle = ColorUtils.colorForTid(index) + if (data.startNS === CpuAbilityMonitorStruct.hoverCpuAbilityStruct?.startNS&&isHover) { + context2D.lineWidth = 1; + context2D.globalAlpha = 0.6; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / maxCpuUtilization); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, width, drawHeight) + context2D.beginPath() + context2D.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, 3, 0, 2 * Math.PI, true) + context2D.fill() + context2D.globalAlpha = 1.0; + context2D.stroke(); + context2D.beginPath() + context2D.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight + 4); + context2D.lineWidth = 3; + context2D.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight + 4) + context2D.stroke(); + } else { + context2D.globalAlpha = 0.6; + context2D.lineWidth = 1; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0)) / maxCpuUtilization); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, width, drawHeight) + } + } + context2D.globalAlpha = 1.0; + context2D.lineWidth = 1; + } + + static setCpuAbilityFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { + let startPointX: number, endPointX: number + + if ((node.startNS || 0) < startNS) { + startPointX = 0 + } else { + startPointX = ns2x((node.startNS || 0), startNS, endNS, totalNS, frame); + } + if ((node.startNS || 0) + (node.dur || 0) > endNS) { + endPointX = frame.width; + } else { + endPointX = ns2x((node.startNS || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); + } + let frameWidth: number = endPointX - startPointX <= 1 ? 1 : endPointX - startPointX; + if (!node.frame) { + node.frame = {}; + } + node.frame.x = Math.floor(startPointX); + node.frame.y = frame.y + padding; + node.frame.width = Math.ceil(frameWidth); + node.frame.height = Math.floor(frame.height - padding * 2); + } +} + +export class CpuAbility { + context: any + params: any +} \ No newline at end of file diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerCpuFreqLimits.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerCpuFreqLimits.ts new file mode 100644 index 0000000000000000000000000000000000000000..0c48cfe68c1a0a1494d959e1b2f33e5388de8351 --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerCpuFreqLimits.ts @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BaseStruct, drawFlagLine, + drawLines, + drawLoading, + drawSelection, drawWakeUp, isFrameContainPoint, + ns2x, + Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {ColorUtils} from "../../component/trace/base/ColorUtils.js"; +import { TraceRow } from "../../component/trace/base/TraceRow.js"; +import {convertJSON} from "../logic-worker/ProcedureLogicWorkerCommon.js"; + +export class CpuFreqLimitRender extends Render{ + renderMainThread(req: { useCache: boolean; context: CanvasRenderingContext2D; cpu: number; type: string;maxFreq:number;maxFreqName:string }, row: TraceRow) { + let list = row.dataList = convertJSON(row.dataList); + let filter = row.dataListCache; + let chartColor = ColorUtils.colorForTid(req.cpu); + freqLimits(list, filter, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, row.frame, req.useCache || !TraceRow.range!.refresh); + req.context.beginPath(); + let maxFreq = req.maxFreq; + let maxFreqName = req.maxFreqName; + if (row.isHover) { + for (let re of filter) { + if (re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { + CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = re; + break; + } + } + } + for (let re of filter) { + CpuFreqLimitsStruct.draw(req.context, re,maxFreq) + } + req.context.closePath(); + let s = maxFreqName + let textMetrics = req.context.measureText(s); + req.context.globalAlpha = 0.8 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(s, 4, 5 + 9) + } + + render(req: RequestMessage, list: Array, filter: Array) { + if (req.lazyRefresh) { + freqLimits(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + freqLimits(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startNs, arr[arr.length - 1].startNs + arr[arr.length - 1].dur) + } + req.context.beginPath(); + let maxFreq = req.params.maxFreq; + let maxFreqName = req.params.maxFreqName; + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = undefined; + if (req.isHover) { + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x && req.hoverX <= re.frame.x + re.frame.width && req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height) { + CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = re; + break; + } + } + } else { + CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = req.params.hoverCpuFreqLimitsStruct; + } + CpuFreqLimitsStruct.selectCpuFreqLimitsStruct = req.params.selectCpuFreqLimitsStruct; + for (let re of filter) { + CpuFreqLimitsStruct.draw(req.context, re,maxFreq) + } + drawSelection(req.context, req.params); + req.context.closePath(); + let s = maxFreqName + let textMetrics = req.context.measureText(s); + req.context.globalAlpha = 0.8 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(s, 4, 5 + 9) + drawWakeUp(req.context, req.wakeupBean, req.startNS, req.endNS, req.totalNS, req.frame); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct + }); + } + +} + +export function freqLimits(list: Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, use: boolean) { + if (use && res.length > 0) { + res.forEach(it => CpuFreqLimitsStruct.setFreqLimitFrame(it, 5, startNS || 0, endNS || 0, totalNS || 0, frame)); + return; + } + res.length = 0; + if (list) { + for (let i = 0, len = list.length; i < len; i++) { + let it = list[i]; + if (i === list.length - 1) { + it.dur = (endNS || 0) - (it.startNs || 0) + } else { + it.dur = (list[i + 1].startNs || 0) - (it.startNs || 0) + } + if ((it.startNs || 0) + (it.dur || 0) > (startNS || 0) && (it.startNs || 0) < (endNS || 0)) { + CpuFreqLimitsStruct.setFreqLimitFrame(list[i], 5, startNS || 0, endNS || 0, totalNS || 0, frame) + if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && (list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0))) { + + } else { + res.push(it) + } + } + } + } + +} + +export class CpuFreqLimitsStruct extends BaseStruct { + static hoverCpuFreqLimitsStruct: CpuFreqLimitsStruct | undefined; + static selectCpuFreqLimitsStruct: CpuFreqLimitsStruct | undefined; + static minAlpha = 0.4; + static maxAlpha = 0.8; + startNs: number | undefined; + dur:number = 0; + max: number | undefined; + min: number | undefined; + cpu:number = 0; + + static draw(ctx: CanvasRenderingContext2D, data: CpuFreqLimitsStruct,maxFreq:number) { + if (data.frame) { + let width = data.frame.width || 0; + let drawMaxHeight: number = Math.floor(((data.max || 0) * (data.frame.height || 0)) / maxFreq); + let drawMinHeight: number = Math.floor(((data.min || 0) * (data.frame.height || 0)) / maxFreq); + let index = data.cpu || 0 + index += 2 + ctx.fillStyle = ColorUtils.colorForTid(index) + ctx.strokeStyle = ColorUtils.colorForTid(index) + if (data.startNs === CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct?.startNs||data.startNs === CpuFreqLimitsStruct.selectCpuFreqLimitsStruct?.startNs) { + ctx.lineWidth = 1; + ctx.globalAlpha = this.minAlpha; + this.drawArcLine(ctx,data,drawMaxHeight,drawMaxHeight - drawMinHeight) + ctx.globalAlpha = this.maxAlpha; + this.drawArcLine(ctx,data,drawMinHeight,drawMinHeight) + } else { + ctx.globalAlpha = this.minAlpha; + ctx.lineWidth = 1; + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawMaxHeight, width, drawMaxHeight - drawMinHeight) + ctx.globalAlpha = this.maxAlpha; + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawMinHeight, width, drawMinHeight) + } + } + ctx.globalAlpha = 1.0; + ctx.lineWidth = 1; + } + + static drawArcLine(ctx: CanvasRenderingContext2D,data: CpuFreqLimitsStruct,yStartHeight:number,drawHeight:number){ + if (data.frame) { + let width = data.frame.width || 0; + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - yStartHeight, width, drawHeight) + ctx.globalAlpha = this.maxAlpha; + ctx.beginPath() + ctx.arc(data.frame.x, data.frame.y + data.frame.height - yStartHeight, 3, 0, 2 * Math.PI, true) + ctx.fill() + ctx.stroke(); + ctx.beginPath() + ctx.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - yStartHeight); + ctx.lineWidth = 3; + ctx.lineTo(data.frame.x + width, data.frame.y + data.frame.height - yStartHeight) + ctx.stroke(); + } + } + + static setFreqLimitFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { + let x1: number, x2: number; + if ((node.startNs || 0) < startNS) { + x1 = 0; + } else { + x1 = ns2x((node.startNs || 0), startNS, endNS, totalNS, frame); + } + if ((node.startNs || 0) + (node.dur || 0) > endNS) { + x2 = frame.width; + } else { + x2 = ns2x((node.startNs || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); + } + let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1; + if (!node.frame) { + node.frame = {}; + } + node.frame.x = Math.floor(x1); + node.frame.y = frame.y + padding; + node.frame.width = Math.ceil(getV); + node.frame.height = Math.floor(frame.height - padding * 2); + } +} \ No newline at end of file diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerCpuState.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerCpuState.ts new file mode 100644 index 0000000000000000000000000000000000000000..7eaeb401a55230828014c2d2da4006ec592bede2 --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerCpuState.ts @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BaseStruct, + drawFlagLine, + drawLines, + drawLoading, drawSelection, + drawWakeUp, ns2x, PerfRender, Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; +import {ColorUtils} from "../../component/trace/base/ColorUtils.js"; +import {convertJSON} from "../logic-worker/ProcedureLogicWorkerCommon.js"; + +export class CpuStateRender extends PerfRender { + + renderMainThread(req: { useCache: boolean; context: CanvasRenderingContext2D; type: string; cpu: number }, row: TraceRow) { + let list = row.dataList = convertJSON(row.dataList); + let filter = row.dataListCache; + let chartColor = ColorUtils.colorForTid(req.cpu); + if(list && row.dataList2.length == 0){ + row.dataList2 = this.getList(list,TraceRow.range!.endNS,req.cpu) + } + this.cpuState(list, row.dataList2, req.type!, filter, req.cpu, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, row.frame, req.useCache || !TraceRow.range!.refresh); + req.context.beginPath(); + req.context.font = "11px sans-serif"; + req.context.fillStyle = chartColor; + req.context.strokeStyle = chartColor; + req.context.globalAlpha = 0.6; + let path = new Path2D(); + let find = false; + let offset = 3; + for (let re of filter) { + CpuStateStruct.draw(req.context, path, re); + if (row.isHover) { + if (re.frame && row.hoverX >= re.frame.x - offset && row.hoverX <= re.frame.x + re.frame.width + offset) { + CpuStateStruct.hoverStateStruct = re; + find = true; + } + } + } + if (!find && row.isHover) CpuStateStruct.hoverStateStruct = undefined; + req.context.fill(path); + } + + render(req: RequestMessage, list: Array, filter: Array, dataList2: Array) { + if (req.lazyRefresh) { + this.cpuState(list, dataList2, req.type!, filter, req.params.cpu, req.startNS, req.endNS, req.totalNS, req.frame, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + this.cpuState(list, dataList2, req.type!, filter, req.params.cpu, req.startNS, req.endNS, req.totalNS, req.frame, false); + } + } + CpuStateStruct.hoverStateStruct = undefined; + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + if (filter.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, filter[0].startTs, filter[filter.length - 1].startTs + filter[filter.length - 1].dur) + } + req.context.beginPath(); + drawLines(req.context, req.xs, req.frame.height, req.lineColor); + if (req.isHover) { + let offset = 3; + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x - offset && req.hoverX <= re.frame.x + re.frame.width + offset) { + CpuStateStruct.hoverStateStruct = re; + break; + } + } + } + CpuStateStruct.selectStateStruct = req.params.selectStateStruct; + req.context.font = "11px sans-serif"; + req.context.fillStyle = req.chartColor; + req.context.strokeStyle = req.chartColor; + req.context.globalAlpha = 0.6; + let path = new Path2D(); + for (let re of filter) { + CpuStateStruct.draw(req.context, path, re); + } + req.context.fill(path); + drawSelection(req.context, req.params); + drawWakeUp(req.context, req.wakeupBean, req.startNS, req.endNS, req.totalNS, req.frame); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + let msg = { + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: CpuStateStruct.hoverStateStruct + } + self.postMessage(msg); + } + + cpuState(arr: Array, arr2: Array, type: string, res: Array, cpu: number, startNS: number, endNS: number, totalNS: number, frame: any, use: boolean) { + if (use && res.length > 0) { + for (let i = 0, len = res.length; i < len; i++) { + if ((res[i].startTs || 0) + (res[i].dur || 0) >= startNS && (res[i].startTs || 0) <= endNS) { + CpuStateStruct.setFrame(res[i], 5, startNS, endNS, totalNS, frame) + } else { + res[i].frame = null; + } + } + return; + } + res.length = 0; + if (arr) { + let list: Array = arr2; + res.length = 0; + let pns = (endNS - startNS) / frame.width;//每个像素多少ns + let y = frame.y + 5; + let height = frame.height - 10; + let left = 0, right = 0; + for (let i = 0, j = list.length - 1, ib = true, jb = true; i < list.length, j >= 0; i++, j--) { + if (list[j].startTs <= endNS && jb) { + right = j; + jb = false; + } + if (list[i].startTs + list[i].dur >= startNS && ib) { + left = i; + ib = false; + } + if (!ib && !jb) { + break; + } + } + let slice = list.slice(left, right + 1); + let sum = 0; + for (let i = 0; i < slice.length; i++) { + if (!slice[i].frame) { + slice[i].frame = {}; + slice[i].frame.y = y; + slice[i].frame.height = height; + } + if (slice[i].dur >= pns) { + slice[i].v = true; + CpuStateStruct.setFrame(slice[i], 5, startNS, endNS, totalNS, frame) + } else { + if (i > 0) { + let c = slice[i].startTs - slice[i - 1].startTs - slice[i - 1].dur + if (c < pns && sum < pns) { + sum += c + slice[i - 1].dur; + slice[i].v = false; + } else { + slice[i].v = true; + CpuStateStruct.setFrame(slice[i], 5, startNS, endNS, totalNS, frame) + sum = 0; + } + } + } + } + res.push(...slice.filter(it => it.v)); + } + } + + getList(arr: Array, endNS: number, cpu: number): Array { + let heights = [4, 12, 21, 30] + for (let i = 0, len = arr.length; i < len; i++) { + let it = arr[i]; + it.height = heights[it.value] + it.cpu = cpu; + if (i === arr.length - 1) { + it.dur = (endNS || 0) - (it.startTs || 0) + } else { + it.dur = (arr[i + 1].startTs || 0) - (it.startTs || 0) + } + } + return arr; + } + +} + +export class CpuStateStruct extends BaseStruct { + static hoverStateStruct: CpuStateStruct | undefined; + static selectStateStruct: CpuStateStruct | undefined; + dur: number | undefined + value: string | undefined + startTs: number | undefined + height: number | undefined + cpu: number | undefined + + static draw(ctx: CanvasRenderingContext2D, path: Path2D, data: CpuStateStruct) { + if (data.frame) { + if (data.startTs === CpuStateStruct.hoverStateStruct?.startTs || data.startTs === CpuStateStruct.selectStateStruct?.startTs) { + path.rect(data.frame.x, 35 - (data.height || 0), data.frame.width, data.height || 0) + ctx.lineWidth = 1; + ctx.globalAlpha = 1.0; + ctx.beginPath() + ctx.arc(data.frame.x, 35 - (data.height || 0), 3, 0, 2 * Math.PI, true) + ctx.stroke() + ctx.beginPath() + ctx.moveTo(data.frame.x + 3, 35 - (data.height || 0)); + ctx.lineWidth = 3; + ctx.lineTo(data.frame.x + data.frame.width, 35 - (data.height || 0)) + ctx.stroke(); + ctx.lineWidth = 1; + ctx.globalAlpha = 0.6; + ctx.fillRect(data.frame.x, 35 - (data.height || 0), data.frame.width, data.height || 0) + } else { + ctx.globalAlpha = 0.6; + path.rect(data.frame.x, 35 - (data.height || 0), data.frame.width, data.height || 0) + } + } + } + + static setCpuFrame(node: any, pns: number, startNS: number, endNS: number, frame: any) { + if ((node.startTime || 0) < startNS) { + node.frame.x = 0; + } else { + node.frame.x = Math.floor(((node.startTs || 0) - startNS) / pns); + } + if ((node.startTime || 0) + (node.dur || 0) > endNS) { + node.frame.width = frame.width - node.frame.x; + } else { + node.frame.width = Math.ceil(((node.startTs || 0) + (node.dur || 0) - startNS) / pns - node.frame.x); + } + if (node.frame.width < 1) { + node.frame.width = 1; + } + } + static setFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { + let x1: number, x2: number; + if ((node.startTs || 0) < startNS) { + x1 = 0; + } else { + x1 = ns2x((node.startTs || 0), startNS, endNS, totalNS, frame); + } + if ((node.startTs || 0) + (node.dur || 0) > endNS) { + x2 = frame.width; + } else { + x2 = ns2x((node.startTs || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); + } + let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1; + if (!node.frame) { + node.frame = {}; + } + node.frame.x = Math.ceil(x1); + node.frame.y = frame.y + padding; + node.frame.width = Math.floor(getV); + node.frame.height = node.height; + } +} diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerDiskIoAbility.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerDiskIoAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..8bd6d8ddcaf92494782c798e0f0d63361d853db7 --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerDiskIoAbility.ts @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ColorUtils } from "../../component/trace/base/ColorUtils.js"; +import { + BaseStruct, dataFilterHandler, + drawFlagLine, + drawLines, + drawLoading, + drawSelection, drawWakeUp, isFrameContainPoint, + ns2x, Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; + +export class DiskIoAbilityRender extends Render{ + renderMainThread(req: { + context: CanvasRenderingContext2D, + useCache: boolean, + type: string, + maxDiskRate:number, + maxDiskRateName:string + }, row: TraceRow) { + let list = row.dataList; + let filter = row.dataListCache; + dataFilterHandler(list,filter,{ + startKey: "startNS", + durKey: "dur", + startNS: TraceRow.range?.startNS ?? 0, + endNS: TraceRow.range?.endNS ?? 0, + totalNS: TraceRow.range?.totalNS ?? 0, + frame: row.frame, + paddingTop: 5, + useCache: req.useCache || !(TraceRow.range?.refresh ?? false) + }) + req.context.beginPath(); + let find = false; + for (let re of filter) { + DiskAbilityMonitorStruct.draw(req.context, re,req.maxDiskRate,row.isHover) + if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { + DiskAbilityMonitorStruct.hoverDiskAbilityStruct = re; + find = true; + } + } + if (!find && row.isHover) DiskAbilityMonitorStruct.hoverDiskAbilityStruct = undefined; + req.context.closePath(); + let textMetrics = req.context.measureText(req.maxDiskRateName); + req.context.globalAlpha = 0.8 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(req.maxDiskRateName, 4, 5 + 9) + } + + render(req: RequestMessage, list: Array, filter: Array) { + if (req.lazyRefresh) { + diskIoAbility(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + diskIoAbility(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startNS, arr[arr.length - 1].startNS + arr[arr.length - 1].dur) + } + req.context.beginPath(); + let maxDiskRate = req.params.maxDiskRate; + let maxDiskRateName = req.params.maxDiskRateName; + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + DiskAbilityMonitorStruct.hoverDiskAbilityStruct = undefined; + if (req.isHover) { + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x && req.hoverX <= re.frame.x + re.frame.width && req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height) { + DiskAbilityMonitorStruct.hoverDiskAbilityStruct = re; + break; + } + } + } + DiskAbilityMonitorStruct.selectDiskAbilityStruct = req.params.selectDiskAbilityStruct; + for (let re of filter) { + DiskAbilityMonitorStruct.draw(req.context, re, maxDiskRate,true) + } + drawSelection(req.context, req.params); + req.context.closePath(); + let textMetrics = req.context.measureText(maxDiskRateName); + req.context.globalAlpha = 0.8 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(maxDiskRateName, 4, 5 + 9) + drawWakeUp(req.context, req.wakeupBean, req.startNS, req.endNS, req.totalNS, req.frame); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: DiskAbilityMonitorStruct.hoverDiskAbilityStruct + }); + } +} + +export function diskIoAbility(list: Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, use: boolean) { + if (use && res.length > 0) { + for (let i = 0; i < res.length; i++) { + let item = res[i]; + if ((item.startNS || 0) + (item.dur || 0) > (startNS || 0) && (item.startNS || 0) < (endNS || 0)) { + DiskAbilityMonitorStruct.setDiskIOFrame(item, 5, startNS || 0, endNS || 0, totalNS || 0, frame) + } else { + item.frame = null; + } + } + return; + } + res.length = 0; + if (list) { + for (let index = 0; index < list.length; index++) { + let item = list[index]; + if (index === list.length - 1) { + item.dur = (endNS || 0) - (item.startNS || 0) + } else { + item.dur = (list[index + 1].startNS || 0) - (item.startNS || 0) + } + if ((item.startNS || 0) + (item.dur || 0) > (startNS || 0) && (item.startNS || 0) < (endNS || 0)) { + DiskAbilityMonitorStruct.setDiskIOFrame(list[index], 5, startNS || 0, endNS || 0, totalNS || 0, frame) + if (index > 0 && ((list[index - 1].frame?.x || 0) == (list[index].frame?.x || 0) && (list[index - 1].frame?.width || 0) == (list[index].frame?.width || 0))) { + + } else { + res.push(item) + } + } + } + } + +} + +export class DiskAbilityMonitorStruct extends BaseStruct { + static maxDiskRate: number = 0 + static maxDiskRateName: string = "0 KB/S" + static hoverDiskAbilityStruct: DiskAbilityMonitorStruct | undefined; + static selectDiskAbilityStruct: DiskAbilityMonitorStruct | undefined; + value: number | undefined + startNS: number | undefined + dur: number | undefined //自补充,数据库没有返回 + + static draw(context2D: CanvasRenderingContext2D, data: DiskAbilityMonitorStruct, maxDiskRate: number,isHover:boolean) { + if (data.frame) { + let width = data.frame.width || 0; + let index = 2; + context2D.fillStyle = ColorUtils.colorForTid(index) + context2D.strokeStyle = ColorUtils.colorForTid(index) + if (data.startNS === DiskAbilityMonitorStruct.hoverDiskAbilityStruct?.startNS && isHover) { + context2D.lineWidth = 1; + context2D.globalAlpha = 0.6; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / maxDiskRate); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, width, drawHeight) + context2D.beginPath() + context2D.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, 3, 0, 2 * Math.PI, true) + context2D.fill() + context2D.globalAlpha = 1.0; + context2D.stroke(); + context2D.beginPath() + context2D.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight + 4); + context2D.lineWidth = 3; + context2D.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight + 4) + context2D.stroke(); + } else { + context2D.globalAlpha = 0.6; + context2D.lineWidth = 1; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0)) / maxDiskRate); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, width, drawHeight) + } + } + context2D.globalAlpha = 1.0; + context2D.lineWidth = 1; + } + + static setDiskIOFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { + let startPointX: number, endPointX: number + + if ((node.startNS || 0) < startNS) { + startPointX = 0 + } else { + startPointX = ns2x((node.startNS || 0), startNS, endNS, totalNS, frame); + } + if ((node.startNS || 0) + (node.dur || 0) > endNS) { + endPointX = frame.width; + } else { + endPointX = ns2x((node.startNS || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); + } + let frameWidth: number = endPointX - startPointX <= 1 ? 1 : endPointX - startPointX; + if (!node.frame) { + node.frame = {}; + } + node.frame.x = Math.floor(startPointX); + node.frame.y = frame.y + padding; + node.frame.width = Math.ceil(frameWidth); + node.frame.height = Math.floor(frame.height - padding * 2); + } +} diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerEnergyAnomaly.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerEnergyAnomaly.ts new file mode 100644 index 0000000000000000000000000000000000000000..8a50003f464186427e2d048109e9c40a996ddcbb --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerEnergyAnomaly.ts @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ColorUtils } from "../../component/trace/base/ColorUtils.js"; +import { + BaseStruct, + drawFlagLine, + drawLines, + drawLoading, + drawSelection, isFrameContainPoint, + PerfRender, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; + +export class EnergyAnomalyRender extends PerfRender { + renderMainThread(req: { useCache: boolean; context: CanvasRenderingContext2D; type: string; appName:string;canvasWidth:number}, row: TraceRow) { + let list = row.dataList + let filter = row.dataListCache; + anomaly(list, filter,TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, row.frame, req.appName,req.useCache || !TraceRow.range!.refresh) + req.context.beginPath(); + let find = false; + let spApplication = document.getElementsByTagName("sp-application")[0]; + let isDark = spApplication.hasAttribute("dark"); + drawLegend(req, isDark); + for (let re of filter) { + EnergyAnomalyStruct.draw(req.context, re) + if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { + EnergyAnomalyStruct.hoverEnergyAnomalyStruct = re; + find = true; + } + } + if (!find && row.isHover) EnergyAnomalyStruct.hoverEnergyAnomalyStruct = undefined; + req.context.fillStyle = ColorUtils.FUNC_COLOR[0] + req.context.strokeStyle = ColorUtils.FUNC_COLOR[0]; + req.context.closePath(); + } + + render(req: RequestMessage, list: Array, filter: Array,dataList2:Array){ + if (req.lazyRefresh) { + anomaly(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.params.appName, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + anomaly(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.params.appName, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.canvas.width, req.canvas.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startNS, arr[arr.length - 1].startNS) + } + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + req.context.stroke(); + req.context.beginPath(); + EnergyAnomalyStruct.hoverEnergyAnomalyStruct = undefined; + if (req.isHover) { + let offset = 3; + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x - offset && req.hoverX <= re.frame.x + re.frame.width + offset) { + EnergyAnomalyStruct.hoverEnergyAnomalyStruct = re; + break; + } + } + } else { + EnergyAnomalyStruct.hoverEnergyAnomalyStruct = req.params.hoverStruct; + } + EnergyAnomalyStruct.selectEnergyAnomalyStruct = req.params.selectEnergyAnomalyStruct; + req.context.fillStyle = ColorUtils.FUNC_COLOR[0] + req.context.strokeStyle = ColorUtils.FUNC_COLOR[0]; + for (let re of filter) { + EnergyAnomalyStruct.draw(req.context, re); + } + drawLegend(req); + drawSelection(req.context, req.params); + req.context.closePath(); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: EnergyAnomalyStruct.hoverEnergyAnomalyStruct + }); + } +} + +export function drawLegend(req: any, isDark?: boolean) { + req.context.font = "12px Arial"; + let text = req.context.measureText("System Abnormality"); + req.context.fillStyle = "#E64566"; + req.context.strokeStyle = "#E64566"; + let textColor = isDark ? "#FFFFFF" : "#333"; + let canvasEndX = req.context.canvas.clientWidth - EnergyAnomalyStruct.OFFSET_WIDTH; + let rectPadding: number; + let textPadding: number; + let textMargin: number; + let currentTextWidth: number; + let lastTextMargin: number; + rectPadding = 280; + textPadding = 270; + textMargin = 250; + currentTextWidth = canvasEndX - textMargin + text.width; + lastTextMargin = currentTextWidth + 12; + req!.context.fillRect((canvasEndX - rectPadding), 12, 8, 8); + req.context.globalAlpha = 1 + req.context.fillStyle = textColor; + req.context.textBaseline = "middle" + req.context.fillText("System Abnormality", canvasEndX - textPadding, 18); + req.context.fillStyle = "#FFC880"; + req.context.strokeStyle = "#FFC880"; + req.context.fillRect(currentTextWidth, 12, 8, 8); + req.context.globalAlpha = 1 + req.context.fillStyle = textColor; + req.context.textBaseline = "middle" + req.context.fillText("Application Abnormality", lastTextMargin, 18); + req.context.fillStyle = "#333"; +} + +export function anomaly(arr: Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, appName: string | undefined, use: boolean) { + if (use && res.length > 0 ) { + let pns = (endNS - startNS) / frame.width; + let y = frame.y; + for (let i = 0; i < res.length; i++) { + let it = res[i]; + if((it.startNS || 0) > startNS && (it.startNS || 0) < endNS){ + if (!it.frame) { + it.frame = {}; + it.frame.y = y; + } + it.frame.height = it.height; + EnergyAnomalyStruct.setAnomalyFrame(it, pns, startNS, endNS, frame); + }else{ + it.frame = null; + } + } + return; + } + + res.length = 0; + if (arr) { + let y = frame.y; + let pns = (endNS - startNS) / frame.width; + for (let index = 0; index < arr.length; index++) { + let item = arr[index]; + if (!item.frame) { + item.frame = {}; + item.frame.y = y; + } + item.frame.height = item.height; + if ((item.startNS + 50000) > (startNS || 0) && (item.startNS || 0) < (endNS || 0)) { + EnergyAnomalyStruct.setAnomalyFrame(item, pns, startNS || 0, endNS || 0, frame) + if ((item.appKey === "APPNAME" && item.Value.split(",").indexOf(appName) >= 0)) { + res.push(item) + } + if (item.appKey != "APPNAME") { + res.push(item) + } + } + } + } +} + +export class EnergyAnomalyStruct extends BaseStruct { + static hoverEnergyAnomalyStruct: EnergyAnomalyStruct | undefined; + static selectEnergyAnomalyStruct: EnergyAnomalyStruct | undefined; + static SYSTEM_EXCEPTION = new Set(["ANOMALY_SCREEN_OFF_ENERGY", "ANOMALY_ALARM_WAKEUP", + "ANOMALY_KERNEL_WAKELOCK", "ANOMALY_CPU_HIGH_FREQUENCY", "ANOMALY_WAKEUP"]); + static OFFSET_WIDTH: number = 266 + type: number | undefined + startNS: number | undefined + height: number | undefined + eventName: string | undefined + + static draw(ctx: CanvasRenderingContext2D, data: EnergyAnomalyStruct) { + if (data.frame) { + EnergyAnomalyStruct.drawRoundRectPath(ctx, data.frame.x - 7, 20 - 7, 12, data) + } + + } + + static drawRoundRectPath(ctx: CanvasRenderingContext2D, x: number, y: number, radius: number, data: EnergyAnomalyStruct) { + ctx.beginPath(); + ctx.arc(x + 7, y + 22, radius, 0, Math.PI * 2); + ctx.closePath(); + let color = ""; + if(EnergyAnomalyStruct.SYSTEM_EXCEPTION.has(data.eventName)){ + color = '#E64566'; + }else { + color = "#FFC880"; + } + // 填充背景颜色 + ctx.fillStyle = color; + ctx.fill(); + ctx.stroke(); + // 填充文字颜色 + ctx.font = "12px Arial"; + ctx.fillStyle = ColorUtils.GREY_COLOR; + ctx.textAlign = "center"; + ctx.fillText("E", x + 7, y + 23); + } + + static setAnomalyFrame(node: any, pns: number, startNS: number, endNS: number, frame: any) { + if ((node.startNS || 0) < startNS) { + node.frame.x = 0; + } else { + node.frame.x = Math.floor(((node.startNS || 0) - startNS) / pns); + } + if ((node.startNS || 0) > endNS) { + node.frame.width = frame.width - node.frame.x; + } else { + node.frame.width = Math.ceil(((node.startNS || 0) - startNS) / pns - node.frame.x); + } + if (node.frame.width < 1) { + node.frame.width = 1; + } + } + +} + + + + + diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerEnergyPower.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerEnergyPower.ts new file mode 100644 index 0000000000000000000000000000000000000000..1b2cbea1310ac127517ea1c929fe7656b9978160 --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerEnergyPower.ts @@ -0,0 +1,374 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BaseStruct, + drawFlagLine, drawLines, + drawLoading, + drawSelection, isFrameContainPoint, + ns2x, + Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; + +export class EnergyPowerRender extends Render { + + renderMainThread(req: { useCache: boolean; context: CanvasRenderingContext2D; type: string; appName:string;}, row: TraceRow) { + let list = row.dataList + let filter = row.dataListCache; + power(list, filter,TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, row.frame,req.useCache || !TraceRow.range!.refresh, req.appName) + req.context.beginPath(); + let find = false; + for (let i = 0; i < filter.length; i++) { + let re = filter[i] + EnergyPowerStruct.draw(req,i, re,row) + if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { + EnergyPowerStruct.hoverEnergyPowerStruct = re; + find = true; + } + } + if (!find && row.isHover) EnergyPowerStruct.hoverEnergyPowerStruct = undefined; + TraceRow.range!.refresh = true + if (EnergyPowerStruct.maxPower != 0) { + let s = EnergyPowerStruct.maxPower + "mAs" + let textMetrics = req.context.measureText(s); + req.context.globalAlpha = 1.0 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(s, 4, 5 + 9) + } + req.context.closePath(); + let spApplication = document.getElementsByTagName("sp-application")[0]; + let isDark = spApplication.hasAttribute("dark"); + drawLegend(req, isDark); + } + + render(req: RequestMessage, list: Array, filter: Array) { + if (req.lazyRefresh) { + power(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.useCache + || !req.range.refresh, req.params.maxPowerName); + } else { + if (!req.useCache) { + power(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, false, req.params.maxPowerName); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.canvas.width, EnergyPowerStruct.rowHeight); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startNS, + arr[arr.length - 1].startNS + arr[arr.length - 1].dur) + } + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + req.context.beginPath(); + EnergyPowerStruct.hoverEnergyPowerStruct = undefined; + if (req.isHover) { + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x && req.hoverX <= re.frame.x + re.frame.width && req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height) { + EnergyPowerStruct.hoverEnergyPowerStruct = re; + break; + } + } + } + EnergyPowerStruct.selectEnergyPowerStruct = req.params.selectEnergyPowerStruct; + for (let index = 0; index < filter.length; index++) { + // EnergyPowerStruct.draw(req, index, filter[index]) + } + req.context.stroke(); + drawSelection(req.context, req.params); + req.context.closePath(); + if (EnergyPowerStruct.maxPower != 0) { + let s = EnergyPowerStruct.maxPower + "mAs" + let textMetrics = req.context.measureText(s); + req.context.globalAlpha = 1.0 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(s, 4, 5 + 9) + } + drawLegend(req) + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, + req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: EnergyPowerStruct.hoverEnergyPowerStruct + }); + } +} + +export function drawLegend(req: any, isDark?: boolean){ + let textList = ["CPU", "LOCATION", "GPU", "DISPLAY", "CAMERA", "BLUETOOTH", "FLASHLIGHT", "AUDIO", "WIFISCAN"] + for (let index = 0; index < textList.length; index++) { + let text = req.context.measureText(textList[index]); + req.context.fillStyle = EnergyPowerStruct.getHistogramColor(textList[index]); + req.context.globalAlpha = 1 + let canvasEndX = req.context.canvas.clientWidth - EnergyPowerStruct.OFFSET_WIDTH; + let textColor = isDark ? "#FFFFFF" : "#333"; + if(index == 0){ + req!.context.fillRect(canvasEndX - (EnergyPowerStruct.powerItemNumber * 80), 12, 8, 8); + req.context.globalAlpha = 1 + req.context.fillStyle = textColor; + req.context.textBaseline = "middle" + req.context.fillText(textList[index], canvasEndX - (EnergyPowerStruct.powerItemNumber * 80) + 10, 18) + EnergyPowerStruct.currentTextWidth = canvasEndX - (EnergyPowerStruct.powerItemNumber * 80) + 40 + text.width + } else { + req!.context.fillRect(EnergyPowerStruct.currentTextWidth, 12, 8, 8); + req.context.globalAlpha = 1 + req.context.fillStyle = textColor; + req.context.textBaseline = "middle" + req!.context.fillText(textList[index], EnergyPowerStruct.currentTextWidth + 12, 18); + EnergyPowerStruct.currentTextWidth = EnergyPowerStruct.currentTextWidth + 40 + text.width + } + } + req.context.fillStyle = "#333"; +} + +export function power(list: Array, res: Array, startNS: number, endNS: number, totalNS: number, + frame: any, use: boolean, appName: string) { + if (use && res.length > 0) { + for (let i = 0; i < res.length; i++) { + let item = res[i]; + let obj = item[appName] + if (obj != undefined) { + if ((obj.ts + 1000000000) > (startNS || 0) && (obj.ts || 0) < (endNS || 0)) { + EnergyPowerStruct.setPowerFrame(item, 5, startNS || 0, endNS || 0, + totalNS || 0, frame) + } else { + obj.frame = null; + } + } + } + return; + } + res.length = 0; + if (list) { + let firstList: Array = [] + EnergyPowerStruct.maxPower = 0 + for (let index = 0; index < list.length; index++) { + let item = list[index]; + let obj = item[appName] + if (obj != undefined) { + if ((obj.ts + 1000000000) > (startNS || 0) && (obj.ts || 0) < (endNS || 0)) { + firstList.push(obj) + } + } + } + + let array = firstList.sort((a, b) => a.ts - b.ts); + for (let index = 0; index < array.length; index++) { + if (res.length == 0) { + res.push(array[index]) + } else { + let rightTime = array[index].ts + 500000000; + let leftTime = array[index].ts - 500000000; + let obj = res[res.length - 1]; + if (obj.ts >= leftTime && obj.ts <= rightTime) { + obj.cpu = obj.cpu == 0 ? array[index].cpu : obj.cpu + obj.location = obj.location == 0 ? array[index].location : obj.location + obj.gpu = obj.gpu == 0 ? array[index].gpu : obj.gpu + obj.display = obj.display == 0 ? array[index].display : obj.display + obj.camera = obj.camera == 0 ? array[index].camera : obj.camera + obj.bluetooth = obj.bluetooth == 0 ? array[index].bluetooth : obj.bluetooth + obj.flashlight = obj.flashlight == 0 ? array[index].flashlight : obj.flashlight + obj.audio = obj.audio ? array[index].audio : obj.audio + obj.wifiscan = obj.wifiscan == 0 ? array[index].wifiscan : obj.wifiscan + } else { + res.push(array[index]) + } + } + } + res.forEach(item => { + EnergyPowerStruct.setPowerFrame(item, 5, startNS || 0, endNS || 0, + totalNS || 0, frame) + let max = (item.cpu || 0) + (item.location || 0) + (item.gpu || 0) + (item.display || 0) + (item.camera + || 0) + (item.bluetooth || 0) + (item.flashlight || 0) + (item.audio || 0) + (item.wifiscan || 0) + if (max > EnergyPowerStruct.maxPower) { + EnergyPowerStruct.maxPower = max + } + }) + } +} + +export class EnergyPowerStruct extends BaseStruct { + static maxPower: number = 0 + static maxPowerName: string = "0" + static powerItemNumber: number = 9 + static currentTextWidth: number = 0 + static rowHeight: number = 200 + static appName: string | undefined + static hoverEnergyPowerStruct: EnergyPowerStruct | undefined; + static selectEnergyPowerStruct: EnergyPowerStruct | undefined; + static OFFSET_WIDTH: number = 266 + name: string | undefined + ts: number = 0 + cpu: number = 0 + location: number = 0 + gpu: number = 0 + display: number = 0 + camera: number = 0 + bluetooth: number = 0 + flashlight: number = 0 + audio: number = 0 + wifiscan: number = 0 + + static draw(req: any, index: number, data: EnergyPowerStruct,row:TraceRow) { + if (data.frame) { + let width = data.frame.width || 0; + req!.context.globalAlpha = 1.0; + req!.context.lineWidth = 1; + this.currentTextWidth = 0 + let cpuHeight = this.drawHistogram(req, data, -1, data.cpu!, "CPU", row.frame); + let locationHeight = this.drawHistogram(req, data, cpuHeight, data.location!, "LOCATION", row.frame); + let gpuHeight = this.drawHistogram(req, data, cpuHeight - locationHeight, data.gpu!, + "GPU", row.frame); + let displayHeight = this.drawHistogram(req, data, + cpuHeight - locationHeight - gpuHeight, data.display!, "DISPLAY", row.frame); + let cameraHeight = this.drawHistogram(req, data, cpuHeight - locationHeight - gpuHeight - + displayHeight, data.camera!, "CAMERA", row.frame); + let bluetoothHeight = this.drawHistogram(req, data, cpuHeight - locationHeight - gpuHeight - + displayHeight - cameraHeight, data.bluetooth!, "BLUETOOTH", row.frame); + let flashlightHeight = this.drawHistogram(req, data, cpuHeight - locationHeight - gpuHeight - + displayHeight - cameraHeight - bluetoothHeight, data.flashlight!, "FLASHLIGHT", row.frame); + let audioHeight = this.drawHistogram(req, data, cpuHeight - locationHeight - gpuHeight - + displayHeight - cameraHeight - bluetoothHeight - flashlightHeight, data.audio!, + "AUDIO", row.frame); + let wifiHeight = this.drawHistogram(req, data, cpuHeight - locationHeight - gpuHeight - + displayHeight - cameraHeight - bluetoothHeight - flashlightHeight - audioHeight, data.wifiscan!, + "WIFISCAN", row.frame); + let maxPointY = this.drawPolyline(req, index, data, row.frame, wifiHeight) + if (data.ts === EnergyPowerStruct.hoverEnergyPowerStruct?.ts) { + let endPointX = ns2x(((data.ts || 0) + 500000000), TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, row.frame); + let startPointX = ns2x(((data.ts || 0) - 500000000), TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, row.frame); + let frameWidth = endPointX - startPointX <= 1 ? 1 : endPointX - startPointX; + req.context.globalAlpha = 1 + req!.context.lineWidth = 2; + req.context.fillStyle = "#333" + req!.context.strokeRect(startPointX, maxPointY, frameWidth, req.context.canvas.width - maxPointY); + } + } + req!.context.globalAlpha = 1.0; + req!.context.lineWidth = 1; + } + + static drawHistogram(req: RequestMessage, data: EnergyPowerStruct, height: number, itemValue: number, + textItem: string,rowFrame:any): number { + let endPointX = ns2x(((data.ts || 0) + 500000000), TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, rowFrame); + let startPointX = ns2x(((data.ts || 0) - 500000000), TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, rowFrame); + let frameWidth = endPointX - startPointX <= 1 ? 1 : endPointX - startPointX; + let histogramColor = this.getHistogramColor(textItem); + req!.context.fillStyle = histogramColor; + req!.context.strokeStyle = histogramColor; + let dataHeight: number = Math.floor(((itemValue || 0) * (this.rowHeight - 40)) / + EnergyPowerStruct.maxPower); + if (itemValue != 0 && dataHeight < 15) { + dataHeight = 15 + } + let drawStartY = 0; + + if (height == -1) { + drawStartY = data.frame!.y + this.rowHeight - dataHeight + 4; + req!.context.fillRect(startPointX, drawStartY, frameWidth, dataHeight); + return drawStartY; + } else { + drawStartY = height - dataHeight; + req!.context.fillRect(startPointX, drawStartY, frameWidth, dataHeight); + if(textItem == 'WIFISCAN'){ + return drawStartY; + } + return dataHeight; + } + } + + static drawPolyline(req: RequestMessage, index: number, data: EnergyPowerStruct, rowFrame:any, totalHeight: number) { + let pointX = ns2x((data.ts || 0), TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, rowFrame); + let maxHeight = (data.cpu || 0) + (data.location || 0) + (data.gpu || 0) + (data.display || 0) + (data.camera + || 0) + (data.bluetooth || 0) + (data.flashlight || 0) + (data.audio || 0) + (data.wifiscan || 0) + let drawHeight: number = Math.floor(((maxHeight || 0) * (this.rowHeight - 40)) / + EnergyPowerStruct.maxPower); + let drawY = data.frame!.y + this.rowHeight - drawHeight + 5 + req!.context.fillStyle = "#ED6F21"; + req!.context.strokeStyle = "#ED6F21"; + + if (index == 0) { + req.context.beginPath() + req.context.arc(pointX, totalHeight, 4, 0, 2 * Math.PI) + req.context.fill() + req.context.moveTo(pointX, totalHeight) + } else { + req.context.lineTo(pointX, totalHeight); + req.context.stroke(); + req.context.beginPath() + req.context.arc(pointX, totalHeight, 4, 0, 2 * Math.PI) + req.context.fill() + } + return totalHeight + } + + static setPowerFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { + let startPointX: number + let endPointX: number + if ((node.ts || 0) < startNS) { + startPointX = 0 + } else { + startPointX = ns2x(((node.ts || 0) - 500000000), startNS, endNS, totalNS, frame); + } + if ((node.ts + 500000000) > endNS) { + endPointX = frame.width; + } else { + endPointX = ns2x((node.ts + 500000000), startNS, endNS, totalNS, frame); + } + let frameWidth = endPointX - startPointX <= 1 ? 1 : endPointX - startPointX; + if (!node.frame) { + node.frame = {}; + } + node.frame.x = Math.floor(startPointX); + node.frame.y = frame.y + padding; + node.frame.width = Math.ceil(frameWidth); + node.frame.height = Math.floor(frame.height - padding * 2); + } + + static getHistogramColor(textItem: string): string { + switch (textItem) { + case 'CPU': + return "#92D6CC"; + case 'LOCATION': + return "#61CFBE" + case 'GPU': + return "#86C5E3" + case 'DISPLAY': + return "#46B1E3" + case 'CAMERA': + return "#C386F0" + case 'BLUETOOTH': + return "#8981F7" + case 'AUDIO': + return "#AC49F5" + case 'WIFISCAN': + return "#92C4BD" + default: + return "#564AF7" + } + } +} diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerEnergyState.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerEnergyState.ts new file mode 100644 index 0000000000000000000000000000000000000000..41bf8673d39d29a758941f31a1160d446d8a5285 --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerEnergyState.ts @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BaseStruct, + drawFlagLine, + drawLines, + drawLoading, + drawSelection, isFrameContainPoint, + ns2x, + Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; + +export class EnergyStateRender extends Render { + + renderMainThread(req: { useCache: boolean; context: CanvasRenderingContext2D; type: string;maxState:number; maxStateName:string;}, row: TraceRow) { + let list = row.dataList + let filter = row.dataListCache; + state(list, filter,TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, row.frame,req.useCache || !TraceRow.range!.refresh) + req.context.beginPath(); + let find = false; + for (let i = 0; i < filter.length; i++) { + let re = filter[i] + EnergyStateStruct.draw(req.context, re,req.maxState,req.maxStateName) + if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { + EnergyStateStruct.hoverEnergyStateStruct = re; + find = true; + } + } + if (!find && row.isHover) EnergyStateStruct.hoverEnergyStateStruct = undefined; + if (req.maxStateName != "enable" && req.maxStateName != "disable" && req.maxStateName != "-1") { + let s = req.maxStateName + let textMetrics = req.context.measureText(s); + req.context.globalAlpha = 1.0 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(s, 4, 5 + 9) + } + req.context.closePath(); + } + + render(req: RequestMessage, list: Array, filter: Array) { + if (req.lazyRefresh) { + state(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + state(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.canvas.width, req.canvas.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startNS, + arr[arr.length - 1].startNS + arr[arr.length - 1].dur) + } + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + req.context.beginPath(); + EnergyStateStruct.maxState = req.params.maxState; + EnergyStateStruct.maxStateName = req.params.maxStateName; + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + EnergyStateStruct.hoverEnergyStateStruct = undefined; + if (req.isHover) { + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x && req.hoverX <= re.frame.x + re.frame.width && req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height) { + EnergyStateStruct.hoverEnergyStateStruct = re; + break; + } + } + } + EnergyStateStruct.selectEnergyStateStruct = req.params.selectEnergyStateStruct; + for (let re of filter) { + EnergyStateStruct.draw(req.context, re,0,"") + } + drawSelection(req.context, req.params); + req.context.closePath(); + if (EnergyStateStruct.maxStateName != "enable" && EnergyStateStruct.maxStateName != "disable" && EnergyStateStruct.maxStateName != "-1") { + let s = EnergyStateStruct.maxStateName + let textMetrics = req.context.measureText(s); + req.context.globalAlpha = 1.0 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(s, 4, 5 + 9) + } + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, + req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: EnergyStateStruct.hoverEnergyStateStruct + }); + } +} + +export function state(list: Array, res: Array, startNS: number, endNS: number, totalNS: number, + frame: any, use: boolean) { + if (use && res.length > 0) { + for (let i = 0; i < res.length; i++) { + let item = res[i]; + if ((item.startNs || 0) + (item.dur || 0) > (startNS || 0) && (item.startNs || 0) < (endNS || 0)) { + EnergyStateStruct.setStateFrame(item, 5, startNS || 0, endNS || 0, + totalNS || 0, frame) + } else { + item.frame = null; + } + } + return; + } + res.length = 0; + if (list) { + for (let index = 0; index < list.length; index++) { + let item = list[index]; + if (index === list.length - 1) { + item.dur = (endNS || 0) - (item.startNs || 0) + } else { + item.dur = (list[index + 1].startNs || 0) - (item.startNs || 0) + } + if ((item.startNs || 0) + (item.dur || 0) > (startNS || 0) && (item.startNs || 0) < (endNS || 0)) { + EnergyStateStruct.setStateFrame(list[index], 5, startNS || 0, endNS || 0, + totalNS || 0, frame) + if (index > 0 && ((list[index - 1].frame?.x || 0) == (list[index].frame?.x || 0) && (list[index - 1].frame?.width || 0) == (list[index].frame?.width || 0))) { + + } else { + res.push(item) + } + } + } + } +} + +export class EnergyStateStruct extends BaseStruct { + static maxState: number = 0 + static maxStateName: string = "0" + static hoverEnergyStateStruct: EnergyStateStruct | undefined; + static selectEnergyStateStruct: EnergyStateStruct | undefined; + type: string | undefined + value: number | undefined + startNs: number | undefined + dur: number | undefined + + sensorType: number | undefined + pkg_name: string | undefined + deviceState: number | undefined + deviceType: number | undefined + + static draw(context2D: CanvasRenderingContext2D, data: EnergyStateStruct,maxState:number,maxStateName:string) { + if (data.frame) { + let width = data.frame.width || 0; + let drawColor = this.setDrawColor(data.type!); + context2D.fillStyle = drawColor; + context2D.strokeStyle = drawColor; + context2D.globalAlpha = 1.0; + context2D.lineWidth = 1; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0)) / maxState); + if (maxStateName === "enable" || maxStateName === "disable") { + if (data.value == 0) { + drawHeight = data.frame.height; + context2D.fillRect(data.frame.x, data.frame.y + 4, width, data.frame.height) + } + } else { + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, width, drawHeight) + } + if (data.startNs === EnergyStateStruct.hoverEnergyStateStruct?.startNs) { + let pointy = data.frame.y + data.frame.height + 4 + if (data.value == 0) { + pointy -= drawHeight + } + context2D.beginPath() + context2D.arc(data.frame.x, pointy, 3, 0, 2 * Math.PI, true) + context2D.fill() + context2D.globalAlpha = 1.0; + context2D.stroke(); + context2D.beginPath() + context2D.moveTo(data.frame.x + 3, pointy); + context2D.lineWidth = 3; + context2D.lineTo(data.frame.x + width, pointy) + context2D.stroke(); + } + } + context2D.globalAlpha = 1.0; + context2D.lineWidth = 1; + } + + static setStateFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { + let startPointX: number, endPointX: number + + if ((node.startNs || 0) < startNS) { + startPointX = 0 + } else { + startPointX = ns2x((node.startNs || 0), startNS, endNS, totalNS, frame); + } + if ((node.startNs || 0) + (node.dur || 0) > endNS) { + endPointX = frame.width; + } else { + endPointX = ns2x((node.startNs || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); + } + let frameWidth: number = endPointX - startPointX <= 1 ? 1 : endPointX - startPointX; + if (!node.frame) { + node.frame = {}; + } + node.frame.x = Math.floor(startPointX); + node.frame.y = frame.y + padding; + node.frame.width = Math.ceil(frameWidth); + node.frame.height = Math.floor(frame.height - padding * 2); + } + + static setDrawColor(eventType: string): string { + switch (eventType) { + case 'BRIGHTNESS_NIT': + return "#92D6CC"; + case 'SIGNAL_LEVEL': + return "#61CFBE" + case 'WIFI_EVENT_RECEIVED': + return "#46B1E3" + case 'AUDIO_STREAM_CHANGE': + return "#ED6F21" + case 'WIFI_STATE': + return "#61CFBE" + case 'LOCATION_SWITCH_STATE': + return "#61CFBE" + case 'SENSOR_STATE': + return "#61CFBE" + default: + return "#61CFBE" + } + } +} \ No newline at end of file diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerEnergySystem.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerEnergySystem.ts new file mode 100644 index 0000000000000000000000000000000000000000..8111942aeb8e04d008564793975040ff30991e7b --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerEnergySystem.ts @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BaseStruct, + drawFlagLine, drawLines, + drawLoading, + drawSelection, isFrameContainPoint, + ns2x, + Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; + +export class EnergySystemRender extends Render { + renderMainThread(req: { useCache: boolean; context: CanvasRenderingContext2D; type: string;}, row: TraceRow) { + let list = row.dataList + let filter = row.dataListCache; + system(list, filter,TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, row.frame,req.useCache || !TraceRow.range!.refresh) + req.context.beginPath(); + let find = false; + let a: any = {} + for (let i = 0; i < filter.length; i++) { + let re = filter[i] + + EnergySystemStruct.draw(req.context, re) + if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { + EnergySystemStruct.hoverEnergySystemStruct = re; + if (re.type == 0) { + if (re.count != undefined) { + a.workScheduler = re.count + } else { + a.workScheduler = "0" + } + } + if (re.type == 1) { + if (re.count != undefined) { + a.power = re.count + "" + } else { + a.power = "0" + } + } + + if (re.type == 2) { + if (re.count != undefined) { + a.location = re.count + "" + } else { + a.location = "0" + } + } + find = true; + } + } + if (!find && row.isHover) EnergySystemStruct.hoverEnergySystemStruct = undefined; + if (EnergySystemStruct.hoverEnergySystemStruct) { + EnergySystemStruct.hoverEnergySystemStruct!.workScheduler = a.workScheduler == undefined ? "0" : a.workScheduler + EnergySystemStruct.hoverEnergySystemStruct!.power = a.power == undefined ? "0" : a.power + EnergySystemStruct.hoverEnergySystemStruct!.location = a.location == undefined ? "0" : a.location + } + let spApplication = document.getElementsByTagName("sp-application")[0]; + let isDark = spApplication.hasAttribute("dark"); + drawLegend(req, isDark); + req.context.closePath(); + } + + render(req: RequestMessage, list: Array, filter: Array) { + if (req.lazyRefresh) { + system(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + system(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.canvas.width, req.canvas.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startNS, arr[arr.length - 1].startNS + arr[arr.length - 1].dur) + } + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + req.context.beginPath(); + EnergySystemStruct.hoverEnergySystemStruct = undefined; + if (req.isHover) { + let a: any = {} + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x && req.hoverX <= re.frame.x + re.frame.width) { + EnergySystemStruct.hoverEnergySystemStruct = re; + if (re.type == 0) { + if (re.count != undefined) { + a.workScheduler = re.count + } else { + a.workScheduler = "0" + } + } + if (re.type == 1) { + if (re.count != undefined) { + a.power = re.count + "" + } else { + a.power = "0" + } + } + + if (re.type == 2) { + if (re.count != undefined) { + a.location = re.count + "" + } else { + a.location = "0" + } + } + } + } + if (EnergySystemStruct.hoverEnergySystemStruct) { + EnergySystemStruct.hoverEnergySystemStruct!.workScheduler = a.workScheduler == undefined ? "0" : a.workScheduler + EnergySystemStruct.hoverEnergySystemStruct!.power = a.power == undefined ? "0" : a.power + EnergySystemStruct.hoverEnergySystemStruct!.location = a.location == undefined ? "0" : a.location + } + + } + EnergySystemStruct.selectEnergySystemStruct = req.params.selectEnergySystemStruct; + for (let re of filter) { + EnergySystemStruct.draw(req.context, re) + } + drawLegend(req); + drawSelection(req.context, req.params); + req.context.closePath(); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: EnergySystemStruct.hoverEnergySystemStruct + }); + } +} + +export function drawLegend(req: RequestMessage | any, isDark?: boolean) { + let textList = ["WORKSCHEDULER", "POWER_RUNNINGLOCK", "LOCATION"] + for (let index = 0; index < textList.length; index++) { + let text = req.context.measureText(textList[index]); + req.context.fillStyle = EnergySystemStruct.getColor(index); + let canvasEndX = req.context.canvas.clientWidth - EnergySystemStruct.OFFSET_WIDTH; + let textColor = isDark ? "#FFFFFF" : "#333"; + if (textList[index] == "WORKSCHEDULER") { + req.context.fillRect(canvasEndX - (EnergySystemStruct.itemNumber * 120), 12, 8, 8); + req.context.globalAlpha = 1 + req.context.textBaseline = "middle" + req.context.fillStyle = textColor; + req.context.fillText(textList[index], canvasEndX - (EnergySystemStruct.itemNumber * 120) + 10, 18) + EnergySystemStruct.currentTextWidth = canvasEndX - (EnergySystemStruct.itemNumber * 120) + 40 + text.width + } else { + req.context.fillRect(EnergySystemStruct.currentTextWidth, 12, 8, 8); + req.context.globalAlpha = 1 + req.context.fillStyle = textColor; + req.context.textBaseline = "middle" + req.context.fillText(textList[index], EnergySystemStruct.currentTextWidth + 12, 18); + EnergySystemStruct.currentTextWidth = EnergySystemStruct.currentTextWidth + 40 + text.width + } + } + req.context.fillStyle = "#333"; +} + +export function system(list: Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, use: boolean) { + if (use && res.length > 0) { + for (let i = 0; i < res.length; i++) { + let item = res[i]; + if ((item.startNs || 0) + (item.dur || 0) > (startNS || 0) && (item.startNs || 0) < (endNS || 0)) { + EnergySystemStruct.setSystemFrame(item, 10, startNS || 0, endNS || 0, totalNS || 0, frame) + } else { + item.frame = null; + } + } + return; + } + res.length = 0; + if (list) { + for (let i = 0; i < 3; i++) { + let arr = list[i]; + if (arr) { + for (let index = 0; index < arr.length; index++) { + let item = arr[index]; + if (index === arr.length - 1) { + item.dur = (endNS || 0) - (item.startNs || 0) + } else { + item.dur = (arr[index + 1].startNs || 0) - (item.startNs || 0) + } + if (item.count == 0) { + item.dur = 0 + } + if ((item.startNs || 0) + (item.dur || 0) > (startNS || 0) && (item.startNs || 0) < (endNS || 0)) { + EnergySystemStruct.setSystemFrame(item, 10, startNS || 0, endNS || 0, totalNS || 0, frame) + res.push(item) + } + } + } + } + } +} + +export class EnergySystemStruct extends BaseStruct { + static hoverEnergySystemStruct: EnergySystemStruct | undefined; + static selectEnergySystemStruct: EnergySystemStruct | undefined; + static itemNumber: number = 3 + static currentTextWidth: number = 0 + static OFFSET_WIDTH: number = 266 + type: number | undefined + startNs: number | undefined + dur: number | undefined + count: number | undefined + workScheduler: string | undefined + power: string | undefined + location: string | undefined + + static draw(context2D: CanvasRenderingContext2D, data: EnergySystemStruct) { + if (data.frame) { + let width = data.frame.width || 0; + context2D.globalAlpha = 1.0; + context2D.lineWidth = 1; + context2D.fillStyle = this.getColor(data.type!); + context2D.strokeStyle = this.getColor(data.type!); + context2D.fillRect(data.frame.x, data.frame.y + 4, width, data.frame.height) + } + context2D.globalAlpha = 1.0; + context2D.lineWidth = 1; + } + + static setSystemFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { + let startPointX: number; + let endPointX: number; + if ((node.startNs || 0) < startNS) { + startPointX = 0 + } else { + startPointX = ns2x((node.startNs || 0), startNS, endNS, totalNS, frame); + } + if ((node.startNs || 0) + (node.dur || 0) > endNS) { + endPointX = frame.width; + } else { + endPointX = ns2x((node.startNs || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); + } + let frameWidth: number = endPointX - startPointX <= 1 ? 1 : endPointX - startPointX; + if (!node.frame) { + node.frame = {}; + } + node.frame.x = Math.floor(startPointX); + if (node.type === 0) { + node.frame.y = frame.y + padding * 2.5; + } else if (node.type === 1) { + node.frame.y = frame.y + (padding * 4.5); + } else if (node.type === 2) { + node.frame.y = frame.y + (padding * 6.5); + } + node.frame.width = Math.ceil(frameWidth); + node.frame.height = Math.floor(padding); + } + + static getColor(textItem: number): string { + switch (textItem) { + case 0: + return "#E64566"; + case 1: + return "#FFC880"; + default: + return "#564AF7"; + } + } +} diff --git a/host/ide/src/trace/database/ProcedureWorkerFPS.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerFPS.ts similarity index 47% rename from host/ide/src/trace/database/ProcedureWorkerFPS.ts rename to host/ide/src/trace/database/ui-worker/ProcedureWorkerFPS.ts index 48bb896313a1e31d514f9a9bd9e46f31ae28e48f..a23e691d3310ec5629e067905432e1ef753e7fac 100644 --- a/host/ide/src/trace/database/ProcedureWorkerFPS.ts +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerFPS.ts @@ -13,11 +13,109 @@ * limitations under the License. */ -import {BaseStruct, ns2x, Rect} from "./ProcedureWorkerCommon.js"; +import { + BaseStruct, drawFlagLine, + drawLines, + drawLoading, + drawSelection, drawWakeUp, isFrameContainPoint, + ns2x, + Rect, Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; -export function fps(list: Array, res: Set, startNS: number, endNS: number, totalNS: number, frame: any) { - res.clear(); +export class FpsRender extends Render{ + renderMainThread(req: { + context: CanvasRenderingContext2D, + useCache: boolean, + type: string, + }, row: TraceRow) { + let list = row.dataList; + let filter = row.dataListCache; + fps(list, filter, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, row.frame, req.useCache || !(TraceRow.range!.refresh)); + req.context.beginPath(); + let find = false; + for (let re of filter) { + FpsStruct.draw(req.context, re) + if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { + FpsStruct.hoverFpsStruct = re; + find = true; + } + } + if (!find && row.isHover) FpsStruct.hoverFpsStruct = undefined; + req.context.closePath(); + let maxFps = FpsStruct.maxFps + "FPS" + let textMetrics = req.context.measureText(maxFps); + req.context.globalAlpha = 0.8 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(maxFps, 4, 5 + 9); + } + + render(req: RequestMessage, list: Array, filter: Array) { + if (req.lazyRefresh) { + fps(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + fps(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startNS, arr[arr.length - 1].startNS + arr[arr.length - 1].dur) + } + req.context.beginPath(); + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + FpsStruct.hoverFpsStruct = undefined; + if (req.isHover) { + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x && req.hoverX <= re.frame.x + re.frame.width && req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height) { + FpsStruct.hoverFpsStruct = re; + break; + } + } + } else { + FpsStruct.hoverFpsStruct = req.params.hoverFpsStruct; + } + for (let re of filter) { + FpsStruct.draw(req.context, re) + } + drawSelection(req.context, req.params); + req.context.closePath(); + let maxFps = FpsStruct.maxFps + "FPS" + let textMetrics = req.context.measureText(maxFps); + req.context.globalAlpha = 0.8 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(maxFps, 4, 5 + 9); + drawWakeUp(req.context, req.wakeupBean, req.startNS, req.endNS, req.totalNS, req.frame); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: FpsStruct.hoverFpsStruct + }); + } +} + +export function fps(list: Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, use: boolean) { + if (use && res.length > 0) { + res.forEach(it => FpsStruct.setFrame(it, 5, startNS, endNS, totalNS, frame)); + return; + } FpsStruct.maxFps = 0 + res.length = 0; if (list) { for (let i = 0, len = list.length; i < len; i++) { let it = list[i]; @@ -34,7 +132,7 @@ export function fps(list: Array, res: Set, startNS: number, endNS: num if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && (list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0))) { } else { - res.add(list[i]) + res.push(list[i]) } } } diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerFileSystem.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerFileSystem.ts new file mode 100644 index 0000000000000000000000000000000000000000..dd8a50a5b674f7a95a8752e113391f369fef4cb9 --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerFileSystem.ts @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BaseStruct, + drawFlagLine, + drawLines, + drawLoading, + drawSelection, PerfRender, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; + +export class FileSystemRender extends PerfRender{ + renderMainThread(req: { + context: CanvasRenderingContext2D, + useCache: boolean, + type: string, + chartColor:string + }, row:TraceRow){ + let list= row.dataList; + let filter = row.dataListCache; + let groupBy10MS = (TraceRow.range?.scale || 50) > 40_000_000; + let isDiskIO :boolean = req.type.includes("disk-io"); + if(list && row.dataList2.length == 0){ + row.dataList2 = isDiskIO ? FileSysChartStruct.groupBy10MSWithMaxLatency(list) : FileSysChartStruct.groupBy10MSWithCount(list); + } + fileSysChart(list, row.dataList2, req.type, filter,TraceRow.range?.startNS ?? 0, TraceRow.range?.endNS ?? 0, TraceRow.range?.totalNS ?? 0, row.frame, groupBy10MS,isDiskIO,req.useCache || (TraceRow.range?.refresh ?? false)); + req.context.beginPath(); + let find = false; + let hoverRect:FileSysChartStruct|undefined = undefined; + for (let re of filter) { + if (row.isHover && re.frame && row.hoverX >= re.frame.x && row.hoverX <= re.frame.x + re.frame.width) {//&& req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height + if(hoverRect == undefined || re.size! > hoverRect.size!){ + hoverRect = re; + find = true; + } + } + if(re.frame && re.frame!.x > row.hoverX + 3 ){ + break; + } + } + if(hoverRect){ + FileSysChartStruct.hoverFileSysStruct = hoverRect; + } + for (let re of filter) { + FileSysChartStruct.draw(req.context, re,req.chartColor); + } + if(!find && row.isHover) FileSysChartStruct.hoverFileSysStruct = undefined; + req.context.closePath(); + } + + render(req: RequestMessage, list: Array, filter: Array,dataList2:Array){ + let groupBy10MS = req.scale > 20_000_000; + let isDiskIO :boolean = req.type!.includes("disk-io"); + if(isDiskIO){ + groupBy10MS = true; + } + if (req.lazyRefresh) { + fileSysChart(list, dataList2, req.type!, filter, req.startNS, req.endNS, req.totalNS, req.frame, groupBy10MS, isDiskIO,req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + fileSysChart(list, dataList2, req.type!, filter, req.startNS, req.endNS, req.totalNS, req.frame, groupBy10MS, isDiskIO,false); + } + } + let hoverStruct : FileSysChartStruct | undefined; + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startNS, arr[arr.length - 1].startNS + arr[arr.length - 1].dur) + } + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + req.context.stroke(); + req.context.beginPath(); + if (req.isHover) { + let offset = groupBy10MS ? 0 : 3; + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x - offset && req.hoverX <= re.frame.x + re.frame.width + offset) {//&& req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height + hoverStruct = re; + break; + } + } + } + for (let re of filter) { + FileSysChartStruct.draw(req.context, re,req.chartColor); + } + drawSelection(req.context, req.params); + req.context.closePath(); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + let msg = { + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: hoverStruct + } + self.postMessage(msg); + } +} + +export function fileSysChart(arr: Array, arr2: Array, type: string, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, groupBy10MS: boolean, isDiskIO:boolean,use: boolean) { + if (use && res.length > 0 ) {//&& !groupBy10MS + let pns = (endNS - startNS) / frame.width; + let y = frame.y; + for (let i = 0; i < res.length; i++) { + let it = res[i]; + if((it.startNS || 0) + (it.dur || 0) > startNS && (it.startNS || 0) < endNS){ + if (!it.frame) { + it.frame = {}; + it.frame.y = y; + } + it.frame.height = it.height; + FileSysChartStruct.setFrame(it, pns, startNS, endNS, frame); + }else{ + it.frame = null; + } + } + return; + } + res.length = 0; + if(arr){ + let list: Array = []; + let pns = (endNS - startNS) / frame.width; + let y = frame.y; + if(groupBy10MS){ + list = arr2.filter(it => (it.startNS || 0) + (it.dur || 0) > startNS && (it.startNS || 0) < endNS); + let groups = list.map(it => { + if (!it.frame) { + it.frame = {}; + it.frame.y = y; + } + it.frame.height = it.height; + FileSysChartStruct.setFrame(it, pns, startNS, endNS, frame); + return it; + }).reduce((pre, current, index, arr) => { + (pre[`${current.frame.x}`] = pre[`${current.frame.x}`] || []).push(current); + return pre; + }, {}); + Reflect.ownKeys(groups).map((kv => { + // let arr = (groups[kv].sort((a: any, b: any) => b.frame.width - a.frame.width)); + res.push(groups[kv][0]); + })); + }else{ + let filter = arr.filter(it => (it.startNS || 0) + (it.dur || 0) > startNS && (it.startNS || 0) < endNS); + list = isDiskIO ? FileSysChartStruct.computeHeightNoGroupLatency(filter,totalNS) : FileSysChartStruct.computeHeightNoGroup(filter,totalNS); + list.map(it => { + if (!it.frame) { + it.frame = {}; + it.frame.y = y; + } + it.frame.height = it.height; + FileSysChartStruct.setFrame(it, pns, startNS, endNS, frame); + res.push(it); + }) + } + } +} + +export class FileSysChartStruct extends BaseStruct { + static hoverFileSysStruct: FileSysChartStruct | undefined; + startNS: number | undefined; + endNS: number | undefined; + dur: number | undefined; + size: number | undefined; + height: number | undefined; + group10Ms: boolean | undefined; + + static draw(ctx: CanvasRenderingContext2D, data: FileSysChartStruct,chartColor:string) { + if (data.frame) { + ctx.fillStyle = chartColor; + ctx.strokeStyle = chartColor; + ctx.fillRect(data.frame.x, 40 - (data.height || 0), data.frame.width, data.height || 0) + } + } + + static setFrame(node: any, pns: number, startNS: number, endNS: number, frame: any) { + if ((node.startNS || 0) < startNS) { + node.frame.x = 0; + } else { + node.frame.x = Math.floor(((node.startNS || 0) - startNS) / pns); + } + if ((node.startNS || 0) + (node.dur || 0) > endNS) { + node.frame.width = frame.width - node.frame.x; + } else { + node.frame.width = Math.ceil(((node.startNS || 0) + (node.dur || 0) - startNS) / pns - node.frame.x); + } + if (node.frame.width < 1) { + node.frame.width = 1; + } + } + + static computeHeightNoGroup(array:Array,totalNS:number):Array{ + if(array.length > 0){ + let time :Array<{time:number,type:number}> = []; + array.map((item) => { + time.push({time:item.startNS,type:1}); + time.push({time:item.endNS || totalNS,type:-1}); + }) + time = time.sort((a,b) => a.time - b.time); + let arr:Array = []; + let first = { + startNS: time[0].time ?? 0, + dur: 0, + size:1, + group10Ms:false, + height:1, + }; + arr.push(first); + let max = 2 + for (let i = 1,len = time.length; i < len; i++) { + let heap = { + startNS: time[i].time, + dur: 0, + size:0, + group10Ms:false, + height: 0 + }; + arr[i - 1].dur = heap.startNS - arr[i - 1].startNS; + if (i == len - 1) { + heap.dur = totalNS - heap.startNS; + } + heap.size = arr[i - 1].size + time[i].type; + heap.height = Math.floor(heap.size / 6 * 36); + max = max > heap.size ? max : heap.size; + arr.push(heap) + } + arr.map(it => it.height = Math.floor(it.size / max * 36)) + return arr; + }else{ + return []; + } + } + + static groupBy10MSWithCount(array: Array): Array { + let obj = array.map(it => { + it.timestamp_group = Math.trunc(it.startNS / 1_000_000_0) * 1_000_000_0; + return it; + }).reduce((pre, current) => { + (pre[current["timestamp_group"]] = pre[current["timestamp_group"]] || []).push(current); + return pre; + }, {}); + let arr: any[] = []; + let max = 1; + for (let aKey in obj) { + max = obj[aKey].length > max ? obj[aKey].length : max + } + for (let aKey in obj) { + let ns = parseInt(aKey); + let height: number = Math.floor(obj[aKey].length / max * 36); + arr.push({ + startNS: ns, + dur: 1_000_000_0, + group10Ms:true, + size:obj[aKey].length, + height: height < 1 ? 1 : height, + }) + } + return arr; + } + + static computeHeightNoGroupLatency(array:Array,totalNS:number):Array{ + if(array.length > 0){ + let max = 0; + let arr:Array = []; + for (let io of array) { + let ioItem = { + startNS: io.startNS, + dur: io.endNS > totalNS ? totalNS - io.startNS : io.endNS - io.startNS, + size:io.dur, + group10Ms:false, + height: 0 + }; + max = max > ioItem.size ? max : ioItem.size; + arr.push(ioItem) + } + arr.map(it => { + let height = Math.floor(it.size / max * 36); + it.height = height < 1 ? 1 : height; + }) + return arr; + }else{ + return []; + } + } + + static groupBy10MSWithMaxLatency(array: Array): Array { + let obj = array.map(it => { + it.timestamp_group = Math.trunc(it.startNS / 1_000_000_0) * 1_000_000_0; + return it; + }).reduce((pre, current) => { + if(pre[current["timestamp_group"]] == undefined || pre[current["timestamp_group"]] == null){ + pre[current["timestamp_group"]] = []; + } + if(pre[current["timestamp_group"]].length > 0){ + let p = pre[current["timestamp_group"]][0]; + if(p.dur < current.dur){ + pre[current["timestamp_group"]][0] = current; + } + }else{ + pre[current["timestamp_group"]][0] = current; + } + return pre; + }, {}); + let arr: any[] = []; + let max = 1; + for (let aKey in obj) { + max = obj[aKey][0].dur > max ? obj[aKey][0].dur : max + } + for (let aKey in obj) { + let ns = parseInt(aKey); + let height: number = Math.floor(obj[aKey][0].dur / max * 36); + arr.push({ + startNS: ns, + dur: 1_000_000_0, + group10Ms:true, + size:obj[aKey][0].dur, + height: height < 1 ? 1 : height, + }) + } + return arr; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/database/ProcedureWorkerFreq.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerFreq.ts similarity index 58% rename from host/ide/src/trace/database/ProcedureWorkerFreq.ts rename to host/ide/src/trace/database/ui-worker/ProcedureWorkerFreq.ts index 8a2097d2d5bfc0dbeb0bc6e38fb3a9df741ed92f..9681c14c41370c33c94e25d72cbf8d0661f835bf 100644 --- a/host/ide/src/trace/database/ProcedureWorkerFreq.ts +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerFreq.ts @@ -13,31 +13,57 @@ * limitations under the License. */ -import {BaseStruct, ColorUtils, ns2x} from "./ProcedureWorkerCommon.js"; +import {ColorUtils} from "../../component/trace/base/ColorUtils.js"; +import { + BaseStruct, dataFilterHandler, + isFrameContainPoint, + Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; -export function freq(list: Array, res: Set, startNS: number, endNS: number, totalNS: number, frame: any) { - res.clear(); - if (list) { - for (let i = 0, len = list.length; i < len; i++) { - let it = list[i]; - if (i === list.length - 1) { - it.dur = (endNS || 0) - (it.startNS || 0) - } else { - it.dur = (list[i + 1].startNS || 0) - (it.startNS || 0) - } - if ((it.startNS || 0) + (it.dur || 0) > (startNS || 0) && (it.startNS || 0) < (endNS || 0)) { - CpuFreqStruct.setFreqFrame(list[i], 5, startNS || 0, endNS || 0, totalNS || 0, frame) - if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && (list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0))) { - - } else { - res.add(it) - } +export class FreqRender extends Render { + renderMainThread(req: { + context: CanvasRenderingContext2D, + useCache: boolean, + type: string, + }, row: TraceRow) { + let list = row.dataList; + let filter = row.dataListCache; + dataFilterHandler(list,filter,{ + startKey: "startNS", + durKey: "dur", + startNS: TraceRow.range?.startNS ?? 0, + endNS: TraceRow.range?.endNS ?? 0, + totalNS: TraceRow.range?.totalNS ?? 0, + frame: row.frame, + paddingTop: 5, + useCache: req.useCache || !(TraceRow.range?.refresh ?? false) + }) + req.context.beginPath(); + let find = false; + for (let re of filter) { + CpuFreqStruct.draw(req.context, re) + if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { + CpuFreqStruct.hoverCpuFreqStruct = re; + find = true; } } + if (!find && row.isHover) CpuFreqStruct.hoverCpuFreqStruct = undefined; + req.context.closePath(); + let s = CpuFreqStruct.maxFreqName + let textMetrics = req.context.measureText(s); + req.context.globalAlpha = 0.8 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(s, 4, 5 + 9) } - } + export class CpuFreqStruct extends BaseStruct { static maxFreq: number = 0 static maxFreqName: string = "0 GHz" @@ -55,7 +81,7 @@ export class CpuFreqStruct extends BaseStruct { index += 2 ctx.fillStyle = ColorUtils.colorForTid(index) ctx.strokeStyle = ColorUtils.colorForTid(index) - if (data.startNS === CpuFreqStruct.hoverCpuFreqStruct?.startNS) { + if (data.startNS === CpuFreqStruct.hoverCpuFreqStruct?.startNS || data.startNS === CpuFreqStruct.selectCpuFreqStruct?.startNS) { ctx.lineWidth = 1; ctx.globalAlpha = 0.6; let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / CpuFreqStruct.maxFreq); @@ -81,27 +107,6 @@ export class CpuFreqStruct extends BaseStruct { ctx.lineWidth = 1; } - static setFreqFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { - let x1: number, x2: number; - if ((node.startNS || 0) < startNS) { - x1 = 0; - } else { - x1 = ns2x((node.startNS || 0), startNS, endNS, totalNS, frame); - } - if ((node.startNS || 0) + (node.dur || 0) > endNS) { - x2 = frame.width; - } else { - x2 = ns2x((node.startNS || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); - } - let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1; - if (!node.frame) { - node.frame = {}; - } - node.frame.x = Math.floor(x1); - node.frame.y = frame.y + padding; - node.frame.width = Math.ceil(getV); - node.frame.height = Math.floor(frame.height - padding * 2); - } } const textPadding = 2; \ No newline at end of file diff --git a/host/ide/src/trace/database/ProcedureWorkerFunc.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerFunc.ts similarity index 49% rename from host/ide/src/trace/database/ProcedureWorkerFunc.ts rename to host/ide/src/trace/database/ui-worker/ProcedureWorkerFunc.ts index 773ff7bc0d00c16508f92be40ae1ff42543501b5..8c23b56ba7e7819adb06bc36e926de22eafe72d4 100644 --- a/host/ide/src/trace/database/ProcedureWorkerFunc.ts +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerFunc.ts @@ -13,22 +13,72 @@ * limitations under the License. */ -import {BaseStruct, ColorUtils, ns2x, Rect} from "./ProcedureWorkerCommon.js"; - -export function func(list: Array, res: Set, startNS: number, endNS: number, totalNS: number, frame: any) { - res.clear(); - if (list) { - for (let i = 0, len = list.length; i < len; i++) { - let it = list[i]; - if ((it.startTs || 0) + (it.dur || 0) > (startNS || 0) && (it.startTs || 0) < (endNS || 0)) { - FuncStruct.setFuncFrame(list[i], 0, startNS || 0, endNS || 0, totalNS || 0, frame) - if (i > 0 && (list[i - 1].frame?.y || 0) == (list[i].frame?.y || 0) && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && (list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0))) { +import {ColorUtils} from "../../component/trace/base/ColorUtils.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; +import { + BaseStruct, + isFrameContainPoint, + ns2x, + Rect, Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +export class FuncRender extends Render { + renderMainThread(req: { useCache: boolean; context: CanvasRenderingContext2D; type: string }, row: TraceRow) { + let list = row.dataList; + let filter = row.dataListCache; + func(list, filter, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, row.frame, req.useCache || !TraceRow.range!.refresh); + req.context.beginPath(); + let find = false; + for (let re of filter) { + FuncStruct.draw(req.context, re) + if(row.isHover){ + if (re.dur == 0 || re.dur == null || re.dur == undefined) { + if (re.frame && row.hoverX >= re.frame.x - 5 && row.hoverX <= re.frame.x + 5 && row.hoverY >= re.frame.y && row.hoverY <= re.frame.y + re.frame.height) { + FuncStruct.hoverFuncStruct = re; + find = true; + } } else { - res.add(list[i]) + if (re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { + FuncStruct.hoverFuncStruct = re; + find = true; + } } } } + if (!find && row.isHover) FuncStruct.hoverFuncStruct = undefined; + req.context.closePath(); + } + + render(req: RequestMessage, list: Array, filter: Array) { + + } +} + +export function func(list: Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, use: boolean) { + if (use && res.length > 0) { + for (let i = 0, len = res.length; i < len; i++) { + if ((res[i].startTs || 0) + (res[i].dur || 0) >= startNS && (res[i].startTs || 0) <= endNS) { + FuncStruct.setFuncFrame(res[i], 0, startNS, endNS, totalNS, frame) + } else { + res[i].frame = null; + } + } + return; + } + res.length = 0; + if (list) { + let groups = list.filter(it => (it.startTs ?? 0) + (it.dur ?? 0) >= startNS && (it.startTs ?? 0) <= endNS).map(it => { + FuncStruct.setFuncFrame(it, 0, startNS, endNS, totalNS, frame) + return it; + }).reduce((pre, current, index, arr) => { + (pre[`${current.frame.x}-${current.depth}`] = pre[`${current.frame.x}-${current.depth}`] || []).push(current); + return pre; + }, {}); + Reflect.ownKeys(groups).map((kv => { + let arr = (groups[kv].sort((a: any, b: any) => b.dur - a.dur)); + res.push(arr[0]); + })); } } @@ -38,6 +88,7 @@ export class FuncStruct extends BaseStruct { argsetid: number | undefined // 53161 depth: number | undefined // 0 dur: number | undefined // 570000 + flag: string | undefined // 570000 funName: string | undefined //"binder transaction" id: number | undefined // 92749 is_main_thread: number | undefined // 0 @@ -45,46 +96,52 @@ export class FuncStruct extends BaseStruct { startTs: number | undefined // 9729867000 threadName: string | undefined // "Thread-15" tid: number | undefined // 2785 + identify: number | undefined track_id: number | undefined // 414 static setFuncFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { let x1: number, x2: number; - if ((node.startTs || 0) < startNS) { - x1 = 0; - } else { + if ((node.startTs || 0) > startNS && (node.startTs || 0) < endNS) { x1 = ns2x((node.startTs || 0), startNS, endNS, totalNS, frame); - } - if ((node.startTs || 0) + (node.dur || 0) > endNS) { - x2 = frame.width; } else { + x1 = 0; + } + if ((node.startTs || 0) + (node.dur || 0) > startNS && (node.startTs || 0) + (node.dur || 0) < endNS) { x2 = ns2x((node.startTs || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); + } else { + x2 = frame.width; } - let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1; if (!node.frame) { node.frame = {}; } + let getV: number = x2 - x1 < 1 ? 1 : x2 - x1; node.frame.x = Math.floor(x1); - node.frame.y = 0; - node.frame.width = Math.floor(getV); + node.frame.y = node.depth * 20; + node.frame.width = Math.ceil(getV); node.frame.height = 20; } + static draw(ctx: CanvasRenderingContext2D, data: FuncStruct) { if (data.frame) { let isBinder = FuncStruct.isBinder(data); if (data.dur == undefined || data.dur == null || data.dur == 0) { } else { - ctx.fillStyle = ColorUtils.FUNC_COLOR[(data.funName?.length || 0) % ColorUtils.FUNC_COLOR.length] + ctx.globalAlpha = 1; + ctx.fillStyle = ColorUtils.FUNC_COLOR[ColorUtils.hashFunc(data.funName || '', 0, ColorUtils.FUNC_COLOR.length)];//data.depth || let miniHeight = 20 + if(FuncStruct.hoverFuncStruct&&data.funName == FuncStruct.hoverFuncStruct.funName){ + ctx.globalAlpha = 0.7; + } ctx.fillRect(data.frame.x, data.frame.y, data.frame.width, miniHeight - padding * 2) if (data.frame.width > 10) { ctx.fillStyle = "#fff" - FuncStruct.drawString(ctx, data.funName || '', 5, data.frame) + FuncStruct.drawString(ctx, `${data.funName || ''}`, 5, data.frame) } if (FuncStruct.isSelected(data)) { ctx.strokeStyle = "#000" - ctx.lineWidth = 1 - ctx.strokeRect(data.frame.x, data.frame.y, data.frame.width, miniHeight - padding * 2) + ctx.lineWidth = 2 + ctx.strokeRect(data.frame.x, data.frame.y + 1, data.frame.width, miniHeight - padding * 2 - 2) } } } @@ -110,9 +167,7 @@ export class FuncStruct extends BaseStruct { static isSelected(data: FuncStruct): boolean { return (FuncStruct.selectFuncStruct != undefined && FuncStruct.selectFuncStruct.startTs == data.startTs && - FuncStruct.selectFuncStruct.depth == data.depth && - FuncStruct.selectFuncStruct.dur == data.dur && - FuncStruct.selectFuncStruct.funName == data.funName) + FuncStruct.selectFuncStruct.depth == data.depth) } static isBinder(data: FuncStruct): boolean { @@ -128,6 +183,19 @@ export class FuncStruct extends BaseStruct { return false; } } + + static isBinderAsync(data: FuncStruct): boolean { + if (data.funName != null && + ( + data.funName.toLowerCase().includes("async") + ) + ) { + return true; + } else { + return false; + } + } } -const padding = 1; \ No newline at end of file +const padding = 1; + diff --git a/host/ide/src/trace/database/ProcedureWorkerHeap.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerHeap.ts similarity index 39% rename from host/ide/src/trace/database/ProcedureWorkerHeap.ts rename to host/ide/src/trace/database/ui-worker/ProcedureWorkerHeap.ts index 9a11b403c1df8dc3d9c4537310cda9a312d28ff9..2f47033e38c73e1fa1cdf8a032bc30641d953199 100644 --- a/host/ide/src/trace/database/ProcedureWorkerHeap.ts +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerHeap.ts @@ -13,20 +13,113 @@ * limitations under the License. */ -import {BaseStruct, ns2x, Rect} from "./ProcedureWorkerCommon.js"; +import { + BaseStruct, drawFlagLine, + drawLines, + drawLoading, + drawSelection, drawWakeUp, isFrameContainPoint, + ns2x, + Rect, Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; +export class NativeMemoryRender extends Render{ + renderMainThread(req: any, row: TraceRow) { + } +} +export class HeapRender{ + + renderMainThread(req:{ + context: CanvasRenderingContext2D, + useCache: boolean, + type: string, + },row:TraceRow){ + let list= row.dataList; + let filter = row.dataListCache; + heap(list, filter, TraceRow.range?.startNS ?? 0, TraceRow.range?.endNS ?? 0, TraceRow.range?.totalNS ?? 0, row.frame, req.useCache || (TraceRow.range?.refresh ?? false)); + req.context.beginPath(); + let find = false; + for (let re of filter) { + if (row.isHover && re.frame && !find && isFrameContainPoint(re.frame,row.hoverX,row.hoverY)) { + HeapStruct.hoverHeapStruct = re; + find = true; + } + } + for (let re of filter) { + HeapStruct.draw(req.context,re,row.drawType) + } + if(!find && row.isHover) HeapStruct.hoverHeapStruct = undefined; + req.context.closePath(); + } -export function heap(list: Array, res: Set, startNS: number, endNS: number, totalNS: number, frame: any) { - res.clear(); - if (list) { - for (let i = 0; i < list.length; i++) { - let it = list[i]; + render(req: RequestMessage, list: Array, filter: Array) { + if (req.lazyRefresh) { + heap(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + heap(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.canvas.width, req.canvas.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startTime, arr[arr.length - 1].startTime + arr[arr.length - 1].dur) + } + req.context.beginPath(); + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + HeapStruct.hoverHeapStruct = undefined; + if (req.isHover) { + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x && req.hoverX <= re.frame.x + re.frame.width && req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height) { + HeapStruct.hoverHeapStruct = re; + break; + } + } + } else { + HeapStruct.hoverHeapStruct = req.params.hoverHeapStruct; + } + for (let re of filter) { + HeapStruct.draw(req.context, re,req.params.drawType) + } + drawSelection(req.context, req.params); + drawWakeUp(req.context, req.wakeupBean, req.startNS, req.endNS, req.totalNS, req.frame); + req.context.closePath(); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: HeapStruct.hoverHeapStruct + }); + } +} +export function heap(list: Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, use: boolean) { + if (use && res.length > 0) { + for (let i = 0; i < res.length; i++) { + let it = res[i]; if ((it.startTime || 0) + (it.dur || 0) > (startNS || 0) && (it.startTime || 0) < (endNS || 0)) { - HeapStruct.setFrame(list[i], 5, startNS || 0, endNS || 0, totalNS || 0, frame) - if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && (list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0))) { - continue; - } else { - res.add(list[i]) + HeapStruct.setFrame(res[i], 5, startNS || 0, endNS || 0, totalNS || 0, frame) + } else { + res[i].frame = null; + } + } + return; + } + res.length = 0; + for (let i = 0,len = list.length; i < len; i++) { + let it = list[i]; + if ((it.startTime || 0) + (it.dur || 0) > (startNS || 0) && (it.startTime || 0) < (endNS || 0)) { + HeapStruct.setFrame(it, 5, startNS || 0, endNS || 0, totalNS || 0, frame) + if(i > 0){ + let last = list[i-1]; + if(last.frame?.x != it.frame.x || last.frame.width != it.frame.width){ + res.push(it); } + }else{ + res.push(it); } } } @@ -38,8 +131,11 @@ export class HeapStruct extends BaseStruct { endTime: number | undefined dur: number | undefined heapsize: number | undefined + density: number | undefined maxHeapSize: number = 0 minHeapSize: number = 0 + maxDensity: number = 0 + minDensity: number = 0 static setFrame(node: HeapStruct, padding: number, startNS: number, endNS: number, totalNS: number, frame: Rect) { let x1: number, x2: number; @@ -59,20 +155,28 @@ export class HeapStruct extends BaseStruct { node.frame = rectangle; } - static draw(ctx: CanvasRenderingContext2D, data: HeapStruct) { + static draw(ctx: CanvasRenderingContext2D, data: HeapStruct,drawType:number) { if (data.frame) { let width = data.frame.width || 0; ctx.fillStyle = "#2db3aa" ctx.strokeStyle = "#2db3aa" - if (data.startTime === HeapStruct.hoverHeapStruct?.startTime) { - ctx.lineWidth = 1; - ctx.globalAlpha = 0.6; - let drawHeight:number = 0; - if(data.minHeapSize < 0 ){ + let drawHeight: number = 0; + if(drawType == 0){ + if (data.minHeapSize < 0) { drawHeight = Math.ceil((((data.heapsize || 0) - data.minHeapSize) * (data.frame.height || 0)) / (data.maxHeapSize - data.minHeapSize)); - }else{ + } else { drawHeight = Math.ceil(((data.heapsize || 0) * (data.frame.height || 0)) / data.maxHeapSize); } + }else{ + if (data.minDensity < 0) { + drawHeight = Math.ceil((((data.density || 0) - data.minDensity) * (data.frame.height || 0)) / (data.maxDensity - data.minDensity)); + } else { + drawHeight = Math.ceil(((data.density || 0) * (data.frame.height || 0)) / data.maxDensity); + } + } + if (data == HeapStruct.hoverHeapStruct) { + ctx.lineWidth = 1; + ctx.globalAlpha = 0.6; ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) ctx.beginPath() ctx.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight, 3, 0, 2 * Math.PI, true) @@ -87,7 +191,6 @@ export class HeapStruct extends BaseStruct { } else { ctx.globalAlpha = 0.6; ctx.lineWidth = 1; - let drawHeight: number = Math.ceil(((data.heapsize || 0) * (data.frame.height || 0)) / data.maxHeapSize); ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) } } diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfCPU.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfCPU.ts new file mode 100644 index 0000000000000000000000000000000000000000..d3c40a20738a4b8fad629dc79e238759fd9471c4 --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfCPU.ts @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ColorUtils } from "../../component/trace/base/ColorUtils.js"; +import { + BaseStruct, + drawFlagLine, + drawLines, + drawLoading, + drawSelection, PerfRender, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; +import {HiPerfThreadStruct} from "./ProcedureWorkerHiPerfThread.js"; + +export class HiperfCpuRender extends PerfRender{ + + renderMainThread(req: any,row:TraceRow) { + let list= row.dataList; + let filter = row.dataListCache; + let groupBy10MS = req.scale > 30_000_000; + if(list && row.dataList2.length == 0 ){ + row.dataList2 = HiPerfCpuStruct.groupBy10MS(list, req.maxCpu, req.intervalPerf); + } + hiPerfCpu(list, row.dataList2, req.type!, filter, TraceRow.range?.startNS ??0, TraceRow.range?.endNS??0, TraceRow.range?.totalNS??0, row.frame, groupBy10MS, req.maxCpu, req.intervalPerf, req.useCache || (TraceRow.range?.refresh ?? false)); + req.context.beginPath(); + req.context.fillStyle = ColorUtils.FUNC_COLOR[0]; + req.context.strokeStyle = ColorUtils.FUNC_COLOR[0]; + let path = new Path2D(); + let find = false; + let offset = groupBy10MS ? 0 : 3; + for (let re of filter) { + if (row.isHover && re.frame && row.hoverX >= re.frame.x - offset && row.hoverX <= re.frame.x + re.frame.width + offset) {//&& req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height + HiPerfCpuStruct.hoverStruct = re; + find = true; + } + HiPerfCpuStruct.draw(req.context, path, re, groupBy10MS); + } + if (!find && row.isHover) HiPerfCpuStruct.hoverStruct = undefined; + if (groupBy10MS) { + req.context.fill(path); + } else { + req.context.stroke(path); + } + req.context.closePath(); + } + + render(req: RequestMessage, list: Array, filter: Array,dataList2:Array){ + let groupBy10MS = req.scale > 100_000_000; + if(list && dataList2.length == 0 ){ + dataList2 = HiPerfCpuStruct.groupBy10MS(list, req.params.maxCpu, req.intervalPerf); + } + if (req.lazyRefresh) { + hiPerfCpu(list, dataList2, req.type!, filter, req.startNS, req.endNS, req.totalNS, req.frame, groupBy10MS, req.params.maxCpu, req.intervalPerf, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + hiPerfCpu(list, dataList2, req.type!, filter, req.startNS, req.endNS, req.totalNS, req.frame, groupBy10MS, req.params.maxCpu, req.intervalPerf, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startNS, arr[arr.length - 1].startNS + arr[arr.length - 1].dur) + } + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + req.context.stroke(); + req.context.beginPath(); + HiPerfCpuStruct.hoverStruct = undefined; + if (req.isHover) { + let offset = groupBy10MS ? 0 : 3; + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x - offset && req.hoverX <= re.frame.x + re.frame.width + offset) {//&& req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height + HiPerfCpuStruct.hoverStruct = re; + break; + } + } + } else { + HiPerfCpuStruct.hoverStruct = req.params.hoverStruct; + } + HiPerfCpuStruct.selectStruct = req.params.selectStruct; + req.context.fillStyle = ColorUtils.FUNC_COLOR[0]; + req.context.strokeStyle = ColorUtils.FUNC_COLOR[0]; + let path = new Path2D(); + for (let re of filter) { + HiPerfCpuStruct.draw(req.context, path, re, groupBy10MS); + } + if (groupBy10MS) { + req.context.fill(path); + } else { + req.context.stroke(path); + } + drawSelection(req.context, req.params); + req.context.closePath(); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: HiPerfCpuStruct.hoverStruct + }); + } +} + +export function hiPerfCpu(arr: Array, arr2: any, type: string, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, groupBy10MS: boolean, maxCpu: number | undefined, intervalPerf: number, use: boolean) { + if (use && res.length > 0 ) {//&& !groupBy10MS + let pns = (endNS - startNS) / frame.width; + let y = frame.y; + for (let i = 0; i < res.length; i++) { + let it = res[i]; + if((it.startNS || 0) + (it.dur || 0) > startNS && (it.startNS || 0) < endNS){ + if (!it.frame) { + it.frame = {}; + it.frame.y = y; + } + it.frame.height = it.height; + HiPerfCpuStruct.setFrame(it, pns, startNS, endNS, frame); + }else{ + it.frame = null; + } + } + return; + } + res.length = 0; + if (arr) { + let list: Array = groupBy10MS ? arr2 : arr; + let pns = (endNS - startNS) / frame.width; + let y = frame.y; + let filter = list.filter(it => (it.startNS || 0) + (it.dur || 0) > startNS && (it.startNS || 0) < endNS) + if(groupBy10MS){ + filter.map(it => { + if (!it.frame) { + it.frame = {}; + it.frame.y = y; + } + it.frame.height = it.height; + HiPerfCpuStruct.setFrame(it, pns, startNS, endNS, frame); + res.push(it) + }) + }else{ + filter.map(it => { + if (!it.frame) { + it.frame = {}; + it.frame.y = y; + } + it.frame.height = it.height; + HiPerfCpuStruct.setFrame(it, pns, startNS, endNS, frame); + return it; + }).reduce((pre, current) => { + if (!pre[`${current.frame.x}`]) { + pre[`${current.frame.x}`] = []; + pre[`${current.frame.x}`].push(current); + if (res.length == 0) { + res.push(current); + } + if (res[res.length - 1] && Math.abs(current.frame.x - res[res.length - 1].frame.x) > 4) { + res.push(current); + } + } + return pre; + }, {}); + } + } +} + +export class HiPerfCpuStruct extends BaseStruct { + static hoverStruct: HiPerfCpuStruct | undefined; + static selectStruct: HiPerfCpuStruct | undefined; + static path = new Path2D('M 100,100 h 50 v 50 h 50'); + id: number | undefined; + callchain_id: number | undefined; + timestamp: number | undefined; + thread_id: number | undefined; + event_count: number | undefined; + event_type_id: number | undefined; + cpu_id: number | undefined; + thread_state: string | undefined; + //------------------------------------------------------ + startNS: number | undefined; + endNS: number | undefined; + dur: number | undefined; + height: number | undefined; + cpu: number | undefined; + + static draw(ctx: CanvasRenderingContext2D, path: Path2D, data: HiPerfCpuStruct, groupBy10MS: boolean) { + if (data.frame) { + if (groupBy10MS) { + let width = data.frame.width; + path.rect(data.frame.x, 40 - (data.height || 0), width, data.height || 0) + } else { + path.moveTo(data.frame.x + 7, 20); + HiPerfCpuStruct.drawRoundRectPath(path, data.frame.x - 7, 20 - 7, 14, 14, 3) + path.moveTo(data.frame.x, 27); + path.lineTo(data.frame.x, 33); + } + } + } + + static drawRoundRectPath(cxt: Path2D, x: number, y: number, width: number, height: number, radius: number) { + cxt.arc(x + width - radius, y + height - radius, radius, 0, Math.PI / 2); + cxt.lineTo(x + radius, y + height); + cxt.arc(x + radius, y + height - radius, radius, Math.PI / 2, Math.PI); + cxt.lineTo(x + 0, y + radius); + cxt.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2); + cxt.lineTo(x + width - radius, y + 0); + cxt.arc(x + width - radius, y + radius, radius, Math.PI * 3 / 2, Math.PI * 2); + cxt.lineTo(x + width, y + height - radius); + cxt.moveTo(x + width / 3, y + height / 5); + cxt.lineTo(x + width / 3, y + height / 5 * 4); + cxt.moveTo(x + width / 3, y + height / 5); + cxt.bezierCurveTo(x + width / 3 + 7, y + height / 5 - 2, x + width / 3 + 7, y + height / 5 + 6, x + width / 3, y + height / 5 + 4); + } + + static setFrame(node: any, pns: number, startNS: number, endNS: number, frame: any) { + if ((node.startNS || 0) < startNS) { + node.frame.x = 0; + } else { + node.frame.x = Math.floor(((node.startNS || 0) - startNS) / pns); + } + if ((node.startNS || 0) + (node.dur || 0) > endNS) { + node.frame.width = frame.width - node.frame.x; + } else { + node.frame.width = Math.ceil(((node.startNS || 0) + (node.dur || 0) - startNS) / pns - node.frame.x); + } + if (node.frame.width < 1) { + node.frame.width = 1; + } + } + + static groupBy10MS(array: Array, maxCpu: number | undefined, intervalPerf: number): Array { + let obj = array.map(it => { + it.timestamp_group = Math.trunc(it.startNS / 1_000_000_0) * 1_000_000_0; + return it; + }).reduce((pre, current) => { + (pre[current["timestamp_group"]] = pre[current["timestamp_group"]] || []).push(current); + return pre; + }, {}); + let arr: any[] = []; + for (let aKey in obj) { + let ns = parseInt(aKey); + let height: number = 0; + if (maxCpu != undefined) { + height = Math.floor(obj[aKey].length / (10 / intervalPerf) / maxCpu * 40); + } else { + height = Math.floor(obj[aKey].length / (10 / intervalPerf) * 40); + } + arr.push({ + startNS: ns, + dur: 1_000_000_0, + height: height, + }) + } + return arr; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfEvent.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfEvent.ts new file mode 100644 index 0000000000000000000000000000000000000000..6972d2c1e03629406db94f4f40d2d362474686c7 --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfEvent.ts @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ColorUtils } from "../../component/trace/base/ColorUtils.js"; +import { + BaseStruct, + drawFlagLine, + drawLines, + drawLoading, + drawSelection, PerfRender, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; + +export class HiperfEventRender extends PerfRender{ + + renderMainThread(req: any,row:TraceRow) { + let list= row.dataList; + let list2= row.dataList2; + let filter = row.dataListCache; + let groupBy10MS = req.scale > 30_000_000; + if(list && row.dataList2.length ==0){ + row.dataList2 = HiPerfEventStruct.groupBy10MS(list, req.intervalPerf,req.type); + } + HiPerfEvent(list, list2, req.type!, filter, TraceRow.range?.startNS ??0, TraceRow.range?.endNS??0, TraceRow.range?.totalNS??0, row.frame, groupBy10MS, req.intervalPerf, req.useCache || (TraceRow.range?.refresh ?? false)); + req.context.beginPath(); + req.context.fillStyle = ColorUtils.FUNC_COLOR[0]; + req.context.strokeStyle = ColorUtils.FUNC_COLOR[0]; + let offset = groupBy10MS ? 0 : 3; + let path = new Path2D(); + let find = false; + for (let re of filter) { + HiPerfEventStruct.draw(req.context, path, re, groupBy10MS); + if(row.isHover){ + if (re.frame && row.hoverX >= re.frame.x - offset && row.hoverX <= re.frame.x + re.frame.width + offset) {//&& req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height + HiPerfEventStruct.hoverStruct = re; + find = true; + } + } + } + if (!find && row.isHover) HiPerfEventStruct.hoverStruct = undefined; + groupBy10MS ? req.context.fill(path) : req.context.stroke(path); + let maxEvent = HiPerfEventStruct.maxEvent!.get(req.type!) || 0; + let textMetrics = req.context.measureText(maxEvent); + req.context.globalAlpha = 0.8 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(maxEvent, 4, 5 + 9); + req.context.stroke(); + req.context.closePath(); + } + + render(req: RequestMessage, list: Array, filter: Array, dataList2: Array) { + let groupBy10MS = req.scale > 100_000_000; + if (req.lazyRefresh) { + HiPerfEvent(list, dataList2, req.type!, filter, req.startNS, req.endNS, req.totalNS, req.frame, groupBy10MS, req.intervalPerf, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + HiPerfEvent(list, dataList2, req.type!, filter, req.startNS, req.endNS, req.totalNS, req.frame, groupBy10MS, req.intervalPerf, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startNS, arr[arr.length - 1].startNS + arr[arr.length - 1].dur) + } + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + req.context.stroke(); + req.context.beginPath(); + HiPerfEventStruct.hoverStruct = undefined; + req.context.fillStyle = ColorUtils.FUNC_COLOR[0]; + req.context.strokeStyle = ColorUtils.FUNC_COLOR[0]; + if (req.isHover) { + let offset = groupBy10MS ? 0 : 3; + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x - offset && req.hoverX <= re.frame.x + re.frame.width + offset) {//&& req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height + HiPerfEventStruct.hoverStruct = re; + break; + } + } + } else { + HiPerfEventStruct.hoverStruct = req.params.hoverStruct; + } + HiPerfEventStruct.selectStruct = req.params.selectStruct; + let path = new Path2D(); + for (let re of filter) { + HiPerfEventStruct.draw(req.context, path, re, groupBy10MS); + } + groupBy10MS ? req.context.fill(path) : req.context.stroke(path); + drawSelection(req.context, req.params); + let maxEvent = HiPerfEventStruct.maxEvent!.get(req.type!) || 0; + let textMetrics = req.context.measureText(maxEvent); + req.context.globalAlpha = 0.8 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(maxEvent, 4, 5 + 9); + req.context.stroke(); + req.context.closePath(); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: HiPerfEventStruct.hoverStruct + }); + } +} +export function HiPerfEvent(arr: Array, arr2: any, type: string, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, groupBy10MS: boolean, intervalPerf: number, use: boolean) { + if (use && res.length > 0) { + let pns = (endNS - startNS) / frame.width; + let y = frame.y; + for (let i = 0; i < res.length; i++) { + let it = res[i]; + if ((it.startNS || 0) + (it.dur || 0) > startNS && (it.startNS || 0) < endNS) { + if (!it.frame) { + it.frame = {}; + it.frame.y = y; + } + it.frame.height = it.height; + HiPerfEventStruct.setFrame(it, pns, startNS, endNS, frame); + } else { + it.frame = null; + } + } + return; + } + res.length = 0; + if (arr) { + let list: Array = groupBy10MS ? arr2 : arr; + let pns = (endNS - startNS) / frame.width; + let y = frame.y; + let filter = list.filter(it => (it.startNS || 0) + (it.dur || 0) > startNS && (it.startNS || 0) < endNS) + if(groupBy10MS){ + filter.map(it => { + if (!it.frame) { + it.frame = {}; + it.frame.y = y; + } + it.frame.height = it.height; + HiPerfEventStruct.setFrame(it, pns, startNS, endNS, frame); + res.push(it) + }) + }else{ + filter.map(it => { + if (!it.frame) { + it.frame = {}; + it.frame.y = y; + } + it.frame.height = it.height; + HiPerfEventStruct.setFrame(it, pns, startNS, endNS, frame); + return it; + }).reduce((pre, current) => { + if (!pre[`${current.frame.x}`]) { + pre[`${current.frame.x}`] = []; + pre[`${current.frame.x}`].push(current); + if (res.length == 0) { + res.push(current); + } + if (res[res.length - 1] && Math.abs(current.frame.x - res[res.length - 1].frame.x) > 4) { + res.push(current); + } + } + return pre; + }, {}); + } + } +} + +export class HiPerfEventStruct extends BaseStruct { + static hoverStruct: HiPerfEventStruct | undefined; + static selectStruct: HiPerfEventStruct | undefined; + static path = new Path2D('M 100,100 h 50 v 50 h 50'); + id: number | undefined; + callchain_id: number | undefined; + timestamp: number | undefined; + thread_id: number | undefined; + event_count: number | undefined; + event_type_id: number | undefined; + cpu_id: number | undefined; + thread_state: string | undefined; + startNS: number | undefined; + endNS: number | undefined; + dur: number | undefined; + height: number | undefined; + cpu: number | undefined; + static maxEvent: Map | undefined = new Map(); + sum: number | undefined; + max: number | undefined; + + static draw(ctx: CanvasRenderingContext2D, path: Path2D, data: HiPerfEventStruct, groupBy10MS: boolean) { + if (data.frame) { + if (groupBy10MS) { + let width = data.frame.width; + path.rect(data.frame.x, 40 - (data.height || 0), width, data.height || 0) + } else { + path.moveTo(data.frame.x + 7, 20); + HiPerfEventStruct.drawRoundRectPath(path, data.frame.x - 7, 20 - 7, 14, 14, 3) + path.moveTo(data.frame.x, 27); + path.lineTo(data.frame.x, 33); + } + } + } + + static drawRoundRectPath(cxt: Path2D, x: number, y: number, width: number, height: number, radius: number) { + cxt.arc(x + width - radius, y + height - radius, radius, 0, Math.PI / 2); + cxt.lineTo(x + radius, y + height); + cxt.arc(x + radius, y + height - radius, radius, Math.PI / 2, Math.PI); + cxt.lineTo(x + 0, y + radius); + cxt.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2); + cxt.lineTo(x + width - radius, y + 0); + cxt.arc(x + width - radius, y + radius, radius, Math.PI * 3 / 2, Math.PI * 2); + cxt.lineTo(x + width, y + height - radius); + cxt.moveTo(x + width / 3, y + height / 5); + cxt.lineTo(x + width / 3, y + height / 5 * 4); + cxt.moveTo(x + width / 3, y + height / 5); + cxt.bezierCurveTo(x + width / 3 + 7, y + height / 5 - 2, x + width / 3 + 7, y + height / 5 + 6, x + width / 3, y + height / 5 + 4); + } + + static setFrame(node: any, pns: number, startNS: number, endNS: number, frame: any) { + if ((node.startNS || 0) < startNS) { + node.frame.x = 0; + } else { + node.frame.x = Math.floor(((node.startNS || 0) - startNS) / pns); + } + if ((node.startNS || 0) + (node.dur || 0) > endNS) { + node.frame.width = frame.width - node.frame.x; + } else { + node.frame.width = Math.ceil(((node.startNS || 0) + (node.dur || 0) - startNS) / pns - node.frame.x); + } + if (node.frame.width < 1) { + node.frame.width = 1; + } + } + + static groupBy10MS(array: Array, intervalPerf: number, type: string): Array { + let obj = array.map(it => { + it.timestamp_group = Math.trunc(it.startNS / 1_000_000_0) * 1_000_000_0; + return it; + }).reduce((pre, current) => { + (pre[current["timestamp_group"]] = pre[current["timestamp_group"]] || []).push(current); + return pre; + }, {}); + let arr: any[] = []; + let max = 0; + for (let aKey in obj) { + let sum = obj[aKey].reduce((pre: any, cur: any) => { + return pre + cur.event_count + }, 0) + if (sum > max) max = sum; + let ns = parseInt(aKey); + arr.push({ + startNS: ns, + dur: 1_000_000_0, + height: 0, + sum: sum, + }) + } + if (typeof (HiPerfEventStruct.maxEvent!.get(type)) === "undefined") { + HiPerfEventStruct.maxEvent!.set(type, max); + } + arr.map(it => { + it.height = Math.floor(40 * it.sum / max); + it.max = max; + return it; + }) + return arr; + } +} diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfProcess.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfProcess.ts new file mode 100644 index 0000000000000000000000000000000000000000..e4b4bdb4864d54af4158e1aa169e84704e7afead --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfProcess.ts @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ColorUtils } from "../../component/trace/base/ColorUtils.js"; +import { + BaseStruct, + drawFlagLine, + drawLines, + drawLoading, + drawSelection, PerfRender, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {HiPerfCpuStruct} from "./ProcedureWorkerHiPerfCPU.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; + +export class HiperfProcessRender extends PerfRender{ + + renderMainThread(req: any,row:TraceRow) { + let list= row.dataList; + let filter = row.dataListCache; + let groupBy10MS = req.scale > 30_000_000; + if(list && row.dataList2.length == 0 ){ + row.dataList2 = HiPerfProcessStruct.groupBy10MS(list, req.intervalPerf); + } + hiPerfProcess(list,row.dataList2, filter, TraceRow.range?.startNS ??0, TraceRow.range?.endNS??0, TraceRow.range?.totalNS??0, row.frame, groupBy10MS, req.intervalPerf, req.useCache || (TraceRow.range?.refresh ?? false)); + req.context.beginPath(); + req.context.fillStyle = ColorUtils.FUNC_COLOR[0]; + req.context.strokeStyle = ColorUtils.FUNC_COLOR[0]; + let path = new Path2D(); + let offset = groupBy10MS ? 0 : 3; + let find = false; + for (let re of filter) { + HiPerfProcessStruct.draw(req.context, path, re, groupBy10MS); + if (row.isHover) { + if (re.frame && row.hoverX >= re.frame.x - offset && row.hoverX <= re.frame.x + re.frame.width + offset) {//&& req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height + HiPerfProcessStruct.hoverStruct = re; + find = true; + } + } + } + if (!find && row.isHover) HiPerfProcessStruct.hoverStruct = undefined; + groupBy10MS ? req.context.fill(path) : req.context.stroke(path); + req.context.closePath(); + } + + render(req: RequestMessage, list: Array, filter: Array, dataList2: Array) { + let groupBy10MS = req.scale > 100_000_000; + if (req.lazyRefresh) { + hiPerfProcess(list, dataList2,filter, req.startNS, req.endNS, req.totalNS, req.frame, groupBy10MS, req.intervalPerf, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + hiPerfProcess(list,dataList2, filter, req.startNS, req.endNS, req.totalNS, req.frame, groupBy10MS, req.intervalPerf, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startNS, arr[arr.length - 1].startNS + arr[arr.length - 1].dur) + } + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + req.context.stroke(); + req.context.beginPath(); + HiPerfProcessStruct.hoverStruct = undefined; + req.context.fillStyle = ColorUtils.FUNC_COLOR[0]; + req.context.strokeStyle = ColorUtils.FUNC_COLOR[0]; + if (req.isHover) { + let offset = groupBy10MS ? 0 : 3; + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x - offset && req.hoverX <= re.frame.x + re.frame.width + offset) {//&& req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height + HiPerfProcessStruct.hoverStruct = re; + break; + } + } + } else { + HiPerfProcessStruct.hoverStruct = req.params.hoverStruct; + } + HiPerfProcessStruct.selectStruct = req.params.selectStruct; + let path = new Path2D(); + for (let re of filter) { + HiPerfProcessStruct.draw(req.context, path, re, groupBy10MS); + } + groupBy10MS ? req.context.fill(path) : req.context.stroke(path); + req.context.closePath(); + drawSelection(req.context, req.params); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: HiPerfProcessStruct.hoverStruct + }); + } +} + +export function hiPerfProcess(arr: Array,arr2: Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, groupBy10MS: boolean, intervalPerf: number, use: boolean) { + if (use && res.length > 0) { + let pns = (endNS - startNS) / frame.width; + let y = frame.y; + for (let i = 0; i < res.length; i++) { + let it = res[i]; + if ((it.startNS || 0) + (it.dur || 0) > startNS && (it.startNS || 0) < endNS) { + if (!it.frame) { + it.frame = {}; + it.frame.y = y; + } + it.frame.height = it.height; + HiPerfProcessStruct.setFrame(it, pns, startNS, endNS, frame); + } else { + it.frame = null; + } + } + return; + } + res.length = 0; + if (arr) { + let list = groupBy10MS ? arr2 : arr; + let pns = (endNS - startNS) / frame.width; + let y = frame.y; + for (let i = 0, len = list.length; i < len; i++) { + let it = list[i]; + if ((it.startNS || 0) + (it.dur || 0) > startNS && (it.startNS || 0) < endNS) { + if (!list[i].frame) { + list[i].frame = {}; + list[i].frame.y = y; + } + list[i].frame.height = it.height; + HiPerfProcessStruct.setFrame(list[i], pns, startNS, endNS, frame) + if (groupBy10MS) { + if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) + && ((list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0)) + && ((list[i - 1].frame?.height || 0) == (list[i].frame?.height || 0)) + )) { + } else { + res.push(list[i]) + } + } else { + if (i > 0 && (Math.abs((list[i - 1].frame?.x || 0) - (list[i].frame?.x || 0)) < 4)) { + } else { + res.push(list[i]) + } + } + + } + } + } +} + +export class HiPerfProcessStruct extends BaseStruct { + static hoverStruct: HiPerfProcessStruct | undefined; + static selectStruct: HiPerfProcessStruct | undefined; + id: number | undefined; + callchain_id: number | undefined; + timestamp: number | undefined; + thread_id: number | undefined; + event_count: number | undefined; + event_type_id: number | undefined; + cpu_id: number | undefined; + thread_state: string | undefined; + //------------------------------------------------------ + startNS: number | undefined; + endNS: number | undefined; + dur: number | undefined; + height: number | undefined; + cpu: number | undefined; + group: number | undefined; + + static draw(ctx: CanvasRenderingContext2D, path: Path2D, data: HiPerfProcessStruct, groupBy10MS: boolean) { + if (data.frame) { + if (groupBy10MS) { + let width = data.frame.width; + path.rect(data.frame.x, 40 - (data.height || 0), width, data.height || 0) + } else { + path.moveTo(data.frame.x + 7, 20); + HiPerfCpuStruct.drawRoundRectPath(path, data.frame.x - 7, 20 - 7, 14, 14, 3) + path.moveTo(data.frame.x, 27); + path.lineTo(data.frame.x, 33); + } + } + } + + static setFrame(node: any, pns: number, startNS: number, endNS: number, frame: any) { + if ((node.startNS || 0) < startNS) { + node.frame.x = 0; + } else { + node.frame.x = Math.floor(((node.startNS || 0) - startNS) / pns); + } + if ((node.startNS || 0) + (node.dur || 0) > endNS) { + node.frame.width = frame.width - node.frame.x; + } else { + node.frame.width = Math.ceil(((node.startNS || 0) + (node.dur || 0) - startNS) / pns - node.frame.x); + } + if (node.frame.width < 1) { + node.frame.width = 1; + } + } + + static groupBy10MS(array: Array, intervalPerf: number): Array { + let obj = array.map(it => { + it.timestamp_group = Math.trunc(it.startNS / 1_000_000_0) * 1_000_000_0; + return it; + }).reduce((pre, current) => { + (pre[current["timestamp_group"]] = pre[current["timestamp_group"]] || []).push(current); + return pre; + }, {}); + let arr: any[] = []; + for (let aKey in obj) { + let ns = parseInt(aKey); + let height: number = 0; + height = Math.floor(obj[aKey].length / (10 / intervalPerf) * 40); + arr.push({ + startNS: ns, + height: height, + dur: 1_000_000_0, + }) + } + return arr; + } +} diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfReport.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfReport.ts new file mode 100644 index 0000000000000000000000000000000000000000..6d91e159a7b37be5925b475b11e701248bfd8ee1 --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfReport.ts @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ColorUtils } from "../../component/trace/base/ColorUtils.js"; +import { + BaseStruct, + drawFlagLine, + drawLines, + drawLoading, + drawSelection, PerfRender, + RequestMessage +} from "./ProcedureWorkerCommon.js"; + +import {TraceRow} from "../../component/trace/base/TraceRow.js"; + +export class HiperfReportRender extends PerfRender { + + renderMainThread(req: any,row:TraceRow) { + let list= row.dataList; + let filter = row.dataListCache; + let groupBy10MS = req.scale > 30_000_000; + if(list && row.dataList2.length ==0){ + row.dataList2 = HiPerfReportStruct.groupBy10MS(list, req.intervalPerf); + } + HiPerfReport(list, row.dataList2, req.type!, filter, TraceRow.range?.startNS ??0, TraceRow.range?.endNS??0, TraceRow.range?.totalNS??0, row.frame, groupBy10MS, req.intervalPerf, req.useCache || (TraceRow.range?.refresh ?? false)); + req.context.beginPath(); + req.context.fillStyle = ColorUtils.FUNC_COLOR[0]; + req.context.strokeStyle = ColorUtils.FUNC_COLOR[0]; + let path = new Path2D(); + let offset = groupBy10MS ? 0 : 3; + let find = false; + for (let re of filter) { + HiPerfReportStruct.draw(req.context, path, re, groupBy10MS); + if (row.isHover) { + if (re.frame && row.hoverX >= re.frame.x - offset && row.hoverX <= re.frame.x + re.frame.width + offset) {//&& req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height + HiPerfReportStruct.hoverStruct = re; + find = true; + } + } + } + if (!find && row.isHover) HiPerfReportStruct.hoverStruct = undefined; + groupBy10MS ? req.context.fill(path) : req.context.stroke(path); + req.context.closePath(); + } + + render(req: RequestMessage, list: Array, filter: Array, dataList2: Array) { + let groupBy10MS = req.scale > 100_000_000; + if (req.lazyRefresh) { + HiPerfReport(list, dataList2, req.type!, filter, req.startNS, req.endNS, req.totalNS, req.frame, groupBy10MS, req.intervalPerf, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + HiPerfReport(list, dataList2, req.type!, filter, req.startNS, req.endNS, req.totalNS, req.frame, groupBy10MS, req.intervalPerf, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startNS, arr[arr.length - 1].startNS + arr[arr.length - 1].dur) + } + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + req.context.stroke(); + req.context.beginPath(); + HiPerfReportStruct.hoverStruct = undefined; + req.context.fillStyle = ColorUtils.FUNC_COLOR[0]; + req.context.strokeStyle = ColorUtils.FUNC_COLOR[0]; + if (req.isHover) { + let offset = groupBy10MS ? 0 : 3; + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x - offset && req.hoverX <= re.frame.x + re.frame.width + offset) {//&& req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height + HiPerfReportStruct.hoverStruct = re; + break; + } + } + } else { + HiPerfReportStruct.hoverStruct = req.params.hoverStruct; + } + HiPerfReportStruct.selectStruct = req.params.selectStruct; + let path = new Path2D(); + for (let re of filter) { + HiPerfReportStruct.draw(req.context, path, re, groupBy10MS); + } + groupBy10MS ? req.context.fill(path) : req.context.stroke(path); + req.context.closePath(); + drawSelection(req.context, req.params); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: HiPerfReportStruct.hoverStruct + }); + } +} + +export function HiPerfReport(arr: Array, arr2: any, type: string, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, groupBy10MS: boolean, intervalPerf: number, use: boolean) { + if (use && res.length > 0) { + let pns = (endNS - startNS) / frame.width; + let y = frame.y; + for (let i = 0; i < res.length; i++) { + let it = res[i]; + if ((it.startNS || 0) + (it.dur || 0) > startNS && (it.startNS || 0) < endNS) { + if (!it.frame) { + it.frame = {}; + it.frame.y = y; + } + it.frame.height = it.height; + HiPerfReportStruct.setFrame(it, pns, startNS, endNS, frame); + } else { + it.frame = null; + } + } + return; + } + res.length = 0; + if (arr) { + let list: Array = groupBy10MS ? arr2 : arr; + let pns = (endNS - startNS) / frame.width; + let y = frame.y; + list.filter(it => (it.startNS || 0) + (it.dur || 0) > startNS && (it.startNS || 0) < endNS).map(it => { + if (!it.frame) { + it.frame = {}; + it.frame.y = y; + } + it.frame.height = it.height; + HiPerfReportStruct.setFrame(it, pns, startNS, endNS, frame); + return it; + }).reduce((pre, current, index, arr) => { + if (!pre[`${current.frame.x}`]) { + pre[`${current.frame.x}`] = []; + pre[`${current.frame.x}`].push(current); + if (groupBy10MS) { + res.push(current); + } else { + if (res.length == 0) { + res.push(current); + } + if (res[res.length - 1] && Math.abs(current.frame.x - res[res.length - 1].frame.x) > 4) { + res.push(current); + } + } + } + return pre; + }, {}); + } +} + +export class HiPerfReportStruct extends BaseStruct { + static hoverStruct: HiPerfReportStruct | undefined; + static selectStruct: HiPerfReportStruct | undefined; + static path = new Path2D('M 100,100 h 50 v 50 h 50'); + id: number | undefined; + callchain_id: number | undefined; + timestamp: number | undefined; + thread_id: number | undefined; + event_count: number | undefined; + event_type_id: number | undefined; + cpu_id: number | undefined; + thread_state: string | undefined; + startNS: number | undefined; + endNS: number | undefined; + dur: number | undefined; + height: number | undefined; + cpu: number | undefined; + + static draw(ctx: CanvasRenderingContext2D, path: Path2D, data: HiPerfReportStruct, groupBy10MS: boolean) { + if (data.frame) { + if (groupBy10MS) { + let width = data.frame.width; + path.rect(data.frame.x, 40 - (data.height || 0), width, data.height || 0) + } else { + path.moveTo(data.frame.x + 7, 20); + HiPerfReportStruct.drawRoundRectPath(path, data.frame.x - 7, 20 - 7, 14, 14, 3) + path.moveTo(data.frame.x, 27); + path.lineTo(data.frame.x, 33); + } + } + } + + static drawRoundRectPath(cxt: Path2D, x: number, y: number, width: number, height: number, radius: number) { + cxt.arc(x + width - radius, y + height - radius, radius, 0, Math.PI / 2); + cxt.lineTo(x + radius, y + height); + cxt.arc(x + radius, y + height - radius, radius, Math.PI / 2, Math.PI); + cxt.lineTo(x + 0, y + radius); + cxt.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2); + cxt.lineTo(x + width - radius, y + 0); + cxt.arc(x + width - radius, y + radius, radius, Math.PI * 3 / 2, Math.PI * 2); + cxt.lineTo(x + width, y + height - radius); + cxt.moveTo(x + width / 3, y + height / 5); + cxt.lineTo(x + width / 3, y + height / 5 * 4); + cxt.moveTo(x + width / 3, y + height / 5); + cxt.bezierCurveTo(x + width / 3 + 7, y + height / 5 - 2, x + width / 3 + 7, y + height / 5 + 6, x + width / 3, y + height / 5 + 4); + } + + static setFrame(node: any, pns: number, startNS: number, endNS: number, frame: any) { + if ((node.startNS || 0) < startNS) { + node.frame.x = 0; + } else { + node.frame.x = Math.floor(((node.startNS || 0) - startNS) / pns); + } + if ((node.startNS || 0) + (node.dur || 0) > endNS) { + node.frame.width = frame.width - node.frame.x; + } else { + node.frame.width = Math.ceil(((node.startNS || 0) + (node.dur || 0) - startNS) / pns - node.frame.x); + } + if (node.frame.width < 1) { + node.frame.width = 1; + } + } + + static groupBy10MS(array: Array, intervalPerf: number): Array { + let obj = array.map(it => { + it.timestamp_group = Math.trunc(it.startNS / 1_000_000_0) * 1_000_000_0; + return it; + }).reduce((pre, current) => { + (pre[current["timestamp_group"]] = pre[current["timestamp_group"]] || []).push(current); + return pre; + }, {}); + let arr: any[] = []; + let max = 0; + for (let aKey in obj) { + let sum = obj[aKey].reduce((pre: any, cur: any) => { + return pre + cur.event_count + }, 0) + if (sum > max) max = sum; + let ns = parseInt(aKey); + arr.push({ + startNS: ns, + dur: 1_000_000_0, + height: 0, + sum: sum, + }) + } + arr.map(it => { + it.height = Math.floor(40 * it.sum / max); + return it; + }) + return arr; + } +} diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfThread.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfThread.ts new file mode 100644 index 0000000000000000000000000000000000000000..e5afdf34811515aab4085c20502f45b6a92e9397 --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfThread.ts @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ColorUtils } from "../../component/trace/base/ColorUtils.js"; +import { + BaseStruct, + drawFlagLine, + drawLines, + drawLoading, + drawSelection, PerfRender, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {HiPerfCpuStruct} from "./ProcedureWorkerHiPerfCPU.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; + +export class HiperfThreadRender extends PerfRender { + renderMainThread(req: any,row:TraceRow) { + let list= row.dataList; + let filter = row.dataListCache; + let groupBy10MS = req.scale > 30_000_000; + if(list && row.dataList2.length == 0 ){ + row.dataList2 = HiPerfThreadStruct.groupBy10MS(list, req.intervalPerf); + } + hiPerfThread(list, row.dataList2,filter, TraceRow.range?.startNS ??0, TraceRow.range?.endNS??0, TraceRow.range?.totalNS??0, row.frame, groupBy10MS, req.intervalPerf, req.useCache || (TraceRow.range?.refresh ?? false)); + req.context.beginPath(); + req.context.fillStyle = ColorUtils.FUNC_COLOR[0]; + req.context.strokeStyle = ColorUtils.FUNC_COLOR[0]; + let path = new Path2D(); + let offset = groupBy10MS ? 0 : 3; + let find = false; + for (let re of filter) { + HiPerfThreadStruct.draw(req.context, path, re, groupBy10MS); + if (row.isHover) { + if (re.frame && row.hoverX >= re.frame.x - offset && row.hoverX <= re.frame.x + re.frame.width + offset) {//&& req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height + HiPerfThreadStruct.hoverStruct = re; + find = true; + } + } + } + if (!find && row.isHover) HiPerfThreadStruct.hoverStruct = undefined; + groupBy10MS ? req.context.fill(path) : req.context.stroke(path); + req.context.closePath(); + } + + render(req: RequestMessage, list: Array, filter: Array, dataList2: Array) { + let groupBy10MS = req.scale > 100_000_000; + if (req.lazyRefresh) { + hiPerfThread(list, dataList2,filter, req.startNS, req.endNS, req.totalNS, req.frame, groupBy10MS, req.intervalPerf, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + hiPerfThread(list,dataList2, filter, req.startNS, req.endNS, req.totalNS, req.frame, groupBy10MS, req.intervalPerf, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startNS, arr[arr.length - 1].startNS + arr[arr.length - 1].dur) + } + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + req.context.stroke(); + req.context.beginPath(); + HiPerfThreadStruct.hoverStruct = undefined; + req.context.fillStyle = ColorUtils.FUNC_COLOR[0]; + req.context.strokeStyle = ColorUtils.FUNC_COLOR[0]; + if (req.isHover) { + let offset = groupBy10MS ? 0 : 3; + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x - offset && req.hoverX <= re.frame.x + re.frame.width + offset) {//&& req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height + HiPerfThreadStruct.hoverStruct = re; + break; + } + } + } else { + HiPerfThreadStruct.hoverStruct = req.params.hoverStruct; + } + HiPerfThreadStruct.selectStruct = req.params.selectStruct; + let path = new Path2D(); + for (let re of filter) { + HiPerfThreadStruct.draw(req.context, path, re, groupBy10MS); + } + groupBy10MS ? req.context.fill(path) : req.context.stroke(path); + req.context.stroke(); + req.context.closePath(); + drawSelection(req.context, req.params); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: HiPerfThreadStruct.hoverStruct + }); + } +} + +export function hiPerfThread(arr: Array,arr2:Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, groupBy10MS: boolean, intervalPerf: number, use: boolean) { + if (use && res.length > 0) { + let pns = (endNS - startNS) / frame.width; + let y = frame.y; + for (let i = 0; i < res.length; i++) { + let it = res[i]; + if ((it.startNS || 0) + (it.dur || 0) > startNS && (it.startNS || 0) < endNS) { + if (!it.frame) { + it.frame = {}; + it.frame.y = y; + } + it.frame.height = it.height; + HiPerfThreadStruct.setFrame(it, pns, startNS, endNS, frame); + } else { + it.frame = null; + } + } + return; + } + res.length = 0; + if (arr) { + let list = groupBy10MS ? arr2 : arr; + let pns = (endNS - startNS) / frame.width; + let y = frame.y; + for (let i = 0, len = list.length; i < len; i++) { + let it = list[i]; + if ((it.startNS || 0) + (it.dur || 0) > startNS && (it.startNS || 0) < endNS) { + if (!list[i].frame) { + list[i].frame = {}; + list[i].frame.y = y; + } + list[i].frame.height = it.height; + HiPerfThreadStruct.setFrame(list[i], pns, startNS, endNS, frame) + if (groupBy10MS) { + if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) + && ((list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0)) + && ((list[i - 1].frame?.height || 0) == (list[i].frame?.height || 0)) + )) { + + } else { + res.push(list[i]) + } + } else { + if (i > 0 && (Math.abs((list[i - 1].frame?.x || 0) - (list[i].frame?.x || 0)) < 4)) { + } else { + res.push(list[i]) + } + } + } + } + } +} + +export class HiPerfThreadStruct extends BaseStruct { + static hoverStruct: HiPerfThreadStruct | undefined; + static selectStruct: HiPerfThreadStruct | undefined; + id: number | undefined; + callchain_id: number | undefined; + timestamp: number | undefined; + thread_id: number | undefined; + event_count: number | undefined; + event_type_id: number | undefined; + cpu_id: number | undefined; + thread_state: string | undefined; + //------------------------------------------------------ + startNS: number | undefined; + endNS: number | undefined; + dur: number | undefined; + height: number | undefined; + cpu: number | undefined; + + static draw(ctx: CanvasRenderingContext2D, path: Path2D, data: HiPerfThreadStruct, groupBy10MS: boolean) { + if (data.frame) { + if (groupBy10MS) { + let width = data.frame.width; + path.rect(data.frame.x, 40 - (data.height || 0), width, data.height || 0) + } else { + path.moveTo(data.frame.x + 7, 20); + HiPerfCpuStruct.drawRoundRectPath(path, data.frame.x - 7, 20 - 7, 14, 14, 3) + path.moveTo(data.frame.x, 27); + path.lineTo(data.frame.x, 33); + } + } + } + + static setFrame(node: any, pns: number, startNS: number, endNS: number, frame: any) { + if ((node.startNS || 0) < startNS) { + node.frame.x = 0; + } else { + node.frame.x = Math.floor(((node.startNS || 0) - startNS) / pns); + } + if ((node.startNS || 0) + (node.dur || 0) > endNS) { + node.frame.width = frame.width - node.frame.x; + } else { + node.frame.width = Math.ceil(((node.startNS || 0) + (node.dur || 0) - startNS) / pns - node.frame.x); + } + if (node.frame.width < 1) { + node.frame.width = 1; + } + } + + static groupBy10MS(array: Array, intervalPerf: number): Array { + let obj = array.map(it => { + it.timestamp_group = Math.trunc(it.startNS / 1_000_000_0) * 1_000_000_0; + return it; + }).reduce((pre, current) => { + (pre[current["timestamp_group"]] = pre[current["timestamp_group"]] || []).push(current); + return pre; + }, {}); + let arr: any[] = []; + for (let aKey in obj) { + let ns = parseInt(aKey); + let height: number = 0; + height = Math.floor(obj[aKey].length / (10 / intervalPerf) * 40); + arr.push({ + startNS: ns, + height: height, + dur: 1_000_000_0, + }) + } + return arr; + } +} diff --git a/host/ide/src/trace/database/ProcedureWorkerMem.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerMem.ts similarity index 33% rename from host/ide/src/trace/database/ProcedureWorkerMem.ts rename to host/ide/src/trace/database/ui-worker/ProcedureWorkerMem.ts index 1405ee962bb994c0ad6907013c6fe0561e92f85c..b4c13146acac8c8e6f3db8de054ea9e974e8b627 100644 --- a/host/ide/src/trace/database/ProcedureWorkerMem.ts +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerMem.ts @@ -13,7 +13,85 @@ * limitations under the License. */ -import {BaseStruct, ColorUtils, ns2x} from "./ProcedureWorkerCommon.js"; +import { ColorUtils } from "../../component/trace/base/ColorUtils.js"; +import { TraceRow } from "../../component/trace/base/TraceRow.js"; +import { + BaseStruct, + drawFlagLine, + drawLines, + drawLoading, + drawSelection, drawWakeUp, isFrameContainPoint, + ns2x, PerfRender, Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {CpuStruct} from "./ProcedureWorkerCPU.js"; + +export class MemRender extends Render{ + renderMainThread(req: { useCache: boolean; context: CanvasRenderingContext2D; type: string }, row: TraceRow) { + let list = row.dataList; + let filter = row.dataListCache; + mem(list, filter, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, row.frame, req.useCache || !TraceRow.range!.refresh); + req.context.beginPath(); + let find = false; + for (let re of filter) { + ProcessMemStruct.draw(req.context, re); + if(row.isHover){ + if (re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { + ProcessMemStruct.hoverProcessMemStruct = re; + find = true; + } + } + } + if (!find && row.isHover) ProcessMemStruct.hoverProcessMemStruct = undefined; + req.context.closePath(); + } + + render(req: RequestMessage, list: Array, filter: Array) { + if (req.lazyRefresh) { + mem(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + mem(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startTime, arr[arr.length - 1].startTime + arr[arr.length - 1].dur) + } + req.context.beginPath(); + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + ProcessMemStruct.hoverProcessMemStruct = undefined; + if (req.isHover) { + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x && req.hoverX <= re.frame.x + re.frame.width && req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height) { + ProcessMemStruct.hoverProcessMemStruct = re; + break; + } + } + } else { + ProcessMemStruct.hoverProcessMemStruct = req.params.hoverProcessMemStruct; + } + for (let re of filter) { + ProcessMemStruct.draw(req.context, re) + } + drawSelection(req.context, req.params); + drawWakeUp(req.context, req.wakeupBean, req.startNS, req.endNS, req.totalNS, req.frame); + req.context.closePath(); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: ProcessMemStruct.hoverProcessMemStruct + }); + } + + +} function setMemFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { let x1: number; @@ -38,8 +116,18 @@ function setMemFrame(node: any, padding: number, startNS: number, endNS: number, node.frame.height = Math.floor(frame.height - padding * 2); } -export function mem(list: Array, res: Set, startNS: number, endNS: number, totalNS: number, frame: any) { - res.clear(); +export function mem(list: Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, use: boolean) { + if (use && res.length > 0) { + for (let i = 0, len = res.length; i < len; i++) { + if ((res[i].startTime || 0) + (res[i].duration || 0) > startNS && (res[i].startTime || 0) < endNS) { + setMemFrame(res[i], 5, startNS, endNS, totalNS, frame) + }else{ + res[i].frame = null; + } + } + return; + } + res.length = 0; if (list) { for (let i = 0, len = list.length; i < len; i++) { let it = list[i]; @@ -48,7 +136,7 @@ export function mem(list: Array, res: Set, startNS: number, endNS: num if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && (list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0))) { } else { - res.add(list[i]) + res.push(list[i]) } } } @@ -56,12 +144,12 @@ export function mem(list: Array, res: Set, startNS: number, endNS: num } export class ProcessMemStruct extends BaseStruct { + static hoverProcessMemStruct: ProcessMemStruct | undefined; trackId: number | undefined processName: string | undefined pid: number | undefined upid: number | undefined trackName: string | undefined - type: string | undefined track_id: string | undefined value: number | undefined @@ -75,10 +163,27 @@ export class ProcessMemStruct extends BaseStruct { let width = data.frame.width || 0; ctx.fillStyle = ColorUtils.colorForTid(data.maxValue || 0) ctx.strokeStyle = ColorUtils.colorForTid(data.maxValue || 0) - ctx.globalAlpha = 0.6; - ctx.lineWidth = 1; - let drawHeight: number = ((data.value || 0) * (data.frame.height || 0) * 1.0) / (data.maxValue || 1); - ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + if (data.track_id === ProcessMemStruct.hoverProcessMemStruct?.track_id && data.startTime === ProcessMemStruct.hoverProcessMemStruct?.startTime) { + ctx.lineWidth = 1; + ctx.globalAlpha = 0.6; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / (data.maxValue || 0)); + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + ctx.beginPath() + ctx.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight, 3, 0, 2 * Math.PI, true) + ctx.fill() + ctx.globalAlpha = 1.0; + ctx.stroke(); + ctx.beginPath() + ctx.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight); + ctx.lineWidth = 3; + ctx.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight) + ctx.stroke(); + } else { + ctx.globalAlpha = 0.6; + ctx.lineWidth = 1; + let drawHeight: number = ((data.value || 0) * (data.frame.height || 0) * 1.0) / (data.maxValue || 1); + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + } } ctx.globalAlpha = 1.0; ctx.lineWidth = 1; diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerMemoryAbility.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerMemoryAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..302433f2f833874b12b0235e9c99de4d9b928b1f --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerMemoryAbility.ts @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ColorUtils } from "../../component/trace/base/ColorUtils.js"; +import { + BaseStruct, dataFilterHandler, + drawFlagLine, + drawLines, + drawLoading, + drawSelection, drawWakeUp, isFrameContainPoint, + ns2x, Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; + +export class MemoryAbilityRender extends Render{ + renderMainThread(req: { + context: CanvasRenderingContext2D, + useCache: boolean, + type: string, + maxMemoryByte:number, + maxMemoryByteName:string, + + }, row: TraceRow) { + let list = row.dataList; + let filter = row.dataListCache; + dataFilterHandler(list,filter,{ + startKey: "startNS", + durKey: "dur", + startNS: TraceRow.range?.startNS ?? 0, + endNS: TraceRow.range?.endNS ?? 0, + totalNS: TraceRow.range?.totalNS ?? 0, + frame: row.frame, + paddingTop: 5, + useCache: req.useCache || !(TraceRow.range?.refresh ?? false) + }) + req.context.beginPath(); + let find = false; + for (let re of filter) { + MemoryAbilityMonitorStruct.draw(req.context, re ,req.maxMemoryByte ,row.isHover) + if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { + MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = re; + find = true; + } + } + if (!find && row.isHover) MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = undefined; + req.context.closePath(); + let textMetrics = req.context.measureText(req.maxMemoryByteName); + req.context.globalAlpha = 0.8 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(req.maxMemoryByteName, 4, 5 + 9) + } + + render(req: RequestMessage, list: Array, filter: Array) { + if (req.lazyRefresh) { + memoryAbility(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + memoryAbility(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startNS, arr[arr.length - 1].startNS + arr[arr.length - 1].dur) + } + req.context.beginPath(); + MemoryAbilityMonitorStruct.maxMemoryByte = req.params.maxMemoryByte; + MemoryAbilityMonitorStruct.maxMemoryByteName = req.params.maxMemoryByteName; + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = undefined; + if (req.isHover) { + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x && req.hoverX <= re.frame.x + re.frame.width && req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height) { + MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = re; + break; + } + } + } + MemoryAbilityMonitorStruct.selectMemoryAbilityStruct = req.params.selectMemoryAbilityStruct; + for (let re of filter) { + MemoryAbilityMonitorStruct.draw(req.context, re ,MemoryAbilityMonitorStruct.maxMemoryByte,true) + } + drawSelection(req.context, req.params); + req.context.closePath(); + let s = MemoryAbilityMonitorStruct.maxMemoryByteName + let textMetrics = req.context.measureText(s); + req.context.globalAlpha = 0.8 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(s, 4, 5 + 9) + drawWakeUp(req.context, req.wakeupBean, req.startNS, req.endNS, req.totalNS, req.frame); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct + }); + } +} + +export function memoryAbility(list: Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, use: boolean) { + if (use && res.length > 0) { + for (let i = 0; i < res.length; i++) { + let item = res[i]; + if ((item.startNS || 0) + (item.dur || 0) > (startNS || 0) && (item.startNS || 0) < (endNS || 0)) { + MemoryAbilityMonitorStruct.setMemoryFrame(item, 5, startNS || 0, endNS || 0, totalNS || 0, frame) + } else { + item.frame = null; + } + } + return; + } + res.length = 0; + if (list) { + for (let index = 0; index < list.length; index++) { + let item = list[index]; + if (index === list.length - 1) { + item.dur = (endNS || 0) - (item.startNS || 0) + } else { + item.dur = (list[index + 1].startNS || 0) - (item.startNS || 0) + } + if ((item.startNS || 0) + (item.dur || 0) > (startNS || 0) && (item.startNS || 0) < (endNS || 0)) { + MemoryAbilityMonitorStruct.setMemoryFrame(list[index], 5, startNS || 0, endNS || 0, totalNS || 0, frame) + if (index > 0 && ((list[index - 1].frame?.x || 0) == (list[index].frame?.x || 0) && (list[index - 1].frame?.width || 0) == (list[index].frame?.width || 0))) { + + } else { + res.push(item) + } + } + } + } +} + +export class MemoryAbilityMonitorStruct extends BaseStruct { + static maxMemoryByte: number = 0 + static maxMemoryByteName: string = "0 MB" + static hoverMemoryAbilityStruct: MemoryAbilityMonitorStruct | undefined; + static selectMemoryAbilityStruct: MemoryAbilityMonitorStruct | undefined; + cpu: number | undefined + value: number | undefined + startNS: number | undefined + dur: number | undefined + + static draw(context2D: CanvasRenderingContext2D, data: MemoryAbilityMonitorStruct,maxMemoryByte:number,isHover:boolean) { + if (data.frame) { + let width = data.frame.width || 0; + let index = 2; + context2D.fillStyle = ColorUtils.colorForTid(index) + context2D.strokeStyle = ColorUtils.colorForTid(index) + if (data.startNS === MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct?.startNS && isHover) { + context2D.lineWidth = 1; + context2D.globalAlpha = 0.6; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / maxMemoryByte); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, width, drawHeight) + context2D.beginPath() + context2D.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, 3, 0, 2 * Math.PI, true) + context2D.fill() + context2D.globalAlpha = 1.0; + context2D.stroke(); + context2D.beginPath() + context2D.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight + 4); + context2D.lineWidth = 3; + context2D.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight + 4) + context2D.stroke(); + } else { + context2D.globalAlpha = 0.6; + context2D.lineWidth = 1; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0)) / maxMemoryByte); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, width, drawHeight) + } + } + context2D.globalAlpha = 1.0; + context2D.lineWidth = 1; + } + + static setMemoryFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { + let startPointX: number, endPointX: number + + if ((node.startNS || 0) < startNS) { + startPointX = 0 + } else { + startPointX = ns2x((node.startNS || 0), startNS, endNS, totalNS, frame); + } + if ((node.startNS || 0) + (node.dur || 0) > endNS) { + endPointX = frame.width; + } else { + endPointX = ns2x((node.startNS || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); + } + let frameWidth: number = endPointX - startPointX <= 1 ? 1 : endPointX - startPointX; + if (!node.frame) { + node.frame = {}; + } + node.frame.x = Math.floor(startPointX); + node.frame.y = frame.y + padding; + node.frame.width = Math.ceil(frameWidth); + node.frame.height = Math.floor(frame.height - padding * 2); + } +} + +const textPadding = 2; diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerNetworkAbility.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerNetworkAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..5b048067123422adfb53fa1545d619af5577646c --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerNetworkAbility.ts @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ColorUtils } from "../../component/trace/base/ColorUtils.js"; +import { + BaseStruct, dataFilterHandler, + drawFlagLine, + drawLines, + drawLoading, + drawSelection, drawWakeUp, isFrameContainPoint, + ns2x, Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; +export class NetworkAbilityRender extends Render{ + + renderMainThread(req: { + context: CanvasRenderingContext2D, + useCache: boolean, + type: string, + maxNetworkRate:number, + maxNetworkRateName:string + }, row: TraceRow) { + let list = row.dataList; + let filter = row.dataListCache; + dataFilterHandler(list,filter,{ + startKey: "startNS", + durKey: "dur", + startNS: TraceRow.range?.startNS ?? 0, + endNS: TraceRow.range?.endNS ?? 0, + totalNS: TraceRow.range?.totalNS ?? 0, + frame: row.frame, + paddingTop: 5, + useCache: req.useCache || !(TraceRow.range?.refresh ?? false) + }) + req.context.beginPath(); + let find = false; + for (let re of filter) { + NetworkAbilityMonitorStruct.draw(req.context, re,req.maxNetworkRate,row.isHover) + if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { + NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = re; + find = true; + } + } + if (!find && row.isHover) NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = undefined; + req.context.closePath(); + let textMetrics = req.context.measureText(req.maxNetworkRateName); + req.context.globalAlpha = 0.8 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(req.maxNetworkRateName, 4, 5 + 9) + } + + render(req: RequestMessage, list: Array, filter: Array) { + + } +} + + +export class NetworkAbilityMonitorStruct extends BaseStruct { + static maxNetworkRate: number = 0 + static maxNetworkRateName: string = "0 KB/S" + static hoverNetworkAbilityStruct: NetworkAbilityMonitorStruct | undefined; + static selectNetworkAbilityStruct: NetworkAbilityMonitorStruct | undefined; + value: number | undefined + startNS: number | undefined + + static draw(context2D: CanvasRenderingContext2D, data: NetworkAbilityMonitorStruct, maxNetworkRate: number,isHover:boolean) { + if (data.frame) { + let width = data.frame.width || 0; + let index = 2; + context2D.fillStyle = ColorUtils.colorForTid(index) + context2D.strokeStyle = ColorUtils.colorForTid(index) + if (data.startNS === NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct?.startNS && isHover) { + context2D.lineWidth = 1; + context2D.globalAlpha = 0.6; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / maxNetworkRate); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, width, drawHeight) + context2D.beginPath() + context2D.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, 3, 0, 2 * Math.PI, true) + context2D.fill() + context2D.globalAlpha = 1.0; + context2D.stroke(); + context2D.beginPath() + context2D.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight + 4); + context2D.lineWidth = 3; + context2D.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight + 4) + context2D.stroke(); + } else { + context2D.globalAlpha = 0.6; + context2D.lineWidth = 1; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0)) / maxNetworkRate); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, width, drawHeight) + } + } + context2D.globalAlpha = 1.0; + context2D.lineWidth = 1; + } +} diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerPerfCallchains.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerPerfCallchains.ts new file mode 100644 index 0000000000000000000000000000000000000000..c9d75979c472fb39e1666254430323171a89ca1e --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerPerfCallchains.ts @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class PerfCallChainThread extends Worker { + busy: boolean = false; + taskMap: any = {}; + uuid(): string { + // @ts-ignore + return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11) + .replace(/[018]/g, (c: any) => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)); + } + + queryFunc(name: string, args: any, handler: Function, action: string | null) { + this.busy = true; + let id = this.uuid(); + this.taskMap[id] = handler + let msg = { + id: id, + name: name, + action: action || "exec", + params: args, + } + this.postMessage(msg); + } + +} + +export class PerfCallChainPool { + maxThreadNumber: number = 0; + works: Array = []; + + close = async () => { + for (let i = 0; i < this.works.length; i++) { + let thread = this.works[i]; + thread.terminate(); + } + this.works.length = 0; + } + + init = async () => { + await this.close(); + let thread = new PerfCallChainThread("trace/component/chart/PerfDataQuery.js", {type: "module"})//trace/component/chart/PerfDataQuery.js + thread!.onmessage = (event: MessageEvent) => { + thread.busy = false; + let fun = thread.taskMap[event.data.id]; + if (fun) { + fun(event.data.results); + } + Reflect.deleteProperty(thread.taskMap, event.data.id); + } + thread!.onmessageerror = e => { + } + thread!.onerror = e => { + } + thread!.busy = false; + this.works?.push(thread!); + } + + submit(name: string, args: any, handler: Function, action: string | null) { + let noBusyThreads = this.works.filter(it => !it.busy); + let thread: PerfCallChainThread + if (noBusyThreads.length > 0) { //取第一个空闲的线程进行任务 + thread = noBusyThreads[0]; + thread.queryFunc(name, args, handler, action) + } else { // 随机插入一个线程中 + thread = this.works[Math.floor(Math.random() * this.works.length)] + thread.queryFunc(name, args, handler, action) + } + } + +} + +export const callChainsPool = new PerfCallChainPool() \ No newline at end of file diff --git a/host/ide/src/trace/database/ProcedureWorkerProcess.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerProcess.ts similarity index 46% rename from host/ide/src/trace/database/ProcedureWorkerProcess.ts rename to host/ide/src/trace/database/ui-worker/ProcedureWorkerProcess.ts index 01669edf0aadec9ff2143c76bf87dce618035b36..1e3967b23b5d331a9f123246b551777bf087a9b5 100644 --- a/host/ide/src/trace/database/ProcedureWorkerProcess.ts +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerProcess.ts @@ -13,11 +13,81 @@ * limitations under the License. */ -import {BaseStruct, ColorUtils, ns2x} from "./ProcedureWorkerCommon.js"; +import { ColorUtils } from "../../component/trace/base/ColorUtils.js"; +import { + BaseStruct, + drawFlagLine, + drawLines, + drawLoading, + drawSelection, drawWakeUp, + ns2x, Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; import {CpuStruct} from "./ProcedureWorkerCPU.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; -export function proc(list: Array, res: Set, startNS: number, endNS: number, totalNS: number, frame: any) { - res.clear(); +export class ProcessRender extends Render { + renderMainThread(req: any, row: TraceRow) { + let list = row.dataList; + let filter = row.dataListCache; + proc(list, filter, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, row.frame, req.useCache || !(TraceRow.range!.refresh)); + req.context.beginPath(); + let path = new Path2D(); + let miniHeight: number = 0; + miniHeight = Math.round((row.frame.height - (CpuStruct.cpuCount * 2)) / CpuStruct.cpuCount) + req.context.fillStyle = ColorUtils.colorForTid(req.pid || 0) + for (let re of filter) { + ProcessStruct.draw(req.context, path, re, miniHeight); + } + req.context.fill(path); + req.context.closePath(); + } + + render(req: RequestMessage, list: Array, filter: Array) { + if (req.lazyRefresh) { + proc(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + proc(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startTime, arr[arr.length - 1].startTime + arr[arr.length - 1].dur) + } + req.context.beginPath(); + CpuStruct.cpuCount = req.params.cpuCount; + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + let path = new Path2D(); + let miniHeight: number = 0; + miniHeight = Math.round((req.frame.height - (CpuStruct.cpuCount * 2)) / CpuStruct.cpuCount) + req.context.fillStyle = ColorUtils.colorForTid(req.params.pid || 0) + for (let re of filter) { + ProcessStruct.draw(req.context, path, re, miniHeight); + } + req.context.fill(path); + drawSelection(req.context, req.params); + drawWakeUp(req.context, req.wakeupBean, req.startNS, req.endNS, req.totalNS, req.frame); + req.context.closePath(); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: undefined + }); + } +} +export function proc(list: Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any,use:boolean) { + if(use && res.length > 0){ + res.forEach(it=>ProcessStruct.setProcessFrame(it, 5, startNS || 0, endNS || 0, totalNS || 0, frame)) + return; + } + res.length = 0 ; if (list) { for (let i = 0, len = list.length; i < len; i++) { let it = list[i]; @@ -26,7 +96,7 @@ export function proc(list: Array, res: Set, startNS: number, endNS: nu if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && (list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0))) { } else { - res.add(list[i]) + res.push(list[i]) } } } @@ -49,12 +119,9 @@ export class ProcessStruct extends BaseStruct { type: string | undefined utid: number | undefined - static draw(ctx: CanvasRenderingContext2D, data: ProcessStruct) { + static draw(ctx: CanvasRenderingContext2D,path:Path2D, data: ProcessStruct,miniHeight:number) { if (data.frame) { - let width = data.frame.width || 0; - ctx.fillStyle = ColorUtils.colorForTid(data.pid || 0) - let miniHeight = Math.round(data.frame.height / CpuStruct.cpuCount) - ctx.fillRect(data.frame.x, data.frame.y + (data.cpu || 0) * miniHeight + padding, data.frame.width, miniHeight - padding * 2) + path.rect(data.frame.x, data.frame.y + (data.cpu || 0) * miniHeight + padding, data.frame.width, miniHeight) } } @@ -92,8 +159,8 @@ export class ProcessStruct extends BaseStruct { node.frame = {}; } node.frame.x = Math.floor(x1); - node.frame.y = Math.floor(frame.y + padding); + node.frame.y = Math.floor(frame.y + 2); node.frame.width = Math.ceil(getV); node.frame.height = Math.floor(frame.height - padding * 2); } -} \ No newline at end of file +} diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerSmaps.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerSmaps.ts new file mode 100644 index 0000000000000000000000000000000000000000..f7f310edd492985ade541f361bb58040c191c45e --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerSmaps.ts @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BaseStruct, dataFilterHandler, + drawFlagLine, + drawLines, + drawSelection, isFrameContainPoint, + ns2x, + Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; +import {CpuAbilityMonitorStruct} from "./ProcedureWorkerCpuAbility.js"; + +export class SmapsRender extends Render { + renderMainThread(req: { + context: CanvasRenderingContext2D, + useCache: boolean, + type: string, + rowName:string, + maxValue:number + }, row: TraceRow) { + let list = row.dataList; + let filter = row.dataListCache; + dataFilterHandler(list,filter,{ + startKey: "startNS", + durKey: "dur", + startNS: TraceRow.range?.startNS ?? 0, + endNS: TraceRow.range?.endNS ?? 0, + totalNS: TraceRow.range?.totalNS ?? 0, + frame: row.frame, + paddingTop: 5, + useCache: req.useCache || !(TraceRow.range?.refresh ?? false) + }) + req.context.beginPath(); + let drawColor = "#0A59F7" + if (req.rowName != undefined) { + switch (req.rowName) { + case "dirty": + drawColor = "#0A59F7"; + break; + case "swapper": + drawColor = "#46B1E3"; + break; + case "resident_size": + drawColor = "#564AF7"; + break; + } + } + let find = false; + for (let re of filter) { + SmapsStruct.draw(req.context, re,req.maxValue,drawColor,row.isHover) + if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { + SmapsStruct.hoverSmapsStruct = re; + find = true; + } + } + if (!find && row.isHover) SmapsStruct.hoverSmapsStruct = undefined; + + req.context.closePath(); + } + + render(req: RequestMessage, list: Array, filter: Array) { + if (req.lazyRefresh) { + smaps(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + smaps(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + req.context.beginPath(); + let maxValue = 0; + let maxValueName = ""; + if (req.params.maxValue != undefined || req.params.maxValueName != undefined) { + maxValue = req.params.maxValue; + maxValueName = req.params.maxValueName; + } + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + SmapsStruct.hoverSmapsStruct = undefined; + if (req.isHover) { + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x && req.hoverX <= re.frame.x + re.frame.width && req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height) { + SmapsStruct.hoverSmapsStruct = re; + break; + } + } + } + let drawColor = "#0A59F7" + if (req.params.rowName != undefined) { + switch (req.params.rowName) { + case "dirty": + drawColor = "#0A59F7"; + break; + case "swapper": + drawColor = "#46B1E3"; + break; + case "resident_size": + drawColor = "#564AF7"; + break; + } + } + SmapsStruct.selectSmapsStruct = req.params.selectSmapsStruct; + for (let re of filter) { + SmapsStruct.draw(req.context, re, maxValue, drawColor,true) + } + drawSelection(req.context, req.params); + req.context.closePath(); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: SmapsStruct.hoverSmapsStruct + }); + } +} + +export function smaps(list: Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, use: boolean) { + if (use && res.length > 0) { + for (let i = 0; i < res.length; i++) { + let item = res[i]; + if ((item.startNS || 0) + (item.dur || 0) > (startNS || 0) && (item.startNS || 0) < (endNS || 0)) { + SmapsStruct.setSmapsFrame(item, 5, startNS || 0, endNS || 0, totalNS || 0, frame) + } else { + item.frame = null; + } + } + return; + } + res.length = 0; + if (list) { + for (let index = 0; index < list.length; index++) { + let item = list[index]; + if (index === list.length - 1) { + item.dur = (endNS || 0) - (item.startNS || 0) + } else { + item.dur = (list[index + 1].startNS || 0) - (item.startNS || 0) + } + if ((item.startNS || 0) + (item.dur || 0) > (startNS || 0) && (item.startNS || 0) < (endNS || 0)) { + SmapsStruct.setSmapsFrame(list[index], 5, startNS || 0, endNS || 0, totalNS || 0, frame) + if (index > 0 && ((list[index - 1].frame?.x || 0) == (list[index].frame?.x || 0) && (list[index - 1].frame?.width || 0) == (list[index].frame?.width || 0))) { + + } else { + res.push(item) + } + } + } + } +} + +export class SmapsStruct extends BaseStruct { + static maxValue: number = 0 + static maxValueName: string = "0 KB/S" + static hoverSmapsStruct: SmapsStruct | undefined; + static selectSmapsStruct: SmapsStruct | undefined; + value: number | undefined + startNS: number | undefined + dur: number | undefined + + static draw(context2D: CanvasRenderingContext2D, data: SmapsStruct, maxValue: number, drawColor: string,isHover:boolean) { + if (data.frame) { + let width = data.frame.width || 0; + context2D.fillStyle = drawColor + context2D.strokeStyle = drawColor + if (data.startNS === SmapsStruct.hoverSmapsStruct?.startNS&&isHover) { + context2D.lineWidth = 1; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / maxValue); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, width, drawHeight) + context2D.beginPath() + context2D.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, 3, 0, 2 * Math.PI, true) + context2D.fill() + context2D.globalAlpha = 1.0; + context2D.stroke(); + context2D.beginPath() + context2D.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight + 4); + context2D.lineWidth = 3; + context2D.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight + 4) + context2D.stroke(); + } else { + context2D.lineWidth = 1; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0)) / maxValue); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, width, drawHeight) + } + } + context2D.globalAlpha = 1.0; + context2D.lineWidth = 1; + } + + static setSmapsFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { + let startPointX: number, endPointX: number + + if ((node.startNS || 0) < startNS) { + startPointX = 0 + } else { + startPointX = ns2x((node.startNS || 0), startNS, endNS, totalNS, frame); + } + if ((node.startNS || 0) + (node.dur || 0) > endNS) { + endPointX = frame.width; + } else { + endPointX = ns2x((node.startNS || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); + } + let frameWidth: number = endPointX - startPointX <= 1 ? 1 : endPointX - startPointX; + if (!node.frame) { + node.frame = {}; + } + node.frame.x = Math.floor(startPointX); + node.frame.y = frame.y + padding; + node.frame.width = Math.ceil(frameWidth); + node.frame.height = Math.floor(frame.height - padding * 2); + } +} \ No newline at end of file diff --git a/host/ide/src/trace/database/ProcedureWorkerThread.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerThread.ts similarity index 80% rename from host/ide/src/trace/database/ProcedureWorkerThread.ts rename to host/ide/src/trace/database/ui-worker/ProcedureWorkerThread.ts index a285e7982af4cc05018df8adf1d568b3e25980b9..c41affda7a55cdb3bee85fbbf858222eca1dc2e0 100644 --- a/host/ide/src/trace/database/ProcedureWorkerThread.ts +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerThread.ts @@ -13,25 +13,49 @@ * limitations under the License. */ -import {BaseStruct, ns2x, Rect} from "./ProcedureWorkerCommon.js"; +import { + BaseStruct, dataFilterHandler, + isFrameContainPoint, + Rect, Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; -export function thread(list: Array, res: Set, startNS: number, endNS: number, totalNS: number, frame: any) { - res.clear(); - if (list) { - for (let i = 0, len = list.length; i < len; i++) { - let it = list[i]; - if ((it.startTime || 0) + (it.dur || 0) > startNS && (it.startTime || 0) < endNS) { - ThreadStruct.setThreadFrame(list[i], 5, startNS, endNS, totalNS, frame) - if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && (list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0))) { - - } else { - res.add(list[i]) - } +export class ThreadRender extends Render { + renderMainThread(req: { + context: CanvasRenderingContext2D, + useCache: boolean, + type: string, + }, row: TraceRow) { + let list = row.dataList; + let filter = row.dataListCache; + // thread(list, filter, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, row.frame, req.useCache || !(TraceRow.range!.refresh)); + dataFilterHandler(list,filter,{ + startKey: "startTime", + durKey: "dur", + startNS: TraceRow.range?.startNS ?? 0, + endNS: TraceRow.range?.endNS ?? 0, + totalNS: TraceRow.range?.totalNS ?? 0, + frame: row.frame, + paddingTop: 5, + useCache: req.useCache || !(TraceRow.range?.refresh ?? false) + }) + req.context.beginPath(); + for (let re of filter) { + ThreadStruct.draw(req.context, re) + if (row.isHover && re.frame && isFrameContainPoint(re.frame!,row.hoverX,row.hoverY)) { + ThreadStruct.hoverThreadStruct = re; } } + req.context.closePath(); + } + + render(req: RequestMessage, list: Array, filter: Array) { + } } + const padding = 3; export class ThreadStruct extends BaseStruct { @@ -78,29 +102,6 @@ export class ThreadStruct extends BaseStruct { state: string | undefined // "S" type: string | undefined // "thread" - static setThreadFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { - let x1: number; - let x2: number; - if ((node.startTime || 0) < startNS) { - x1 = 0; - } else { - x1 = ns2x((node.startTime || 0), startNS, endNS, totalNS, frame); - } - if ((node.startTime || 0) + (node.dur || 0) > endNS) { - x2 = frame.width; - } else { - x2 = ns2x((node.startTime || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); - } - let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1; - if (!node.frame) { - node.frame = {}; - } - node.frame.x = Math.floor(x1); - node.frame.y = frame.y + padding; - node.frame.width = Math.ceil(getV); - node.frame.height = 30 - padding * 2; - } - static draw(ctx: CanvasRenderingContext2D, data: ThreadStruct) { if (data.frame) { ctx.globalAlpha = 1 @@ -125,7 +126,7 @@ export class ThreadStruct extends BaseStruct { ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) ctx.fillStyle = "#fff"; data.frame.width > 4 && ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame); - } else if("T" == data.state || "t" == data.state) { + } else if ("T" == data.state || "t" == data.state) { ctx.fillStyle = ThreadStruct.traceColor; ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) ctx.fillStyle = "#fff"; diff --git a/host/ide/src/trace/database/ProcedureWorkerTimeline.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerTimeline.ts similarity index 95% rename from host/ide/src/trace/database/ProcedureWorkerTimeline.ts rename to host/ide/src/trace/database/ui-worker/ProcedureWorkerTimeline.ts index 4d9d47d50b62343664fea0303967cf35b5a69d87..b830fb358b8b4a3a83097797c1daf2659a0cb99f 100644 --- a/host/ide/src/trace/database/ProcedureWorkerTimeline.ts +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerTimeline.ts @@ -13,9 +13,10 @@ * limitations under the License. */ -import {ns2s, Rect} from "./ProcedureWorkerCommon.js"; -import {CpuStruct} from "../bean/CpuStruct.js"; -import {ColorUtils} from "../component/trace/base/ColorUtils.js"; +import {ns2s, Rect, Render, RequestMessage} from "./ProcedureWorkerCommon.js"; +import {ColorUtils} from "../../component/trace/base/ColorUtils.js"; +import { TraceRow } from "../../component/trace/base/TraceRow.js"; +import {CpuStruct} from "./ProcedureWorkerCPU.js"; //绘制时间轴 let timeRuler: TimeRuler | undefined; @@ -24,6 +25,33 @@ let sportRuler: SportRuler | undefined; let offsetTop: number = 0; let offsetLeft: number = 0; +export class TimelineRender extends Render{ + renderMainThread(req: any, row: TraceRow) { + } + render(req: RequestMessage, list: Array, filter: Array){ + timeline(req.canvas, req.context, req.startNS, req.endNS, req.totalNS, req.frame, + req.params.keyPressCode, req.params.keyUpCode, + req.params.mouseDown, req.params.mouseUp, + req.params.mouseMove, req.params.mouseOut, + req.params.offsetLeft, req.params.offsetTop, + (a: any) => { + //@ts-ignore + self.postMessage({ + id: "timeline", + type: "timeline-range-changed", + results: a, + }); + } + ); + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: null, + }); + } +} + // @ts-ignore export function timeline(canvas: OffscreenCanvas, ctx: OffscreenCanvasRenderingContext2D, startNS: number, endNS: number, totalNS: number, frame: Rect, keyPressCode: any, keyUpCode: any, mouseDown: any, mouseUp: any, mouseMove: any, mouseOut: any, _offsetLeft: number, _offsetTop: number, changeHandler: Function) { offsetLeft = _offsetLeft; diff --git a/host/ide/src/trace/database/ui-worker/ProcedureWorkerVirtualMemory.ts b/host/ide/src/trace/database/ui-worker/ProcedureWorkerVirtualMemory.ts new file mode 100644 index 0000000000000000000000000000000000000000..80c30c63bf7403281666b659bd5b10fe0cd80b72 --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProcedureWorkerVirtualMemory.ts @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ColorUtils } from "../../component/trace/base/ColorUtils.js"; +import { + BaseStruct, + drawFlagLine, + drawLines, + drawLoading, + drawSelection, drawWakeUp, isFrameContainPoint, + ns2x, Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; + +export class VirtualMemoryRender extends Render { + renderMainThread(req: { + context: CanvasRenderingContext2D, + useCache: boolean, + type: string, + }, row:TraceRow) { + mem(row.dataList, row.dataListCache, TraceRow.range?.startNS || 0, TraceRow.range?.endNS || 0, TraceRow.range?.totalNS || 0, row.frame, req.useCache || (TraceRow.range?.refresh ?? false)); + req.context.beginPath(); + let find = false; + for (let re of row.dataListCache) { + if (row.isHover && re.frame && isFrameContainPoint(re.frame,row.hoverX,row.hoverY)) { + VirtualMemoryStruct.hoverStruct = re; + find = true; + } + VirtualMemoryStruct.draw(req.context, re) + } + if(!find && row.isHover) VirtualMemoryStruct.hoverStruct = undefined; + req.context.closePath(); + } + + render(req: RequestMessage, list: Array, filter: Array) { + if (req.lazyRefresh) { + mem(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + mem(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startTime, arr[arr.length - 1].startTime + arr[arr.length - 1].dur) + } + req.context.beginPath(); + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + VirtualMemoryStruct.hoverStruct = undefined; + if (req.isHover) { + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x && req.hoverX <= re.frame.x + re.frame.width && req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height) { + VirtualMemoryStruct.hoverStruct = re; + break; + } + } + } else { + VirtualMemoryStruct.hoverStruct = req.params.hoverStruct; + } + for (let re of filter) { + VirtualMemoryStruct.draw(req.context, re) + } + drawSelection(req.context, req.params); + drawWakeUp(req.context, req.wakeupBean, req.startNS, req.endNS, req.totalNS, req.frame); + req.context.closePath(); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: VirtualMemoryStruct.hoverStruct + }); + } +} + +function setMemFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { + let x1: number; + let x2: number; + if ((node.startTime || 0) <= startNS) { + x1 = 0; + } else { + x1 = ns2x((node.startTime || 0), startNS, endNS, totalNS, frame); + } + if ((node.startTime || 0) + (node.duration || 0) >= endNS) { + x2 = frame.width; + } else { + x2 = ns2x((node.startTime || 0) + (node.duration || 0), startNS, endNS, totalNS, frame); + } + let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1; + if (!node.frame) { + node.frame = {}; + } + node.frame.x = Math.floor(x1); + node.frame.y = Math.floor(frame.y + padding); + node.frame.width = Math.ceil(getV); + node.frame.height = Math.floor(frame.height - padding * 2); +} + +export function mem(list: Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, use: boolean) { + if (use && res.length > 0) { + for (let i = 0, len = res.length; i < len; i++) { + if ((res[i].startTime || 0) + (res[i].duration || 0) > startNS && (res[i].startTime || 0) < endNS) { + setMemFrame(res[i], 5, startNS, endNS, totalNS, frame) + } else { + res[i].frame = null; + } + } + return; + } + res.length = 0; + if (list) { + for (let i = 0, len = list.length; i < len; i++) { + let it = list[i]; + if ((it.startTime || 0) + (it.duration || 0) > startNS && (it.startTime || 0) < endNS) { + setMemFrame(list[i], 5, startNS, endNS, totalNS, frame) + if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && (list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0))) { + + } else { + res.push(list[i]) + } + } + } + } +} + +export class VirtualMemoryStruct extends BaseStruct { + static hoverStruct: VirtualMemoryStruct | undefined; + filterID: number | undefined + value: number | undefined + startTime: number | undefined + duration: number | undefined + maxValue: number | undefined + delta: number | undefined; + + static draw(ctx: CanvasRenderingContext2D, data: VirtualMemoryStruct) { + if (data.frame) { + let width = data.frame.width || 0; + ctx.fillStyle = ColorUtils.colorForTid(data.maxValue || 0) + ctx.strokeStyle = ColorUtils.colorForTid(data.maxValue || 0) + if (data === VirtualMemoryStruct.hoverStruct) { + ctx.lineWidth = 1; + ctx.globalAlpha = 0.6; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / (data.maxValue || 1)); + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + ctx.beginPath() + ctx.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight, 3, 0, 2 * Math.PI, true) + ctx.fill() + ctx.globalAlpha = 1.0; + ctx.stroke(); + ctx.beginPath() + ctx.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight); + ctx.lineWidth = 3; + ctx.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight) + ctx.stroke(); + } else { + ctx.globalAlpha = 0.6; + ctx.lineWidth = 1; + let drawHeight: number = ((data.value || 0) * (data.frame.height || 0) * 1.0) / (data.maxValue || 1); + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + } + } + ctx.globalAlpha = 1.0; + ctx.lineWidth = 1; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/database/ui-worker/ProduceWorkerSdkCounter.ts b/host/ide/src/trace/database/ui-worker/ProduceWorkerSdkCounter.ts new file mode 100644 index 0000000000000000000000000000000000000000..5928b9eb25641c2e3be04c4130b322df0afce9c5 --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProduceWorkerSdkCounter.ts @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BaseStruct, + drawFlagLine, + drawLines, + drawLoading, + drawSelection, + drawWakeUp, isFrameContainPoint, + ns2x, + Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; + +export class SdkCounterRender extends Render { + renderMainThread(req: { + context: CanvasRenderingContext2D, + useCache: boolean, + type: string, + maxName:string, + maxValue:number + }, row : TraceRow) { + let list= row.dataList; + let filter = row.dataListCache; + let maxCounter = req.maxValue; + let maxCounterName = req.maxName; + this.counter(list, filter, TraceRow.range?.startNS ?? 0, TraceRow.range?.endNS ?? 0, TraceRow.range?.totalNS ?? 0, row.frame,req.useCache || (TraceRow.range?.refresh ?? false)); + req.context.beginPath(); + let find = false; + for (let re of filter) { + if (row.isHover && re.frame && isFrameContainPoint(re.frame,row.hoverX,row.hoverY)) {//&& req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height + CounterStruct.hoverCounterStruct = re; + find = true; + } + CounterStruct.draw(req.context, re, maxCounter) + } + if(!find && row.isHover) CounterStruct.hoverCounterStruct = undefined; + req.context.closePath(); + let textMetrics = req.context.measureText(maxCounterName); + req.context.globalAlpha = 0.8 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(maxCounterName, 4, 5 + 9) + } + + render(req: RequestMessage, list: Array, filter: Array) { + if (req.lazyRefresh) { + this.counter(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + this.counter(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.frame.width, req.frame.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startNS, arr[arr.length - 1].startNS + arr[arr.length - 1].dur) + } + req.context.beginPath(); + let maxCounter = req.params.maxCounter; + let maxCounterName = req.params.maxCounterName; + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + CounterStruct.hoverCounterStruct = undefined; + if (req.isHover) { + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x && req.hoverX <= re.frame.x + re.frame.width && req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height) { + CounterStruct.hoverCounterStruct = re; + break; + } + } + } + CounterStruct.selectCounterStruct = req.params.selectCounterStruct; + for (let re of filter) { + CounterStruct.draw(req.context, re, maxCounter) + } + drawSelection(req.context, req.params); + req.context.closePath(); + let textMetrics = req.context.measureText(maxCounterName); + req.context.globalAlpha = 0.8 + req.context.fillStyle = "#f0f0f0" + req.context.fillRect(0, 5, textMetrics.width + 8, 18) + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + req.context.fillText(maxCounterName, 4, 5 + 9) + drawWakeUp(req.context, req.wakeupBean, req.startNS, req.endNS, req.totalNS, req.frame); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: CounterStruct.hoverCounterStruct + }); + } + + counter(list: Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, use: boolean) { + if (use && res.length > 0) { + for (let index = 0; index < res.length; index++) { + let item = res[index]; + if ((item.ts || 0) + (item.dur || 0) > (startNS || 0) && (item.ts || 0) < (endNS || 0)) { + CounterStruct.setCounterFrame(res[index], 5, startNS || 0, endNS || 0, totalNS || 0, frame) + } else { + res[index].frame = null; + } + } + return; + } + res.length = 0; + if (list) { + for (let index = 0; index < list.length; index++) { + let item = list[index]; + if (index === list.length - 1) { + item.dur = (endNS || 0) - (item.ts || 0) + } else { + item.dur = (list[index + 1].ts || 0) - (item.ts || 0) + } + if ((item.ts || 0) + (item.dur || 0) > (startNS || 0) && (item.ts || 0) < (endNS || 0)) { + CounterStruct.setCounterFrame(list[index], 5, startNS || 0, endNS || 0, totalNS || 0, frame) + if (index > 0 && ((list[index - 1].frame?.x || 0) == (list[index].frame?.x || 0) && (list[index - 1].frame?.width || 0) == (list[index].frame?.width || 0))) { + + } else { + res.push(item) + } + } + } + } + } +} + + +export class CounterStruct extends BaseStruct { + static maxCounter: number = 0 + static maxCounterName: string = "" + static hoverCounterStruct: CounterStruct | undefined; + static selectCounterStruct: CounterStruct | undefined; + + value: number | undefined + ts: number | undefined + counter_id: number | undefined + + + static draw(context2D: CanvasRenderingContext2D, data: CounterStruct, maxCounter: number) { + if (data.frame) { + let width = data.frame.width || 0; + context2D.fillStyle = "#67B0FC" + context2D.strokeStyle = "#67B0FC" + if (data.ts === CounterStruct.hoverCounterStruct?.ts) { + context2D.lineWidth = 1; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / maxCounter); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, width, drawHeight) + context2D.beginPath() + context2D.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, 3, 0, 2 * Math.PI, true) + context2D.fill() + context2D.globalAlpha = 1.0; + context2D.stroke(); + context2D.beginPath() + context2D.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight + 4); + context2D.lineWidth = 3; + context2D.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight + 4) + context2D.stroke(); + } else { + context2D.lineWidth = 1; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0)) / maxCounter); + context2D.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, width, drawHeight) + } + } + context2D.globalAlpha = 1.0; + context2D.lineWidth = 1; + } + + static setCounterFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { + let startPointX: number, endPointX: number + + if ((node.ts || 0) < startNS) { + startPointX = 0 + } else { + startPointX = ns2x((node.ts || 0), startNS, endNS, totalNS, frame); + } + if ((node.ts || 0) + (node.dur || 0) > endNS) { + endPointX = frame.width; + } else { + endPointX = ns2x((node.ts || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); + } + let frameWidth: number = endPointX - startPointX <= 1 ? 1 : endPointX - startPointX; + if (!node.frame) { + node.frame = {}; + } + node.frame.x = Math.floor(startPointX); + node.frame.y = frame.y + padding; + node.frame.width = Math.ceil(frameWidth); + node.frame.height = Math.floor(frame.height - padding * 2); + } +} diff --git a/host/ide/src/trace/database/ui-worker/ProduceWorkerSdkSlice.ts b/host/ide/src/trace/database/ui-worker/ProduceWorkerSdkSlice.ts new file mode 100644 index 0000000000000000000000000000000000000000..5e093ed40cce4e197e80f91c57247d593d7a689d --- /dev/null +++ b/host/ide/src/trace/database/ui-worker/ProduceWorkerSdkSlice.ts @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BaseStruct, + drawFlagLine, + drawLines, + drawLoading, + drawSelection, + drawWakeUp, isFrameContainPoint, + ns2x, + Render, + RequestMessage +} from "./ProcedureWorkerCommon.js"; +import {TraceRow} from "../../component/trace/base/TraceRow.js"; +import {CounterStruct} from "./ProduceWorkerSdkCounter.js"; + +export class SdkSliceRender extends Render { + renderMainThread(req: { + context: CanvasRenderingContext2D, + useCache: boolean, + type: string, + maxName:string, + maxValue:number + }, row : TraceRow) { + let list= row.dataList; + let filter = row.dataListCache; + SdkSliceStruct.maxSdkSlice = req.maxValue; + SdkSliceStruct.maxSdkSliceName = req.maxName; + this.sdkSlice(list, filter, TraceRow.range?.startNS ?? 0, TraceRow.range?.endNS ?? 0, TraceRow.range?.totalNS ?? 0, row.frame,req.useCache || (TraceRow.range?.refresh ?? false)); + req.context.beginPath(); + let find = false; + for (let re of filter) { + if (row.isHover && re.frame && isFrameContainPoint(re.frame,row.hoverX,row.hoverY)) {//&& req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height + SdkSliceStruct.hoverSdkSliceStruct = re; + find = true; + } + SdkSliceStruct.draw(req.context, re) + + } + if(!find && row.isHover) SdkSliceStruct.hoverSdkSliceStruct = undefined; + req.context.closePath(); + } + + render(req: RequestMessage, list: Array, filter: Array) { + if (req.lazyRefresh) { + this.sdkSlice(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.useCache || !req.range.refresh); + } else { + if (!req.useCache) { + this.sdkSlice(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, false); + } + } + if (req.canvas) { + req.context.clearRect(0, 0, req.canvas.width, req.canvas.height); + let arr = filter; + if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) { + drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startNS, arr[arr.length - 1].startNS + arr[arr.length - 1].dur) + } + req.context.beginPath(); + SdkSliceStruct.maxSdkSlice = req.params.maxSdkSlice; + SdkSliceStruct.maxSdkSliceName = req.params.maxSdkSliceName; + drawLines(req.context, req.xs, req.frame.height, req.lineColor) + SdkSliceStruct.hoverSdkSliceStruct = undefined; + if (req.isHover) { + for (let re of filter) { + if (re.frame && req.hoverX >= re.frame.x && req.hoverX <= re.frame.x + re.frame.width && req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height) { + SdkSliceStruct.hoverSdkSliceStruct = re; + break; + } + } + } + SdkSliceStruct.selectSdkSliceStruct = req.params.selectSdkSliceStruct; + for (let re of filter) { + SdkSliceStruct.draw(req.context, re) + } + drawSelection(req.context, req.params); + req.context.closePath(); + req.context.globalAlpha = 0.8 + req.context.fillStyle = "#f0f0f0" + req.context.globalAlpha = 1 + req.context.fillStyle = "#333" + req.context.textBaseline = "middle" + drawWakeUp(req.context, req.wakeupBean, req.startNS, req.endNS, req.totalNS, req.frame); + drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime); + } + // @ts-ignore + self.postMessage({ + id: req.id, + type: req.type, + results: req.canvas ? undefined : filter, + hover: SdkSliceStruct.hoverSdkSliceStruct + }); + } + + sdkSlice(list: Array, res: Array, startNS: number, endNS: number, totalNS: number, frame: any, use: boolean) { + if (use && res.length > 0) { + for (let index = 0; index < res.length; index++) { + let item = res[index]; + if ((item.end_ts || 0) > (startNS || 0) && (item.start_ts || 0) < (endNS || 0)) { + SdkSliceStruct.setSdkSliceFrame(res[index], 5, startNS || 0, endNS || 0, totalNS || 0, frame) + } else { + res[index].frame = null; + } + } + return; + } + res.length = 0; + if (list) { + for (let index = 0; index < list.length; index++) { + let item = list[index]; + if (item.start_ts >= startNS && item.end_ts == 0) { + item.end_ts = endNS; + } + if ((item.end_ts || 0) > (startNS || 0) && (item.start_ts || 0) < (endNS || 0)) { + SdkSliceStruct.setSdkSliceFrame(list[index], 5, startNS || 0, endNS || 0, totalNS || 0, frame) + if (index > 0 && ((list[index - 1].frame?.x || 0) == (list[index].frame?.x || 0) && (list[index - 1].frame?.width || 0) == (list[index].frame?.width || 0))) { + + } else { + res.push(item) + } + } + } + } + } +} + +export class SdkSliceStruct extends BaseStruct { + static maxSdkSlice: number = 0 + static maxSdkSliceName: string = "" + static hoverSdkSliceStruct: SdkSliceStruct | undefined; + static selectSdkSliceStruct: SdkSliceStruct | undefined; + + start_ts: number | undefined + end_ts: number | undefined + + value: number | undefined + slice_message: string | undefined + + static draw(ctx: CanvasRenderingContext2D, data: SdkSliceStruct) { + if (data.frame) { + let width = data.frame.width || 0; + let index = 4; + ctx.fillStyle = "#6DC0DC" + ctx.strokeStyle = "#6DC0DC" + if (data.start_ts === SdkSliceStruct.hoverSdkSliceStruct?.start_ts) { + ctx.lineWidth = 1; + ctx.fillRect(data.frame.x, data.frame.y + 4, width, data.frame.height - 10) + ctx.beginPath() + ctx.arc(data.frame.x, data.frame.y + 4, 3, 0, 2 * Math.PI, true) + ctx.fill() + ctx.globalAlpha = 1.0; + ctx.stroke(); + ctx.beginPath() + ctx.moveTo(data.frame.x + 3, data.frame.y + 4); + ctx.lineWidth = 3; + ctx.lineTo(data.frame.x + width, data.frame.y + 4) + ctx.stroke(); + } else { + ctx.lineWidth = 1; + ctx.fillRect(data.frame.x, data.frame.y + 4, width, data.frame.height - 10) + } + } + } + + static setSdkSliceFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { + let startPointX: number, endPointX: number + + if ((node.start_ts || 0) < startNS) { + startPointX = 0 + } else { + startPointX = ns2x((node.start_ts || 0), startNS, endNS, totalNS, frame); + } + if ((node.end_ts || 0) > endNS) { + endPointX = frame.width; + } else { + endPointX = ns2x((node.end_ts || 0), startNS, endNS, totalNS, frame); + } + let frameWidth: number = endPointX - startPointX <= 1 ? 1 : endPointX - startPointX; + if (!node.frame) { + node.frame = {}; + } + node.frame.x = Math.floor(startPointX); + node.frame.y = frame.y + padding; + node.frame.width = Math.ceil(frameWidth); + node.frame.height = Math.floor(frame.height - padding * 2); + } + +} diff --git a/host/ide/src/trace/grpc/HiProfilerClient.ts b/host/ide/src/trace/grpc/HiProfilerClient.ts index c4bbdb0672dee199ec09b4ac0285b01da95362fa..2375eca41581eaea6e27cba3e28dbede335414c6 100644 --- a/host/ide/src/trace/grpc/HiProfilerClient.ts +++ b/host/ide/src/trace/grpc/HiProfilerClient.ts @@ -12,12 +12,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import {Address, ProfilerClient} from "./ProfilerClient.js"; export class HiProfilerClient { private _client: ProfilerClient; private _address: Address; + public constructor(clients: ProfilerClient, addr: Address) { + this._client = clients; + this._address = addr; + }; + get client(): ProfilerClient { return this._client; } @@ -34,13 +40,8 @@ export class HiProfilerClient { this._address = value; } - public constructor(clients: ProfilerClient, addr: Address) { - this._client = clients; - this._address = addr; - }; - - public getProfilerClient(): ProfilerClient{ - return this._client; + public getProfilerClient(): ProfilerClient { + return this._client; } public getCapabilities() { diff --git a/host/ide/src/trace/grpc/ProfilerClient.ts b/host/ide/src/trace/grpc/ProfilerClient.ts index 73f01998fa2ae0acd0723ca47055d33d614c2060..25038dc82d17cdf214a31591ec51145fc461263f 100644 --- a/host/ide/src/trace/grpc/ProfilerClient.ts +++ b/host/ide/src/trace/grpc/ProfilerClient.ts @@ -12,122 +12,107 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import * as path from 'path'; -const profilerServicePath = path.join(__dirname,'../proto', 'profiler_service.proto'); +const profilerServicePath = path.join(__dirname, '../proto', 'profiler_service.proto'); export class ProfilerClient { - // proto filePaths - private _filePaths: Array | undefined; - // client - private _client: any; - // profiler_proto - private _profiler_proto: any; - // ProfilerClient constructor - public constructor(address: Address) { - // load client port - let clientPort = this.loadAddress(address); - // load proto file - this.start(clientPort, profilerServicePath); - }; - - get filePaths(): Array | undefined { - return this._filePaths; - } - - set filePaths(value: Array | undefined) { - this._filePaths = value; - } - - get client(): any { - return this._client; - } - - set client(value: any) { - this._client = value; - } - - get profiler_proto(): any { - return this._profiler_proto; - } - - set profiler_proto(value: any) { - this._profiler_proto = value; - } - - start(address: string, filePath: string){ - // let loadPackage = proto_load.loadSync( - // filePath, - // { - // keepCase: true, - // longs: String, - // enums: String, - // defaults: true, - // oneofs: true - // } - // ); - // // profiler Proto - // this._profiler_proto = rpc.loadPackageDefinition(loadPackage); - // // get profilerProto service - // let profilerProto = this._profiler_proto.profiler; - // // client - // this._client = new profilerProto.IProfilerService('127.0.0.1:5555', rpc.credentials.createInsecure()); - } - - // Address - loadAddress(clientAddress: Address): string{ - return clientAddress.host + ':' + clientAddress.port; - }; - - public getProfilerClient(callback: any): any{ - return this._client; - }; - - public getCapabilities(callback: any) { - this._client. - this._client.getCapabilities(callback); - callback(); - }; - - public createSession(callback: any) { - this._client.createSession(callback); - callback(); - }; - - public startSession(callback: any) { - this._client.startSession(callback); - callback(); - }; - - public stopSession(callback: any) { - this._client.stopSession(callback); - callback(); - }; - - public destroySession(callback: any) { - this._client.destroySession(callback); - callback(); - }; - - public keepSession(callback: any) { - this._client.keepSession(callback); - callback(); - }; - - public shutdown(): void { - - }; - - public getChannel() { - return this._client.channelInterpretation; - }; + // proto filePaths + private _filePaths: Array | undefined; + // client + private _client: any; + // profiler_proto + private _profiler_proto: any; + + // ProfilerClient constructor + public constructor(address: Address) { + // load client port + let clientPort = this.loadAddress(address); + // load proto file + this.start(clientPort, profilerServicePath); + }; + + get filePaths(): Array | undefined { + return this._filePaths; + } + + set filePaths(value: Array | undefined) { + this._filePaths = value; + } + + get client(): any { + return this._client; + } + + set client(value: any) { + this._client = value; + } + + get profiler_proto(): any { + return this._profiler_proto; + } + + set profiler_proto(value: any) { + this._profiler_proto = value; + } + + start(address: string, filePath: string) { + } + + // Address + loadAddress(clientAddress: Address): string { + return clientAddress.host + ':' + clientAddress.port; + }; + + public getProfilerClient(callback: any): any { + return this._client; + }; + + public getCapabilities(callback: any) { + this._client.this._client.getCapabilities(callback); + callback(); + }; + + public createSession(callback: any) { + this._client.createSession(callback); + callback(); + }; + + public startSession(callback: any) { + this._client.startSession(callback); + callback(); + }; + + public stopSession(callback: any) { + this._client.stopSession(callback); + callback(); + }; + + public destroySession(callback: any) { + this._client.destroySession(callback); + callback(); + }; + + public keepSession(callback: any) { + this._client.keepSession(callback); + callback(); + }; + + public shutdown(): void { + + }; + + public getChannel() { + return this._client.channelInterpretation; + }; } export interface Address { - // port - port: string | number; + // port + port: string | number; - // host - host?: string | number; + // host + host?: string | number; } diff --git a/host/ide/src/trace/grpc/ProfilerController.ts b/host/ide/src/trace/grpc/ProfilerController.ts index bbc186a0c4b0dcccbba554244a326c6db99b5c85..941709da605d862edc504226b5277aa4b7e1c725 100644 --- a/host/ide/src/trace/grpc/ProfilerController.ts +++ b/host/ide/src/trace/grpc/ProfilerController.ts @@ -12,28 +12,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + export class ClientContainer { - // private _credentials: rpc.ChannelCredentials | undefined; - // private _clients: { service: any, client?: rpc.Client, target: any }[] = []; private _port: string | number | undefined; private _host: string | undefined; - /* get clients(): { service: any; client?: rpc.Client; target: any }[] { - return this._clients; - } - - set clients(value: { service: any; client?: rpc.Client; target: any }[]) { - this._clients = value; - }*/ - - /* get credentials(): rpc.ChannelCredentials | undefined { - return this._credentials; - } - - set credentials(value: rpc.ChannelCredentials | undefined) { - this._credentials = value; - }*/ - get port(): string | number | undefined { return this._port; } @@ -51,21 +34,6 @@ export class ClientContainer { } public registryClient(target: any, path: string) { - // let packageDefinition = proto_load.loadSync(path, { - // keepCase: true, - // longs: String, - // enums: String, - // defaults: true, - // oneofs: true - // }); - // let protoDescriptor = rpc.loadPackageDefinition(packageDefinition); - // - // const packages = Object.keys(protoDescriptor); - // for (let packageKey of packages) { - // for (let key in protoDescriptor[packageKey]) { - // - // } - // } }; public start() { @@ -74,23 +42,15 @@ export class ClientContainer { } private loadSettings() { - let { host, port} = SettingRegistry.settings; + let {host, port} = SettingRegistry.settings; this._host = host; this._port = port; } private _registryClient() { - // for (let clientContainer of this._clients) { - // let client: rpc.Client = new clientContainer.service( - // `${this.host}:${this.port}`, - // this.credentials - // ); - // clientContainer.client = client; - // } } } - export class SettingRegistry { static settings: Settings; diff --git a/host/ide/test/base-ui/button/LitButton.test.ts b/host/ide/test/base-ui/button/LitButton.test.ts index cf05686eba2d3082e14fc1d6d32c604c0dcc49b8..b9e577f267a7f75b0ff792878d970b37a53e8649 100644 --- a/host/ide/test/base-ui/button/LitButton.test.ts +++ b/host/ide/test/base-ui/button/LitButton.test.ts @@ -22,4 +22,69 @@ describe('button Test', ()=>{ let litButton = new LitButton(); expect(litButton).not.toBeUndefined() }); + it('buttonTest02', function () { + let litButton = new LitButton(); + litButton.text =" " + expect(litButton.text).toBe(" ") + }); + it('buttonTest03', function () { + let litButton = new LitButton(); + litButton.text = "test" + expect(litButton.text).toBe("test") + }); + it('buttonTest04', function () { + let litButton = new LitButton(); + litButton.back = "test" + expect(litButton.back).toBe("test") + }); + it('buttonTest05', function () { + let litButton = new LitButton(); + litButton.icon = "test" + expect(litButton.icon).toBe("test") + }); + it('buttonTest06', function () { + let litButton = new LitButton(); + litButton.height = "test" + expect(litButton.height).toBe("test") + }); + it('buttonTest07', function () { + let litButton = new LitButton(); + litButton.width = "test" + expect(litButton.width).toBe("test") + }); + it('buttonTest08', function () { + let litButton = new LitButton(); + litButton.color = "test" + expect(litButton.color).toBeUndefined() + }); + it('buttonTest09', function () { + let litButton = new LitButton(); + litButton.font_size = "test" + expect(litButton.font_size).toBeUndefined() + }); + it('buttonTest10', function () { + let litButton = new LitButton(); + litButton.border = "test" + expect(litButton.border).toBeUndefined() + }); + it('buttonTest11', function () { + let litButton = new LitButton(); + litButton.padding = "test" + expect(litButton.padding).toBeUndefined() + }); + it('buttonTest12', function () { + let litButton = new LitButton(); + litButton.justify_content = "test" + expect(litButton.justify_content).toBeUndefined() + }); + it('buttonTest13', function () { + let litButton = new LitButton(); + litButton.border_radius = "test" + expect(litButton.border_radius).toBeUndefined() + }); + it('buttonTest14', function () { + let litButton = new LitButton(); + litButton.margin_icon = "test" + expect(litButton.margin_icon).toBeUndefined() + }); }) diff --git a/host/ide/test/base-ui/checkbox/LitCheckBox.test.ts b/host/ide/test/base-ui/checkbox/LitCheckBox.test.ts index 3512ce08425f9a10ee6a9330ff3b4779a247025e..79972fbf76e65e5c0b05dcac410ad544a18db408 100644 --- a/host/ide/test/base-ui/checkbox/LitCheckBox.test.ts +++ b/host/ide/test/base-ui/checkbox/LitCheckBox.test.ts @@ -57,4 +57,105 @@ describe('checkBox Test', ()=>{ litCheckBox.checked = false expect(litCheckBox.checked).toBeFalsy(); }); + it('checkBoxTest06', function () { + document.body.innerHTML = ` + ` + let litCheckBox = new LitCheckBox(); + litCheckBox.indeterminate = false + expect(litCheckBox.indeterminate).toBeFalsy(); + }); + + it('checkBoxTest07', function () { + document.body.innerHTML = ` + ` + let litCheckBox = new LitCheckBox(); + litCheckBox.indeterminate = true + expect(litCheckBox.indeterminate).toBeTruthy(); + }); + + it('checkBoxTest08', function () { + let litCheckBox = new LitCheckBox(); + expect(litCheckBox.initHtml()).toMatchInlineSnapshot(` +" + + + + " +`); + }); }) \ No newline at end of file diff --git a/host/ide/test/base-ui/checkbox/LitCheckBoxWithText.test.ts b/host/ide/test/base-ui/checkbox/LitCheckBoxWithText.test.ts index 271b2437f6cf61c15a193536602f04da7df598dc..5d4b5bb400a70db954770f90e7a84683326add04 100644 --- a/host/ide/test/base-ui/checkbox/LitCheckBoxWithText.test.ts +++ b/host/ide/test/base-ui/checkbox/LitCheckBoxWithText.test.ts @@ -55,18 +55,65 @@ describe('checkBoxWithText Test', ()=>{ it('checkBoxWithTextTest05', function () { let litCheckBoxWithText = new LitCheckBoxWithText(); - expect(litCheckBoxWithText.lowerlimit).toEqual(undefined); + expect(litCheckBoxWithText.lowerLimit).toEqual("0"); }); it('checkBoxWithTextTest05', function () { let litCheckBoxWithText = new LitCheckBoxWithText(); - litCheckBoxWithText.lowerlimit = "111" - expect(litCheckBoxWithText.lowerlimit).toEqual("111"); + litCheckBoxWithText.lowerLimit = "111" + expect(litCheckBoxWithText.lowerLimit).toEqual("111"); }); it('checkBoxWithTextTest05', function () { let litCheckBoxWithText = new LitCheckBoxWithText(); - litCheckBoxWithText.uplimit = "111" - expect(litCheckBoxWithText.uplimit).toEqual("111"); + litCheckBoxWithText.upLimit = "111" + expect(litCheckBoxWithText.upLimit).toEqual("111"); + }); + + it('checkBoxWithTextTest05', function () { + let litCheckBoxWithText = new LitCheckBoxWithText(); + expect(litCheckBoxWithText.initHtml()).toMatchInlineSnapshot(` +" + + + + + " +`); + }); + + it('checkBoxWithTextTest06', function () { + let litCheckBoxWithText = new LitCheckBoxWithText(); + expect(litCheckBoxWithText.attributeChangedCallback("checked")).toBeUndefined(); + }); + + it('checkBoxWithTextTest07', function () { + let litCheckBoxWithText = new LitCheckBoxWithText(); + expect(litCheckBoxWithText.attributeChangedCallback("text")).toBeUndefined(); + }); + + it('checkBoxWithTextTest08', function () { + let litCheckBoxWithText = new LitCheckBoxWithText(); + expect(litCheckBoxWithText.attributeChangedCallback("lowerLimit")).toBeUndefined(); + }); + + it('checkBoxWithTextTest09', function () { + let litCheckBoxWithText = new LitCheckBoxWithText(); + expect(litCheckBoxWithText.attributeChangedCallback("upLimit")).toBeUndefined(); }); }) \ No newline at end of file diff --git a/host/ide/test/base-ui/checkbox/LitCheckGroup.test.ts b/host/ide/test/base-ui/checkbox/LitCheckGroup.test.ts index 57bd9df3cf91d8dfbdc5d6208844b4f485058142..02ce41c34d17a3ed012186c0a21e5dc21cbcf585 100644 --- a/host/ide/test/base-ui/checkbox/LitCheckGroup.test.ts +++ b/host/ide/test/base-ui/checkbox/LitCheckGroup.test.ts @@ -36,4 +36,33 @@ describe('LitCheckGroup Test', ()=>{ expect(litCheckGroup.value).toEqual([]); }); + it('LitCheckGroupTest03', function () { + let litCheckGroup = new LitCheckGroup(); + expect(litCheckGroup.initHtml()).toMatchInlineSnapshot(` +" + + " +`); + }); + }) \ No newline at end of file diff --git a/host/ide/test/base-ui/icon/LitIcon.test.ts b/host/ide/test/base-ui/icon/LitIcon.test.ts index dd3ab13755303d49378248bf0e2ab9c11efbf49b..63aca5ddbed04942dcd2137deaff984e4776b471 100644 --- a/host/ide/test/base-ui/icon/LitIcon.test.ts +++ b/host/ide/test/base-ui/icon/LitIcon.test.ts @@ -56,4 +56,43 @@ describe("testLitIcon Test", () => { litIcon.name = "sss" expect(litIcon.name).toBe("sss") }); + + it('testLitIcon07', () => { + let litIcon = new LitIcon(); + expect(litIcon.color = "#FFF").not.toBeUndefined(); + }); + + it('testLitIcon07', () => { + let litIcon = new LitIcon(); + expect(litIcon.initHtml()).toMatchInlineSnapshot(` +" + + + + + " +`); + }); }) diff --git a/host/ide/test/base-ui/menu/LitMainMenu.test.ts b/host/ide/test/base-ui/menu/LitMainMenu.test.ts index dc0fc181d802969b974befe9817ab6548afb2e17..019a65caa711023273cdfa370787a3e8285117c2 100644 --- a/host/ide/test/base-ui/menu/LitMainMenu.test.ts +++ b/host/ide/test/base-ui/menu/LitMainMenu.test.ts @@ -56,4 +56,106 @@ describe("LitMainMenu Test", () => { ] expect(litMainMenu.menus.length).toBe(1) }); + + it('LitMainMenu03', () => { + let litMainMenu = new LitMainMenu(); + expect(litMainMenu.initHtml()).toMatchInlineSnapshot(` +" + +
+ +
+ +
+
+
+ +
+
+
+ " +`); + }); + + it('LitMainMenu04', () => { + let litMainMenu = new LitMainMenu(); + litMainMenu.menus = [ + { + collapsed: true, + title: 'Navigation', + describe: 'Open or record a new trace', + children: [ + { + title: "Open trace file", + icon: "folder", + fileChoose: true, + fileHandler: function (ev: InputEvent) { + } + + }, + { + title: "Record new trace", icon: "copyhovered", clickHandler: function (item: MenuItem) { + } + } + ] + } + ] + expect(litMainMenu.menus.length).toBe(1) + }); }) diff --git a/host/ide/test/base-ui/menu/LitMainMenuGroup.test.ts b/host/ide/test/base-ui/menu/LitMainMenuGroup.test.ts index 5c870524864714552a9681c2eb18b4afe5ae838c..915a9fcdd2524cda457d055e02f87f8336eacf65 100644 --- a/host/ide/test/base-ui/menu/LitMainMenuGroup.test.ts +++ b/host/ide/test/base-ui/menu/LitMainMenuGroup.test.ts @@ -36,9 +36,97 @@ describe("litMainMenuGroup Test", () => { expect(litMainMenuGroup.collapsed).toBeTruthy() }); - it('litMainMenuGroup03', () => { + it('litMainMenuGroup04', () => { let litMainMenuGroup = new LitMainMenuGroup(); litMainMenuGroup.collapsed = false expect(litMainMenuGroup.collapsed).toBeFalsy() }); + + it('litMainMenuGroup06', () => { + let litMainMenuGroup = new LitMainMenuGroup(); + expect(litMainMenuGroup.radius).toBeFalsy() + }); + + it('litMainMenuGroup07', () => { + let litMainMenuGroup = new LitMainMenuGroup(); + expect(litMainMenuGroup.initHtml()).toMatchInlineSnapshot(` +" + +
+
+ + " +`); + }); + + it('litMainMenuGroup04', () => { + let litMainMenuGroup = new LitMainMenuGroup(); + litMainMenuGroup.nocollapsed = true + expect(litMainMenuGroup.nocollapsed).toBeTruthy() + }); + + it('litMainMenuGroup04', () => { + let litMainMenuGroup = new LitMainMenuGroup(); + litMainMenuGroup.nocollapsed = false + expect(litMainMenuGroup.nocollapsed).toBeFalsy() + }); + + it('litMainMenuGroup05', () => { + let litMainMenuGroup = new LitMainMenuGroup(); + expect(litMainMenuGroup.collapsed).toBeFalsy() + }); }) diff --git a/host/ide/test/base-ui/menu/LitMainMenuItem.test.ts b/host/ide/test/base-ui/menu/LitMainMenuItem.test.ts index 4dc93a17147dad3337b1f7d8715777aa0d0ac8d7..43da66014027f20666f8748f1d4c5f4e5de16fe9 100644 --- a/host/ide/test/base-ui/menu/LitMainMenuItem.test.ts +++ b/host/ide/test/base-ui/menu/LitMainMenuItem.test.ts @@ -51,4 +51,127 @@ describe("litMainMenuItem Test", () => { litMainMenuItem.title ="test03" expect(litMainMenuItem.title).toEqual("test03") }); + + it('litMainMenuItem06', () => { + document.body.innerHTML = ` + ` + let litMainMenuItem = new LitMainMenuItem(); + expect(litMainMenuItem.isFile()).toBeFalsy(); + }); + + it('litMainMenuItem07', () => { + document.body.innerHTML = ` + ` + let litMainMenuItem = new LitMainMenuItem(); + litMainMenuItem.disabled = true; + expect(litMainMenuItem.disabled).toBeTruthy(); + }); + + it('litMainMenuItem08', () => { + document.body.innerHTML = ` + ` + let litMainMenuItem = new LitMainMenuItem(); + litMainMenuItem.disabled = false; + expect(litMainMenuItem.disabled).toBeFalsy(); + }); + + it('litMainMenuItem09', () => { + let litMainMenuItem = new LitMainMenuItem(); + expect(litMainMenuItem.initHtml()).toMatchInlineSnapshot(` +" + + + + " +`); + }); + it('litMainMenuItem10', () => { + let litMainMenuItem = new LitMainMenuItem(); + litMainMenuItem.back = true + expect(litMainMenuItem.back).toBeTruthy() + }) + it('litMainMenuItem11', () => { + let litMainMenuItem = new LitMainMenuItem(); + litMainMenuItem.back = false + expect(litMainMenuItem.back).toBeFalsy() + }) + + it('litMainMenuItem12', () => { + const onclick = jest.fn(); + let menuItem = document.body.innerHTML = ` + + ` + const menu = document.getElementById('menu'); + expect(onclick).not.toBeCalled(); + menu!.onclick = onclick; + menu!.click(); + expect(onclick).toBeCalled(); + expect(onclick).toHaveBeenCalledTimes(1); + }); }) diff --git a/host/ide/test/base-ui/popover/LitPopContent.test.ts b/host/ide/test/base-ui/popover/LitPopContent.test.ts index b21ca9bbe6a7ab54ae05c5436ca6089a976a999a..c0a04d9733960ca332edf0cfd7450504bfd72afe 100644 --- a/host/ide/test/base-ui/popover/LitPopContent.test.ts +++ b/host/ide/test/base-ui/popover/LitPopContent.test.ts @@ -49,4 +49,51 @@ describe("LitPopCont Test", () => { litPopContent.name = "11" expect(litPopContent.name).toEqual("11") }); + + it('LitPopCont05', () => { + let litPopContent = new LitPopContent(); + expect(litPopContent.initHtml()).toMatchInlineSnapshot(` +" + +
+ +
+ " +`); + }); + + it('LitPopCont06', () => { + let litPopContent = new LitPopContent(); + expect(litPopContent.attributeChangedCallback("open","",null || "false")).toBeUndefined() + }); + + it('LitPopCont07', () => { + let litPopContent = new LitPopContent(); + expect(litPopContent.attributeChangedCallback("name","",'')).toBeUndefined(); + }); }) diff --git a/host/ide/test/base-ui/popover/LitPopover.test.ts b/host/ide/test/base-ui/popover/LitPopover.test.ts index a8be4f48cc2a9b0df11221286b0572cfc5be2e2c..2c34a9e2704a7028abd712ba749646167cfed44f 100644 --- a/host/ide/test/base-ui/popover/LitPopover.test.ts +++ b/host/ide/test/base-ui/popover/LitPopover.test.ts @@ -40,7 +40,6 @@ describe("LitPopover Test", () => { expect(litPopover.open).toBeFalsy() }); - it('LitPopover05', () => { let litPopover = new LitPopover(); litPopover.direction = "topleft" @@ -82,7 +81,6 @@ describe("LitPopover Test", () => { expect(litPopover.select).toEqual(["# Samples"]) }); - it('LitPopover09', () => { let litPopover = new LitPopover(); litPopover.type = "radio" @@ -93,4 +91,343 @@ describe("LitPopover Test", () => { }] expect(litPopover.select).toEqual(["# Samples"]) }); + + it('LitPopover10', () => { + let litPopover = new LitPopover(); + litPopover.type = "multiple-text" + litPopover.title = "tee" + litPopover.dataSource = [{ + text: "# Samples", + isSelected: true + }] + expect(litPopover.trigger).not.toBeUndefined(); + }); + + it('LitPopover11', () => { + let litPopover = new LitPopover(); + litPopover.type = "multiple-text" + litPopover.title = "tee" + litPopover.dataSource = [{ + text: "# Samples", + isSelected: false + }] + expect(litPopover.limit).toEqual({textLowerLimit:"0",textUpperLimit:"∞"}); + }); + + it('LitPopover14', () => { + let litPopover = new LitPopover(); + litPopover.type = "data-ming" + litPopover.title = "tee" + litPopover.dataSource = [{ + text: "# Samples", + isSelected: false + }] + expect(litPopover.limit).toEqual({textLowerLimit:"",textUpperLimit:""}); + }); + + it('LitPopover15', () => { + let litPopover = new LitPopover(); + litPopover.type = "multiple-text" + litPopover.title = "tee" + litPopover.dataSource = [{ + text: "# Samples", + isSelected: true + }] + expect(litPopover.limit).toEqual({textLowerLimit:"0",textUpperLimit:"∞"}); + }); + + it('LitPopover12', () => { + let litPopover = new LitPopover(); + expect(litPopover.initHtml()).toMatchInlineSnapshot(` +" + + + " +`); + }); + + it('LitPopover13', () => { + let litPopover = new LitPopover(); + expect(litPopover.connectedCallback()).toBeUndefined() + }); + + it('LitPopover16', () => { + const onclick = jest.fn(); + let litPopover = document.body.innerHTML = ` + + ` + const popover = document.getElementById('popover'); + expect(onclick).not.toBeCalled(); + popover!.onclick = onclick; + popover!.click(); + expect(onclick).toBeCalled(); + expect(onclick).toHaveBeenCalledTimes(1); + }); }) diff --git a/host/ide/test/base-ui/popover/LitPopoverTitle.test.ts b/host/ide/test/base-ui/popover/LitPopoverTitle.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..dbbf0f6801875dad99ceefa5a3a688fdbdebb0be --- /dev/null +++ b/host/ide/test/base-ui/popover/LitPopoverTitle.test.ts @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitPopoverTitle} from "../../../dist/base-ui/popover/LitPopoverTitle"; + +describe("LitPopoverTitle Test", () => { + it('LitPopoverTitle01', () => { + let litPopoverTitle = new LitPopoverTitle(); + expect(litPopoverTitle.attributeChangedCallback('name','old','new')).toBeUndefined(); + }); +}) diff --git a/host/ide/test/base-ui/popover/LitPopoverV.test.ts b/host/ide/test/base-ui/popover/LitPopoverV.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..042c9721048ae1266625c0402c77824dc77ca2d7 --- /dev/null +++ b/host/ide/test/base-ui/popover/LitPopoverV.test.ts @@ -0,0 +1,446 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitPopover} from "../../../dist/base-ui/popover/LitPopoverV.js"; + +describe("LitPopoverV Test", () => { + it('LitPopoverV01', () => { + let litPopover = new LitPopover(); + expect(litPopover).not.toBeUndefined() + expect(litPopover).not.toBeNull() + }); + it('LitPopoverV02', () => { + let litPopoverV = new LitPopover(); + expect(litPopoverV.visible).toBe("false"); + }); + it('LitPopoverV03', () => { + let litPopoverV = new LitPopover(); + litPopoverV.visible = true; + expect(litPopoverV.visible).toBe("true"); + }); + it('LitPopoverV04', () => { + let litPopoverV = new LitPopover(); + litPopoverV.visible = false; + expect(litPopoverV.visible).toBe("false"); + }); + it('LitPopoverV05', () => { + let litPopoverV = new LitPopover(); + expect(litPopoverV.trigger).toBe("hover"); + }); + it('LitPopoverV06', () => { + let litPopoverV = new LitPopover(); + litPopoverV.trigger = "click"; + expect(litPopoverV.trigger).toBe("click"); + }); + + it('LitPopoverV07', () => { + let litPopoverV = new LitPopover(); + litPopoverV.title = "test"; + expect(litPopoverV.title).toBe("test"); + }); + + it('LitPopoverV08', () => { + let litPopoverV = new LitPopover(); + litPopoverV.width = "10px"; + expect(litPopoverV.width).toBe("10px"); + }); + + it('LitPopoverV09', () => { + let litPopoverV = new LitPopover(); + litPopoverV.width = "10px"; + expect(litPopoverV.width).toBe("10px"); + }); + + it('LitPopoverV10', () => { + let litPopoverV = new LitPopover(); + expect(litPopoverV.width).toBe("max-content"); + }); + + + it('LitPopoverV11', () => { + let litPopoverV = new LitPopover(); + expect(litPopoverV.haveRadio).toBeNull(); + }); + + it('LitPopoverV12', () => { + document.body.innerHTML = `` + let popver = document.querySelector("#litpop") as LitPopover; + expect(popver.haveRadio).toBeNull(); + }); + + it('LitPopoverV13', () => { + let litPopoverV = new LitPopover(); + expect(litPopoverV.initHtml()).toMatchInlineSnapshot(` +" + + +
+
null
+
+
+ + " +`); + }); + it('LitPopoverV14', () => { + document.body.innerHTML = `` + let popver = document.querySelector("#litpop") as LitPopover; + expect(popver.adoptedCallback()).toBeUndefined() + }); +}); \ No newline at end of file diff --git a/host/ide/test/base-ui/progress-bar/LitProgressBar.test.ts b/host/ide/test/base-ui/progress-bar/LitProgressBar.test.ts index 0f2f37d313c34438c46b524784c12b6e177b0e64..5cd62a629e055621a0d822a7d00a658233ed4e48 100644 --- a/host/ide/test/base-ui/progress-bar/LitProgressBar.test.ts +++ b/host/ide/test/base-ui/progress-bar/LitProgressBar.test.ts @@ -21,7 +21,58 @@ describe('LitProgressBar Test', ()=>{ litProgressBar.loading = '' litProgressBar.loading = 'load' - it('LitProgressBarTest03', ()=>{ + it('LitProgressBarTest01', ()=>{ expect(litProgressBar.loading).toBeTruthy(); }) + + it('LitProgressBarTest02', ()=>{ + expect(litProgressBar.initHtml()).toMatchInlineSnapshot(` +" + +
+
+
+
+ " +`); + }) }) diff --git a/host/ide/test/base-ui/radiobox/LitRadioBox.test.ts b/host/ide/test/base-ui/radiobox/LitRadioBox.test.ts index 7bd211a9d4b35cc0ba2c08f92e8e3127c4112739..c41a42e2f026837d68e4734ea780801e1e1e2641 100644 --- a/host/ide/test/base-ui/radiobox/LitRadioBox.test.ts +++ b/host/ide/test/base-ui/radiobox/LitRadioBox.test.ts @@ -37,8 +37,175 @@ describe('LitRadioBox Test', ()=>{ expect(litRadioBox.value).toBe('value'); }) + it('LitRadioBoxTest03', ()=>{ + expect(litRadioBox.initHtml()).toMatchInlineSnapshot(` +" + + + + " +`); + }) + it('litRadioGroupTest01', ()=>{ let isReturn = litRadioGroup.value.length == 0 expect(isReturn).toBeTruthy(); }) + + it('litRadioGroupTest02', ()=>{ + expect(litRadioGroup.initHtml()).toMatchInlineSnapshot(` +" + + " +`); + }) }) diff --git a/host/ide/test/base-ui/select/LitAllocationSelect.test.ts b/host/ide/test/base-ui/select/LitAllocationSelect.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..66c0002138a1e7409ad82c0d760e6cc7edc8d5ac --- /dev/null +++ b/host/ide/test/base-ui/select/LitAllocationSelect.test.ts @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitAllocationSelect} from "../../../dist/base-ui/select/LitAllocationSelect.js"; + +describe('LitAllocationSelect Test', () => { + let litAllocationSelect = new LitAllocationSelect() + it('LitAllocationSelectTest01', function () { + expect(litAllocationSelect.value).toBe("") + }) + it('LitAllocationSelectTest02',()=> { + expect(litAllocationSelect.processData).toBeUndefined() + + }) + it('LitAllocationSelectTest03', function () { + expect(litAllocationSelect.placement).toBe("") + + }) + it('LitAllocationSelectTest04', function () { + litAllocationSelect.placement = true + expect(litAllocationSelect.placement).toBeTruthy() + + }) + it('LitAllocationSelectTest05', function () { + litAllocationSelect.placement = false + expect(litAllocationSelect.placement).toBeFalsy() + + }) + it('LitAllocationSelectTest06', function () { + expect(litAllocationSelect.listHeight).toBe("256px") + + }) + it('LitAllocationSelectTest07', function () { + litAllocationSelect.listHeight = "test" + expect(litAllocationSelect.listHeight).toBe("test") + + }) + it('LitAllocationSelectTest08', function () { + litAllocationSelect.placeholder = "test" + expect(litAllocationSelect.placeholder).toBe("test") + }) + it('LitAllocationSelectTest09', ()=> { + expect(litAllocationSelect.initElements()).toBeUndefined() + }) + + it('LitAllocationSelectTest10',()=> { + litAllocationSelect.processData = []; + expect(litAllocationSelect.processData).toBe(undefined); + }) + + it('LitAllocationSelectTest12',()=> { + litAllocationSelect.processData = ['1','2','3']; + expect(litAllocationSelect.processData).toBe(undefined); + }) + + it('LitAllocationSelectTest11', () => { + const onclick = jest.fn(); + let allocationSelect = document.body.innerHTML = ` + + ` + const select = document.getElementById('select'); + expect(onclick).not.toBeCalled(); + select!.onclick = onclick; + select!.click(); + expect(onclick).toBeCalled(); + expect(onclick).toHaveBeenCalledTimes(1); + }); +}) \ No newline at end of file diff --git a/host/ide/test/base-ui/select/LitSelect.test.ts b/host/ide/test/base-ui/select/LitSelect.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..ace0cb00c7063e441f2dcfd030154bb386988b25 --- /dev/null +++ b/host/ide/test/base-ui/select/LitSelect.test.ts @@ -0,0 +1,415 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitButton, LitSelect} from "../../../dist/base-ui/select/LitSelect.js"; +import {LitSelectOption} from "../../../src/base-ui/select/LitSelectOption"; + +describe('LitSelect Test', ()=>{ + + it('LitSelectTest01', function () { + let litSelect = new LitSelect(); + expect(litSelect).not.toBeUndefined() + }); + + it('LitSelectTest02', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + expect(select).not.toBeUndefined() + }); + + it('LitSelectTest03', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.value = "value" + expect(select.value).toBe('value'); + }); + + it('LitSelectTest04', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.border = "value" + expect(select.border).toBe('true'); + }); + it('LitSelectTest05', function () { + let lit = new LitSelect(); + expect(lit.border).toBe('true'); + }); + it('LitSelectTest06', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.listHeight = true; + expect(select.listHeight).toBe('true'); + }); + + it('LitSelectTest07', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.defaultValue = true; + expect(select.defaultValue).toBe('true'); + }); + + it('LitSelectTest08', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.loading = 1 + expect(select.loading).toBe(true); + }); + + it('LitSelectTest09', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + expect(select.isMultiple()).toBe(false); + }); + + it('LitSelectTest10', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.inputElement.value = "3333"; + select.click(); + expect(select.focused).toBe(true); + }); + + it('LitSelectTest11', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.clear() + expect(select.inputElement.value).toBe(""); + }); + + it('LitSelectTest12', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + expect(select.reset()).toBeUndefined(); + }); + + it('LitSelectTest13', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + let newTag =select.newTag("111","111"); + expect(newTag.text).toBe("111"); + }); + it('LitSelectTest14', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.dataSource = [{key:"111"}] + let cleart = select.clearElement as HTMLElement; + cleart.click(); + expect(select.inputElement.value).toBe(""); + + }); + + it('LitSelectTest15', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + let input = select.inputElement as HTMLInputElement; + input.value = "11" + expect(select.inputElement.value).toBe("11"); + + }); + + it('LitSelectTest16', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.dataSource = [{key:"111"}] + expect(select.inputElement.value).toBe(""); + + }); + + it('LitSelectTest17', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.placeholder = true; + expect(select.placeholder).toBe('true'); + }); + it('LitSelectTest20', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.rounded = 1 + expect(select.rounded).toBe(true); + }); + + it('LitSelectTest21', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.placement = 1 + expect(select.placement).toBe("1"); + }); + + it('LitSelectTest18', function () { + let litSelect = new LitSelect(); + expect(litSelect.initHtml()).toMatchInlineSnapshot(` +" + +
+
+
+ + + + +
+
+ + +
+ " +`); + }); + + it('LitSelectTest23', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.canInsert = true + expect(select.canInsert).toBeTruthy(); + }); + it('LitSelectTest24', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.rounded =false + expect(select.rounded).toBeFalsy() + }); + it('LitSelectTest25', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.placement =false + expect(select.placement).toBeFalsy() + }); + it('LitSelectTest26', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.border =true + expect(select.border).toBeTruthy() + }); + it('LitSelectTest27', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.canInsert =false + expect(select.canInsert).toBeFalsy() + }); + it('LitSelectTest28', function () { + document.body.innerHTML = `` + let select = document.querySelector("#litSelect") as LitSelect; + select.loading =false + expect(select.loading).toBeFalsy() + }); + + it('LitSelectTest29', function () { + let lit = new LitSelect(); + lit.border = false; + expect(lit.border).toBe('false'); + }); + + it('LitSelectTest30', function () { + let litSelect = document.body.innerHTML = ` + + + ` as LitSelect; + let select = document.querySelector("#litSelect") as LitSelect; + expect(select.reset()).toBeUndefined(); + }); +}) diff --git a/host/ide/test/base-ui/select/LitSelectOption.test.ts b/host/ide/test/base-ui/select/LitSelectOption.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..30f3450726a54eb3519f5f5ce25dcf51eb964dad --- /dev/null +++ b/host/ide/test/base-ui/select/LitSelectOption.test.ts @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitSelectOption} from "../../../dist/base-ui/select/LitSelectOption.js"; + +describe('LitSelectOption Test', ()=> { + it('LitSelectOptionTest01', function () { + document.body.innerHTML = ""; + let inner = document.querySelector("#aa") as LitSelectOption; + expect(inner).not.toBeUndefined() + }); + it('LitSelectOptionTest03', function () { + expect(LitSelectOption.adoptedCallback).toBeUndefined() + + }); + + it('LitSelectOptionTest04', function () { + expect(LitSelectOption.disconnectedCallback).toBeUndefined() + + }); + + it('LitSelectOptionTest05', function () { + expect(LitSelectOption.attributeChangedCallback).toBeUndefined() + + }); + + it('LitSelectOption02', function () { + let litSelect = new LitSelectOption(); + expect(litSelect.initHtml()).toMatchInlineSnapshot(` +" + +
+ +
+ + + " +`); + }); +}); \ No newline at end of file diff --git a/host/ide/test/base-ui/select/LitSelectV.test.ts b/host/ide/test/base-ui/select/LitSelectV.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..9b7ba4cdad65550e143a8f3e3745f8dcf340c33e --- /dev/null +++ b/host/ide/test/base-ui/select/LitSelectV.test.ts @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitSelectV} from "../../../dist/base-ui/select/LitSelectV.js"; + +describe('LitSelectV Test', () => { + let litSelectV = new LitSelectV() + it('LitSelectVTest01', function () { + expect(litSelectV.value).not.toBeUndefined() + }) + it('LitSelectVTest02', function () { + litSelectV.rounded = true + expect(litSelectV.rounded).toBeTruthy() + }) + it('LitSelectVTest06', function () { + litSelectV.rounded = false + expect(litSelectV.rounded).toBeFalsy() + }) + it('LitSelectVTest03', function () { + expect(litSelectV.placement).toBe("") + + }) + it('LitSelectVTest04', function () { + litSelectV.placement = true + expect(litSelectV.placement).toBeTruthy() + + }) + it('LitSelectVTest05', function () { + litSelectV.placement = false + expect(litSelectV.placement).toBeFalsy() + + }) + it('LitSelectVTest07', function () { + litSelectV.boder = true + expect(litSelectV.border).toBeTruthy() + }) + it('LitSelectVTest08', function () { + litSelectV.border = false + expect(litSelectV.border).toBe("false") + }) + it('LitSelectVTest14', function () { + litSelectV.border = true + expect(litSelectV.border).toBe("true") + }) + it('LitSelectVTest09', function () { + litSelectV.defaultValue = "test" + expect(litSelectV.defaultValue).toBe("test") + }) + it('LitSelectVTest010', function () { + litSelectV.placeholder = "test" + expect(litSelectV.placeholder).toBe("test") + }) + it('LitSelectVTest011', function () { + litSelectV.all = true + expect(litSelectV.all).toBeTruthy() + }) + it('LitSelectVTest012', function () { + litSelectV.all = false + expect(litSelectV.all).toBeFalsy() + }) + it('LitSelectVTest013', function () { + let value = [{ + length:1, + }] + let valueStr = "" + expect(litSelectV.dataSource(value,valueStr)).toBeUndefined() + }) + it('LitSelectVTest014', function () { + let value = [{ + length:1, + }] + let valueStr = "aa" + expect(litSelectV.dataSource(value,valueStr)).toBeUndefined() + }) + it('LitSelectVTest015', function () { + expect(litSelectV.connectedCallback()).toBeUndefined() + }) + it('LitSelectVTest016', function () { + let valueStr = "aa"; + expect(litSelectV.dataSource([],valueStr)).toBeUndefined(); + }) + it('LitSelectVTest017', function () { + let value = [{ + length:1, + }]; + let valueStr = "aa"; + litSelectV.all = true; + expect(litSelectV.dataSource(value,valueStr)).toBeUndefined(); + }) + it('LitSelectVTest018', function () { + let value = [{ + length:1, + }]; + let valueStr = "aa"; + litSelectV.title = "Event List"; + expect(litSelectV.dataSource(value,valueStr)).toBeUndefined(); + }) +}) \ No newline at end of file diff --git a/host/ide/test/base-ui/slice/lit-slicer.test.ts b/host/ide/test/base-ui/slice/lit-slicer.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..185b4c7ec3685092e049ed2e6dc225fbb41a1723 --- /dev/null +++ b/host/ide/test/base-ui/slice/lit-slicer.test.ts @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +// @ts-ignore +import {LitSlicer,LitSlicerTrack} from "../../../dist/base-ui/slicer/lit-slicer.js"; + +describe('slicer Test', ()=>{ + it('slicerTest01', function () { + let litSlicer = new LitSlicer(); + expect(litSlicer).not.toBeUndefined() + expect(litSlicer).not.toBeNull() + }); + it('slicerTest02', function () { + let litSlicerTrack = new LitSlicerTrack(); + expect(litSlicerTrack).not.toBeUndefined() + expect(litSlicerTrack).not.toBeNull() + }); + it('slicerTest03', function () { + let litSlicerTrack = new LitSlicerTrack(); + expect(litSlicerTrack.rangeLeft).toBe(200) + + }) + it('slicerTest04', function () { + let litSlicerTrack = new LitSlicerTrack(); + litSlicerTrack.rangeLeft = true + expect(litSlicerTrack.rangeLeft).not.toBeTruthy() + + }) + it('slicerTest05', function () { + let litSlicerTrack = new LitSlicerTrack(); + expect(litSlicerTrack.rangeRight).toBe(300) + }) + it('slicerTest09', function () { + let litSlicerTrack = new LitSlicerTrack(); + litSlicerTrack.rangeRight = false + expect(litSlicerTrack.rangeRight).toBeFalsy() + }) + it('slicerTest06', function () { + let litSlicer = new LitSlicer(); + expect(litSlicer.attributeChangedCallback()).toBeUndefined() + }) + it('slicerTest07', function () { + let litSlicerTrack = new LitSlicerTrack(); + expect(litSlicerTrack.adoptedCallback()).toBeUndefined() + }) + it('slicerTest08', function () { + let litSlicerTrack = new LitSlicerTrack(); + expect(litSlicerTrack.attributeChangedCallback()).toBeUndefined() + }) + it('slicerTest10', function () { + let litSlicer = new LitSlicer(); + litSlicer.direction ="h"; + expect(litSlicer. connectedCallback()).toBeUndefined() + }) + it('slicerTest11', function () { + let litSlicer = new LitSlicer(); + litSlicer.direction ="v"; + expect(litSlicer.direction).toBeUndefined() + }) + it('slicerTest12', function () { + let litSlicer = new LitSlicer(); + litSlicer.style ="v"; + expect(litSlicer.style).toBeUndefined() + }) +}) \ No newline at end of file diff --git a/host/ide/test/base-ui/slider/LitSlider.test.ts b/host/ide/test/base-ui/slider/LitSlider.test.ts index d05e457757270f7c444a7ffd859e5cffc1e9120a..599f1fc9f8a3bd079bc93231a2627ca7ed417745 100644 --- a/host/ide/test/base-ui/slider/LitSlider.test.ts +++ b/host/ide/test/base-ui/slider/LitSlider.test.ts @@ -26,10 +26,6 @@ describe('LitSlider Test', ()=>{ litSliderPanel.percent = 'percent' litSliderPanel.resultUnit = 'resultUnit' - litSliderPanel.litSlider = jest.fn(()=> true) - - litSliderPanel.sliderStyle = 'sliderStyle' - it('LitSliderTest01', ()=>{ expect(litSliderPanel.disabledX).toEqual(''); }) @@ -59,6 +55,10 @@ describe('LitSlider Test', ()=>{ }) it('LitSliderTest08', ()=>{ + litSliderPanel.litSliderStyle = jest.fn(()=>true) + litSliderPanel.litSliderStyle.minRange = jest.fn(()=>2) + litSliderPanel.litSliderStyle.maxRange = jest.fn(()=>1) + litSliderPanel.litSliderStyle.stepSize = jest.fn(()=>1) expect(litSliderPanel.renderDefaultSlider()).toBeUndefined(); }) @@ -67,10 +67,139 @@ describe('LitSlider Test', ()=>{ }) it('LitSliderTest10', ()=>{ - litSliderPanel.litSlider.removeEventListener = jest.fn(()=> true) - litSliderPanel.litSlider.removeEventListener = jest.fn(()=> true) - litSliderPanel.litSliderButton = jest.fn(()=> true) - litSliderPanel.litSliderButton.removeEventListener = jest.fn(()=> true) expect(litSliderPanel.disconnectedCallback()).toBeUndefined(); }) + + it('LitSliderTest11', ()=>{ + expect(litSliderPanel.disconnectedCallback()).toBeUndefined(); + }) + + it('LitSliderTest12', function () { + expect(litSliderPanel.attributeChangedCallback("percent","","0%" || null)).toBeUndefined(); + }); + + it('LitSliderTest13', function () { + expect(litSliderPanel.initHtml()).toMatchInlineSnapshot(` +" + + +
+ +
+ " +`); + }); + + it('LitSliderTest14', ()=>{ + litSliderPanel.disabledX = false; + expect(litSliderPanel.disabledX).toBeFalsy(); + }); + + it('LitSliderTest15', ()=>{ + litSliderPanel.customSlider = false; + expect(litSliderPanel.customSlider).toBeFalsy(); + }); + + it('LitSliderTest16', ()=>{ + expect(litSliderPanel.formatSeconds(36000)).toBe('10:00:00'); + }); + + it('LitSliderTest17', ()=>{ + expect(litSliderPanel.formatSeconds(4000)).toBe('01:06:40'); + }) + + }) diff --git a/host/ide/test/base-ui/switch/LitSwitch.test.ts b/host/ide/test/base-ui/switch/LitSwitch.test.ts index c0094b0a5583cee0b5d49cc45190e01327af11fa..fbc0144d69c4001b6b29419547b6af6b21fb4c23 100644 --- a/host/ide/test/base-ui/switch/LitSwitch.test.ts +++ b/host/ide/test/base-ui/switch/LitSwitch.test.ts @@ -20,6 +20,8 @@ describe('LitSwitch Test', ()=>{ let litSwitch = new LitSwitch(); litSwitch.checked = true litSwitch.checked = false + litSwitch.disabled = true + litSwitch.disabled =false it('LitSwitchTest01', ()=>{ expect(litSwitch.name).toBeNull(); @@ -53,4 +55,78 @@ describe('LitSwitch Test', ()=>{ it('LitSwitchTest08', ()=>{ expect(litSwitch.attributeChangedCallback('checked', 'disabled', null)).toBeUndefined() }) + + it('LitSwitchTest09', ()=>{ + expect(litSwitch.initHtml()).toMatchInlineSnapshot(` +" + + + " +`); + }) }) diff --git a/host/ide/test/base-ui/table/LitTable.test.ts b/host/ide/test/base-ui/table/LitTable.test.ts index b011898ce8c6729a0412d1ca8bdc8553e204cd3c..d0aecd359cea38b58e8b0117aaa4bd6f4b1a5c20 100644 --- a/host/ide/test/base-ui/table/LitTable.test.ts +++ b/host/ide/test/base-ui/table/LitTable.test.ts @@ -15,8 +15,15 @@ // @ts-ignore import {LitTable} from "../../../dist/base-ui/table/lit-table.js"; +import {LitTableColumn} from "../../../src/base-ui/table/lit-table-column.js"; -describe('LitTable Test', ()=>{ +describe('LitTable Test', () => { + window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); let litTable = new LitTable(); litTable.selectable = true litTable.selectable = false @@ -27,59 +34,465 @@ describe('LitTable Test', ()=>{ litTable.dataSource = [{ id: 1, name: 'name' - },{ + }, { id: 2, name: 'nameValue' }] + const td = { + style: { + position: 'sticky', + left: '0px', + right: '0px', + boxShadow: '3px 0px 5px #33333333' + } + } + const placement = "left" - JSON.parse = jest.fn(()=>[['children', 'father'], ['children', 'father']]) + const element = { + style: { + display: 'none', + transform: 'translateY' + }, + childNodes:{forEach:true}, + onclick: 1 + } + const rowObject = { + children: { + length: 1, + }, + data: [{isSelected:undefined}], + depth: 1, + top: 1 + } + const firstElement = { + style: { + display: 'none', + paddingLeft: "", + transform: 'translateY' - litTable.columns = litTable.columns || jest.fn(()=>true) - litTable.ds = jest.fn(()=>[{ + }, + innerHTML: "", + title: "", + firstChild: null, + onclick: 1 + + }||undefined + + JSON.parse = jest.fn(() => [['children', 'father'], ['children', 'father']]) + + litTable.columns = litTable.columns || jest.fn(() => true) + litTable.ds = jest.fn(() => [{ id: 1, name: 'name' - },{ + }, { id: 2, name: 'nameValue' }]) - litTable.tbodyElement = jest.fn(()=> ({ + litTable.tbodyElement = jest.fn(() => ({ innerHTML: '' })) - litTable.tableColumns = jest.fn(()=>[]) + litTable.tableColumns = jest.fn(() => []) - litTable.tableColumns.forEach = jest.fn(()=>[]) + litTable.tableColumns.forEach = jest.fn(() => []) - it('LitTableTest01', ()=>{ + it('LitTableTest01', () => { expect(litTable.adoptedCallback()).toBeUndefined(); }) - it('LitTableTest02', ()=>{ - litTable.ds.forEach = jest.fn(()=> true) + it('LitTableTest02', () => { + litTable.ds.forEach = jest.fn(() => true) expect(litTable.renderTable()).toBeUndefined(); }) - // it('LitTableTest03', ()=>{ - // litTable.parentNode = jest.fn(()=> true) - // litTable.parentNode.append = jest.fn(()=> true) - // expect(litTable.renderTreeTable()).toBeUndefined(); - // }) - - it('LitTableTest04', ()=>{ + it('LitTableTest04', () => { litTable.switch = document.querySelector("#switch") as HTMLInputElement; expect(litTable.connectedCallback()).toBeUndefined() }) - it('LitTableTest05', ()=>{ + it('LitTableTest05', () => { let rowLength = litTable.getCheckRows().length == 0; expect(rowLength).toBeTruthy() }) - it('LitTableTest06', ()=>{ - expect(litTable.deleteRowsCondition(()=>{ + it('LitTableTest06', () => { + expect(litTable.deleteRowsCondition(() => { return true })).toBeUndefined() }) + + it('LitTableTest07', () => { + expect(litTable.selectable).not.toBeUndefined() + }) + + it('LitTableTest08', () => { + litTable.selectable = true + expect(litTable.selectable).toBeTruthy() + }) + + it('LitTableTest09', () => { + expect(litTable.scrollY).not.toBeUndefined() + }) + + it('LitTableTest10', () => { + expect(litTable.dataSource).not.toBeUndefined() + }) + + it('LitTableTest11', () => { + expect(litTable.recycleDataSource).not.toBeUndefined() + }) + + it('LitTableTest12', () => { + expect(litTable.fixed(td, placement)).toBeUndefined() + }) + + it('LitTableTest13', () => { + expect(litTable.fixed(td, "right")).toBe(undefined) + }) + + it('LitTableTest14', () => { + expect(litTable.meauseElementHeight()).toBe(27) + }) + + it('LitTableTest15', () => { + expect(litTable.meauseTreeElementHeight()).toBe(27) + }) + + it('LitTableTest16', () => { + document.body.innerHTML = "" + let table = document.querySelector("#tab") as LitTable; + let htmlElement = document.createElement('lit-table-column') as LitTableColumn; + htmlElement.setAttribute('title', "1"); + htmlElement.setAttribute('data-index', "1"); + htmlElement.setAttribute('key', "1"); + htmlElement.setAttribute('align', 'flex-start'); + htmlElement.setAttribute('height', '32px'); + table!.appendChild(htmlElement); + setTimeout(() => { + table.recycleDataSource = [{ + id: 1, + name: 'name' + }, { + id: 2, + name: 'nameValue' + }] + expect(table.meauseTreeElementHeight()).toBe(27) + }, 20) + }) + + it('LitTableTest17', () => { + expect(litTable.shadowRoot.innerHTML).toMatchInlineSnapshot(` +" + + + + +
+
+
+
+
+
+
+ " +`); + }) + + it('LitTableTest18', () => { + expect(litTable.createExpandBtn({expanded:false})).not.toBeUndefined() + }) + + it('LitTableTest19', () => { + expect(litTable.reMeauseHeight()).toBeUndefined(); + }) + + it('LitTableTest20', () => { + const rowData= { + data:[{ + isSelected:undefined + }], + } + litTable.columns.forEach = jest.fn(()=>true) + expect(litTable.createNewTableElement(rowData)).not.toBeUndefined(); + }) + + it('LitTableTest21', () => { + expect(litTable.freshCurrentLine(element)).toBeUndefined(); + }) + + it('LitTableTest22', () => { + litTable.recycleDs.length = 1 + litTable.setCurrentSelection = jest.fn(()=>true) + expect(litTable.scrollToData()).toBeUndefined(); + }) + + it('LitTableTest23', () => { + expect(litTable.expandList()).toBeUndefined(); + }) + + it('LitTableTest24', () => { + expect(litTable.clearAllSelection()).toBeUndefined(); + }) + + it('LitTableTest25', () => { + expect(litTable.dispatchRowClickEvent({data:{isSelected:""}})).toBeUndefined(); + }) + + it('LitTableTest26', () => { + litTable.treeElement = jest.fn(()=>undefined) + litTable.treeElement.children = jest.fn(()=>[1]) + litTable.columns.forEach = jest.fn(()=>true) + litTable.treeElement.lastChild= jest.fn(()=>true) + litTable.treeElement.lastChild.style= jest.fn(()=>true) + expect(litTable.createNewTreeTableElement({data:""})).not.toBeUndefined(); + }); + + it('LitTableTest27', () => { + litTable.tableElement = jest.fn(()=>undefined) + litTable.tableElement.scrollTop = jest.fn(()=>1) + expect(litTable.move1px()).toBeUndefined(); + }) + + it('LitTableTest28', () => { + document.body.innerHTML = `` + let litTable = document.querySelector('#aaa') as LitTable + expect(litTable.renderTreeTable()).toBeUndefined(); + }) + + it('LitTableTest29', () => { + document.body.innerHTML = `` + let litTable = document.querySelector('#aaa') as LitTable + expect(litTable.setMouseIn(true,[])).toBeUndefined(); + }) + + it('LitTableTest30', () => { + document.body.innerHTML = `` + let litTable = document.querySelector('#aaa') as LitTable + const data = { + isSelected:true + } + expect(litTable.setCurrentSelection(data)).toBeUndefined(); + }) + + it("LitTableTest31",() => { + document.body.innerHTML = ``; + let litTable = document.querySelector('#aaa') as LitTable; + litTable.formatName =true; + expect(litTable.formatName).toBeTruthy(); + }) + it("LitTableTest32",() => { + let litTable =new LitTable(); + expect(litTable.formatName()).toBe(""); + }) + + it("LitTableTest33",() => { + let litTable =new LitTable(); + expect(litTable.dataExportInit()).toBeUndefined(); + }) + it("LitTableTest34",() => { + let litTable =new LitTable(); + expect(litTable.exportData()).toBeUndefined(); + }) + + it('LitTableTest35', () => { + expect(litTable.formatExportData()).not.toBeUndefined(); + }) + + it('LitTableTest36', () => { + expect(litTable.setSelectedRow(true,[])).toBeUndefined(); + + }) + + it('LitTableTest37', () => { + document.body.innerHTML = ``; + let litTable = document.querySelector('#aaa') as LitTable; + litTable.setAttribute('tree',true); + expect(litTable.dataSource).toStrictEqual([]); + }); + + it('LitTableTest38', () => { + document.body.innerHTML = ``; + let litTable = document.querySelector('#aaa') as LitTable; + litTable.rememberScrollTop = true; + expect(litTable.recycleDataSource).toStrictEqual([]); + }); + + it("LitTableTest39",() => { + let litTable =new LitTable(); + expect(litTable.dataExportInit()).toBeUndefined(); + }); + + it('LitTableTest40', () => { + litTable.columns = undefined; + expect(litTable.formatExportData()).toStrictEqual([]); + }); + }) + diff --git a/host/ide/test/base-ui/table/LitTableColumn.test.ts b/host/ide/test/base-ui/table/LitTableColumn.test.ts index 6a1fc57dc499056ffd0f3af004f74369215f7ef8..3c4b6d7ccda569d8b5962ab562cae33b226b43ae 100644 --- a/host/ide/test/base-ui/table/LitTableColumn.test.ts +++ b/host/ide/test/base-ui/table/LitTableColumn.test.ts @@ -27,4 +27,18 @@ describe('LitTableGroup Test', ()=>{ it('LitTableGroupTest02', ()=>{ expect(litTableColumn.connectedCallback()).toBeUndefined(); }) + + it('LitTableGroupTest03', ()=>{ + expect(litTableColumn.shadowRoot.innerHTML).toMatchInlineSnapshot(` +" + + + " +`); + }) }) diff --git a/host/ide/test/base-ui/table/LitTableGroup.test.ts b/host/ide/test/base-ui/table/LitTableGroup.test.ts index 64ce85e320da07b7b950c46573f75cf6f71c57e3..6cda3ac11b5c2128f8814bf3ab562e498a7fb9e5 100644 --- a/host/ide/test/base-ui/table/LitTableGroup.test.ts +++ b/host/ide/test/base-ui/table/LitTableGroup.test.ts @@ -27,4 +27,15 @@ describe('LitTableGroup Test', ()=>{ it('LitTableGroupTest02', ()=>{ expect(litTableGroup.title).toBe('title'); }) + + it('LitTableGroupTest03', ()=>{ + expect(litTableGroup.shadowRoot.innerHTML).toMatchInlineSnapshot(` +" + + + " +`) + }) }) diff --git a/host/ide/test/base-ui/table/TableRowObject.test.ts b/host/ide/test/base-ui/table/TableRowObject.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..5864b8468d8db0f5dda06af4af37c8ceedb7e83a --- /dev/null +++ b/host/ide/test/base-ui/table/TableRowObject.test.ts @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {TableRowObject} from "../../../dist/base-ui/table/TableRowObject.js"; + +describe('TableRowObject Test', ()=>{ + + it('TableRowObjectTest01', ()=>{ + expect(new TableRowObject().top).toBe(0); + }) +}); \ No newline at end of file diff --git a/host/ide/test/base-ui/tabs/LitTabpane.test.ts b/host/ide/test/base-ui/tabs/LitTabpane.test.ts index 2094ef94c137d232e6a4d97626bc9ba32cd70a96..03884a6e1c1fc617c6cafe0e6f976a010e7411f4 100644 --- a/host/ide/test/base-ui/tabs/LitTabpane.test.ts +++ b/host/ide/test/base-ui/tabs/LitTabpane.test.ts @@ -20,7 +20,8 @@ describe('LitTabPane Test', ()=>{ let litTabPane = new LitTabpane(); litTabPane.tab = 'tab' - litTabPane.disabled = 'disabled' + litTabPane.disabled = null || false + litTabPane.disabled = !null || !false litTabPane.hidden = 'hidden' litTabPane.closeable = false litTabPane.key = 'key' @@ -40,14 +41,47 @@ describe('LitTabPane Test', ()=>{ it('LitTabPaneTest4', ()=>{ expect(litTabPane.disabled).toBeTruthy(); }) + it('LitTabPaneTest5', ()=>{ expect(litTabPane.hidden).toBeTruthy(); }) + it('LitTabPaneTest6', ()=>{ litTabPane.closeable = 'closeable' expect(litTabPane.closeable).toBeTruthy(); }) + it('LitTabPaneTest7', ()=>{ expect(litTabPane.key).toBe('key'); }) + + it('LitTabPaneTest9 ', function () { + expect(litTabPane.connectedCallback()).toBeUndefined() + + }); + + it('LitTabPaneTest10 ', function () { + expect(litTabPane.disconnectedCallback()).toBeUndefined() + + }); + + it('LitTabPaneTest11 ', function () { + expect(litTabPane.adoptedCallback()).toBeUndefined() + + }); + it('LitTabPaneTest8', ()=>{ + expect(litTabPane.initHtml()).toMatchInlineSnapshot(` +" + + + " +`); + }) }) diff --git a/host/ide/test/base-ui/tabs/LitTabs.test.ts b/host/ide/test/base-ui/tabs/LitTabs.test.ts index 06a740dbf6c48fc33908084313e0dbd1ed2b2385..b1b9d0724057925ffd0fb3e957dd738f101b5af2 100644 --- a/host/ide/test/base-ui/tabs/LitTabs.test.ts +++ b/host/ide/test/base-ui/tabs/LitTabs.test.ts @@ -16,6 +16,13 @@ // @ts-ignore import {LitTabs} from "../../../dist/base-ui/tabs/lit-tabs.js"; +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + describe('LitSwitch Test', ()=>{ let litTabs = new LitTabs(); @@ -23,7 +30,8 @@ describe('LitSwitch Test', ()=>{ litTabs.mode = 'mode' litTabs.activekey = 'activekey' - litTabs.nav = jest.fn(()=>{ + + litTabs.nav = jest.fn(()=>{ let el = document.createElement('div'); let htmlDivElement = document.createElement('div'); htmlDivElement.setAttribute('class', 'nav-item[data-key=\'${key}\']') @@ -40,19 +48,14 @@ describe('LitSwitch Test', ()=>{ return ['fd'] }) - // it('litTabsTest01', ()=>{ - // litTabs.nav = jest.fn(()=> true) - // litTabs.nav.querySelector = jest.fn(()=> { - // return document.createElement('div') as HTMLDivElement - // }) - // litTabs.nav.querySelectorAll = jest.fn(()=> true) - // expect(litTabs.updateLabel('key', 'value')).toBeUndefined(); - // }) - it('litTabsTest1', ()=>{ expect(litTabs.activekey).toBe('activekey'); }) + it('litTabsTest01', ()=>{ + expect(litTabs.onTabClick).toBeUndefined(); + }) + it('litTabsTest02', ()=>{ litTabs.nav = jest.fn(()=> true) litTabs.nav.querySelector = jest.fn(()=> { @@ -78,34 +81,47 @@ describe('LitSwitch Test', ()=>{ }) litTabs.nav.querySelectorAll = jest.fn(()=> true) - expect(litTabs.updateHidden('key', 'value')).toBeUndefined(); + expect(litTabs.updateHidden('key', "true")).toBeUndefined(); + }) + + it('litTabsTest13', ()=>{ + litTabs.nav = jest.fn(()=> true) + litTabs.nav.querySelector = jest.fn(()=> { + return document.createElement('div') as HTMLDivElement + }) + litTabs.nav.querySelectorAll = jest.fn(()=> true) + + expect(litTabs.updateHidden('key', !"true")).toBeUndefined(); }) it('litTabsTest05', ()=>{ expect(litTabs.initTabPos()).toBeUndefined(); }) - // it('litTabsTest07', ()=>{ + it('litTabsTest07', ()=>{ // litTabs.nav.querySelectorAll = jest.fn(()=> true) // litTabs.nav.querySelectorAll.forEach = jest.fn(()=> true) - // expect(litTabs.activeByKey('newKey')).toBeNull(); - // }) + expect(litTabs.activeByKey(null||undefined)).toBeUndefined(); + }) it('litTabsTest06', ()=>{ expect(litTabs.activePane('Key')).toBeFalsy(); }) - it('litTabsTest07', ()=>{ + it('litTabsTest007', ()=>{ expect(litTabs.connectedCallback()).toBeUndefined() }) it('litTabsTest8', ()=>{ - expect(litTabs.attributeChangedCallback('disabled', 'disabled', '')).toBeUndefined() + expect(litTabs.attributeChangedCallback('activekey', 'disabled', 'activekey')).toBeUndefined() }) it('litTabsTest9', ()=>{ expect(litTabs.adoptedCallback()).toBeUndefined(); }) + it('litTabsTest09', ()=>{ + expect(litTabs.disconnectedCallback()).toBeUndefined(); + }) it('litTabsTest10', ()=>{ expect(litTabs.position).toBe('position'); }) @@ -113,4 +129,428 @@ describe('LitSwitch Test', ()=>{ it('litTabsTest11', ()=>{ expect(litTabs.mode).toBe('mode'); }) + + it('litTabsTest12', ()=>{ + expect(litTabs.shadowRoot.innerHTML).toMatchInlineSnapshot(` +" + + +
+
+ +
+
+
+
+
+
+ +
+
+ NEED CONTENT +
+
+ " +`); + }) + + it('litTabsTest14', ()=>{ + litTabs.nav = jest.fn(()=> true); + litTabs.nav.querySelector = jest.fn(()=> { + return document.createElement('div') as HTMLDivElement + }); + litTabs.nav.querySelectorAll = jest.fn(()=> true); + expect(litTabs.updateDisabled('key', undefined)).toBeUndefined(); + }); + + it('litTabsTest15', ()=>{ + litTabs.nav = jest.fn(()=> true); + litTabs.nav.querySelector = jest.fn(()=> { + return document.createElement('div') as HTMLDivElement + }); + litTabs.nav.querySelectorAll = jest.fn(()=> true); + expect(litTabs.updateCloseable('key', undefined)).toBeUndefined(); + }); + + it('litTabsTest19', ()=>{ + expect(litTabs.activePane(null)).toBe(false); + }) }) diff --git a/host/ide/test/command/Cmd.test.ts b/host/ide/test/command/Cmd.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..12d4c42f354113b9b3ce1391493c789fdd761206 --- /dev/null +++ b/host/ide/test/command/Cmd.test.ts @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {Cmd} from "../../dist/command/Cmd.js"; + +describe('Cmd', () => { + + it('CmdTest_01', () => { + expect(Cmd.execObjDump("","")).toBeUndefined() + }); + + it('CmdTest_02', () => { + expect(Cmd.execHdcCmd("")).toBeUndefined() + }); + + it('CmdTest_03', () => { + expect(Cmd.execFileRecv("","")).toBeTruthy() + }); + + it('CmdTest_04', () => { + expect(Cmd.execHdcTraceCmd("","")).toBeUndefined() + }); + + it('CmdTest_05', () => { + let params = [{ + length:0 + }] + expect(Cmd.formatString("",params)).toBe("") + }); + + it('CmdTest_06', () => { + expect(Cmd.showSaveFile()).toBeUndefined() + }); + + it('CmdTest_07', () => { + expect(Cmd.uploadFile()).toBeUndefined() + }); + + it('CmdTest_08', () => { + expect(Cmd.copyFile("","")).toBeUndefined() + }); + + it('CmdTest_09', () => { + expect(Cmd.openFileDialog()).toBeTruthy() + }); + + it('CmdTest_10', () => { + expect(Cmd.formatString("",[])).toBe("") + }); +}) \ No newline at end of file diff --git a/host/ide/test/hdc/HdcDeviceManager.test.ts b/host/ide/test/hdc/HdcDeviceManager.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..e775efb5e71b4e5df40cad4d3c10f2c4bca8b931 --- /dev/null +++ b/host/ide/test/hdc/HdcDeviceManager.test.ts @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {HdcDeviceManager} from "../../dist/hdc/HdcDeviceManager.js"; + +describe('HdcDeviceManager', () => { + + it('HdcDeviceManagerTest_01', () => { + expect(HdcDeviceManager.disConnect(1)).toBeTruthy() + }) + + it('HdcDeviceManagerTest_02', () => { + expect(HdcDeviceManager.fileRecv("1")).toBeTruthy() + }) +}) \ No newline at end of file diff --git a/host/ide/test/hdc/common/BaseConversion.test.ts b/host/ide/test/hdc/common/BaseConversion.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..4b63ddc7c0e77337d075e399b2b53807695f8dc3 --- /dev/null +++ b/host/ide/test/hdc/common/BaseConversion.test.ts @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {toHex8,toHex16,toHex32,toHex64,uint8ArrayToString} from "../../../dist/hdc/common/BaseConversion.js"; + +describe('BaseConversionTest', () => { + + it('BaseConversionTest_toHex8_01', () => { + expect(toHex8('0O8')).toEqual("0O8") + }) + + it('BaseConversionTest_toHex8_02', () => { + expect(toHex8(32)).toEqual("20") + }) + + it('BaseConversionTest_toHex16_01', () => { + expect(toHex16(8)).toEqual("08") + }) + + it('BaseConversionTest_toHex16_02', () => { + expect(toHex16(11)).toEqual("0b") + }) + + it('BaseConversionTest_toHex32_01', () => { + expect(toHex32(33)).toEqual("0021") + }) + + it('BaseConversionTest_toHex32_02', () => { + expect(toHex32(36)).toEqual("0024") + }) + + it('BaseConversionTest_toHex64_01', () => { + expect(toHex64("36")).toEqual("00000036") + }) + + it('BaseConversionTest_toHex64_02', () => { + expect(toHex64(36)).toEqual("00000024") + }) + + it('BaseConversionTest_uint8ArrayToString_01', () => { + expect(uint8ArrayToString([21,31],false)).toEqual("2131") + }) + + it('BaseConversionTest_uint8ArrayToString_02', () => { + expect(uint8ArrayToString([21,31],true)).toEqual("151f") + }) + +}); \ No newline at end of file diff --git a/host/ide/test/hdc/common/ObjectToMemory.test.ts b/host/ide/test/hdc/common/ObjectToMemory.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..13d9fa5dab348e03d59f979674a7cb092175e833 --- /dev/null +++ b/host/ide/test/hdc/common/ObjectToMemory.test.ts @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {objectToMemorySize} from "../../../dist/hdc/common/ObjectToMemorySize.js"; +describe('ObjectToMemoryTest', () => { + + let obj = new objectToMemorySize(); + it('ObjectToMemoryTest_objectToSize_01', () => { + expect(obj.objectToSize(12)).toEqual(8) + }) + + it('ObjectToMemoryTest_objectToSize_02', () => { + expect(obj.objectToSize(true)).toEqual(4) + }) + + it('ObjectToMemoryTest_objectToSize_03', () => { + expect(obj.objectToSize("abc")).toEqual(6) + }) + + it('ObjectToMemoryTest_objectToSize_04', () => { + expect(obj.objectToSize([1,2])).toEqual(16) + }) + + it('ObjectToMemoryTest_objectToSize_05', () => { + expect(obj.objectToSize({name:"demo",age:12})).toEqual(30) + }) + + // it('ObjectToMemoryTest_objectToSize_06', () => { + // expect(obj.objectToSize(null)).toEqual(0) + // }) + + it('ObjectToMemoryTest_sizeOfObj_01', () => { + expect(obj.sizeOfObj(null)).toEqual(0) + }) + + it('ObjectToMemoryTest_sizeOfObj_02', () => { + expect(obj.sizeOfObj(12)).toEqual(0) + }) + + it('ObjectToMemoryTest_sizeOfObj_03', () => { + expect(obj.sizeOfObj(false)).toEqual(0) + }) + + it('ObjectToMemoryTest_sizeOfObj_04', () => { + expect(obj.sizeOfObj(false)).toEqual(0) + }) + + it('ObjectToMemoryTest_sizeOfObj_05', () => { + expect(obj.sizeOfObj([1,2])).toEqual(20) + }) + + it('ObjectToMemoryTest_sizeOfObj_06', () => { + expect(obj.sizeOfObj({name:"demo",age:12})).toEqual(30) + }) + + it('ObjectToMemoryTest_objectToSize_07', () => { + expect(obj.objectToSize(undefined)).toEqual(0); + }); + + it('ObjectToMemoryTest_sizeOfObj_08', () => { + let object = { + [1]:2, + [3]:4, + [5]:6, + [7]:8, + }; + expect(obj.sizeOfObj(object)).toEqual(40); + }); +}); \ No newline at end of file diff --git a/host/ide/test/hdc/common/Serialize.test.ts b/host/ide/test/hdc/common/Serialize.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..efc4362f3ca1bfea6788cdb73ac18613b8f8fb24 --- /dev/null +++ b/host/ide/test/hdc/common/Serialize.test.ts @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {Serialize} from "../../../dist/hdc/common/Serialize.js" + +describe('Serialize Test', ()=> { + it('Serialize Test01', function () { + let banne = { + banner:1, + authType:1, + sessionId:1, + connectKey:1, + buf:'', + } + expect(Serialize.serializeSessionHandShake(banne)).not.toBeUndefined() + + }) + it('Serialize Test02', function () { + let payloadProtect = { + channelId:1, + commandFlag:1, + checkSum:1, + vCode:1, + } + expect(Serialize.serializePayloadProtect(payloadProtect)).not.toBeUndefined() + + }) + it('Serialize Test03', function () { + let transferConfig = { + fileSize:1, + atime:1, + mtime:1, + options:1, + path:1, + optionalName:1, + updateIfNew:1, + compressType:1, + holdTimestamp:1, + functionName:1, + clientCwd:1, + reserve1:1, + reserve2:1, + } + expect(Serialize.serializeTransferConfig(transferConfig)).not.toBeUndefined() + }) + it('Serialize Test04', function () { + let transferPayload = { + index:1, + compressType:1, + compressSize:1, + uncompressSize:1, + } + expect(Serialize.serializeTransferPayload(transferPayload)).not.toBeUndefined() + }) + it('Serialize Test06', function () { + let data ={ + buffer:1, + } + // @ts-ignore + let uint8Array = new Uint8Array(data); + let dataBuffer = uint8Array.buffer; + expect(Serialize.parseTransferConfig(data)).not.toBeUndefined() + }) + it('Serialize Test05', function () { + let tagKey = 1; + expect(Serialize.readTagWireType(tagKey)).not.toBeUndefined() + }) + it('Serialize Test07', function () { + let data ={ + buffer:1, + } + // @ts-ignore + let uint8Array = new Uint8Array(data); + let dataBuffer = uint8Array.buffer; + expect(Serialize.parsePayloadProtect(data)).not.toBeUndefined() + }) + + it('Serialize Test08', function () { + expect(Serialize.writeVarIntU64(100_000_000)).not.toBeUndefined(); + }); + + it('Serialize Test09', function () { + let data ={ + buffer:1, + } + // @ts-ignore + let uint8Array = new Uint8Array(data); + expect(Serialize.parseString(uint8Array,1)).not.toBeUndefined(); + }); + + it('Serialize Test10', function () { + let data ={ + buffer:1, + } + // @ts-ignore + let uint8Array = new Uint8Array(data); + expect(Serialize.parseHandshake(uint8Array)).toEqual({"_authType": -1, "_banner": "", "_buf": "", "_connectKey": "", "_sessionId": -1, "_version": ""}); + }); + + it('Serialize Test11', function () { + expect(Serialize.writeVarIntU32(100_000_000)).not.toBeUndefined(); + }) +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneCpuByProcess.test.ts b/host/ide/test/hdc/common/Utils.test.ts similarity index 31% rename from host/ide/test/trace/component/trace/sheet/TabPaneCpuByProcess.test.ts rename to host/ide/test/hdc/common/Utils.test.ts index 94fb290f37b9f2728598024db51d122228852d31..821ba765ad5ec584ac6a132a6f9db2e8a345e9f3 100644 --- a/host/ide/test/trace/component/trace/sheet/TabPaneCpuByProcess.test.ts +++ b/host/ide/test/hdc/common/Utils.test.ts @@ -14,40 +14,46 @@ */ // @ts-ignore -import {TabPaneCpuByProcess} from "../../../../../dist/trace/component/trace/sheet/TabPaneCpuByProcess.js" -const sqlit = require("../../../../../dist/trace/database/SqlLite.js") -jest.mock("../../../../../dist/trace/database/SqlLite.js"); -describe('TabPaneCpuByProcess Test', () => { - let tabPaneCpuByProcess = new TabPaneCpuByProcess(); - tabPaneCpuByProcess.sortByColumn = jest.fn(()=> true) - - it('TabPaneCpuByProcessTest01', function () { - expect(tabPaneCpuByProcess.sortByColumn({ - key: 'name', - sort: () => { - } - })).toBeTruthy(); - }); +import {Utils} from "../../../dist/hdc/common/Utils.js"; + +describe('UtilsTest', () => { + + it('UtilsTest_getLocalId_01', () => { + expect(Utils.getLocalId()).toBeTruthy() + }) - it('TabPaneCpuByProcessTest02', function () { - let mockgetTabCpuByProcess = sqlit.getTabCpuByProcess - mockgetTabCpuByProcess.mockResolvedValue([{process : "test", - wallDuration: 10, - occurrences: 10 - }, - {process : "test2", - wallDuration: 11, - occurrences: 11 - }] - ) - let a = {rightNs: 1, cpus: [11, 12, 13]} - expect(tabPaneCpuByProcess.data = a).toBeTruthy(); + it('UtilsTest_getLocalId_02', () => { + Utils.localId = 4294967295; + expect(Utils.getLocalId()).toBe(1); }); - it('TabPaneCpuByProcessTest03', function () { - let mockgetTabCpuByProcess = sqlit.getTabCpuByProcess - mockgetTabCpuByProcess.mockResolvedValue([]) - let a = {rightNs: 1, cpus: [11, 12, 13]} - expect(tabPaneCpuByProcess.data = a).toBeTruthy(); + it('UtilsTest_getSessionId_01', () => { + expect(Utils.getSessionId()).toBeTruthy() + }) + + it('UtilsTest_formatCommand_01', () => { + expect(Utils.formatCommand("hdc_std shell killall hiprofilerd hiprofiler_plugins native_daemon hiperf" + + " hiprofiler_cmd")).toEqual({"bJumpDo": false, "cmdFlag": 1001, "parameters": "killall hiprofilerd hiprofiler_plugins native_daemon hiperf hiprofiler_cmd"}) + }) + + it('UtilsTest_formatCommand_02', () => { + expect(Utils.formatCommand("abc")).toEqual({"bJumpDo": true, "cmdFlag": -1, "parameters": ""}) + }) + + it('UtilsTest_formatCommand_03', () => { + expect(Utils.formatCommand("hdc")).toEqual({"bJumpDo": true, "cmdFlag": -1, "parameters": ""}); }); -}) + + it('UtilsTest_numToHexString_01', () => { + expect(Utils.numToHexString(1)).toBe("0x1") + }) + + it('UtilsTest_numToHexString_02', () => { + expect(Utils.numToHexString(-1)).toBe("0xffffffff") + }) + + it('UtilsTest_numToHexString_03', () => { + expect(Utils.numToHexString(undefined)).toBe("0x0") + }) + +}); \ No newline at end of file diff --git a/host/ide/test/hdc/hdcclient/AsyncQueue.test.ts b/host/ide/test/hdc/hdcclient/AsyncQueue.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..ffcd28b59ea19e2258c3b7658a3903bac2aaa737 --- /dev/null +++ b/host/ide/test/hdc/hdcclient/AsyncQueue.test.ts @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {AsyncQueue, DataMessageQueue} from "../../../dist/hdc/hdcclient/AsyncQueue.js"; + +describe('AsyncQueueTest', () => { + let queue = new DataMessageQueue(); + let dataMessageQueue = new DataMessageQueue(); + let asqueue = new AsyncQueue(); + it('AsyncQueueTest_DataMessageQueue_01', () => { + expect(queue.push("abc")).toEqual(true) + }) + + it('AsyncQueueTest_DataMessageQueue_02', () => { + expect(queue.size()).toEqual(1) + }) + + it('AsyncQueueTest_DataMessageQueue_03', () => { + expect(queue.pop()).toEqual("abc") + }) + + it('AsyncQueueTest_DataMessageQueue_04', () => { + expect(queue.push(null)).toEqual(false) + }); + + it('AsyncQueueTest_AsyncQueue_01', () => { + let dataMessageQueue = new DataMessageQueue(); + dataMessageQueue.push("aaa"); + asqueue.enqueue(dataMessageQueue); + expect(asqueue.dequeue()).toBeTruthy() + }) + +}); \ No newline at end of file diff --git a/host/ide/test/hdc/hdcclient/FormatCommand.test.ts b/host/ide/test/hdc/hdcclient/FormatCommand.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..fe62b1fa2662b6aef964daea2ebca5ae47f2ff9a --- /dev/null +++ b/host/ide/test/hdc/hdcclient/FormatCommand.test.ts @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {FormatCommand} from "../../../dist/hdc/hdcclient/FormatCommand.js"; +// @ts-ignore +import {CmdConstant} from "../../../dist/command/CmdConstant.js"; + +describe('FormatCommandTest', () => { + it('FormatCommandTest_FormatCommand_01', () => { + expect(FormatCommand.string2FormatCommand(CmdConstant.CMD_TRACE_FILE_SIZE)).toEqual({"bJumpDo": true, "cmdFlag": -1, "parameters": ""}) + }) + + it('FormatCommandTest_FormatCommand_02', () => { + expect(FormatCommand.string2FormatCommand("shell ps")).toEqual({"bJumpDo": false, "cmdFlag": 1001, "parameters": "ps"}) + }) + + it('FormatCommandTest_FormatCommand_03', () => { + expect(FormatCommand.string2FormatCommand("shell")).toEqual({"bJumpDo": false, "cmdFlag": 2000, "parameters": ""}) + }) + + it('FormatCommandTest_FormatCommand_04', () => { + expect(FormatCommand.string2FormatCommand("file recv demo")).toEqual({"bJumpDo": false, "cmdFlag":3000, "parameters": "demo"}) + }) + + it('FormatCommandTest_FormatCommand_05', () => { + expect(FormatCommand.string2FormatCommand("file send demo")).toEqual({"bJumpDo": false, "cmdFlag": 3000, "parameters": "demo"}) + }) + + it('FormatCommandTest_FormatCommand_06', () => { + expect(FormatCommand.string2FormatCommand(CmdConstant.CMD_GET_HIPERF_EVENTS)).toEqual({"bJumpDo": true, "cmdFlag": -1, "parameters": ""}) + }) + + it('FormatCommandTest_FormatCommand_07', () => { + expect(FormatCommand.string2FormatCommand("null")).toEqual({"bJumpDo": true, "cmdFlag": -1, "parameters": ""}) + }) +}); \ No newline at end of file diff --git a/host/ide/test/hdc/hdcclient/HdcClient.test.ts b/host/ide/test/hdc/hdcclient/HdcClient.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..d298241fb4f616e1db2635d70d3fb1b6343211a6 --- /dev/null +++ b/host/ide/test/hdc/hdcclient/HdcClient.test.ts @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {HdcClient} from "../../../dist/hdc/hdcclient/HdcClient.js" +import {HdcCommand} from "../../../src/hdc/hdcclient/HdcCommand"; + +describe('HdcClient Test', ()=>{ + it('HdcClientTest01', function () { + let hdcClient = new HdcClient() + expect(hdcClient.constructor()).toBeUndefined() + + }) + it('HdcClientTest02', function () { + let hdcClient = new HdcClient() + expect(hdcClient.bindStream()).toBeUndefined() + + }) + it('HdcClientTest03', function () { + let hdcClient = new HdcClient() + expect(hdcClient.bindStopStream()).toBeUndefined() + + }) + it('HdcClientTest04', function () { + let hdcClient = new HdcClient() + expect(hdcClient.unbindStream()).toBeTruthy() + + }) + it('HdcClientTest05', function () { + let hdcClient = new HdcClient() + expect(hdcClient.unbindStopStream()).toBeTruthy() + + }) + + it('HdcClientTest06', async ()=> { + let hdcClient = new HdcClient(); + await expect(hdcClient.connectDevice()).rejects.not.toBeUndefined(); + + }); + + it('HdcClientTest07', async ()=> { + let hdcClient = new HdcClient(); + await expect(hdcClient.disconnect()).rejects.not.toBeUndefined(); + + }); + it('HdcClientTest08', function () { + let hdcClient = new HdcClient() + let data ={ + getChannelId:jest.fn(()=>-1) + } + expect(hdcClient.createDataMessage(data)).toBeUndefined() + + }) +}) \ No newline at end of file diff --git a/host/ide/test/hdc/message/DataMessage.test.ts b/host/ide/test/hdc/message/DataMessage.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..2dce2be1d75e38f36d707e51fb923b7b1d27d2b5 --- /dev/null +++ b/host/ide/test/hdc/message/DataMessage.test.ts @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {DataMessage} from "../../../dist/hdc/message/DataMessage.js"; +import {TextEncoder} from "util"; + +describe('DataMessage Test', ()=> { + let dataMessage = new DataMessage(); + dataMessage.body = true; + it('DataMessageTest01', function () { + expect(dataMessage).not.toBeUndefined() + }); + + it('DataMessageTest02', function () { + expect(dataMessage.usbHead).toBeUndefined() + }); + + it('DataMessageTest03', function () { + dataMessage.usbHead = true; + expect(dataMessage.usbHead).toBeTruthy() + }); + + it('DataMessageTest04', function () { + expect(dataMessage.channelId).toBe(-1) + }); + + it('DataMessageTest05', function () { + dataMessage.channelId = true; + expect(dataMessage.channelId).toBeTruthy() + }); + + it('DataMessageTest06', function () { + expect(dataMessage.result).toBe("") + }); + + it('DataMessageTest07', function () { + dataMessage.result = true; + expect(dataMessage.result).toBeTruthy() + }); + + it('DataMessageTest08', function () { + expect(dataMessage.channelClose).toBeFalsy() + }); + + it('DataMessageTest09', function () { + dataMessage.channelClose = true; + expect(dataMessage.channelClose).toBeTruthy() + }); + + it('DataMessageTest10', function () { + expect(dataMessage.commandFlag).toBe(-1) + }); + + it('DataMessageTest11', function () { + dataMessage.commandFlag = true; + expect(dataMessage.commandFlag).toBeTruthy() + }); + + it('DataMessageTest12', function () { + expect(dataMessage.resArrayBuffer).toBeUndefined() + }); + + it('DataMessageTest13', function () { + dataMessage.resArrayBuffer = true; + expect(dataMessage.resArrayBuffer).toBeTruthy() + }); + + it('DataMessageTest14', function () { + expect(dataMessage.toString()).not.toBeUndefined() + }); + + it('DataMessageTest15', function () { + expect(dataMessage.getChannelId()).not.toBeUndefined() + }); + + it('DataMessageTest16', function () { + expect(dataMessage.getData()).not.toBeUndefined() + }); + + it('DataMessageTest17', function () { + let end = new TextEncoder() + + dataMessage.resArrayBuffer =end.encode("111") + expect(dataMessage.getDataToString()).toBe('111'); + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/FrameChart.test.ts b/host/ide/test/hdc/message/PayloadHead.test.ts similarity index 30% rename from host/ide/test/trace/component/FrameChart.test.ts rename to host/ide/test/hdc/message/PayloadHead.test.ts index 71c0410c77dad47efb71e64efd3353b9633dfbc9..98b292262cc821e45bf5f57c761178091b1e1b16 100644 --- a/host/ide/test/trace/component/FrameChart.test.ts +++ b/host/ide/test/hdc/message/PayloadHead.test.ts @@ -14,64 +14,64 @@ */ // @ts-ignore -import {FrameChart} from "../../../dist/trace/component/FrameChart.js" +import {PayloadHead} from "../../../dist/hdc/message/PayloadHead.js" +describe('PayloadHead Test', ()=> { + let payloadHead = new PayloadHead(); + it('PayloadHeadTest01', function () { + expect(payloadHead).not.toBeUndefined() + }); -describe('FrameChart Test', () => { + it('PayloadHeadTest02', function () { + expect(payloadHead.flag).toBeUndefined() + }); - let node= [ - {children: ''}, - {children:{length:1}} - ] + it('PayloadHeadTest03', function () { + payloadHead.flag = true + expect(payloadHead.flag).toBeTruthy() + }); + it('PayloadHeadTest04', function () { + expect(payloadHead.reserve).toBeUndefined() + }); - it('FrameChartTest01', function () { - let frameChart = new FrameChart(); - frameChart.data = false; - expect(frameChart.data).toBeFalsy(); + it('PayloadHeadTest05', function () { + payloadHead.reserve = true + expect(payloadHead.reserve).toBeTruthy() }); - it('FrameChartTest02', function () { - let frameChart = new FrameChart(); - expect(frameChart.data).toBeUndefined(); + it('PayloadHeadTest06', function () { + expect(payloadHead.protocolVer).toBeUndefined() }); - it('FrameChartTest03', function () { - let frameChart = new FrameChart(); - frameChart.selectTotalSize = true; - expect(frameChart.selectTotalSize).toBeUndefined(); + it('PayloadHeadTest07', function () { + payloadHead.protocolVer = true + expect(payloadHead.protocolVer).toBeTruthy() }); - it('FrameChartTest04', function () { - let frameChart = new FrameChart(); - frameChart.maxDepth = true; - expect(frameChart.maxDepth).toBeUndefined(); + it('PayloadHeadTest08', function () { + expect(payloadHead.headSize).toBeUndefined() }); - it('FrameChartTest05',function () { - let frameChart = new FrameChart(); - let result = frameChart.cavasContext.lineWidth ; - expect(result).toBe(1); - }) + it('PayloadHeadTest9', function () { + payloadHead.headSize = true + expect(payloadHead.headSize).toBeTruthy() + }); - it('FrameChartTest06', function () { - let frameChart = new FrameChart(); - expect(frameChart.drawScale()).toBeUndefined(); + it('PayloadHeadTest10', function () { + expect(payloadHead.dataSize).toBeUndefined() }); - it('FrameChartTest07', function () { - let frameChart = new FrameChart(); - expect(frameChart.calculateChartData()).toBeUndefined(); + it('PayloadHeadTest11', function () { + payloadHead.dataSize = true; + expect(payloadHead.dataSize).toBeTruthy() }); - it('FrameChartTest08', function () { - let frameChart = new FrameChart(); - expect(frameChart.darwTypeChart(node)).toBeUndefined(); + it('PayloadHeadTest12', function () { + expect(payloadHead.toString()).toBeTruthy() }); - it('FrameChartTest09', function () { - let frameChart = new FrameChart(); - frameChart.mode = true; - expect(frameChart.mode).toBeTruthy(); + it('PayloadHeadTest13', function () { + expect(payloadHead.getPayloadHeadLength).toBe(undefined) }); }) \ No newline at end of file diff --git a/host/ide/test/hdc/message/PayloadProtect.test.ts b/host/ide/test/hdc/message/PayloadProtect.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..8819a376b870293238611c273329c3b4a15bd674 --- /dev/null +++ b/host/ide/test/hdc/message/PayloadProtect.test.ts @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {PayloadProtect} from "../../../dist/hdc/message/PayloadProtect.js" + +describe('PayloadProtect Test', ()=> { + let payloadProtect = new PayloadProtect(); + it('PayloadProtectTest01', function () { + expect(payloadProtect).not.toBeUndefined() + }); + + it('PayloadProtectTest02', function () { + expect(payloadProtect.channelId).toBeUndefined() + }); + + it('PayloadProtectTest03', function () { + payloadProtect.channelId = true + expect(payloadProtect.channelId).toBeTruthy() + }); + + it('PayloadProtectTest04', function () { + expect(payloadProtect.commandFlag).toBeUndefined() + }); + + it('PayloadProtectTest05', function () { + payloadProtect.commandFlag = true + expect(payloadProtect.commandFlag).toBeTruthy() + }); + + it('PayloadProtectTest06', function () { + expect(payloadProtect.checkSum).toBeUndefined() + }); + + it('PayloadProtectTest07', function () { + payloadProtect.checkSum = true + expect(payloadProtect.checkSum).toBeTruthy() + }); + + it('PayloadProtectTest08', function () { + expect(payloadProtect.vCode).toBeUndefined() + }); + + it('PayloadProtectTest9', function () { + payloadProtect.vCode = true + expect(payloadProtect.vCode).toBeTruthy() + }); + + it('PayloadProtectTest10', function () { + expect(payloadProtect.toString()).toBeTruthy() + }); +}) \ No newline at end of file diff --git a/host/ide/test/hdc/message/SessionHandShake.test.ts b/host/ide/test/hdc/message/SessionHandShake.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..a7662ea742754d4b1637b75d27b40d5e098f9767 --- /dev/null +++ b/host/ide/test/hdc/message/SessionHandShake.test.ts @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SessionHandShake} from "../../../dist/hdc/message/SessionHandShake.js" + +describe('SessionHandShake Test', ()=> { + let sessionHandShake = new SessionHandShake(); + it('SessionHandShakeTest01', function () { + expect(sessionHandShake).not.toBeUndefined() + }); + + it('SessionHandShakeTest02', function () { + expect(sessionHandShake.banner).toBeUndefined() + }); + + it('SessionHandShakeTest03', function () { + sessionHandShake.banner = true + expect(sessionHandShake.banner).toBeTruthy() + }); + + it('SessionHandShakeTest04', function () { + expect(sessionHandShake.authType).toBeUndefined() + }); + + it('SessionHandShakeTest05', function () { + sessionHandShake.authType = true + expect(sessionHandShake.authType).toBeTruthy() + }); + + it('SessionHandShakeTest06', function () { + expect(sessionHandShake.sessionId).toBeUndefined() + }); + + it('SessionHandShakeTest07', function () { + sessionHandShake.sessionId = true + expect(sessionHandShake.sessionId).toBeTruthy() + }); + + it('SessionHandShakeTest08', function () { + expect(sessionHandShake.connectKey).toBeUndefined() + }); + + it('SessionHandShakeTest9', function () { + sessionHandShake.connectKey = true + expect(sessionHandShake.connectKey).toBeTruthy() + }); + + it('SessionHandShakeTest10', function () { + expect(sessionHandShake.buf).toBeUndefined() + }); + + it('SessionHandShakeTest11', function () { + sessionHandShake.buf = true; + expect(sessionHandShake.buf).toBeTruthy() + }); + + it('SessionHandShakeTest12', function () { + expect(sessionHandShake.version).toBe("") + }); + + it('SessionHandShakeTest13', function () { + sessionHandShake.version = true; + expect(sessionHandShake.version).toBeTruthy() + }); + + it('SessionHandShakeTest14', function () { + expect(sessionHandShake.toString()).toBeTruthy() + }); +}) \ No newline at end of file diff --git a/host/ide/test/hdc/message/TransferConfig.test.ts b/host/ide/test/hdc/message/TransferConfig.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..51a9e6c0f494c64c5a52625768f1115c79b8e2e4 --- /dev/null +++ b/host/ide/test/hdc/message/TransferConfig.test.ts @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TransferConfig} from "../../../dist/hdc/message/TransferConfig.js"; + +describe('TransferConfig Test', ()=> { + let transferConfig = new TransferConfig(); + it('TransferConfigTest01', function () { + expect(transferConfig).not.toBeUndefined() + }); + + it('TransferConfigTest02', function () { + expect(transferConfig.fileSize).toBeUndefined() + }); + + it('TransferConfigTest03', function () { + transferConfig.fileSize = true; + expect(transferConfig.fileSize).toBeTruthy() + }); + + it('TransferConfigTest04', function () { + expect(transferConfig.atime).toBeUndefined() + }); + + it('TransferConfigTest05', function () { + transferConfig.atime = true; + expect(transferConfig.atime).toBeTruthy() + }); + + it('TransferConfigTest06', function () { + expect(transferConfig.mtime).toBeUndefined() + }); + + it('TransferConfigTest07', function () { + transferConfig.mtime = true; + expect(transferConfig.mtime).toBeTruthy() + }); + + it('TransferConfigTest08', function () { + expect(transferConfig.options).toBeFalsy() + }); + + it('TransferConfigTest09', function () { + transferConfig.options = true; + expect(transferConfig.options).toBeTruthy() + }); + + it('TransferConfigTest10', function () { + expect(transferConfig.path).toBeUndefined() + }); + + it('TransferConfigTest11', function () { + transferConfig.path = true; + expect(transferConfig.path).toBeTruthy() + }); + + it('TransferConfigTest12', function () { + expect(transferConfig.optionalName).toBeUndefined() + }); + + it('TransferConfigTest13', function () { + transferConfig.optionalName = true; + expect(transferConfig.optionalName).toBeTruthy() + }); + + it('TransferConfigTest14', function () { + expect(transferConfig.updateIfNew).toBeUndefined() + }); + + it('TransferConfigTest15', function () { + transferConfig.updateIfNew = true; + expect(transferConfig.updateIfNew).toBeTruthy() + }); + + it('TransferConfigTest16', function () { + expect(transferConfig.compressType).toBeUndefined() + }); + + it('TransferConfigTest17', function () { + transferConfig.compressType = true; + expect(transferConfig.compressType).toBeTruthy() + }); + + it('TransferConfigTest18', function () { + expect(transferConfig.holdTimestamp).toBeUndefined() + }); + + it('TransferConfigTest19', function () { + transferConfig.holdTimestamp = true; + expect(transferConfig.holdTimestamp).toBeTruthy() + }); + + it('TransferConfigTest20', function () { + expect(transferConfig.functionName).toBeUndefined() + }); + + it('TransferConfigTest21', function () { + transferConfig.functionName = true; + expect(transferConfig.functionName).toBeTruthy() + }); + + it('TransferConfigTest22', function () { + expect(transferConfig.clientCwd).toBeUndefined() + }); + + it('TransferConfigTest23', function () { + transferConfig.clientCwd = true; + expect(transferConfig.clientCwd).toBeTruthy() + }); + + it('TransferConfigTest24', function () { + expect(transferConfig.reserve1).toBeUndefined() + }); + + it('TransferConfigTest25', function () { + transferConfig.reserve1 = true; + expect(transferConfig.reserve1).toBeTruthy() + }); + + it('TransferConfigTest26', function () { + expect(transferConfig.reserve2).toBeUndefined() + }); + + it('TransferConfigTest27', function () { + transferConfig.reserve2 = true; + expect(transferConfig.reserve2).toBeTruthy() + }); + + it('TransferConfigTest28', function () { + expect(transferConfig.toString()).not.toBeUndefined() + }); +}) \ No newline at end of file diff --git a/host/ide/test/hdc/message/TransferPayload.test.ts b/host/ide/test/hdc/message/TransferPayload.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..0ec3a076784d5f898e15ad7659d0cb1452ef9558 --- /dev/null +++ b/host/ide/test/hdc/message/TransferPayload.test.ts @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TransferPayload} from "../../../dist/hdc/message/TransferPayload.js"; + +describe('TransferPayload Test', ()=> { + let transferPayload = new TransferPayload(); + it('TransferPayloadTest01', function () { + expect(transferPayload).not.toBeUndefined() + }); + + it('TransferPayloadTest02', function () { + expect(transferPayload.index).toBeUndefined() + }); + + it('TransferPayloadTest03', function () { + transferPayload.index = true; + expect(transferPayload.index).toBeTruthy() + }); + + it('TransferPayloadTest04', function () { + expect(transferPayload.compressType).toBeUndefined() + }); + + it('TransferPayloadTest05', function () { + transferPayload.compressType = true; + expect(transferPayload.compressType).toBeTruthy() + }); + + it('TransferPayloadTest06', function () { + expect(transferPayload.compressSize).toBeUndefined() + }); + + it('TransferPayloadTest07', function () { + transferPayload.compressSize = true; + expect(transferPayload.compressSize).toBeTruthy() + }); + + it('TransferPayloadTest08', function () { + expect(transferPayload.uncompressSize).toBeFalsy() + }); + + it('TransferPayloadTest09', function () { + transferPayload.uncompressSize = true; + expect(transferPayload.uncompressSize).toBeTruthy() + }); + + it('TransferPayloadTest10', function () { + expect(transferPayload.toString()).not.toBeUndefined() + }); +}) \ No newline at end of file diff --git a/host/ide/test/hdc/message/USBHead.test.ts b/host/ide/test/hdc/message/USBHead.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..2321c4d6806498fde42e352d81958337798948b4 --- /dev/null +++ b/host/ide/test/hdc/message/USBHead.test.ts @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {USBHead} from "../../../dist/hdc/message/USBHead.js"; + +describe('USBHead Test', ()=> { + let usbHead = new USBHead(); + it('USBHeadTest01', function () { + expect(usbHead).not.toBeUndefined() + }); + + it('USBHeadTest02', function () { + expect(usbHead.flag).toBeUndefined() + }); + + it('USBHeadTest03', function () { + usbHead.flag = true; + expect(usbHead.flag).toBeTruthy() + }); + + it('USBHeadTest04', function () { + expect(usbHead.option).toBeUndefined() + }); + + it('USBHeadTest05', function () { + usbHead.option = true; + expect(usbHead.option).toBeTruthy() + }); + + it('USBHeadTest06', function () { + expect(usbHead.sessionId).toBeUndefined() + }); + + it('USBHeadTest07', function () { + usbHead.sessionId = true; + expect(usbHead.sessionId).toBeTruthy() + }); + + it('USBHeadTest08', function () { + expect(usbHead.dataSize).toBeFalsy() + }); + + it('USBHeadTest09', function () { + usbHead.dataSize = true; + expect(usbHead.dataSize).toBeTruthy() + }); + + it('USBHeadTest10', function () { + expect(usbHead.toString()).not.toBeUndefined() + }); + + it('USBHeadTest11', function () { + usbHead.parseHeadData = jest.fn(()=>undefined) + // let data = { + // getUint8:1, + // getUint32:3 + // } + expect(usbHead.parseHeadData()).toBeUndefined() + }); +}) \ No newline at end of file diff --git a/host/ide/test/log/Log.test.ts b/host/ide/test/log/Log.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..22e43424a1d08dfecb07fc152e2720e9c2216ddd --- /dev/null +++ b/host/ide/test/log/Log.test.ts @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {debug, error, info, log, trace, warn, SpLog, LogLevel} from "../../dist/log/Log.js"; + +describe(' logTest', () => { + `` + it('LogTest01', () => { + error("111") + }) + it('LogTest02', () => { + warn("111") + }) + it('LogTest03', () => { + info("111") + }) + it('LogTest04', () => { + debug("111") + }) + it('LogTest05', () => { + trace("111") + }) + it('LogTest06', () => { + log("111") + }) +}); \ No newline at end of file diff --git a/host/ide/test/trace/SpApplication.test.ts b/host/ide/test/trace/SpApplication.test.ts index c4817f6962f420c00f8a6cceecb5136120d1cfbb..41031316948a477461e590bc5d4aaeef01326470 100644 --- a/host/ide/test/trace/SpApplication.test.ts +++ b/host/ide/test/trace/SpApplication.test.ts @@ -15,7 +15,6 @@ // @ts-ignore import {SpApplication} from "../../dist/trace/SpApplication.js"; -import {LitMainMenu} from "../../src/base-ui/menu/LitMainMenu"; window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ @@ -25,89 +24,372 @@ window.ResizeObserver = window.ResizeObserver || })); describe('spApplication Test', ()=>{ - it('spApplicationTest01', function () { - let spApplication = new SpApplication(); - expect(spApplication).not.toBeUndefined() - }); + it('spApplicationTest01',function (){ + document.body.innerHTML= `` + let element = new SpApplication(); + element.dark = 'dark' + expect(element.dark).toBeTruthy() + }) - it('spApplicationTest02', function () { - let spApplication = new SpApplication(); - expect(spApplication.sqlite).toBeFalsy() - }); + it('spApplicationTest02',function (){ + document.body.innerHTML= `` + let element = new SpApplication(); + element.dark = '' + expect(element.dark).toBeFalsy() + }) + it('spApplicationTest03',function (){ + document.body.innerHTML= `` + let element = new SpApplication(); + element.vs = 'vs' + expect(element.vs).toBeTruthy() + }) - it('spApplicationTest03', function () { - let spApplication = new SpApplication(); - expect(spApplication.wasm).toBeFalsy() - }); + it('spApplicationTest04',function (){ + document.body.innerHTML= `` + let element = new SpApplication(); + element.vs = '' + expect(element.vs).toBeFalsy() + }) - it('spApplicationTest04', function () { - let spApplication = new SpApplication(); - expect(spApplication.server).toBeFalsy() - }); + it('spApplicationTest05',function (){ + document.body.innerHTML= `` + let element = new SpApplication(); + element.server = "server" + expect(element.server).toBeTruthy() + }) + it('spApplicationTest06',function (){ + document.body.innerHTML= `` + let element = new SpApplication(); + element.server = "" + expect(element.server).toBeFalsy() + }) - it('spApplicationTest05', function () { - let spApplication = new SpApplication(); - spApplication.server = true; - expect(spApplication.server).toBeTruthy() - }); + it('spApplicationTest07',function (){ + document.body.innerHTML= `` + let element = new SpApplication(); + element.querySql = "querySql" + expect(element.querySql).toBeTruthy() + }) - it('spApplicationTest06', function () { - let spApplication = new SpApplication(); - spApplication.server = false; - expect(spApplication.server).toBeFalsy() + it('spApplicationTest08',function (){ + document.body.innerHTML= `` + let element = new SpApplication(); + element.querySql = "" + expect(element.querySql).toBeFalsy() + }) + + it('spApplicationTest09',function (){ + document.body.innerHTML= `` + let element = new SpApplication(); + element.search = "search" + expect(element.querySql).toBeTruthy() + }) + + it('spApplicationTest10',function (){ + document.body.innerHTML= `` + let element = new SpApplication(); + element.search = "" + expect(element.search).toBeFalsy() + }) + + it('spApplicationTest11',function (){ + document.body.innerHTML= `` + let element = new SpApplication(); + expect(element.removeSkinListener()).toBeUndefined() + }) + + it('spApplicationTest15',function (){ + document.body.innerHTML = ''; + let spApplication = document.querySelector('#sss') as SpApplication; + expect(spApplication.freshMenuDisable()).toBeUndefined(); + }) + + it('spApplicationTest16',function (){ + document.body.innerHTML = ''; + let spApplication = document.querySelector('#sss') as SpApplication; + expect(spApplication.addSkinListener()).toBeUndefined(); + }) + + it('spApplicationTest17',function (){ + document.body.innerHTML = ''; + let spApplication = document.querySelector('#sss') as SpApplication; + expect(spApplication.removeSkinListener()).toBeUndefined() + }) + + it('spApplicationTest18',function (){ + document.body.innerHTML= "" + let element = document.querySelector("#sp") as SpApplication; + element.dispatchEvent(new Event("dragleave")) + }) + + it('spApplicationTest19',function (){ + document.body.innerHTML= "" + let element = document.querySelector("#sp") as SpApplication; + element.dispatchEvent(new Event("drop")) + SpApplication.removeSkinListener = jest.fn(()=>undefined) + expect(SpApplication.removeSkinListener()).toBeUndefined() + }) + it('spApplicationTest21', function () { + document.body.innerHTML= "" + let element = document.querySelector("#sp") as SpApplication; + expect(element.vsDownload()).toBeUndefined() }); - it('spApplicationTest07', function () { - let spApplication = new SpApplication(); - spApplication.search = false; - expect(spApplication.search).toBeFalsy() + it('spApplicationTest22', function () { + document.body.innerHTML = ''; + let spApplication = document.querySelector('#sss') as SpApplication; + spApplication.showConten = false; + expect(spApplication.showContent).toBeFalsy() }); - it('spApplicationTest08', function () { + it('spApplicationTest23', function () { let spApplication = new SpApplication(); - spApplication.search = true; - expect(spApplication.search).toBeUndefined() + spApplication.openTraceFile = true; + expect(spApplication.openTraceFile).toBeTruthy() }); - it('spApplicationTest09', function () { + it('spApplicationTest24', function () { let spApplication = new SpApplication(); - expect(spApplication.dark).toBeFalsy() + spApplication.openTraceFile = false; + expect(spApplication.openTraceFile).toBeFalsy() }); - it('spApplicationTest010', function () { - let spApplication = new SpApplication(); - spApplication.dark = true; - expect(spApplication.dark).toBeTruthy() + + it('spApplicationTest25', function () { + document.body.innerHTML = ''; + let spApplication = document.querySelector('#sss') as SpApplication; + expect(spApplication.initHtml()).toMatchInlineSnapshot(` +" + +
+ +
+
+
+ + + +
+ +
+ +
+
+ + + + + + + + + +
+
+ " +`); }); - it('spApplicationTest11', function () { - let spApplication = new SpApplication(); + it('spApplicationTest26', function () { + document.body.innerHTML = ''; + let spApplication = document.querySelector('#sss') as SpApplication; spApplication.dark = false; - expect(spApplication.dark).toBeFalsy() + spApplication.skinChangeArray = ['item']; + expect(spApplication.dark).toBeFalsy(); }); - it('spApplicationTest12', function () { - let spApplication = new SpApplication(); - expect(spApplication.vs).toBeFalsy() - }); - it('spApplicationTest013', function () { - let spApplication = new SpApplication(); - spApplication.vs = true; - expect(spApplication.vs).toBeTruthy() + it('spApplicationTest27', function () { + document.body.innerHTML = ''; + let spApplication = document.querySelector('#sss') as SpApplication; + spApplication.dark = true; + spApplication.skinChange = jest.fn(()=>true); + expect(spApplication.dark).toBeTruthy(); }); - it('spApplicationTest14', function () { - let spApplication = new SpApplication(); - spApplication.vs = false; - expect(spApplication.vs).toBeFalsy() + it('spApplicationTest28', function () { + document.body.innerHTML = ''; + let spApplication = document.querySelector('#sss') as SpApplication; + spApplication.dark = false; + spApplication.skinChange2 = jest.fn(()=>true); + expect(spApplication.dark).toBeFalsy(); }); - it('spApplicationTest15',function (){ - let spApplication = new SpApplication(); - expect(spApplication.freshMenuDisable).toBeTruthy() - }) + it('spApplicationTest29', function () { + document.body.innerHTML = ''; + let spApplication = document.querySelector('#sss') as SpApplication; + spApplication.querySql = false; + expect(spApplication.querySql).toBeFalsy(); + }); }) diff --git a/host/ide/test/trace/bean/AbilityMonitor.test.ts b/host/ide/test/trace/bean/AbilityMonitor.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..e716c589c52db02b7728f513843d6d0ddbb6b0f7 --- /dev/null +++ b/host/ide/test/trace/bean/AbilityMonitor.test.ts @@ -0,0 +1,390 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//@ts-ignore +import {SystemCpuSummary, SystemDiskIOSummary, ProcessHistory, LiveProcess, SystemNetworkSummary, SystemMemorySummary} from "../../../dist/trace/bean/AbilityMonitor.js" + +describe('AbilityMonitor Test', ()=>{ + let systemCpuSummary = new SystemCpuSummary(); + let systemDiskIOSummary = new SystemDiskIOSummary(); + let processHistory = new ProcessHistory(); + let liveProcess = new LiveProcess(); + let systemNetworkSummary = new SystemNetworkSummary(); + let systemMemorySummary = new SystemMemorySummary(); + + it('SystemCpuSummaryTest', function () { + systemCpuSummary = { + startTime: -1, + startTimeStr: "startTimeStr", + duration: -1, + durationStr: "durationStr", + totalLoad: -1, + totalLoadStr: "totalLoadStr", + userLoad: -1, + userLoadStr: "userLoadStr", + systemLoad: -1, + systemLoadStr: "systemLoadStr", + threads: -1, + threadsStr: "threadsStr", + }; + + expect(systemCpuSummary).not.toBeUndefined() + expect(systemCpuSummary).toMatchInlineSnapshot({ + startTime: expect.any(Number), + startTimeStr: expect.any(String), + duration: expect.any(Number), + durationStr: expect.any(String), + totalLoad: expect.any(Number), + totalLoadStr: expect.any(String), + userLoad: expect.any(Number), + userLoadStr: expect.any(String), + systemLoad: expect.any(Number), + systemLoadStr: expect.any(String), + threads: expect.any(Number), + threadsStr: expect.any(String) }, ` +Object { + "duration": Any, + "durationStr": Any, + "startTime": Any, + "startTimeStr": Any, + "systemLoad": Any, + "systemLoadStr": Any, + "threads": Any, + "threadsStr": Any, + "totalLoad": Any, + "totalLoadStr": Any, + "userLoad": Any, + "userLoadStr": Any, +} +`); + }); + + it('SystemCpuSummaryTest', function () { + systemDiskIOSummary = { + startTime: 1, + startTimeStr: "startTimeStr", + duration: 1, + durationStr: "durationStr", + dataRead: 1, + dataReadStr: "dataReadStr", + dataReadSec: 1, + dataReadSecStr: "dataReadSecStr", + dataWrite: 1, + dataWriteStr: "dataWriteStr", + dataWriteSec: 1, + dataWriteSecStr: "dataWriteSecStr", + readsIn: 1, + readsInStr: "readsInStr", + readsInSec: 1, + readsInSecStr: "readsInSecStr", + writeOut: 1, + writeOutStr: "writeOutStr", + writeOutSec: 1, + writeOutSecStr: "writeOutSecStr", + } + expect(systemDiskIOSummary).not.toBeUndefined(); + expect(systemDiskIOSummary).toMatchInlineSnapshot({ + startTime: expect.any(Number), + startTimeStr: expect.any(String), + duration: expect.any(Number), + durationStr: expect.any(String), + dataRead: expect.any(Number), + dataReadStr: expect.any(String), + dataReadSec: expect.any(Number), + dataReadSecStr: expect.any(String), + dataWrite: expect.any(Number), + dataWriteStr: expect.any(String), + dataWriteSec: expect.any(Number), + dataWriteSecStr: expect.any(String), + readsIn: expect.any(Number), + readsInStr: expect.any(String), + readsInSec: expect.any(Number), + readsInSecStr: expect.any(String), + writeOut: expect.any(Number), + writeOutStr: expect.any(String), + writeOutSec: expect.any(Number), + writeOutSecStr: expect.any(String) }, ` +Object { + "dataRead": Any, + "dataReadSec": Any, + "dataReadSecStr": Any, + "dataReadStr": Any, + "dataWrite": Any, + "dataWriteSec": Any, + "dataWriteSecStr": Any, + "dataWriteStr": Any, + "duration": Any, + "durationStr": Any, + "readsIn": Any, + "readsInSec": Any, + "readsInSecStr": Any, + "readsInStr": Any, + "startTime": Any, + "startTimeStr": Any, + "writeOut": Any, + "writeOutSec": Any, + "writeOutSecStr": Any, + "writeOutStr": Any, +} +`); + }); + + it('SystemCpuSummaryTest', function () { + systemDiskIOSummary = { + startTime: 1, + startTimeStr: "startTimeStr", + duration: 1, + durationStr: "durationStr", + dataRead: 1, + dataReadStr: "dataReadStr", + dataReadSec: 1, + dataReadSecStr: "dataReadSecStr", + dataWrite: 1, + dataWriteStr: "dataWriteStr", + dataWriteSec: 1, + dataWriteSecStr: "dataWriteSecStr", + readsIn: 1, + readsInStr: "readsInStr", + readsInSec: 1, + readsInSecStr: "readsInSecStr", + writeOut: 1, + writeOutStr: "writeOutStr", + writeOutSec: 1, + writeOutSecStr: "writeOutSecStr", + } + expect(systemDiskIOSummary).not.toBeUndefined(); + expect(systemDiskIOSummary).toMatchInlineSnapshot({ + startTime: expect.any(Number), + startTimeStr: expect.any(String), + duration: expect.any(Number), + durationStr: expect.any(String), + dataRead: expect.any(Number), + dataReadStr: expect.any(String), + dataReadSec: expect.any(Number), + dataReadSecStr: expect.any(String), + dataWrite: expect.any(Number), + dataWriteStr: expect.any(String), + dataWriteSec: expect.any(Number), + dataWriteSecStr: expect.any(String), + readsIn: expect.any(Number), + readsInStr: expect.any(String), + readsInSec: expect.any(Number), + readsInSecStr: expect.any(String), + writeOut: expect.any(Number), + writeOutStr: expect.any(String), + writeOutSec: expect.any(Number), + writeOutSecStr: expect.any(String) }, ` +Object { + "dataRead": Any, + "dataReadSec": Any, + "dataReadSecStr": Any, + "dataReadStr": Any, + "dataWrite": Any, + "dataWriteSec": Any, + "dataWriteSecStr": Any, + "dataWriteStr": Any, + "duration": Any, + "durationStr": Any, + "readsIn": Any, + "readsInSec": Any, + "readsInSecStr": Any, + "readsInStr": Any, + "startTime": Any, + "startTimeStr": Any, + "writeOut": Any, + "writeOutSec": Any, + "writeOutSecStr": Any, + "writeOutStr": Any, +} +`); + }); + + it('ProcessHistoryTest', function () { + processHistory = { + processId: -1, + alive: '', + firstSeen: '', + lastSeen: '', + processName: "", + responsibleProcess: "", + userName: "", + cpuTime: '', + } + expect(processHistory).not.toBeUndefined(); + expect(processHistory).toMatchInlineSnapshot({ + processId: expect.any(Number), + alive: expect.any(String), + firstSeen: expect.any(String), + lastSeen: expect.any(String), + processName: expect.any(String), + responsibleProcess: expect.any(String), + userName: expect.any(String), + cpuTime: expect.any(String) }, ` +Object { + "alive": Any, + "cpuTime": Any, + "firstSeen": Any, + "lastSeen": Any, + "processId": Any, + "processName": Any, + "responsibleProcess": Any, + "userName": Any, +} +`); + }); + + it('LiveProcessTest', function () { + liveProcess = { + processId: -1, + processName: "", + responsibleProcess: "", + userName: "", + cpu: '', + threads: -1, + } + expect(liveProcess).not.toBeUndefined(); + expect(liveProcess).toMatchInlineSnapshot({ + processId: expect.any(Number), + processName: expect.any(String), + responsibleProcess: expect.any(String), + userName: expect.any(String), + cpu: expect.any(String), + threads: expect.any(Number) }, ` +Object { + "cpu": Any, + "processId": Any, + "processName": Any, + "responsibleProcess": Any, + "threads": Any, + "userName": Any, +} +`) + }); + + it('SystemNetworkSummaryTest', function () { + systemNetworkSummary = { + startTime: -1, + startTimeStr: "", + duration: -1, + durationStr: "", + dataReceived: -1, + dataReceivedStr: "", + dataReceivedSec: -1, + dataReceivedSecStr: "", + dataSend: -1, + dataSendStr: "", + dataSendSec: -1, + dataSendSecStr: "", + packetsIn: -1, + packetsInSec: -1, + packetsOut: -1, + packetsOutSec: -1, + } + expect(systemNetworkSummary).not.toBeUndefined(); + expect(systemNetworkSummary).toMatchInlineSnapshot({ + startTime: expect.any(Number), + startTimeStr: expect.any(String), + duration: expect.any(Number), + durationStr: expect.any(String), + dataReceived: expect.any(Number), + dataReceivedStr: expect.any(String), + dataReceivedSec: expect.any(Number), + dataReceivedSecStr: expect.any(String), + dataSend: expect.any(Number), + dataSendStr: expect.any(String), + dataSendSec: expect.any(Number), + dataSendSecStr: expect.any(String), + packetsIn: expect.any(Number), + packetsInSec: expect.any(Number), + packetsOut: expect.any(Number), + packetsOutSec: expect.any(Number) }, ` +Object { + "dataReceived": Any, + "dataReceivedSec": Any, + "dataReceivedSecStr": Any, + "dataReceivedStr": Any, + "dataSend": Any, + "dataSendSec": Any, + "dataSendSecStr": Any, + "dataSendStr": Any, + "duration": Any, + "durationStr": Any, + "packetsIn": Any, + "packetsInSec": Any, + "packetsOut": Any, + "packetsOutSec": Any, + "startTime": Any, + "startTimeStr": Any, +} +`) + }); + + it('systemMemorySummaryTest', function () { + systemMemorySummary = { + startTime: -1, + startTimeStr: "", + duration: -1, + durationStr: "", + memoryTotal: -1, + memoryTotalStr: "", + cached: -1, + cachedStr: "", + swapTotal: -1, + swapTotalStr: "", + appMemory: -1, + cachedFiles: -1, + compressed: -1, + memoryUsed: -1, + wiredMemory: -1, + swapUsed: -1, + } + expect(systemMemorySummary).not.toBeUndefined(); + expect(systemMemorySummary).toMatchInlineSnapshot({ + startTime: expect.any(Number), + startTimeStr: expect.any(String), + duration: expect.any(Number), + durationStr: expect.any(String), + memoryTotal: expect.any(Number), + memoryTotalStr: expect.any(String), + cached: expect.any(Number), + cachedStr: expect.any(String), + swapTotal: expect.any(Number), + swapTotalStr: expect.any(String), + appMemory: expect.any(Number), + cachedFiles: expect.any(Number), + compressed: expect.any(Number), + memoryUsed: expect.any(Number), + wiredMemory: expect.any(Number), + swapUsed: expect.any(Number) }, ` +Object { + "appMemory": Any, + "cached": Any, + "cachedFiles": Any, + "cachedStr": Any, + "compressed": Any, + "duration": Any, + "durationStr": Any, + "memoryTotal": Any, + "memoryTotalStr": Any, + "memoryUsed": Any, + "startTime": Any, + "startTimeStr": Any, + "swapTotal": Any, + "swapTotalStr": Any, + "swapUsed": Any, + "wiredMemory": Any, +} +`) + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/bean/BaseStruct.test.ts b/host/ide/test/trace/bean/BaseStruct.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..4396e2cad5783203b950dcb5d3dc9ebc793f8326 --- /dev/null +++ b/host/ide/test/trace/bean/BaseStruct.test.ts @@ -0,0 +1 @@ +/* * Copyright (C) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //@ts-ignore import { BaseStruct} from "../../../dist/trace/bean/BaseStruct.js" describe('BaseStruct Test', ()=>{ let baseStruct = new BaseStruct(); it('BaseStructTest01', function () { baseStruct = { isHover : false, }; expect(baseStruct).not.toBeUndefined() }) }) \ No newline at end of file diff --git a/host/ide/test/trace/bean/BoxSelection.test.ts b/host/ide/test/trace/bean/BoxSelection.test.ts index 1171184d06f232b293efcfd624c81a8f81ae8d38..b8fa034a6b6e43b72ee016c15819f8f4d14ebeea 100644 --- a/host/ide/test/trace/bean/BoxSelection.test.ts +++ b/host/ide/test/trace/bean/BoxSelection.test.ts @@ -14,27 +14,186 @@ */ // @ts-ignore -import {SelectionParam, SelectionData, Counter, Fps} from "../../../dist/trace/bean/BoxSelection.js" +import {SelectionParam, BoxJumpParam, SelectionData, Counter, Fps} from "../../../dist/trace/bean/BoxSelection.js" describe('BoxSelection Test', ()=>{ let selectionParam = new SelectionParam(); + let boxJumpParam = new BoxJumpParam(); let selectionData = new SelectionData(); let counter = new Counter(); let fps = new Fps(); - it('BoxSelectionTest01', function () { + selectionParam = { + cpus: 1, + threadIds: 2, + trackIds: 1, + funTids: 2, + heapIds: 1, + nativeMemory: 3, + leftNs: 1, + rightNs: 1, + hasFps: true, + statisticsSelectData: 1, + }; + expect(selectionParam).not.toBeUndefined() + expect(selectionParam).toMatchInlineSnapshot({ + cpus: expect.any(Number), + threadIds: expect.any(Number), + trackIds: expect.any(Number), + funTids: expect.any(Number), + heapIds: expect.any(Number), + nativeMemory: expect.any(Number), + leftNs: expect.any(Number), + rightNs: expect.any(Number), + hasFps: expect.any(Boolean) }, ` +Object { + "cpus": Any, + "funTids": Any, + "hasFps": Any, + "heapIds": Any, + "leftNs": Any, + "nativeMemory": Any, + "rightNs": Any, + "statisticsSelectData": 1, + "threadIds": Any, + "trackIds": Any, +} +`); }); it('BoxSelectionTest02', function () { - expect(selectionData).not.toBeUndefined() - }); + boxJumpParam = { + leftNs: 0, + rightNs: 0, + state: "", + processId: 0, + threadId: 0, + }; + expect(boxJumpParam).not.toBeUndefined() + expect(boxJumpParam).toMatchInlineSnapshot({ + leftNs: expect.any(Number), + rightNs: expect.any(Number), + state: expect.any(String), + processId: expect.any(Number), + threadId: expect.any(Number) }, ` +Object { + "leftNs": Any, + "processId": Any, + "rightNs": Any, + "state": Any, + "threadId": Any, +} +`); + }); it('BoxSelectionTest03', function () { + selectionData = { + name: "name", + process: "process", + pid: "pid", + thread: "thread", + tid: "tid", + wallDuration: 0, + avgDuration: "avgDuration", + occurrences: 0, + state: "state", + trackId: 0, + delta: "delta", + rate: "rate", + avgWeight: "avgWeight", + count: "count", + first: "first", + last: "last", + min: "min", + max: "max", + stateJX: "stateJX", + }; + expect(selectionData).not.toBeUndefined() + expect(selectionData).toMatchInlineSnapshot({ + process: expect.any(String), + pid: expect.any(String), + thread: expect.any(String), + tid: expect.any(String), + wallDuration: expect.any(Number), + avgDuration: expect.any(String), + occurrences: expect.any(Number), + state: expect.any(String), + trackId: expect.any(Number), + delta: expect.any(String), + rate: expect.any(String), + avgWeight: expect.any(String), + count: expect.any(String), + first: expect.any(String), + last: expect.any(String), + min: expect.any(String), + max: expect.any(String), + stateJX: expect.any(String) }, ` +Object { + "avgDuration": Any, + "avgWeight": Any, + "count": Any, + "delta": Any, + "first": Any, + "last": Any, + "max": Any, + "min": Any, + "name": "name", + "occurrences": Any, + "pid": Any, + "process": Any, + "rate": Any, + "state": Any, + "stateJX": Any, + "thread": Any, + "tid": Any, + "trackId": Any, + "wallDuration": Any, +} +`); + }); + + it('BoxSelectionTest04', function () { + counter = { + id: 0, + trackId: 0, + name: "", + value: 0, + startTime: 0, + }; expect(counter).not.toBeUndefined() + expect(counter).toMatchInlineSnapshot({ + id: expect.any(Number), + trackId: expect.any(Number), + name: expect.any(String), + value: expect.any(Number), + startTime: expect.any(Number) }, ` +Object { + "id": Any, + "name": Any, + "startTime": Any, + "trackId": Any, + "value": Any, +} +`) }); - it('BoxSelectionTest04', function () { + it('BoxSelectionTest05', function () { + fps = { + startNS: 0, + timeStr: "", + fps: 0, + }; expect(fps).not.toBeUndefined() + expect(fps).toMatchInlineSnapshot({ + startNS: expect.any(Number), + timeStr: expect.any(String), + fps: expect.any(Number) }, ` +Object { + "fps": Any, + "startNS": Any, + "timeStr": Any, +} +`); }); }) diff --git a/host/ide/test/trace/bean/CpuFreqStruct.test.ts b/host/ide/test/trace/bean/CpuFreqStruct.test.ts index 1d716aa3fac33d601e13cb05705be1d3e5e9964c..1a854e79a31be24593664ad1d1b8195dd2c9f09a 100644 --- a/host/ide/test/trace/bean/CpuFreqStruct.test.ts +++ b/host/ide/test/trace/bean/CpuFreqStruct.test.ts @@ -33,7 +33,42 @@ describe('CpuFreqStruct Test', ()=>{ startNS: 200, value: 50 } + + const dataSource = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + value: 50, + maxFreq: 50 + } + it('CpuFreqStructTest01', function () { expect(CpuFreqStruct.draw(ctx, data)).toBeUndefined() + expect(data).toMatchInlineSnapshot({ + startNS: expect.any(Number), + value: expect.any(Number) }, ` +Object { + "frame": Object { + "height": 100, + "width": 100, + "x": 20, + "y": 20, + }, + "startNS": Any, + "value": Any, +} +`); + }); + + it('CpuFreqStructTest02', function () { + expect(CpuFreqStruct.draw(ctx, {startNS:1})).toBeUndefined() + }); + + it('CpuFreqStructTest03 ', function () { + expect(CpuFreqStruct.draw(ctx,dataSource)).toBeUndefined() + }); }) diff --git a/host/ide/test/trace/bean/CpuStruct.test.ts b/host/ide/test/trace/bean/CpuStruct.test.ts index 266521c88c77e39de3dcf8a160b414c70d014684..fb6e0f3b359d26e3e1251828f8e09d94360c9122 100644 --- a/host/ide/test/trace/bean/CpuStruct.test.ts +++ b/host/ide/test/trace/bean/CpuStruct.test.ts @@ -21,6 +21,8 @@ describe('CpuStruct Test', ()=>{ canvas.width = 1; canvas.height = 1; const ctx = canvas.getContext('2d'); + CpuStruct.selectCpuStruct = {}; + const data = { frame: { @@ -32,11 +34,83 @@ describe('CpuStruct Test', ()=>{ startNS: 200, value: 50 } + const data1 = { + frame: { + x: 100, + y: 100, + width: 10, + height: 10 + }, + startNS: 1000, + value: 500 + } + + + it('CpuStructTest01', function () { expect(CpuStruct.draw(ctx, data)).toBeUndefined() + expect(data).toMatchInlineSnapshot({ + startNS: expect.any(Number), + value: expect.any(Number) }, ` +Object { + "frame": Object { + "height": 100, + "width": 100, + "x": 20, + "y": 20, + }, + "startNS": Any, + "value": Any, +} +`); }); it('CpuStructTest02', function () { expect(CpuStruct.equals({}, data)).toBeTruthy(); }); + + it('CpuStructTest03', function () { + expect(CpuStruct.equals(data, data)).toBeTruthy(); + }); + + it('CpuStructTest04', function () { + expect(CpuStruct.equals(data, data1)).toBeTruthy(); + }); + + it('CpuStructTest05', function () { + expect(CpuStruct.draw(ctx, data1)).toBeUndefined() + expect(data1).toMatchInlineSnapshot({ + startNS: expect.any(Number), + value: expect.any(Number) }, ` +Object { + "frame": Object { + "height": 10, + "width": 10, + "x": 100, + "y": 100, + }, + "startNS": Any, + "value": Any, +} +`); + }); + + it('CpuStructTest06', function () { + expect(CpuStruct.equals({}, data)).toBeTruthy(); + expect(CpuStruct.draw(ctx, data1)).toBeUndefined() + expect(data1).toMatchInlineSnapshot({ + startNS: expect.any(Number), + value: expect.any(Number) }, ` +Object { + "frame": Object { + "height": 10, + "width": 10, + "x": 100, + "y": 100, + }, + "startNS": Any, + "value": Any, +} +`); + }); }) diff --git a/host/ide/test/trace/bean/CpuUsage.test.ts b/host/ide/test/trace/bean/CpuUsage.test.ts index 920f4fcddf86c3b7706fe3bb8130a89d007ab6e1..d47ff98c7e6eb0a677ad681ee5e1ccc1a0391c55 100644 --- a/host/ide/test/trace/bean/CpuUsage.test.ts +++ b/host/ide/test/trace/bean/CpuUsage.test.ts @@ -21,10 +21,70 @@ describe('CpuUsage Test', ()=>{ let freq = new Freq(); it('CpuUsageTest01', function () { + cpuUsage = { + cpu: 0, + usage: 0, + usageStr: "", + top1: 0, + top2: 0, + top3: 0, + top1Percent: 0, + top1PercentStr: "", + top2Percent: 0, + top2PercentStr: "", + top3Percent: 0, + top3PercentStr: "", + } expect(cpuUsage).not.toBeUndefined() + expect(cpuUsage).toMatchInlineSnapshot({ + cpu: expect.any(Number), + usage: expect.any(Number), + usageStr: expect.any(String), + top1: expect.any(Number), + top2: expect.any(Number), + top3: expect.any(Number), + top1Percent: expect.any(Number), + top1PercentStr: expect.any(String), + top2Percent: expect.any(Number), + top2PercentStr: expect.any(String), + top3Percent: expect.any(Number), + top3PercentStr: expect.any(String) }, ` +Object { + "cpu": Any, + "top1": Any, + "top1Percent": Any, + "top1PercentStr": Any, + "top2": Any, + "top2Percent": Any, + "top2PercentStr": Any, + "top3": Any, + "top3Percent": Any, + "top3PercentStr": Any, + "usage": Any, + "usageStr": Any, +} +`); }); it('CpuUsageTest02', function () { + cpuUsage = { + cpu: 0, + value: 0, + startNs: 0, + dur: 0, + } expect(freq).not.toBeUndefined() + expect(cpuUsage).toMatchInlineSnapshot({ + cpu: expect.any(Number), + value: expect.any(Number), + startNs: expect.any(Number), + dur: expect.any(Number) }, ` +Object { + "cpu": Any, + "dur": Any, + "startNs": Any, + "value": Any, +} +`); }); }) diff --git a/host/ide/test/trace/bean/DiskAbilityMonitorStruct.test.ts b/host/ide/test/trace/bean/DiskAbilityMonitorStruct.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..5131ad5c5a5872a2486d33055381ce7ba93a7a45 --- /dev/null +++ b/host/ide/test/trace/bean/DiskAbilityMonitorStruct.test.ts @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {DiskAbilityMonitorStruct} from "../../../dist/trace/bean/DiskAbilityMonitorStruct.js" + +describe('DiskAbilityMonitorStruct Test', ()=> { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + + const Sourcedata = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + + }, + value: 50, + maxDiskRate: 50 + + } + + it('DiskAbilityMonitorStructTest01', function () { + expect(DiskAbilityMonitorStruct.draw(ctx, data)).toBeUndefined() + }); + + it('DiskAbilityMonitorStructTest02', function () { + expect(DiskAbilityMonitorStruct.draw(ctx, Sourcedata)).toBeUndefined() + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/bean/EnergyStruct.test.ts b/host/ide/test/trace/bean/EnergyStruct.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..d1b89ba01ca75577887cb6967484ecf872a20979 --- /dev/null +++ b/host/ide/test/trace/bean/EnergyStruct.test.ts @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {EnergyAnomalyStruct, EnergySystemStruct, EnergyPowerStruct, EnergyStateStruct, PowerDetailsEnergy, PowerBatteryEnergy, SystemDetailsEnergy} from "../../../dist/trace/bean/EnergyStruct.js"; + +describe('EnergyStruct Test', ()=> { + let energyAnomalyStruct = new EnergyAnomalyStruct(); + let energySystemStruct = new EnergySystemStruct(); + let energyPowerStruct = new EnergyPowerStruct(); + let energyStateStruct = new EnergyStateStruct(); + let powerDetailsEnergy = new PowerDetailsEnergy(); + let powerBatteryEnergy = new PowerBatteryEnergy(); + let systemDetailsEnergy = new SystemDetailsEnergy(); + + it('energyAnomalyStructTest', function () { + energyAnomalyStruct = { + type: 0, + startNS: 0, + height: 0, + eventName: 'eventName' + }; + expect(energyAnomalyStruct).not.toBeUndefined() + expect(energyAnomalyStruct).toMatchInlineSnapshot({ + type: expect.any(Number), + startNS: expect.any(Number), + height: expect.any(Number), + eventName: expect.any(String) }, ` +Object { + "eventName": Any, + "height": Any, + "startNS": Any, + "type": Any, +} +`); + }); + + it('energySystemStructTest', function () { + energySystemStruct = { + type: 0, + startNs: 0, + dur: 0, + workScheduler: "", + power: "", + location: "" + }; + expect(energySystemStruct).not.toBeUndefined() + expect(energySystemStruct).toMatchInlineSnapshot({ + type: expect.any(Number), + startNs: expect.any(Number), + dur: expect.any(Number), + workScheduler: expect.any(String), + power: expect.any(String), + location: expect.any(String) }, ` +Object { + "dur": Any, + "location": Any, + "power": Any, + "startNs": Any, + "type": Any, + "workScheduler": Any, +} +`); + }); + + it('energyPowerStructTest', function () { + energyPowerStruct = { + type: 0, + name: "", + ts: 0, + cpu: 0, + location: 0, + gpu: 0, + display: 0, + camera: 0, + bluetooth: 0, + flashlight: 0, + audio: 0, + wifiscan: 0 + }; + expect(energyPowerStruct).not.toBeUndefined() + expect(energyPowerStruct).toMatchInlineSnapshot({ + type: expect.any(Number), + name: expect.any(String), + ts: expect.any(Number), + cpu: expect.any(Number), + location: expect.any(Number), + gpu: expect.any(Number), + display: expect.any(Number), + camera: expect.any(Number), + bluetooth: expect.any(Number), + flashlight: expect.any(Number), + audio: expect.any(Number), + wifiscan: expect.any(Number) }, ` +Object { + "audio": Any, + "bluetooth": Any, + "camera": Any, + "cpu": Any, + "display": Any, + "flashlight": Any, + "gpu": Any, + "location": Any, + "name": Any, + "ts": Any, + "type": Any, + "wifiscan": Any, +} +`); + }); + + it('energyStateStructTest', function () { + energyStateStruct = { + type: "", + startNs: 0, + dur: 0, + value: 0 + }; + expect(energyStateStruct).not.toBeUndefined() + expect(energyStateStruct).toMatchInlineSnapshot({ + type: expect.any(String), + startNs: expect.any(Number), + dur: expect.any(Number), + value: expect.any(Number) }, ` +Object { + "dur": Any, + "startNs": Any, + "type": Any, + "value": Any, +} +`); + }); + + + it('powerDetailsEnergyTest', function () { + powerDetailsEnergy = { + event: "", + charge: 0, + background_time: 0, + screen_on_time: 0, + screen_off_time: 0, + load: "-", + usage: 0, + duration: 0, + camera_id: 0, + foreground_count: 0, + background_count: 0, + screen_on_count: 0, + screen_off_count: 0, + count: 0, + appName: "", + uid: 0, + foreground_duration: 0, + foreground_energy: 0, + background_duration: 0, + background_energy: 0, + screen_on_duration: 0, + screen_on_energy: 0, + screen_off_duration: 0, + screen_off_energy: 0, + energy: 0, + energyConsumptionRatio: "" + }; + expect(powerDetailsEnergy).not.toBeUndefined() + expect(powerDetailsEnergy).toMatchInlineSnapshot({ + event: expect.any(String), + charge: expect.any(Number), + background_time: expect.any(Number), + screen_on_time: expect.any(Number), + screen_off_time: expect.any(Number), + load: expect.any(String), + usage: expect.any(Number), + duration: expect.any(Number), + camera_id: expect.any(Number), + foreground_count: expect.any(Number), + background_count: expect.any(Number), + screen_on_count: expect.any(Number), + screen_off_count: expect.any(Number), + count: expect.any(Number), + appName: expect.any(String), + uid: expect.any(Number), + foreground_duration: expect.any(Number), + foreground_energy: expect.any(Number), + background_duration: expect.any(Number), + background_energy: expect.any(Number), + screen_on_duration: expect.any(Number), + screen_on_energy: expect.any(Number), + screen_off_duration: expect.any(Number), + screen_off_energy: expect.any(Number), + energy: expect.any(Number), + energyConsumptionRatio: expect.any(String) }, ` +Object { + "appName": Any, + "background_count": Any, + "background_duration": Any, + "background_energy": Any, + "background_time": Any, + "camera_id": Any, + "charge": Any, + "count": Any, + "duration": Any, + "energy": Any, + "energyConsumptionRatio": Any, + "event": Any, + "foreground_count": Any, + "foreground_duration": Any, + "foreground_energy": Any, + "load": Any, + "screen_off_count": Any, + "screen_off_duration": Any, + "screen_off_energy": Any, + "screen_off_time": Any, + "screen_on_count": Any, + "screen_on_duration": Any, + "screen_on_energy": Any, + "screen_on_time": Any, + "uid": Any, + "usage": Any, +} +`); + }); + + + it('powerBatteryEnergyTest', function () { + powerBatteryEnergy = { + gasGauge: -1, + charge: -1, + screen: -1, + level: -1, + current: -1, + capacity: -1, + appName: "", + uid: -1 + }; + expect(powerBatteryEnergy).not.toBeUndefined() + expect(powerBatteryEnergy).toMatchInlineSnapshot({ + gasGauge: expect.any(Number), + charge: expect.any(Number), + screen: expect.any(Number), + level: expect.any(Number), + current: expect.any(Number), + capacity: expect.any(Number), + appName: expect.any(String), + uid: expect.any(Number) }, ` +Object { + "appName": Any, + "capacity": Any, + "charge": Any, + "current": Any, + "gasGauge": Any, + "level": Any, + "screen": Any, + "uid": Any, +} +`); + }); + + + it('systemDetailsEnergyTest', function () { + systemDetailsEnergy = { + eventName: "", + type: "", + pid: -1, + uid: -1, + state: -1, + workId: "", + name: "", + interval: -1, + level: -1, + tag: "", + message: "", + log_level: "" + }; + expect(systemDetailsEnergy).not.toBeUndefined() + expect(systemDetailsEnergy).toMatchInlineSnapshot({ + eventName: expect.any(String), + type: expect.any(String), + pid: expect.any(Number), + uid: expect.any(Number), + state: expect.any(Number), + workId: expect.any(String), + name: expect.any(String), + interval: expect.any(Number), + level: expect.any(Number), + tag: expect.any(String), + message: expect.any(String), + log_level: expect.any(String) }, ` +Object { + "eventName": Any, + "interval": Any, + "level": Any, + "log_level": Any, + "message": Any, + "name": Any, + "pid": Any, + "state": Any, + "tag": Any, + "type": Any, + "uid": Any, + "workId": Any, +} +`); + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/bean/FpsStruct.test.ts b/host/ide/test/trace/bean/FpsStruct.test.ts index 568a5a581dda243ccc47b271f99675f1c47a0b79..92d7ae3447f5b20d45b809beb108321e9369f975 100644 --- a/host/ide/test/trace/bean/FpsStruct.test.ts +++ b/host/ide/test/trace/bean/FpsStruct.test.ts @@ -32,7 +32,51 @@ describe('FpsStruct Test', ()=>{ startNS: 200, value: 50 } + const node = { + startNS: 200, + frame:2, + dur:3, + } + const padding = 1 + const startNs = 1 + const endNS = 1 + const totalNS = 1 + const frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + const dataSource = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + value: 50, + maxFps: 50 + } + + it('FpsStructTest01', function () { expect(FpsStruct.draw(ctx, data)).toBeUndefined() }); + + it('FpsStructTest04 ', function () { + expect(FpsStruct.draw(ctx,dataSource)).toBeUndefined() + + }); + + it('FpsStructTest02', function () { + let fpsStruct = new FpsStruct(); + expect(fpsStruct).not.toBeUndefined() + }); + + it('FpsStructTest03', function () { + expect(FpsStruct.setFrame(node,padding,startNs,endNS,totalNS,frame)).toBeUndefined() + }); + + + }) diff --git a/host/ide/test/trace/bean/FuncStruct.test.ts b/host/ide/test/trace/bean/FuncStruct.test.ts index f2ac0d789322ff2fcd2a9a5df709d3db805074ac..49e641566f8c2e4c54094937d707aa045c1d0ad4 100644 --- a/host/ide/test/trace/bean/FuncStruct.test.ts +++ b/host/ide/test/trace/bean/FuncStruct.test.ts @@ -51,6 +51,10 @@ describe('FuncStruct Test', ()=>{ it('FuncStructTest03', function () { expect(FuncStruct.drawString(ctx, 2, durData, durData.frame)).toBeUndefined() }); + it('FuncStructTest06 ', function () { + expect(FuncStruct.drawString(ctx,3,durData,durData.frame)).toBeUndefined() + + }); it('FuncStructTest04', function () { expect(FuncStruct.isSelected({ @@ -60,11 +64,33 @@ describe('FuncStruct Test', ()=>{ })).toBeTruthy(); }); + it('FuncStructTest05', function () { expect(FuncStruct.isBinder({ startTs: 10, dur: 10, - funName: '' + funName: null + })).toBeFalsy(); + }); + + it('FuncStructTest07', function () { + expect(FuncStruct.drawString(ctx,300,durData,durData.frame)).toBeUndefined() + + }); + + it('FuncStructTest08', function () { + expect(FuncStruct.isBinderAsync({ + startTs: 10, + dur: 10, + funName: null + })).toBeFalsy(); + }); + + it('FuncStructTest09', function () { + expect(FuncStruct.isBinderAsync({ + startTs: 20, + dur: 20, + funName: 'funName' })).toBeFalsy(); }); }) diff --git a/host/ide/test/trace/bean/HeapBean.test.ts b/host/ide/test/trace/bean/HeapBean.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..0ddf6696d786c71ad80d24ccf508004b21e8f4c9 --- /dev/null +++ b/host/ide/test/trace/bean/HeapBean.test.ts @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {HeapBean} from "../../../dist/trace/bean/HeapBean.js" + +describe('HeapBean Test', ()=>{ + let heapBean = new HeapBean(); + + it('HeapBeanTest01', function () { + heapBean = { + MoudleName: "MoudleName", + AllocationFunction: "AllocationFunction", + Allocations: 0, + Deallocations: 0, + AllocationSize: 0, + DeAllocationSize: 0, + Total: 0, + RemainingSize: 0, + depth: 0, + } + expect(heapBean).not.toBeUndefined() + expect(heapBean).toMatchInlineSnapshot({ + MoudleName: expect.any(String), + AllocationFunction: expect.any(String), + Allocations: expect.any(Number), + Deallocations: expect.any(Number), + AllocationSize: expect.any(Number), + DeAllocationSize: expect.any(Number), + Total: expect.any(Number), + RemainingSize: expect.any(Number), + depth: expect.any(Number) }, ` +Object { + "AllocationFunction": Any, + "AllocationSize": Any, + "Allocations": Any, + "DeAllocationSize": Any, + "Deallocations": Any, + "MoudleName": Any, + "RemainingSize": Any, + "Total": Any, + "depth": Any, +} +`) + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/bean/HeapTreeDataBean.test.ts b/host/ide/test/trace/bean/HeapTreeDataBean.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..4de81a81705b59ecae2ce0707bd28ba8154b4e55 --- /dev/null +++ b/host/ide/test/trace/bean/HeapTreeDataBean.test.ts @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {HeapTreeDataBean} from "../../../dist/trace/bean/HeapTreeDataBean.js" + +describe('HeapTreeDataBean Test', ()=>{ + let heapTreeDataBean = new HeapTreeDataBean(); + + it('HeapTreeDataBeanTest01', function () { + heapTreeDataBean = { + MoudleName: "MoudleName", + AllocationFunction: "AllocationFunction", + startTs: 0, + endTs: 0, + eventType: "eventType", + depth: 0, + heapSize: 0, + eventId: "eventId", + } + expect(heapTreeDataBean).not.toBeUndefined() + expect(heapTreeDataBean).toMatchInlineSnapshot({ + MoudleName: expect.any(String), + AllocationFunction: expect.any(String), + startTs: expect.any(Number), + endTs: expect.any(Number), + eventType: expect.any(String), + depth: expect.any(Number), + heapSize: expect.any(Number), + eventId: expect.any(String) }, ` +Object { + "AllocationFunction": Any, + "MoudleName": Any, + "depth": Any, + "endTs": Any, + "eventId": Any, + "eventType": Any, + "heapSize": Any, + "startTs": Any, +} +`) + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/bean/MemoryAbilityMonitorStruct.test.ts b/host/ide/test/trace/bean/MemoryAbilityMonitorStruct.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..1e74d9a42cb4422fe837d968b7992618cdc5a0b3 --- /dev/null +++ b/host/ide/test/trace/bean/MemoryAbilityMonitorStruct.test.ts @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {MemoryAbilityMonitorStruct} from "../../../dist/trace/bean/MemoryAbilityMonitorStruct.js" + +describe('MemoryAbilityMonitorStruct Test', ()=> { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + + + const Sourcedata = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + maxMemoryByte: 200, + value: 50 + } + + it('MemoryAbilityMonitorStructTest01', function () { + expect(MemoryAbilityMonitorStruct.draw(ctx, data)).toBeUndefined() + }); + + it('MemoryAbilityMonitorStructTest02', function () { + expect(MemoryAbilityMonitorStruct.draw(ctx, Sourcedata)).toBeUndefined() + }); + + + +}) \ No newline at end of file diff --git a/host/ide/test/trace/bean/NativeHook.test.ts b/host/ide/test/trace/bean/NativeHook.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..56f8b4db3bf02ed3a05c276b82c0619215823935 --- /dev/null +++ b/host/ide/test/trace/bean/NativeHook.test.ts @@ -0,0 +1,381 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {NativeHookStatistics, NativeHookMalloc, NativeEventHeap, NativeHookProcess, NativeHookStatisticsTableData, NativeMemory, NativeHookSamplerInfo, NativeHookSampleQueryInfo, NativeHookCallInfo, NativeEvent} from "../../../dist/trace/bean/NativeHook.js" + +describe('NativeHook Test', ()=>{ + + it('NativeHookStatisticsTest01', function () { + let nativeHookStatistics = new NativeHookStatistics(); + nativeHookStatistics = { + eventId: 0, + eventType: "eventType", + subType: "subType", + heapSize: 0, + addr: "addr", + startTs: 0, + endTs: 0, + sumHeapSize: 0, + max: 0, + count: 0, + tid: 0, + isSelected: false, + } + expect(nativeHookStatistics).not.toBeUndefined() + expect(nativeHookStatistics).toMatchInlineSnapshot({ + eventId: expect.any(Number), + eventType: expect.any(String), + subType: expect.any(String), + heapSize: expect.any(Number), + addr: expect.any(String), + startTs: expect.any(Number), + endTs: expect.any(Number), + sumHeapSize: expect.any(Number), + max: expect.any(Number), + count: expect.any(Number), + tid: expect.any(Number), + isSelected: expect.any(Boolean) }, ` +Object { + "addr": Any, + "count": Any, + "endTs": Any, + "eventId": Any, + "eventType": Any, + "heapSize": Any, + "isSelected": Any, + "max": Any, + "startTs": Any, + "subType": Any, + "sumHeapSize": Any, + "tid": Any, +} +`) + }); + + it('NativeEventHeapTest02', function () { + let nativeHookMalloc = new NativeHookMalloc(); + nativeHookMalloc = { + eventType: "eventType", + subType: "subType", + heapSize: 0, + allocByte: 0, + allocCount: 0, + freeByte: 0, + freeCount: 0, + } + expect(nativeHookMalloc).not.toBeUndefined() + expect(nativeHookMalloc).toMatchInlineSnapshot({ + eventType: expect.any(String), + subType: expect.any(String), + heapSize: expect.any(Number), + allocByte: expect.any(Number), + allocCount: expect.any(Number), + freeByte: expect.any(Number), + freeCount: expect.any(Number) }, ` +Object { + "allocByte": Any, + "allocCount": Any, + "eventType": Any, + "freeByte": Any, + "freeCount": Any, + "heapSize": Any, + "subType": Any, +} +`) + }); + + it('NativeEventHeapTest03', function () { + let nativeEventHeap = new NativeEventHeap(); + nativeEventHeap = { + eventType: "eventType", + sumHeapSize: 0, + } + expect(nativeEventHeap).not.toBeUndefined() + expect(nativeEventHeap).toMatchInlineSnapshot({ + eventType: expect.any(String), + sumHeapSize: expect.any(Number) }, ` +Object { + "eventType": Any, + "sumHeapSize": Any, +} +`) + }); + + it('NativeHookProcessTest04', function () { + let nativeHookProcess = new NativeHookProcess(); + nativeHookProcess = { + ipid: 0, + pid: 0, + name: "name", + } + expect(nativeHookProcess).not.toBeUndefined() + expect(nativeHookProcess).toMatchInlineSnapshot({ + ipid: expect.any(Number), + pid: expect.any(Number), + name: expect.any(String) }, ` +Object { + "ipid": Any, + "name": Any, + "pid": Any, +} +`) + }); + + it('NativeHookStatisticsTableDataTest05', function () { + let nativeHookStatisticsTableData = new NativeHookStatisticsTableData(); + nativeHookStatisticsTableData = { + memoryTap: "", + existing: 0, + existingString: "", + allocCount: 0, + freeCount: 0, + totalBytes: 0, + totalBytesString: "", + maxStr: "", + max: 0, + totalCount: 0, + } + expect(nativeHookStatisticsTableData).not.toBeUndefined() + expect(nativeHookStatisticsTableData).toMatchInlineSnapshot({ + memoryTap: expect.any(String), + existing: expect.any(Number), + existingString: expect.any(String), + allocCount: expect.any(Number), + freeCount: expect.any(Number), + totalBytes: expect.any(Number), + totalBytesString: expect.any(String), + maxStr: expect.any(String), + max: expect.any(Number), + totalCount: expect.any(Number) }, ` +Object { + "allocCount": Any, + "existing": Any, + "existingString": Any, + "freeCount": Any, + "max": Any, + "maxStr": Any, + "memoryTap": Any, + "totalBytes": Any, + "totalBytesString": Any, + "totalCount": Any, +} +`) + }); + + it('NativeMemoryTest06', function () { + let nativeMemory = new NativeMemory(); + nativeMemory = { + index: 0, + eventId: 0, + eventType: "eventType", + subType: "subType", + addr: "addr", + startTs: 0, + timestamp: "timestamp", + heapSize: 0, + heapSizeUnit: "heapSizeUnit", + symbol: "symbol", + library: "library", + isSelected: false, + } + expect(nativeMemory).not.toBeUndefined() + expect(nativeMemory).toMatchInlineSnapshot({ + index: expect.any(Number), + eventId: expect.any(Number), + eventType: expect.any(String), + subType: expect.any(String), + addr: expect.any(String), + startTs: expect.any(Number), + timestamp: expect.any(String), + heapSize: expect.any(Number), + heapSizeUnit: expect.any(String), + symbol: expect.any(String), + library: expect.any(String), + isSelected: expect.any(Boolean) }, ` +Object { + "addr": Any, + "eventId": Any, + "eventType": Any, + "heapSize": Any, + "heapSizeUnit": Any, + "index": Any, + "isSelected": Any, + "library": Any, + "startTs": Any, + "subType": Any, + "symbol": Any, + "timestamp": Any, +} +`) + }); + + it('NativeHookCallInfoTest07', function () { + let nativeHookSamplerInfo = new NativeHookSamplerInfo(); + nativeHookSamplerInfo = { + current: "current", + currentSize: 0, + startTs: 0, + heapSize: 0, + snapshot: "snapshot", + growth: "growth", + total: 0, + totalGrowth: "totalGrowth", + existing: 0, + timestamp: "timestamp", + eventId: -1, + } + expect(nativeHookSamplerInfo).not.toBeUndefined() + expect(nativeHookSamplerInfo).toMatchInlineSnapshot({ + current: expect.any(String), + currentSize: expect.any(Number), + startTs: expect.any(Number), + heapSize: expect.any(Number), + snapshot: expect.any(String), + growth: expect.any(String), + total: expect.any(Number), + totalGrowth: expect.any(String), + existing: expect.any(Number), + timestamp: expect.any(String), + eventId: expect.any(Number) }, ` +Object { + "current": Any, + "currentSize": Any, + "eventId": Any, + "existing": Any, + "growth": Any, + "heapSize": Any, + "snapshot": Any, + "startTs": Any, + "timestamp": Any, + "total": Any, + "totalGrowth": Any, +} +`) + }); + + it('NativeHookCallInfoTest08', function () { + let nativeHookSampleQueryInfo = new NativeHookSampleQueryInfo(); + nativeHookSampleQueryInfo = { + eventId: -1, + current: 0, + eventType: "eventType", + subType: "subType", + growth: 0, + existing: 0, + addr: "addr", + startTs: 0, + endTs: 0, + total: 0, + } + + expect(nativeHookSampleQueryInfo).not.toBeUndefined() + expect(nativeHookSampleQueryInfo).toMatchInlineSnapshot({ + eventId: expect.any(Number), + current: expect.any(Number), + eventType: expect.any(String), + subType: expect.any(String), + growth: expect.any(Number), + existing: expect.any(Number), + addr: expect.any(String), + startTs: expect.any(Number), + endTs: expect.any(Number), + total: expect.any(Number) }, ` +Object { + "addr": Any, + "current": Any, + "endTs": Any, + "eventId": Any, + "eventType": Any, + "existing": Any, + "growth": Any, + "startTs": Any, + "subType": Any, + "total": Any, +} +`) + }); + + it('NativeHookCallInfoTest09', function () { + let nativeHookCallInfo = new NativeHookCallInfo(); + nativeHookCallInfo = { + id: "id", + pid: "pid", + library: "library", + title: "title", + count: 0, + type: 0, + heapSize: 0, + heapSizeStr: "heapSizeStr", + eventId: 0, + threadId: 0, + isSelected: false, + } + expect(nativeHookCallInfo).not.toBeUndefined() + expect(nativeHookCallInfo).toMatchInlineSnapshot({ + id: expect.any(String), + pid: expect.any(String), + library: expect.any(String), + title: expect.any(String), + count: expect.any(Number), + type: expect.any(Number), + heapSize: expect.any(Number), + heapSizeStr: expect.any(String), + eventId: expect.any(Number), + threadId: expect.any(Number), + isSelected: expect.any(Boolean) }, ` +Object { + "count": Any, + "eventId": Any, + "heapSize": Any, + "heapSizeStr": Any, + "id": Any, + "isSelected": Any, + "library": Any, + "pid": Any, + "threadId": Any, + "title": Any, + "type": Any, +} +`) + }); + + it('NativeHookCallInfoTest10', function () { + let nativeHookSamplerInfo = new NativeHookSamplerInfo(); + expect(nativeHookSamplerInfo.merageObj(NativeHookSamplerInfo)).toBeUndefined(); + }); + + it('NativeEventHeapTest11', function () { + let nativeEvent = new NativeEvent(); + nativeEvent = { + startTime: 0, + heapSize: 0, + eventType: "", + + } + expect(nativeEvent).not.toBeUndefined() + expect(nativeEvent).toMatchInlineSnapshot({ + startTime: expect.any(Number), + heapSize: expect.any(Number), + eventType: expect.any(String) }, ` +Object { + "eventType": Any, + "heapSize": Any, + "startTime": Any, +} +`) + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/bean/NetworkAbilityMonitorStruct.test.ts b/host/ide/test/trace/bean/NetworkAbilityMonitorStruct.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..c221584f2a8d52a4b3e04efc25f6dcd552cb407b --- /dev/null +++ b/host/ide/test/trace/bean/NetworkAbilityMonitorStruct.test.ts @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {NetworkAbilityMonitorStruct} from "../../../dist/trace/bean/NetworkAbilityMonitorStruct.js" + +describe('NetworkAbilityMonitorStruct Test', ()=> { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + + const Sourcedate = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + value: 50, + maxNetworkRate: 50 + + } + + it('NetworkAbilityMonitorStructTest01', function () { + expect(NetworkAbilityMonitorStruct.draw(ctx, data)).toBeUndefined() + }); + + it('NetworkAbilityMonitorStructTest02', function () { + expect(NetworkAbilityMonitorStruct.draw(ctx, Sourcedate)).toBeUndefined() + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/bean/PerfProfile.test.ts b/host/ide/test/trace/bean/PerfProfile.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..fc1310c8c59ce87f61ccbfcac9da4d1f96b874f5 --- /dev/null +++ b/host/ide/test/trace/bean/PerfProfile.test.ts @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {PerfFile, PerfThread, PerfCallChain, PerfCallChainMerageData, PerfSample, PerfStack, PerfCall, PerfCmdLine} from "../../../dist/trace/bean/PerfProfile.js" + +describe('PerfProfile Test', ()=>{ + let perfFile = new PerfFile(); + let perfThread = new PerfThread(); + let perfCallChain = new PerfCallChain(); + let perfCallChainMerageData = new PerfCallChainMerageData(); + let perfSample = new PerfSample(); + let perfStack = new PerfStack(); + let perfCall = new PerfCall(); + let perfCmdLine = new PerfCmdLine(); + + it('PerfFile Test', function () { + perfFile = { + fileId: 0, + symbol: "symbol", + path: "path", + fileName: "fileName", + }; + + expect(perfFile).not.toBeUndefined() + expect(perfFile).toMatchInlineSnapshot({ + fileId: expect.any(Number), + symbol: expect.any(String), + path: expect.any(String), + fileName: expect.any(String) }, ` +Object { + "fileId": Any, + "fileName": Any, + "path": Any, + "symbol": Any, +} +`); + }); + + it('PerfThread Test', function () { + perfThread = { + tid: 0, + pid: 0, + threadName: "threadName", + processName: "processName", + } + + expect(perfThread).not.toBeUndefined() + expect(perfThread).toMatchInlineSnapshot({ + tid: expect.any(Number), + pid: expect.any(Number), + threadName: expect.any(String), + processName: expect.any(String) }, ` +Object { + "pid": Any, + "processName": Any, + "threadName": Any, + "tid": Any, +} +`); + }); + + it('perfCallChain Test', function () { + perfCallChain = { + tid: 0, + pid: 0, + name: "name", + fileName: "fileName", + threadState: "threadState", + startNS: 0, + dur: 0, + sampleId: 0, + callChainId: 0, + vaddrInFile: 0, + fileId: 0, + symbolId: 0, + parentId: "parentId", + id: "id", + topDownMerageId: "topDownMerageId", + topDownMerageParentId: "topDownMerageParentId", + bottomUpMerageId: "bottomUpMerageId", + bottomUpMerageParentId: "bottomUpMerageParentId", + depth: 0, + } + + expect(perfCallChain).not.toBeUndefined() + expect(perfCallChain).toMatchInlineSnapshot({ + tid: expect.any(Number), + pid: expect.any(Number), + name: expect.any(String), + fileName: expect.any(String), + threadState: expect.any(String), + startNS: expect.any(Number), + dur: expect.any(Number), + sampleId: expect.any(Number), + callChainId: expect.any(Number), + vaddrInFile: expect.any(Number), + fileId: expect.any(Number), + symbolId: expect.any(Number), + parentId: expect.any(String), + id: expect.any(String), + topDownMerageId: expect.any(String), + topDownMerageParentId: expect.any(String), + bottomUpMerageId: expect.any(String), + bottomUpMerageParentId: expect.any(String), + depth: expect.any(Number) }, ` +Object { + "bottomUpMerageId": Any, + "bottomUpMerageParentId": Any, + "callChainId": Any, + "depth": Any, + "dur": Any, + "fileId": Any, + "fileName": Any, + "id": Any, + "name": Any, + "parentId": Any, + "pid": Any, + "sampleId": Any, + "startNS": Any, + "symbolId": Any, + "threadState": Any, + "tid": Any, + "topDownMerageId": Any, + "topDownMerageParentId": Any, + "vaddrInFile": Any, +} +`) + }) + + it('perfCallChain Test', function () { + perfCallChainMerageData = { + id: "id", + parentId: "parentId", + symbolName: "symbolName", + symbol: "symbol", + libName: "libName", + self: "self", + weight: "weight", + selfDur: 0, + dur: 0, + tid: 0, + pid: 0, + type: 0, + isSelected: false, + } + + expect(perfCallChainMerageData).not.toBeUndefined() + expect(perfCallChainMerageData).toMatchInlineSnapshot({ + id: expect.any(String), + parentId: expect.any(String), + symbolName: expect.any(String), + symbol: expect.any(String), + libName: expect.any(String), + self: expect.any(String), + weight: expect.any(String), + selfDur: expect.any(Number), + dur: expect.any(Number), + tid: expect.any(Number), + pid: expect.any(Number), + type: expect.any(Number), + isSelected: expect.any(Boolean) }, ` +Object { + "dur": Any, + "id": Any, + "isSelected": Any, + "libName": Any, + "parentId": Any, + "pid": Any, + "self": Any, + "selfDur": Any, + "symbol": Any, + "symbolName": Any, + "tid": Any, + "type": Any, + "weight": Any, +} +`) + }) + + it('perfSample Test', function () { + perfSample = { + sampleId: 0, + time: 0, + timeString: "timeString", + core: 0, + coreName: "coreName", + state: "state", + pid: 0, + processName: "processName", + tid: 0, + threadName: "threadName", + depth: 0, + addr: "addr", + fileId: 0, + symbolId: 0, + } + expect(perfSample).not.toBeUndefined() + expect(perfSample).toMatchInlineSnapshot({ + sampleId: expect.any(Number), + time: expect.any(Number), + timeString: expect.any(String), + core: expect.any(Number), + coreName: expect.any(String), + state: expect.any(String), + pid: expect.any(Number), + processName: expect.any(String), + tid: expect.any(Number), + threadName: expect.any(String), + depth: expect.any(Number), + addr: expect.any(String), + fileId: expect.any(Number), + symbolId: expect.any(Number) }, ` +Object { + "addr": Any, + "core": Any, + "coreName": Any, + "depth": Any, + "fileId": Any, + "pid": Any, + "processName": Any, + "sampleId": Any, + "state": Any, + "symbolId": Any, + "threadName": Any, + "tid": Any, + "time": Any, + "timeString": Any, +} +`) + }) + + it('perfStack Test', function () { + perfStack = { + symbol: "", + path: "", + fileId: 0, + type: 0, + } + expect(perfStack).not.toBeUndefined() + expect(perfStack).toMatchInlineSnapshot({ + symbol: expect.any(String), + path: expect.any(String), + fileId: expect.any(Number), + type: expect.any(Number) }, ` +Object { + "fileId": Any, + "path": Any, + "symbol": Any, + "type": Any, +} +`) + }) + + it('perfCall Test', function () { + perfCall = { + sampleId: 0, + depth: 0, + name: "name", + } + expect(perfCall).not.toBeUndefined() + expect(perfCall).toMatchInlineSnapshot({ + sampleId: expect.any(Number), + depth: expect.any(Number), + name: expect.any(String) }, ` +Object { + "depth": Any, + "name": Any, + "sampleId": Any, +} +`) + }) + + it('PerfFile Test01', function () { + let perfFile = new PerfFile(); + expect(perfFile.setFileName()).toBeUndefined(); + }); + + it('PerfFile Test02', function () { + let perfFile = new PerfFile(); + let perfF = { + fileId: 0, + symbol: "symbol", + path: "path", + fileName: "fileName", + }; + expect(perfFile.setFileName(perfF)).toBeUndefined(); + }); + + it('PerfCmdLine Test', function () { + perfCmdLine = { + report_value: 'report_value', + }; + expect(perfCmdLine).not.toBeUndefined(); + expect(perfCmdLine).toMatchInlineSnapshot({ + report_value: expect.any(String) }, ` +Object { + "report_value": Any, +} +`); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneSlices.test.ts b/host/ide/test/trace/bean/SdkSummary.test.ts similarity index 33% rename from host/ide/test/trace/component/trace/sheet/TabPaneSlices.test.ts rename to host/ide/test/trace/bean/SdkSummary.test.ts index d00e3b5b9e5a65982037ec7fa77aae610f9be59a..3dbc031fe79ba75fe98d686a61fe3a22945e96cc 100644 --- a/host/ide/test/trace/component/trace/sheet/TabPaneSlices.test.ts +++ b/host/ide/test/trace/bean/SdkSummary.test.ts @@ -14,41 +14,53 @@ */ // @ts-ignore -import {TabPaneSlices} from "../../../../../dist/trace/component/trace/sheet/TabPaneSlices.js" +import { CounterSummary,SdkSliceSummary} from "../../../dist/trace/bean/SdkSummary.js"; -const sqlit = require("../../../../../dist/trace/database/SqlLite.js") -jest.mock("../../../../../dist/trace/database/SqlLite.js"); -describe('TabPaneSlices Test', () => { - let tabPaneSlices = new TabPaneSlices(); +describe('SdkSummary Test', ()=>{ - tabPaneSlices.sortByColumn = jest.fn(()=> true) - - it('TabPaneSlicesTest01', function () { - expect(tabPaneSlices.sortByColumn({ - key: 'name', - sort: () => { - } - })).toBeTruthy(); - }); - - it('TabPaneSlicesTest02', function () { - let mockgetTabThreadStates = sqlit.getTabSlices - mockgetTabThreadStates.mockResolvedValue([{name : "11", - wallDuration: 10, - occurrences: 10, - },{name : "22", - wallDuration: 20, - occurrences: 20, - }] - ) - let a = {rightNs: 1, leftNs: 0, funTids: [11, 12, 13]} - expect(tabPaneSlices.data = a).toBeTruthy(); + it('SdkSummaryTest01', function () { + let counterSummary = new CounterSummary(); + counterSummary = { + value:0, + ts: 0, + counter_id: 0, + } + expect(counterSummary).not.toBeUndefined(); + expect(counterSummary).toMatchInlineSnapshot({ + value: expect.any(Number), + ts: expect.any(Number), + counter_id: expect.any(Number) }, ` +Object { + "counter_id": Any, + "ts": Any, + "value": Any, +} +`) }); - it('TabPaneSlicesTest03', function () { - let mockgetTabThreadStates = sqlit.getTabSlices - mockgetTabThreadStates.mockResolvedValue([]) - let a = {rightNs: 1, leftNs: 0, funTids: [11, 12, 13]} - expect(tabPaneSlices.data = a).toBeTruthy(); + it('SdkSliceSummaryTest02', function () { + let sdkSliceSummary = new SdkSliceSummary(); + sdkSliceSummary = { + start_ts: 0, + end_ts: 0, + value: 0, + column_id: 0, + slice_message: 'slice_message', + } + expect(sdkSliceSummary).not.toBeUndefined(); + expect(sdkSliceSummary).toMatchInlineSnapshot({ + start_ts: expect.any(Number), + end_ts: expect.any(Number), + value: expect.any(Number), + column_id: expect.any(Number), + slice_message: expect.any(String) }, ` +Object { + "column_id": Any, + "end_ts": Any, + "slice_message": Any, + "start_ts": Any, + "value": Any, +} +`) }); }) diff --git a/host/ide/test/trace/bean/SmapsStruct.test.ts b/host/ide/test/trace/bean/SmapsStruct.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..0a2530ae42b77c01765b4ebbeee345bb0b955bb6 --- /dev/null +++ b/host/ide/test/trace/bean/SmapsStruct.test.ts @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {Smaps, SmapsTreeObj} from "../../../dist/trace/bean/SmapsStruct.js"; + +describe('SmapsStruct Test', () => { + it('SmapsStructTest01', function () { + let sMaps = new Smaps() + sMaps = { + tsNS: -1, + start_addr: "start_addr", + end_addr: "end_addr", + permission: "permission", + path: "path", + size: 0, + rss: 0, + pss: 0, + reside: 0, + dirty: 0, + swapper: 0, + address: "address", + type: "type", + dirtyStr: "dirtyStr", + swapperStr: "swapperStr", + rssStr: "rssStr", + pssStr: "pssStr", + sizeStr: "sizeStr", + resideStr: "resideStr" + } + expect(sMaps).not.toBeUndefined(); + expect(sMaps).toMatchInlineSnapshot({ + tsNS: expect.any(Number), + start_addr: expect.any(String), + end_addr: expect.any(String), + permission: expect.any(String), + path: expect.any(String), + size: expect.any(Number), + rss: expect.any(Number), + pss: expect.any(Number), + reside: expect.any(Number), + dirty: expect.any(Number), + swapper: expect.any(Number), + address: expect.any(String), + type: expect.any(String), + dirtyStr: expect.any(String), + swapperStr: expect.any(String), + rssStr: expect.any(String), + pssStr: expect.any(String), + sizeStr: expect.any(String), + resideStr: expect.any(String) }, ` +Object { + "address": Any, + "dirty": Any, + "dirtyStr": Any, + "end_addr": Any, + "path": Any, + "permission": Any, + "pss": Any, + "pssStr": Any, + "reside": Any, + "resideStr": Any, + "rss": Any, + "rssStr": Any, + "size": Any, + "sizeStr": Any, + "start_addr": Any, + "swapper": Any, + "swapperStr": Any, + "tsNS": Any, + "type": Any, +} +`) + }); + + it('SmapsStructTest02', function () { + let sMapsTreeObj = new SmapsTreeObj() + sMapsTreeObj = { + id: "id", + pid: "pid", + rsspro: 0, + rssproStr: "rssproStr", + type: "type", + reg: 0, + regStr: "regStr", + path: "path", + rss: 0, + rssStr: "rssStr", + dirty: 0, + dirtyStr: "dirtyStr", + swapper: 0, + swapperStr: "swapperStr", + pss: 0, + pssStr: "pssStr", + size: 0, + sizeStr: "sizeStr", + respro: 0, + resproStr: "resproStr", + children: [] + } + expect(sMapsTreeObj).not.toBeUndefined(); + expect(sMapsTreeObj).toMatchInlineSnapshot({ + id: expect.any(String), + pid: expect.any(String), + rsspro: expect.any(Number), + rssproStr: expect.any(String), + type: expect.any(String), + reg: expect.any(Number), + regStr: expect.any(String), + path: expect.any(String), + rss: expect.any(Number), + rssStr: expect.any(String), + dirty: expect.any(Number), + dirtyStr: expect.any(String), + swapper: expect.any(Number), + swapperStr: expect.any(String), + pss: expect.any(Number), + pssStr: expect.any(String), + size: expect.any(Number), + sizeStr: expect.any(String), + respro: expect.any(Number), + resproStr: expect.any(String), + children: expect.any(Array) }, ` +Object { + "children": Any, + "dirty": Any, + "dirtyStr": Any, + "id": Any, + "path": Any, + "pid": Any, + "pss": Any, + "pssStr": Any, + "reg": Any, + "regStr": Any, + "respro": Any, + "resproStr": Any, + "rss": Any, + "rssStr": Any, + "rsspro": Any, + "rssproStr": Any, + "size": Any, + "sizeStr": Any, + "swapper": Any, + "swapperStr": Any, + "type": Any, +} +`) + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/bean/StateProcessThread.test.ts b/host/ide/test/trace/bean/StateProcessThread.test.ts index 83be7ef5a9ace39a36da8cc01383120961303f10..935379e77c7e2d2e25b35422c8c0aa03cce71a17 100644 --- a/host/ide/test/trace/bean/StateProcessThread.test.ts +++ b/host/ide/test/trace/bean/StateProcessThread.test.ts @@ -14,12 +14,237 @@ */ // @ts-ignore -import {StateProcessThread} from "../../../dist/trace/bean/StateProcessThread.js" +import {StateProcessThread,SPTChild,SPT,ThreadState,ThreadProcess,SptSlice} from "../../../dist/trace/bean/StateProcessThread.js" describe('StateProcessThread Test', ()=>{ - let stateProcessThread = new StateProcessThread(); it('StateProcessThreadTest01', function () { + let stateProcessThread = new StateProcessThread(); + stateProcessThread = { + id: "id", + pid: "pid", + title: "title", + process: "process", + processId: -1, + thread: "thread", + threadId: -1, + state: "state", + wallDuration: 0, + avgDuration: "avgDuration", + count: 0, + minDuration: 0, + maxDuration: 0, + stdDuration: "stdDuration", + } expect(stateProcessThread).not.toBeUndefined() + expect(stateProcessThread).toMatchInlineSnapshot({ + id: expect.any(String), + pid: expect.any(String), + title: expect.any(String), + process: expect.any(String), + processId: expect.any(Number), + thread: expect.any(String), + threadId: expect.any(Number), + wallDuration: expect.any(Number), + avgDuration: expect.any(String), + count: expect.any(Number), + minDuration: expect.any(Number), + maxDuration: expect.any(Number), + stdDuration: expect.any(String) }, ` +Object { + "avgDuration": Any, + "count": Any, + "id": Any, + "maxDuration": Any, + "minDuration": Any, + "pid": Any, + "process": Any, + "processId": Any, + "state": "state", + "stdDuration": Any, + "thread": Any, + "threadId": Any, + "title": Any, + "wallDuration": Any, +} +`) + }); + + it('SPTChildTest02', function () { + let sptChild = new SPTChild(); + sptChild = { + process: "process", + processId: 0, + processName: "processName", + thread: "thread", + threadId: 0, + threadName: "threadName", + state: "state", + startNs: 0, + startTime: "startTime", + duration: 0, + cpu: 1, + core: "core", + priority: 0, + prior: "prior", + note: "note", + } + expect(sptChild).not.toBeUndefined() + expect(sptChild).toMatchInlineSnapshot({ + process: expect.any(String), + processId: expect.any(Number), + processName: expect.any(String), + thread: expect.any(String), + threadId: expect.any(Number), + threadName: expect.any(String), + state: expect.any(String), + startNs: expect.any(Number), + startTime: expect.any(String), + duration: expect.any(Number), + cpu: expect.any(Number), + core: expect.any(String), + priority: expect.any(Number), + prior: expect.any(String), + note: expect.any(String) }, ` +Object { + "core": Any, + "cpu": Any, + "duration": Any, + "note": Any, + "prior": Any, + "priority": Any, + "process": Any, + "processId": Any, + "processName": Any, + "startNs": Any, + "startTime": Any, + "state": Any, + "thread": Any, + "threadId": Any, + "threadName": Any, +} +`) + }); + + it('SPTTest03', function () { + let spt = new SPT(); + spt = { + process: "process", + processId: 0, + thread: "thread", + threadId: 0, + state: "state", + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "priority", + note: "note", + } + expect(spt).not.toBeUndefined() + expect(spt).toMatchInlineSnapshot({ + process: expect.any(String), + processId: expect.any(Number), + thread: expect.any(String), + threadId: expect.any(Number), + state: expect.any(String), + dur: expect.any(Number), + start_ts: expect.any(Number), + end_ts: expect.any(Number), + cpu: expect.any(Number), + priority: expect.any(String), + note: expect.any(String) }, ` +Object { + "cpu": Any, + "dur": Any, + "end_ts": Any, + "note": Any, + "priority": Any, + "process": Any, + "processId": Any, + "start_ts": Any, + "state": Any, + "thread": Any, + "threadId": Any, +} +`) + }); + + it('ThreadStateTest04', function () { + let threadState = new ThreadState(); + threadState = { + itid: 0, + state: "state", + dur: 0, + ts: 0, + end_ts: 0, + start_ts: 0, + cpu: 0, + } + expect(threadState).not.toBeUndefined() + expect(threadState).toMatchInlineSnapshot({ + itid: expect.any(Number), + state: expect.any(String), + dur: expect.any(Number), + ts: expect.any(Number), + end_ts: expect.any(Number), + start_ts: expect.any(Number), + cpu: expect.any(Number) }, ` +Object { + "cpu": Any, + "dur": Any, + "end_ts": Any, + "itid": Any, + "start_ts": Any, + "state": Any, + "ts": Any, +} +`); + }); + + it('ThreadProcessTest05', function () { + let threadProcess = new ThreadProcess(); + threadProcess = { + id:0, + threadId: 0, + thread: "thread", + processId: 0, + process: "process", + } + expect(threadProcess).not.toBeUndefined(); + expect(threadProcess).toMatchInlineSnapshot({ + id: expect.any(Number), + threadId: expect.any(Number), + thread: expect.any(String), + processId: expect.any(Number), + process: expect.any(String) }, ` +Object { + "id": Any, + "process": Any, + "processId": Any, + "thread": Any, + "threadId": Any, +} +`); + }); + + it('SptSliceTest06', function () { + let sptSlice = new SptSlice(); + sptSlice = { + itid: 0, + ts: 0, + priority: 0, + } + expect(sptSlice).not.toBeUndefined(); + expect(sptSlice).toMatchInlineSnapshot({ + itid: expect.any(Number), + ts: expect.any(Number), + priority: expect.any(Number) }, ` +Object { + "itid": Any, + "priority": Any, + "ts": Any, +} +`); }); }) diff --git a/host/ide/test/trace/bean/ThreadStruct.test.ts b/host/ide/test/trace/bean/ThreadStruct.test.ts index 82c8abf9ed4164162e67b154a48d2b0a5588ccb0..18b16f1977ced3230e368414b2d3d4a7f4bb3615 100644 --- a/host/ide/test/trace/bean/ThreadStruct.test.ts +++ b/host/ide/test/trace/bean/ThreadStruct.test.ts @@ -64,6 +64,11 @@ describe('ThreadStruct Test', () => { expect(ThreadStruct.draw(ctx, dataSource)).toBeUndefined() }); + it('ThreadStructTest11', function () { + dataSource.state = "T"||"t" + expect(ThreadStruct.draw(ctx, dataSource)).toBeUndefined() + }); + it('ThreadStructTest06', function () { expect(ThreadStruct.drawString(ctx, '', 2, dataSource.frame)).toBeUndefined() }); diff --git a/host/ide/test/trace/bean/WakeUpTimeBean.test.ts b/host/ide/test/trace/bean/WakeUpTimeBean.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..fda6441d9eaba3536b41b822535569b50df356b0 --- /dev/null +++ b/host/ide/test/trace/bean/WakeUpTimeBean.test.ts @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {WakeUpTimeBean} from "../../../dist/trace/bean/WakeUpTimeBean.js" + +describe('WakeUpTimeBean Test', () => { + let wakeUpTimeBean = new WakeUpTimeBean(); + it('wakeUpTimeBean', function () { + wakeUpTimeBean = { + wakeTs: 0, + startTs: 0, + preRow: 0 + }; + expect(wakeUpTimeBean).not.toBeUndefined() + expect(wakeUpTimeBean).toMatchInlineSnapshot({ + wakeTs: expect.any(Number), + startTs: expect.any(Number), + preRow: expect.any(Number) }, ` +Object { + "preRow": Any, + "startTs": Any, + "wakeTs": Any, +} +`); + }); +}) diff --git a/host/ide/test/trace/bean/WakeupBean.test.ts b/host/ide/test/trace/bean/WakeupBean.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..0d5b967149a52849d196abfdb806dec91a276cf6 --- /dev/null +++ b/host/ide/test/trace/bean/WakeupBean.test.ts @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {WakeupBean} from "../../../dist/trace/bean/WakeupBean.js" + +describe('WakeupBean Test', () => { + let wakeUpBean = new WakeupBean(); + it('wakeUpBean', function () { + wakeUpBean = { + wakeupTime: 0, + cpu: 0, + process: "", + pid: 0, + thread: "", + tid: 0, + schedulingLatency: 0, + schedulingDesc: "", + ts: 0 + }; + expect(wakeUpBean).not.toBeUndefined() + expect(wakeUpBean).toMatchInlineSnapshot({ + wakeupTime: expect.any(Number), + cpu: expect.any(Number), + process: expect.any(String), + pid: expect.any(Number), + thread: expect.any(String), + tid: expect.any(Number), + schedulingLatency: expect.any(Number), + schedulingDesc: expect.any(String), + ts: expect.any(Number) }, ` +Object { + "cpu": Any, + "pid": Any, + "process": Any, + "schedulingDesc": Any, + "schedulingLatency": Any, + "thread": Any, + "tid": Any, + "ts": Any, + "wakeupTime": Any, +} +`); + }); + +}) diff --git a/host/ide/test/trace/component/DisassemblingWindow.test.ts b/host/ide/test/trace/component/DisassemblingWindow.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..7f6659ad0fbbd0921d86b350cf19a8012e1a129a --- /dev/null +++ b/host/ide/test/trace/component/DisassemblingWindow.test.ts @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {DisassemblingWindow,Disassembling} from "../../../dist/trace/component/DisassemblingWindow.js" + +describe('DisassemblingWindow Test', () => { + let disassemblingWindow = new DisassemblingWindow(); + + it('DisassemblingWindowTest01', function () { + expect(disassemblingWindow.getMap("","")).not.toBeUndefined(); + }); + + it('DisassemblingWindowTest02', function () { + expect(disassemblingWindow.resetCanvas(2,1,1,1)).toBeUndefined(); + }); + + it('DisassemblingWindowTest03', function () { + document.body.innerHTML = '
' + let disassemblingWindow = document.querySelector('#ccc') as DisassemblingWindow + expect(disassemblingWindow.showLoading()).toBeUndefined(); + }); + + it('DisassemblingWindowTest04', function () { + expect(disassemblingWindow.removeCloseListener()).toBeUndefined(); + }); + + it('DisassemblingWindowTest05', function () { + expect(disassemblingWindow.showContent("error","")).toBeUndefined(); + }); + +}) diff --git a/host/ide/test/trace/component/SpFilter.test.ts b/host/ide/test/trace/component/SpFilter.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..78d78ced656182574c4e6b3be19c62c17c39ac43 --- /dev/null +++ b/host/ide/test/trace/component/SpFilter.test.ts @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpFilter} from "../../../dist/trace/component/SpFilter.js" + +describe('SpFilter Test', () => { + + let spFilter = new SpFilter(); + + it('SpFilterTest01', function () { + expect(spFilter.initElements()).toBeUndefined() + }); + + it('SSpFilterTest01', function () { + expect(spFilter.initHtml()).toMatchInlineSnapshot(` +" + +
+ Input Filter +
+ + +
+
+ " +`) + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/SpInfoAndStas.test.ts b/host/ide/test/trace/component/SpInfoAndStas.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..b03f21e798ce6fb7b63ae6e4e1abf25c42e629dc --- /dev/null +++ b/host/ide/test/trace/component/SpInfoAndStas.test.ts @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpInfoAndStats} from "../../../dist/trace/component/SpInfoAndStas.js" + +describe('SpInfoAndStasTest', ()=> { + document.body.innerHTML = `` + let spInfoAndStats = document.querySelector('#ddd') as SpInfoAndStats + it('SpInfoAndStasTest01', function () { + let spInfoAndStats =new SpInfoAndStats(); + expect(spInfoAndStats.initElements()).toBeUndefined() + }); + + it('SpInfoAndStasTest03', function () { + spInfoAndStats.initMetricItemData = jest.fn(()=>true) + expect(spInfoAndStats.initMetricItemData()).toBeTruthy() + }); + + it('SpInfoAndStasTest04', function () { + let spInfoAndStats =new SpInfoAndStats(); + expect(spInfoAndStats.initDataTableStyle({children: + [{length:1,style:{backgroundColor:'var(--dark-background5,#F6F6F6)'}}] + })).toBeUndefined() + }); + + it('SpInfoAndStasTest06 ', function () { + expect(spInfoAndStats.connectedCallback()).toBeUndefined() + + }); + + it('SpInfoAndStasTest07 ', function () { + expect(spInfoAndStats.disconnectedCallback()).toBeUndefined() + + }); + + it('SpInfoAndStasTest08 ', function () { + expect(spInfoAndStats.attributeChangedCallback([],[],[])).toBeUndefined() + + }); + + it('SpInfoAndStasTest05', function () { + expect(spInfoAndStats.initHtml()).toMatchInlineSnapshot(` +" + + +
+ + +
+ " +`); + }); + + it('SpInfoAndStasTest9', function () { + expect(spInfoAndStats.initMetricItemData()).toBeTruthy(); + }); + + + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/SpMetrics.test.ts b/host/ide/test/trace/component/SpMetrics.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..5e78075a509707f5ddc0fb4df4b35946cf37312c --- /dev/null +++ b/host/ide/test/trace/component/SpMetrics.test.ts @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpMetrics} from "../../../dist/trace/component/SpMetrics.js" + +describe('SpMetrics Test', () => { + let spMetrics = new SpMetrics(); + it('SpMetricsTest01', function () { + expect(SpMetrics.initElements).toBeUndefined() + }); + it('SpMetricsTest02', function () { + expect(spMetrics.metric).toBe("") + }); + it('SpMetricsTest03', function () { + spMetrics.metric = true; + expect(spMetrics.metric).toBe("") + }); + it('SpMetricsTest04', function () { + expect(spMetrics.metricResult).toBe("") + + }); + it('SpMetricsTest05', function () { + spMetrics.metricResult = true; + expect(spMetrics.metricResult).toBeTruthy() + }); + + it('SpMetricsTest06', function () { + expect(spMetrics.attributeChangedCallback("metric")).toBeUndefined() + }); + + it('SpMetricsTest07', function () { + expect(spMetrics.attributeChangedCallback("metricResult")).toBeUndefined() + }); + + it('SpMetricsTest08', function () { + expect(spMetrics.initHtml()).toMatchInlineSnapshot(` +" + + +
+
+

Select a metric

+ + + +
+
+ +
+
+ " +`); + }); + + it('SpMetricsTest09', function () { + expect(spMetrics.reset()).toBeUndefined() + }); + + it('SpMetricsTest10', function () { + expect(spMetrics.connectedCallback()).toBeUndefined(); + }); + + it('SpMetricsTest11', function () { + expect(spMetrics.disconnectedCallback()).toBeUndefined(); + }); + + it('SpMetricsTest12', function () { + expect(spMetrics.initMetricSelectOption()).toBeUndefined(); + }); + + it('SpMetricsTest13', function () { + expect(spMetrics.initMetricDataHandle()).toBeUndefined(); + }); + + + + + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/SpQuerySQL.test.ts b/host/ide/test/trace/component/SpQuerySQL.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..e24b60837e825a7159cf43e01c1ebe815f34c36f --- /dev/null +++ b/host/ide/test/trace/component/SpQuerySQL.test.ts @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpQuerySQL} from "../../../dist/trace/component/SpQuerySQL.js" + +describe('SpQuerySQL Test', () => { + let spQuerySQL= new SpQuerySQL(); + + it('SpQuerySQLTest01', function () { + expect(spQuerySQL.checkSupportSqlAbility()).toBeFalsy() + }); + + it('SpQuerySQLTest02', function () { + expect(spQuerySQL.checkSafetySelectSql()).toBeTruthy() + }); + + it('SpQuerySQLTest03', function () { + expect(spQuerySQL.getSelectSqlField()).toBe("") + }); + + it('SpQuerySQLTest04', function () { + expect(spQuerySQL.getSelectSqlTableName()).not.toBeUndefined() + }); + + it('SpQuerySQLTest05', function () { + expect(spQuerySQL.initDataElement()).toBeUndefined() + }); + + it('SpQuerySQLTest06', function () { + spQuerySQL.statDataArray.length = 1 + expect(spQuerySQL.initData()).toBeUndefined() + }); + + it('SpQuerySQLTest07', function () { + expect(spQuerySQL.attributeChangedCallback()).toBeUndefined() + }); + + it('SpQuerySQLTest08', function () { + expect(spQuerySQL.initHtml()).toMatchInlineSnapshot(` +" + +
+
+

Enter query and press cmd/ctrl + Enter

+ + +
+
+
+

Query result - 0 counts

+
+ + +
+
+
+
+
+ " +`); + }); + + it('SpQuerySQLTest09', function () { + expect(spQuerySQL.initDataTableStyle({children:[{length:3,style:{backgroundColor:'var(--dark-background5,#F6F6F6)'}}]})).toBeUndefined() + }); + + it('SpQuerySQLTest010', function () { + expect(spQuerySQL.freshTableHeadResizeStyle()).toBeUndefined(); + }); + + it('SpQuerySQLTest011', function () { + expect(spQuerySQL.reset()).toBeUndefined(); + }); + + it('SpQuerySQLTest012', function () { + let spQuerySQL =new SpQuerySQL(); + expect(spQuerySQL.initDataTableStyle({children: + [{length:1,style:{backgroundColor:'var(--dark-background5,#F6F6F6)'}}] + })).toBeUndefined() + }); + + it('SpQuerySQLTest013', function () { + expect(spQuerySQL.initDataElement()).toBeUndefined(); + }); + + it('SpQuerySQLTest014', function () { + expect(spQuerySQL.connectedCallback()).toBeUndefined(); + }); + + it('SpQuerySQLTest015', function () { + expect(spQuerySQL.disconnectedCallback()).toBeUndefined(); + }); + + it('SpQuerySQLTest016', function () { + expect(spQuerySQL.initData()).toBeUndefined(); + }); + + it('SpQuerySQLTest017', function () { + expect(spQuerySQL.attributeChangedCallback('','','')).toBeUndefined(); + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/SpRecordTrace.test.ts b/host/ide/test/trace/component/SpRecordTrace.test.ts index 0a396a7c47eca687b40fa3795f2dae74337996f8..81169f757990a5736b419cb7856b6572cb18a53c 100644 --- a/host/ide/test/trace/component/SpRecordTrace.test.ts +++ b/host/ide/test/trace/component/SpRecordTrace.test.ts @@ -15,30 +15,155 @@ // @ts-ignore import {SpRecordTrace} from "../../../dist/trace/component/SpRecordTrace.js" + window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ disconnect: jest.fn(), observe: jest.fn(), unobserve: jest.fn(), })); -describe('SpRecordTrace Test', () => { - - let spRecordTrace = new SpRecordTrace(); +describe('SpRecordTrace Test', () => { + document.body.innerHTML = ` + + ` + let spRecordTrace = document.querySelector('#aaa') as SpRecordTrace it('SpRecordTraceTest01', function () { - expect(spRecordTrace.initHtml()).not.toBe('') + expect(SpRecordTrace.initHtml).not.toBe('') }); + it('SpRecordTraceTest02', function () { - expect(spRecordTrace.initElements()).toBeUndefined() - }); - it('SpRecordTraceTest03', function () { - let toReturnWith = spRecordTrace.createFpsPluginConfig(); - expect(toReturnWith.sampleInterval).toBe(1000); + SpRecordTrace.patentNode=jest.fn(()=>true); + expect(SpRecordTrace.initElements).toBeUndefined() }); + it('SpRecordTraceTest04', function () { - let traceEvents = spRecordTrace.createTraceEvents(['Scheduling details', 'CPU Frequency and idle states', - 'High frequency memory', 'Advanced ftrace config', 'Syscalls']); + let traceEvents = SpRecordTrace.createTraceEvents = ['Scheduling details', 'CPU Frequency and idle states', + 'High frequency memory', 'Advanced ftrace config', 'Syscalls' , 'Board voltages & frequency']; expect(traceEvents[0].indexOf('binder/binder_lock')).toBe(-1) }); + it('SpRecordTraceTest05', function () { + spRecordTrace.spAllocations = jest.fn(()=>undefined) + spRecordTrace.spAllocations.appProcess = jest.fn(()=>"") + spRecordTrace.spAllocations.appProcess.indexOf = jest.fn(()=>"") + spRecordTrace.spAllocations.appProcess.lastIndexOf = jest.fn(()=>1) + spRecordTrace.spAllocations.appProcess.slice = jest.fn(()=>1) + expect(spRecordTrace.createNativePluginConfig(1)).toEqual({"configData": {"fileName": "", + "filterSize": undefined, "fpUnwind": undefined, "mallocFreeMatchingCnt": 1000, + "mallocFreeMatchingInterval": 1000, "maxStackDepth": undefined, "pid": 1,"processName": "", + "saveFile": false, "smbPages": undefined, "stringCompressed": true}, "pluginName": "nativehook", "sampleInterval": 1000}) + }); + + it('SpRecordTraceTest06', function () { + expect(spRecordTrace.createFpsPluginConfig()).not.toBeUndefined() + }); + it('SpRecordTraceTest07', function () { + expect(spRecordTrace.vs).not.toBeUndefined() + }); + it('SpRecordTraceTest08', function () { + spRecordTrace.vs = true + expect(spRecordTrace.vs).toBeTruthy() + }); + + it('SpRecordTraceTest10', function () { + let devs = { + length:1, + } + expect(spRecordTrace.compareArray(devs)).toBeTruthy() + }); + it('SpRecordTraceTest09', function () { + spRecordTrace.vs = false + expect(spRecordTrace.vs).toBeFalsy() + }); + it('SpRecordTraceTest11', function () { + let devs = { + length:1, + } + expect(spRecordTrace.compareArray(!devs)).toBeTruthy() + }); + it('SpRecordTraceTest12', function () { + spRecordTrace.showHint = true + expect(spRecordTrace.showHint).toBeUndefined() + }); + it('SpRecordTraceTest13', function () { + spRecordTrace.showHint = false + expect(spRecordTrace.showHint).toBeUndefined() + }); + it('SpRecordTraceTest14', function () { + let event = { + isTrusted:true, + device: { + serialNumber:"string" + } + } + expect(spRecordTrace.usbDisConnectionListener(event)).toBeUndefined() + }); + it('SpRecordTraceTest15', function () { + let traceResult = { + indexOf:jest.fn(()=>undefined) + } + + expect(spRecordTrace.isSuccess(traceResult)).toBe(1) + }); + it('SpRecordTraceTest16', function () { + expect(spRecordTrace.createSessionRequest()).toStrictEqual({"pluginConfigs": [], "requestId": 1, "sessionConfig": {"buffers": + [{"pages": 16384, "policy": 0}], "keepAliveTime": 0, "resultFile": "/data/local/tmp/hiprofiler_data.htrace", "resultMaxSize": 0, + "sampleDuration": 50000, "sessionMode": 0}}) + }); + it('SpRecordTraceTest17', function () { + let that = { + createProcessPlugin:jest.fn(()=>undefined), + createCpuPlugin:jest.fn(()=>undefined), + createDiskIOPlugin:jest.fn(()=>undefined), + createNetworkPlugin:jest.fn(()=>undefined), + } + let request = { + pluginConfigs:{ + push:jest.fn(()=>undefined), + } + } + expect(spRecordTrace.createMonitorPlugin(that, request)).toBeUndefined() + }); + it('SpRecordTraceTest18', function () { + expect(spRecordTrace.createNetworkPlugin()).toStrictEqual({"configData": {"testFile": "/data/local/tmp/"}, + "pluginName": "network-plugin", "sampleInterval": 1000}) + }); + it('SpRecordTraceTest19', function () { + expect(spRecordTrace.createDiskIOPlugin()).toStrictEqual({"configData": {"reportIoStats": "IO_REPORT"}, + "pluginName": "diskio-plugin", "sampleInterval": 1000}) + }); + it('SpRecordTraceTest20', function () { + expect(spRecordTrace.createCpuPlugin()).toStrictEqual({"configData": {"pid": 0, "reportProcessInfo": true}, + "pluginName": "cpu-plugin", "sampleInterval": 1000}) + }); + it('SpRecordTraceTest21', function () { + expect(spRecordTrace.createProcessPlugin()).toStrictEqual({"configData": {"report_cpu": true, + "report_diskio": true, "report_process_tree": true, "report_pss": true}, "pluginName": "process-plugin", "sampleInterval": 1000}) + }); + it('SpRecordTraceTest22', function () { + let traceConfig = { + forEach:jest.fn(()=>undefined) + } + expect(spRecordTrace.createTraceEvents(traceConfig)).toStrictEqual([]) + }); + it('SpRecordTraceTest23', function () { + spRecordTrace.spRecordPerf = jest.fn(()=>undefined) + spRecordTrace.spRecordPerf.getPerfConfig = jest.fn(()=>undefined) + expect(spRecordTrace.createHiperConfig()).toStrictEqual({"configData": {"isRoot": false, + "outfileName": "/data/local/tmp/perf.data", "recordArgs": "-f undefined -a --cpu-limit undefined -e hw-cpu-cycles --call-stack undefined -j undefined"}, "pluginName": "hiperf-plugin", "sampleInterval": NaN}) + }); + + it('SpRecordTraceTest24', function () { + expect(spRecordTrace.isSuccess('Signal')).toBe(2) + }); + + it('SpRecordTraceTest25', function () { + expect(spRecordTrace.isSuccess('The device is abnormal')).toBe(-1); + }); + + it('SpRecordTraceTest26', function () { + expect(spRecordTrace.isSuccess('')).toBe(0); + }); + }) diff --git a/host/ide/test/trace/component/SpRecyclerSystemTrace.test.ts b/host/ide/test/trace/component/SpRecyclerSystemTrace.test.ts index 140f8b6feb64ac239e6f89165e67da4bf2f6d15f..c4642bc575a51697fe16c3e7ad5bbde948726fdd 100644 --- a/host/ide/test/trace/component/SpRecyclerSystemTrace.test.ts +++ b/host/ide/test/trace/component/SpRecyclerSystemTrace.test.ts @@ -26,6 +26,11 @@ import {SpRecyclerSystemTrace} from "../../../dist/trace/component/SpRecyclerSys describe('SpRecyclerSystemTrace Test', ()=>{ let spRecyclerSystemTrace = new SpRecyclerSystemTrace(); + const newEl=1; + const targetEl = { + parentNode:1, + nextSibling:1 + } spRecyclerSystemTrace.initElements = jest.fn(()=> true) @@ -86,9 +91,69 @@ describe('SpRecyclerSystemTrace Test', ()=>{ it('SpRecyclerSystemTraceTest13', function () { expect(spRecyclerSystemTrace.init).toBeTruthy() }); - it('SpRecyclerSystemTraceTest14', function () { - let spRecyclerSystemTrace = new SpRecyclerSystemTrace; - expect(spRecyclerSystemTrace.insertAfter).toBeTruthy() + + it('SpRecyclerSystemTraceTest15', function () { + spRecyclerSystemTrace.loadDatabaseUrl = jest.fn(()=>true) + expect(spRecyclerSystemTrace.loadDatabaseUrl()).toBeTruthy() + }); + + it('SpRecyclerSystemTraceTest16', function () { + spRecyclerSystemTrace.loadDatabaseArrayBuffer = jest.fn(()=>true) + expect(spRecyclerSystemTrace.loadDatabaseArrayBuffer()).toBeTruthy() }); + it('SpRecyclerSystemTraceTest17', function () { + expect(spRecyclerSystemTrace.initHtml()).toMatchInlineSnapshot(` +" + +
+ + + + + + +
+ " +`) + }); + it('SpRecyclerSystemTraceTest18', function () { + const newEl=1; + const targetEl = { + parentNode:{ + insertBefore:jest.fn(()=>true) + }, + nextSibling:1 + } + + expect(spRecyclerSystemTrace.insertAfter(newEl, targetEl)).toBeUndefined() + }); }) diff --git a/host/ide/test/trace/component/SpSystemTrace.test.ts b/host/ide/test/trace/component/SpSystemTrace.test.ts index 10e6d112b616d9d9264835265295381da3f926a9..b85395d89823bbe52a946f79fcad5c07ea5cb58b 100644 --- a/host/ide/test/trace/component/SpSystemTrace.test.ts +++ b/host/ide/test/trace/component/SpSystemTrace.test.ts @@ -14,7 +14,11 @@ */ // @ts-ignore -import {SpSystemTrace} from "../../../dist/trace/component/SpSystemTrace.js" +import {SpSystemTrace} from "../../../dist/trace/component/SpSystemTrace.js"; +// @ts-ignore +import {TraceRow} from "../../../dist/trace/component/trace/base/TraceRow"; +// @ts-ignore +import {procedurePool} from "../../../dist/trace/database/Procedure.js" window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ @@ -25,6 +29,12 @@ window.ResizeObserver = window.ResizeObserver || describe('SpSystemTrace Test', ()=>{ let spSystemTrace = new SpSystemTrace(); + const offset = 1 + const callback=true + const rowId="" + const rowParentId="" + const rowType="" + let smooth=true spSystemTrace.initElements = jest.fn(()=> true) @@ -51,12 +61,19 @@ describe('SpSystemTrace Test', ()=>{ }); it('SpSystemTraceTest06', function () { - expect(spSystemTrace.documentOnMouseUp('MouseUp')).toBeUndefined() + spSystemTrace.timerShaftEL = jest.fn(()=>null) + spSystemTrace.timerShaftEL.sportRuler = jest.fn(()=>undefined) + spSystemTrace.timerShaftEL.sportRuler.frame = jest.fn(()=>"") + spSystemTrace.timerShaftEL.canvas = jest.fn(()=> undefined) + spSystemTrace.timerShaftEL.canvas.offsetLeft = jest.fn(()=>1) + spSystemTrace.timerShaftEL.sportRuler.frame.contains = jest.fn(()=>true) + spSystemTrace.documentOnMouseUp = jest.fn(()=>true) + expect(spSystemTrace.documentOnMouseUp('MouseUp')).toBeTruthy() }); it('SpSystemTraceTest07', function () { - spSystemTrace.rangeSelect = jest.fn(()=>true) - spSystemTrace.rangeSelect.mouseMove = jest.fn(()=>true) + spSystemTrace.timerShaftEL = jest.fn(()=>undefined) + spSystemTrace.timerShaftEL.isScaling = jest.fn(()=>true) expect(spSystemTrace.documentOnMouseMove('MouseMove')).toBeUndefined() }); @@ -68,23 +85,149 @@ describe('SpSystemTrace Test', ()=>{ expect(spSystemTrace.selectStructNull('')).toBeUndefined() }); - it('SpSystemTraceTest10', function () { - expect(spSystemTrace.documentOnClick('OnClick')).toBeUndefined() - }); - it('SpSystemTraceTest11', function () { expect(spSystemTrace.connectedCallback()).toBeUndefined() }); it('SpSystemTraceTest12', function () { + spSystemTrace.timerShaftEL.removeEventListener = jest.fn(()=>true) expect(spSystemTrace.disconnectedCallback()).toBeUndefined() }); - it('SpSystemTraceTest13', function () { - expect(spSystemTrace.goProcess).toBeTruthy() - }); - it('SpSystemTraceTest14', function () { expect(spSystemTrace.loadDatabaseUrl).toBeTruthy() }); + + it('SpSystemTraceTest15', function () { + spSystemTrace.rowsEL = jest.fn(()=>true) + spSystemTrace.rowsEL.scrollTo = jest.fn(()=>offset) + spSystemTrace.rowsEL.removeEventListener = jest.fn(()=>true) + spSystemTrace.rowsEL.addEventListener = jest.fn(()=>true) + expect(spSystemTrace.rowScrollTo(offset,callback)).toBeUndefined() + }); + + it('SpSystemTraceTest16', function () { + let spSystemTrace = new SpSystemTrace({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + expect(spSystemTrace.onClickHandler()).toBeUndefined() + }); + + it('SpSystemTraceTest17', function () { + let spSystemTrace = new SpSystemTrace({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + expect(spSystemTrace.search()).toBeUndefined() + }); + + it('SpSystemTraceTest18', function () { + let spSystemTrace = new SpSystemTrace({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + expect(spSystemTrace.searchCPU()).not.toBeUndefined() + }); + + it('SpSystemTraceTest19', function () { + expect(spSystemTrace.initHtml()).toMatchInlineSnapshot(` +" + +
+ + +
+
+ + +
+ " +`); + }); + + it('SpSystemTraceTest20', function () { + let spSystemTrace = new SpSystemTrace({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + // @ts-ignore + TraceRow.range = jest.fn(()=>undefined) + TraceRow.range.startNS = jest.fn(()=>1) + spSystemTrace.onClickHandler = jest.fn(()=>true) + expect(spSystemTrace.showPreCpuStruct(1,[{length:0}])).toBe(0) + }); + + it('SpSystemTraceTest21', function () { + let spSystemTrace = new SpSystemTrace({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + // @ts-ignore + TraceRow.range = jest.fn(()=>undefined) + TraceRow.range.startNS = jest.fn(()=>1) + spSystemTrace.onClickHandler = jest.fn(()=>true) + expect(spSystemTrace.showNextCpuStruct(1,[{length:0}])).toBe(0) + }); + + it('SpSystemTraceTest22', function () { + let spSystemTrace = new SpSystemTrace({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + procedurePool.clearCache = jest.fn(()=>true) + expect(spSystemTrace.reset()).toBeUndefined() + }); + it('SpSystemTraceTest23', function () { + let spSystemTrace = new SpSystemTrace({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + let structs = [{ + length:1, + starttime:1, + }] + let previous = 1; + let currentIndex = 1; + TraceRow.range = jest.fn(()=>undefined) + TraceRow.range.startNS = jest.fn(()=>1) + expect(spSystemTrace.showStruct(previous, currentIndex, structs)).not.toBeUndefined() + }); + it('SpSystemTraceTest24', function () { + let spSystemTrace = new SpSystemTrace({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + TraceRow.range = jest.fn(()=>undefined) + TraceRow.range.startNS = jest.fn(()=>1) + expect(spSystemTrace.closeAllExpandRows()).toBeUndefined() + }); + it('SpSystemTraceTest25', function () { + let spSystemTrace = new SpSystemTrace({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + spSystemTrace.rowsEL = jest.fn(()=>true) + spSystemTrace.rowsEL.scroll = jest.fn(()=>true) + expect(spSystemTrace.scrollToProcess()).toBeUndefined() + }); + it('SpSystemTraceTest26', function () { + let spSystemTrace = new SpSystemTrace({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + spSystemTrace.rowsEL = jest.fn(()=>true) + spSystemTrace.rowsEL.scroll = jest.fn(()=>true) + expect(spSystemTrace.scrollToDepth()).toBeUndefined() + }); + it('SpSystemTraceTest27', function () { + let spSystemTrace = new SpSystemTrace({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + expect(spSystemTrace.searchThreadsAndProcesses()).toStrictEqual([]) + }); }) diff --git a/host/ide/test/trace/component/SpWelcomePage.test.ts b/host/ide/test/trace/component/SpWelcomePage.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..a9055037c4e5f64886406126daf61a7b7285cd99 --- /dev/null +++ b/host/ide/test/trace/component/SpWelcomePage.test.ts @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpWelcomePage} from "../../../dist/trace/component/SpWelcomePage.js" + +describe('SpWelcomePage Test', () => { + + let spWelcomePage = new SpWelcomePage(); + + it('SpWelcomePageTest01', function () { + expect(spWelcomePage.initElements()).toBeUndefined() + }); + + it('SpWelcomePageTest01', function () { + expect(spWelcomePage.initHtml()).toMatchInlineSnapshot(` +" + +
+ +
+ " +`) + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/Sptext.test.ts b/host/ide/test/trace/component/Sptext.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..16dc910ce9dd7a36673fe4e000b6f17a72651e40 --- /dev/null +++ b/host/ide/test/trace/component/Sptext.test.ts @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {SpText} from "../../../dist/trace/component/Sptext.js" + +describe('Sptext Test', () => { + + let sptext = new SpText(); + + it('SptextTest01', function () { + expect(sptext.initElements()).toBeUndefined() + }); + + it('SptextTest01', function () { + expect(sptext.initHtml()).toMatchInlineSnapshot(` +" + +
+
+ + + + +
+
+ " +`) + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/StackBar.test.ts b/host/ide/test/trace/component/StackBar.test.ts index 271c3b5bea68a6f3933b32b1e54f6980e30fc74c..d43eb0cb0d06ac3ac9763f9117d6e6f14513b6e2 100644 --- a/host/ide/test/trace/component/StackBar.test.ts +++ b/host/ide/test/trace/component/StackBar.test.ts @@ -23,14 +23,17 @@ describe('StackBar Test', () => { it('StackBarTest01', function () { expect(stackBar.initHtml()).not.toBe('') }); + it('StackBarTest02', function () { expect(stackBar.initElements()).toBeUndefined() }); + it('StackBarTest03', function () { let stateWidth = stackBar.getStateWidth('state'); let hasWidth = stateWidth > 0; expect(hasWidth).toBeTruthy(); }); + it('StackBarTest04', function () { let htmlDivElement = stackBar.createBarElement({ state: "", @@ -40,4 +43,25 @@ describe('StackBar Test', () => { let hasDivEl = htmlDivElement.toLocaleString().length > 5; expect(hasDivEl).toBeTruthy(); }); + + it('StackBarTest05', function () { + expect(stackBar.initHtml()).toMatchInlineSnapshot(` +" + +
+
+ " +`); + }); }) diff --git a/host/ide/test/trace/component/chart/FrameChart.test.ts b/host/ide/test/trace/component/chart/FrameChart.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..677d780502724e4afeec920077e4d6317e3c1b4b --- /dev/null +++ b/host/ide/test/trace/component/chart/FrameChart.test.ts @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {FrameChart} from "../../../../dist/trace/component/chart/FrameChart.js" + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe('FrameChart Test', () => { + let node= [ + {children: ''}, + {children:{length:0}} + ] + let node1= [ + {children: ''}, + {children:{length:10}} + ] + let selectData = [length=1] + document.body.innerHTML = '' + let frameChart = document.querySelector('#ccc') as FrameChart + + it('FrameChartTest01', function () { + frameChart.tabPaneScrollTop = false; + expect(frameChart.tabPaneScrollTop).toBeFalsy(); + }); + + it('FrameChartTest02', function () { + expect(frameChart.updateFloatHint()).toBeUndefined(); + }); + + it('FrameChartTest03', function () { + frameChart.calculateChartData = jest.fn(()=>true) + frameChart.calMaxDepth = jest.fn(()=>true) + expect(frameChart.redrawChart(selectData)).toBeUndefined(); + }); + + it('FrameChartTest05', function () { + let index = frameChart.scale(2) + expect(index).toBe(undefined); + }); + + it('FrameChartTest08', function () { + frameChart.translationDraw = jest.fn(()=>true) + expect(frameChart.translation()).toBeUndefined(); + }); + + it('FrameChartTest14', function () { + let frameChart = new FrameChart(); + frameChart.translationDraw = jest.fn(()=>true) + expect(frameChart.translation(-1)).toBeUndefined(); + }); + + it('FrameChartTest09', function () { + frameChart.selectTotalCount = false; + expect(frameChart.selectTotalCount).toBeFalsy(); + }); + + it('FrameChartTest11', function () { + let frameChart = new FrameChart(); + frameChart._mode = 1; + frameChart.drawScale = jest.fn(()=>true) + expect(frameChart.calculateChartData()).not.toBeUndefined(); + }); + + it('FrameChartTest12', function () { + expect(frameChart.updateCanvas()).toBeUndefined(); + }); + + it('FrameChartTest13', function () { + let frameChart = new FrameChart(); + frameChart.translationDraw = jest.fn(()=>true) + frameChart.lastCanvasXInScale = 0 + expect(frameChart.translationByScale()).toBe(undefined); + }); + + it('FrameChartTest21', function () { + let frameChart = new FrameChart(); + frameChart.translationDraw = jest.fn(()=>true) + frameChart.canvasX = 4 + frameChart.lastCanvasXInScale = 1 + expect(frameChart.translationByScale()).toBe(undefined); + }); + + it('FrameChartTest22', function () { + let frameChart = new FrameChart(); + frameChart.translationDraw = jest.fn(()=>true) + expect(frameChart.translationByScale(1)).toBe(undefined); + }); + it('FrameChartTest211', function () { + expect(frameChart.searchData([],2,2)).toBeNull(); + }); + + it('FrameChartTest15', function () { + let frameChart = new FrameChart(); + frameChart.calculateChartData = jest.fn(()=>true) + frameChart.xPoint = 1 + expect(frameChart.translationDraw()).toBe(undefined); + }); + + it('FrameChartTest16', function () { + expect(frameChart.onMouseClick({button:0})).toBeUndefined(); + }); + + it('FrameChartTest17', function () { + let frameChart = new FrameChart(); + expect(frameChart.initHtml()).toMatchInlineSnapshot(` +" + + +
" +`); + }); + + it('FrameChartTest18', function () { + let frameChart = new FrameChart(); + expect(frameChart.drawFrameChart(node)).toBeUndefined(); + }); + + it('FrameChartTest20', function () { + expect(frameChart.searchData([],1,1)).toBeNull(); + }); + + it('FrameChartTest23', function () { + expect(frameChart.onMouseClick({button:2})).toBeUndefined(); + }); + + it('FrameChartTest24', function () { + document.body.innerHTML = `` + expect(frameChart.drawScale()).toBeUndefined(); + }); + + it('FrameChartTest25', function () { + let frameChart = new FrameChart(); + frameChart.selectTotalSize = false; + expect(frameChart.selectTotalSize).toBeFalsy(); + }); + + it('FrameChartTest26', function () { + let frameChart = new FrameChart(); + frameChart.maxDepth = false; + expect(frameChart.maxDepth).toBeFalsy(); + }); + + + it('FrameChartTest27 ', function () { + let frameChart = new FrameChart(); + expect(frameChart.calMaxDepth(node,1)).toBeUndefined() + }); + + it('FrameChartTest28 ', function () { + let frameChart = new FrameChart(); + expect(frameChart.mode).toBeUndefined() + }); + + it('FrameChartTest29', function () { + let frameChart = new FrameChart(); + frameChart.mode =false + expect(frameChart.mode).toBeFalsy() + }); + + it('FrameChartTest30', function () { + frameChart.caldrawArgs = jest.fn(()=>true) + expect(frameChart.caldrawArgs()).toBeTruthy() + }); + + it('FrameChartTest31', function () { + let frameChart = new FrameChart(); + frameChart.data = []; + expect(frameChart.data).toBeFalsy(); + }); + + it('FrameChartTest32', function () { + let frameChart = new FrameChart(); + expect(frameChart.addChartClickListener(()=>{})).toBeUndefined(); + }); + + it('FrameChartTest33', function () { + let frameChart = new FrameChart(); + expect(frameChart.removeChartClickListener(()=>{})).toBeUndefined(); + }); + + it('FrameChartTest34', function () { + let frameChart = new FrameChart(); + expect(frameChart.calMaxDepth(node1,10)).toBeUndefined(); + }); + + it('FrameChartTest35', function () { + let frameChart = new FrameChart(); + frameChart.drawTriangleOnScale = jest.fn(()=>true); + expect(frameChart.drawTriangleOnScale()).toBeTruthy(); + }); + + it('FrameChartTest36', function () { + frameChart._mode = 1; + frameChart.drawScale = jest.fn(()=>true); + expect(frameChart.drawScale()).toBeTruthy(); + }); + + it('FrameChartTest37', function () { + frameChart._mode = 2; + frameChart.drawScale = jest.fn(()=>true); + expect(frameChart.drawScale()).toBeTruthy(); + }); + + it('FrameChartTest38', function () { + frameChart._mode = 3; + frameChart.drawScale = jest.fn(()=>true); + expect(frameChart.drawScale()).toBeTruthy(); + }); + + it('FrameChartTest39', function () { + expect(frameChart.resetTrans()).toBeUndefined(); + }); + + it('FrameChartTest40', function () { + expect(frameChart.onMouseClick({button:2})).toBeUndefined(); + }); + + it('FrameChartTest41', function () { + expect(frameChart.drawDataSet(node,true)).toBeUndefined(); + }); + + + + + + + + + +}) diff --git a/host/ide/test/trace/component/chart/PerfDataQuery.test.ts b/host/ide/test/trace/component/chart/PerfDataQuery.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..7530c641057b4fb8e20c0c7dca353d1dc7267d69 --- /dev/null +++ b/host/ide/test/trace/component/chart/PerfDataQuery.test.ts @@ -0,0 +1,496 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//@ts-ignore +import {perfDataQuery} from "../../../../dist/trace/component/chart/PerfDataQuery.js" + +describe('perfDataQuery Test',()=>{ + + it('perfDataQueryTest01 ', function () { + let callChain = { + symbolId:-1, + fileId:1, + fileName:"unkown", + vaddrInFile:1, + pid:1, + tid:1, + canCharge:true, + path:'', + } + expect(perfDataQuery.setCallChainName(callChain)).toBe("+0x1"); + }); + + it('perfDataQueryTest15 ', function () { + let callChain = { + symbolId:0, + fileId:1, + fileName:"unkown", + vaddrInFile:1, + } + expect(perfDataQuery.setCallChainName(callChain)).toBe("+0x1"); + }); + + it('perfDataQueryTest02 ', function () { + let callChain = { + tid:1, + threadState:"", + bottomUpMerageId:"1", + } + perfDataQuery.threadData[callChain.tid] = jest.fn(()=>[]) + perfDataQuery.threadData[callChain.tid].threadName = jest.fn(()=>"") + expect(perfDataQuery.addProcessThreadStateData(callChain)).toBeUndefined(); + }); + + it('perfDataQueryTest03 ', function () { + perfDataQuery.groupNewTreeNoId = jest.fn(()=>true) + expect(perfDataQuery.getCallChainsBySampleIds([{length:1}],true)).not.toBeUndefined(); + }); + + it('perfDataQueryTest06 ', function () { + let callChain = [{name:""}] + let currentNode = { + initChildren:[], + id:"", + children:[], + } + expect(perfDataQuery.merageChildren(currentNode,callChain,true)).toBeUndefined(); + }); + + it('perfDataQueryTest07 ', function () { + perfDataQuery.perfDataQuery = jest.fn(()=>true) + expect(perfDataQuery.splitTree([],"",true,true)).toBeUndefined(); + }); + + it('perfDataQueryTest08 ', function () { + expect(perfDataQuery.clearSplitMapData("name")).toBeUndefined(); + }); + + it('perfDataQueryTest09 ', function () { + expect(perfDataQuery.resetAllNode([])).toBeUndefined(); + }); + + it('perfDataQueryTest11 ', function () { + expect(perfDataQuery.findSearchNode([],'')).toBeUndefined(); + }); + + it('perfDataQueryTest14 ', function () { + expect(perfDataQuery.initCallChainBottomUp([])).toBeUndefined(); + }); + + it('perfDataQueryTest17 ', function () { + let callChainsData = [{ + tid: 0, + pid: 0, + name: "", + fileName: "", + threadState: "", + startNS: 0, + dur: 0, + sampleId: 0, + callChainId: 0, + vaddrInFile: 0, + fileId: 0, + symbolId: 0, + path: "", + parentId: "", + id: "", + topDownMerageId: "", + topDownMerageParentId: "", + bottomUpMerageId: "", + bottomUpMerageParentId: "", + depth: 0, + previousNode: undefined, + nextNode: undefined, + },{ + tid: 1, + pid: 1, + name: "", + fileName: "", + threadState: "", + startNS: 1, + dur: 1, + sampleId: 1, + callChainId: 0, + vaddrInFile: 0, + fileId: 0, + symbolId: 0, + path: "", + parentId: "", + id: "", + topDownMerageId: "", + topDownMerageParentId: "", + bottomUpMerageId: "", + bottomUpMerageParentId: "", + depth: 0, + previousNode: undefined, + nextNode: undefined, + }] + expect(perfDataQuery.initCallChainBottomUp(callChainsData)).toBeUndefined(); + }); + + it('perfDataQueryTest18 ', function () { + let callChainsData = [{ + tid: 100, + pid: 100, + name: "", + fileName: "", + threadState: "", + startNS: 0, + dur: 0, + sampleId: 0, + callChainId: 0, + vaddrInFile: 0, + fileId: 0, + symbolId: 0, + path: "", + parentId: "", + id: "", + topDownMerageId: "", + topDownMerageParentId: "", + bottomUpMerageId: "", + bottomUpMerageParentId: "", + depth: 0, + previousNode: undefined, + nextNode: undefined, + },{ + tid: 111, + pid: 111, + name: "", + fileName: "", + threadState: "", + startNS: 11, + dur: 11, + sampleId: 11, + callChainId: 0, + vaddrInFile: 0, + fileId: 0, + symbolId: 0, + path: "", + parentId: "", + id: "", + topDownMerageId: "", + topDownMerageParentId: "", + bottomUpMerageId: "", + bottomUpMerageParentId: "", + depth: 0, + previousNode: undefined, + nextNode: undefined, + },{ + tid: 222, + pid: 222, + name: "", + fileName: "", + threadState: "", + startNS: 22, + dur: 22, + sampleId: 22, + callChainId: 0, + vaddrInFile: 0, + fileId: 0, + symbolId: 0, + path: "", + parentId: "", + id: "", + topDownMerageId: "", + topDownMerageParentId: "", + bottomUpMerageId: "", + bottomUpMerageParentId: "", + depth: 0, + previousNode: undefined, + nextNode: undefined, + }] + expect(perfDataQuery.initCallChainBottomUp(callChainsData)).toBeUndefined(); + }); + + it('perfDataQueryTest19 ', function () { + let callChainsData = [{ + tid: 100, + pid: 100, + name: "", + fileName: "", + threadState: "", + startNS: 0, + dur: 0, + sampleId: 0, + callChainId: 0, + vaddrInFile: 0, + fileId: 0, + symbolId: -1, + path: "", + parentId: "", + id: "", + topDownMerageId: "", + topDownMerageParentId: "", + bottomUpMerageId: "", + bottomUpMerageParentId: "", + depth: 0, + previousNode: undefined, + nextNode: undefined, + }] + expect(perfDataQuery.setCallChainName(callChainsData)).not.toBeUndefined(); + }); + + it('perfDataQueryTest21 ', function () { + perfDataQuery.groupNewTreeNoId = jest.fn(()=>true); + let sampleIds = [{ + tid: 10, + pid: 100, + length: 0, + name: "", + fileName: "", + threadState: "", + startNS: 0, + dur: 0, + sampleId: 0, + callChainId: 0, + vaddrInFile: 0, + fileId: 0, + symbolId: -1, + path: "", + parentId: "", + id: "", + topDownMerageId: "", + topDownMerageParentId: "", + bottomUpMerageId: "", + bottomUpMerageParentId: "", + depth: 0, + previousNode: undefined, + nextNode: undefined, + }] + expect(perfDataQuery.getCallChainsBySampleIds(sampleIds, true)).not.toBeUndefined(); + }); + + it('perfDataQueryTest12 ', function () { + let callChainsData = [{ + tid: 100, + pid: 100, + name: "", + fileName: "", + threadState: "", + startNS: 0, + dur: 0, + sampleId: 0, + callChainId: 0, + vaddrInFile: 0, + fileId: 0, + symbolId: -1, + path: "", + parentId: "", + id: "", + topDownMerageId: "", + topDownMerageParentId: "", + bottomUpMerageId: "", + bottomUpMerageParentId: "", + depth: 0, + previousNode: undefined, + nextNode: undefined, + }] + + let currentData = { + id: "", + parentId: "", + currentTreeParentNode: undefined, + symbolName: "", + symbol: "", + libName: "", + path: "", + self: "0s", + weight: "", + selfDur: 0, + dur: 0, + tid: 0, + pid: 0, + isStore: 0, + children: [], + initChildren: [], + type: 0, + vaddrInFile: 0, + isSelected: false, + searchShow: true, + } + expect(perfDataQuery.merageChildren(currentData, callChainsData,true)).toBeUndefined(); + }); + it('perfDataQueryTest14 ', function () { + let node ={ + id: "", + parentId: "", + currentTreeParentNode: undefined, + symbolName: "", + symbol: "", + libName: "", + path: "", + self: "0s", + weight: "", + selfDur: 0, + dur: 0, + tid: 0, + pid: 0, + isStore: 0, + children: [], + initChildren: [], + type: 0, + vaddrInFile: 0, + isSelected: false, + searchShow: true, + } + expect(perfDataQuery.recursionChargeInitTree(node,'',true)).toBeUndefined(); + + }); + + it('perfDataQueryTest15 ', function () { + let node ={ + id: "", + parentId: "", + currentTreeParentNode: undefined, + symbolName: "", + symbol: "", + libName: "", + path: "", + self: "0s", + weight: "", + selfDur: 0, + dur: 0, + tid: 0, + pid: 0, + isStore: 0, + children: [], + initChildren: [], + type: 0, + vaddrInFile: 0, + isSelected: false, + searchShow: true, + } + expect(perfDataQuery.recursionChargeTree(node,'',true)).toBeUndefined(); + + }); + + it('perfDataQueryTest16 ', function () { + let node ={ + id: "", + parentId: "", + currentTreeParentNode: undefined, + symbolName: "", + symbol: "", + libName: "", + path: "", + self: "0s", + weight: "", + selfDur: 0, + dur: 0, + tid: 0, + pid: 0, + isStore: 0, + children: [], + initChildren: [], + type: 0, + vaddrInFile: 0, + isSelected: false, + searchShow: true, + } + expect(perfDataQuery.recursionPruneInitTree(node,'',true)).toBeUndefined(); + + }); + + it('perfDataQueryTest17 ', function () { + let node ={ + id: "", + parentId: "", + currentTreeParentNode: undefined, + symbolName: "", + symbol: "", + libName: "", + path: "", + self: "0s", + weight: "", + selfDur: 0, + dur: 0, + tid: 0, + pid: 0, + isStore: 0, + children: [], + initChildren: [], + type: 0, + vaddrInFile: 0, + isSelected: false, + searchShow: true, + } + expect(perfDataQuery.recursionPruneTree(node,'',true)).toBeUndefined(); + + }); + + it('perfDataQueryTest18 ', function () { + let node ={ + id: "", + parentId: "", + currentTreeParentNode: undefined, + symbolName: "", + symbol: "", + libName: "", + path: "", + self: "0s", + weight: "", + selfDur: 0, + dur: 0, + tid: 0, + pid: 0, + isStore: 0, + children: [], + initChildren: [], + type: 0, + vaddrInFile: 0, + isSelected: false, + searchShow: true, + } + expect(perfDataQuery.recursionChargeByRule(node,'',true)).toBeUndefined(); + + }); + + it('perfDataQueryTest19 ', function () { + let node ={ + id: "", + parentId: "", + currentTreeParentNode: undefined, + symbolName: "", + symbol: "", + libName: "", + path: "", + self: "0s", + weight: "", + selfDur: 0, + dur: 0, + tid: 0, + pid: 0, + isStore: 0, + children: [], + initChildren: [], + type: 0, + vaddrInFile: 0, + isSelected: false, + searchShow: true, + } + expect(perfDataQuery.pruneChildren(node,'')).toBeUndefined(); + + }); + + it('perfDataQueryTest20 ', function () { + + expect(perfDataQuery.clearSplitMapData('')).toBeUndefined(); + + }); + it('perfDataQueryTest21 ', function () { + expect(perfDataQuery.clearSearchNode()).toBeUndefined(); + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/chart/SpAbilityMonitor.test.ts b/host/ide/test/trace/component/chart/SpAbilityMonitor.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..eb49764876b7e6c5d2937670a1aa6898972084f7 --- /dev/null +++ b/host/ide/test/trace/component/chart/SpAbilityMonitor.test.ts @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpAbilityMonitorChart} from "../../../../dist/trace/component/chart/SpAbilityMonitorChart.js"; +import "../../../../dist/trace/component/chart/SpAbilityMonitorChart.js"; +// @ts-ignore +import {SpSystemTrace} from "../../../../dist/trace/component/SpSystemTrace.js"; +import { + queryCPuAbilityMaxData, + queryMemoryMaxData, + queryNetWorkMaxData +} from "../../../../src/trace/database/SqlLite.js"; +const sqlit = require("../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); +describe('SpAbilityMonitorChart Test', () => { + let MockqueryAbilityExits = sqlit.queryAbilityExits; + MockqueryAbilityExits.mockResolvedValue([ + { + event_name: "trace_cpu_usage", + stat_type: "received", + count: 1 + }, + { + event_name: "sys_memory", + stat_type: "received", + count: 1 + }, + { + event_name: "trace_diskio", + stat_type: "received", + count: 1 + }, + { + event_name: "trace_diskio", + stat_type: "received", + count: 1 + } + ]) + let cpudata = sqlit.queryCPuAbilityMaxData; + cpudata.mockResolvedValue([{ + totalLoad: 1, + userLoad: 1, + systemLoad: 1 + }]) + let memorydata = sqlit.queryMemoryMaxData; + memorydata.mockResolvedValue([{ + maxValue: 1, + filter_id: 1 + }]) + + let queryDiskIo = sqlit.queryDiskIoMaxData; + queryDiskIo.mockResolvedValue([{ + bytesRead: 1, + bytesWrite: 1, + readOps: 1, + writeOps:1 + }]) + + let netWorkDiskIo = sqlit.queryNetWorkMaxData; + netWorkDiskIo.mockResolvedValue([{ + maxIn: 1, + maxOut: 1, + maxPacketIn: 1, + maxPacketOut:1 + }]) + let spSystemTrace = new SpSystemTrace(); + let trace = new SpAbilityMonitorChart(spSystemTrace); + it('SpAbilityMonitorChart01', function () { + trace.init() + expect(trace).toBeDefined(); + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneSPT.test.ts b/host/ide/test/trace/component/chart/SpCpuChart.test.ts similarity index 45% rename from host/ide/test/trace/component/trace/sheet/TabPaneSPT.test.ts rename to host/ide/test/trace/component/chart/SpCpuChart.test.ts index e6cdc3d1fc75a223c21db98f3c5717008e79b77d..84a87c085b5066c301f16ed7199745170845142a 100644 --- a/host/ide/test/trace/component/trace/sheet/TabPaneSPT.test.ts +++ b/host/ide/test/trace/component/chart/SpCpuChart.test.ts @@ -14,46 +14,28 @@ */ // @ts-ignore -import {TabPaneSPT} from "../../../../../dist/trace/component/trace/sheet/TabPaneSPT.js" +import {SpChartManager} from "../../../../dist/trace/component/chart/SpChartManager.js"; +// @ts-ignore +import {SpCpuChart} from "../../../../dist/trace/component/chart/SpCpuChart.js"; +import {queryCpuMax} from "../../../../src/trace/database/SqlLite.js"; + +const sqlit = require("../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../dist/trace/database/SqlLite.js"); + window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ disconnect: jest.fn(), observe: jest.fn(), unobserve: jest.fn(), })); -describe('TabPaneSPT Test', () => { - let tabPaneSPT = new TabPaneSPT(); - - let dataArray = [{ - id: "", - pid: "", - title: "", - children: [], - process: "", - processId: 0, - thread: "", - threadId: 0, - state: "", - wallDuration: 0, - avgDuration: "", - count: 0, - minDuration: 0, - maxDuration: 0, - stdDuration: "", - }] - - it('TabPaneSPTTest01', function () { - let result = tabPaneSPT.groupByStateToMap(dataArray); - expect(result.get('').length).toBe(1); +describe('SpCpuChart Test', () => { + let MockqueryCpuMax = sqlit.queryCpuMax; + MockqueryCpuMax.mockResolvedValue([{cpu:1}]) + let ss = new SpChartManager(); + let trace = new SpCpuChart(ss); + it('SpMpsChart01', function () { + trace.init() + expect(trace).toBeDefined(); }); - it('TabPaneSPTTest02', function () { - let result = tabPaneSPT.groupByProcessToMap(dataArray) - expect(result.get(0).length).toBe(1); - }); - - it('TabPaneSPTTest03', function () { - let result = tabPaneSPT.groupByStateProcessToMap(dataArray) - expect(result.get('').get(0).length).toBe(1); - }); -}) +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneContextSwitch.test.ts b/host/ide/test/trace/component/chart/SpFileSystemChart.test.ts similarity index 42% rename from host/ide/test/trace/component/trace/sheet/TabPaneContextSwitch.test.ts rename to host/ide/test/trace/component/chart/SpFileSystemChart.test.ts index 3d3b8e73d2e302cfb792f9a080e45fe6d3b79186..28508b0fc3d6a5dfa4fbfa584fa9b9b96dab079c 100644 --- a/host/ide/test/trace/component/trace/sheet/TabPaneContextSwitch.test.ts +++ b/host/ide/test/trace/component/chart/SpFileSystemChart.test.ts @@ -14,45 +14,32 @@ */ // @ts-ignore -import {TabPaneContextSwitch} from "../../../../../dist/trace/component/trace/sheet/TabPaneContextSwitch.js" +import {SpFileSystemChart} from "../../../../dist/trace/component/chart/SpFileSystemChart.js"; +// @ts-ignore +import {SpChartManager} from "../../../../dist/trace/component/chart/SpChartManager.js"; +const sqlit = require("../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../dist/trace/database/SqlLite.js"); + window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ disconnect: jest.fn(), observe: jest.fn(), unobserve: jest.fn(), })); -describe('TabPaneContextSwitch Test', () => { - let tabPaneContextSwitch = new TabPaneContextSwitch(); - let dataArray = [{ - id: "", - pid: "", - title: "", - children: [], - process: "", - processId: 0, - thread: "", - threadId: 0, - state: "", - wallDuration: 0, - avgDuration: "", - count: 0, - minDuration: 0, - maxDuration: 0, - stdDuration: "", - }] - it('TabPaneContextSwitchTest01', function () { - let result = tabPaneContextSwitch.groupByProcessThreadToMap(dataArray); - expect(result.get(0).length).toBeUndefined(); - }); - - it('TabPaneContextSwitchTest02', function () { - let result = tabPaneContextSwitch.groupByProcessToMap(dataArray) - expect(result.get(0).length).toBe(1); - }); +describe('SpFileSystemChart Test', ()=> { + let hasFileSysData = sqlit.hasFileSysData; + hasFileSysData.mockResolvedValue([{ + fsCount: 2, + vmCount: 2, + ioCount: 0 + }]) - it('TabPaneContextSwitchTest03', function () { - let result = tabPaneContextSwitch.groupByThreadToMap(dataArray) - expect(result.get(0).length).toBe(1); + let ss = new SpChartManager(); + let spFileSystemChart = new SpFileSystemChart(ss); + spFileSystemChart.initFileCallchain = jest.fn(()=>true) + it('SpMpsChart01', function () { + spFileSystemChart.init() + expect(spFileSystemChart).toBeDefined(); }); -}) +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/chart/SpFpsChart.test.ts b/host/ide/test/trace/component/chart/SpFpsChart.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..b17bebfe5a8586ce1186554d7b01cf7947e78bcf --- /dev/null +++ b/host/ide/test/trace/component/chart/SpFpsChart.test.ts @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpFpsChart} from "../../../../dist/trace/component/chart/SpFpsChart.js"; +// @ts-ignore +import {SpChartManager} from "../../../../dist/trace/component/chart/SpChartManager.js"; + +const sqlit = require("../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), +})); +describe('spFpsChart Test', () => { + let spFpsChart = new SpFpsChart(new SpChartManager()) + let fpsMock = sqlit.getFps; + fpsMock.mockResolvedValue([{startNS: 0, fps: 1,},{startNS: 2, fps: 3,}]) + + it('spFpsChart01', function () { + expect(spFpsChart.init()).toBeDefined(); + }); +}) diff --git a/host/ide/test/trace/component/chart/SpFreqChart.test.ts b/host/ide/test/trace/component/chart/SpFreqChart.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..12d58756a6416788269348a2aa70992edb0cef32 --- /dev/null +++ b/host/ide/test/trace/component/chart/SpFreqChart.test.ts @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +// @ts-ignore +import {SpChartManager} from "../../../../dist/trace/component/chart/SpChartManager.js"; +// @ts-ignore +import {SpFreqChart} from "../../../../dist/trace/component/chart/SpFreqChart.js"; + +const sqlit = require("../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), +})); +describe('spFpsChart Test', () => { + let spFpsChart = new SpFreqChart(new SpChartManager()) + + let mockGetCpuLimitFreq = sqlit.getCpuLimitFreq; + mockGetCpuLimitFreq.mockResolvedValue([ + { + startNs: 1000, + max: 100, + min: 20, + cpu: 0 + }, + { + startNs: 2000, + max: 300, + min: 100, + cpu: 1 + }]) + + let mockCpuLimitFreqId = sqlit.getCpuLimitFreqId; + mockCpuLimitFreqId.mockResolvedValue([ + { + cpu: 0, + maxFilterId: 2, + minFilterId: 1 + }, + { + cpu: 1, + maxFilterId: 2, + minFilterId: 1 + }]) + + let mockCpuFreqData = sqlit.queryCpuFreqData; + mockCpuFreqData.mockResolvedValue([ + { + cpu: 0, + value: 100, + startNS: 2000 + }, + { + cpu: 1, + value: 100, + startNS: 3000 + }]) + + + let mockCpuState = sqlit.queryCpuState; + mockCpuState.mockResolvedValue([ + { + startTs: 1000, + value: 100 + }, + { + startTs: 2000, + value: 10 + }]) + + let queryCpuFreqMock = sqlit.queryCpuFreq; + queryCpuFreqMock.mockResolvedValue([ + { + cpu: 0, + filterId: 1 + }, + { + cpu: 1, + filterId: 2 + }]) + + let queryCpuStateFilter = sqlit.queryCpuStateFilter; + queryCpuStateFilter.mockResolvedValue([ + { + cpu: 0, + filterId: 1 + }, + { + cpu: 1, + filterId: 2 + }]) + + let queryCpuMaxFreqMock = sqlit.queryCpuMaxFreq; + queryCpuMaxFreqMock.mockResolvedValue([{maxFreq: 100}]) + + let MockgetCpuLimitFreqId = sqlit.getCpuLimitFreqId + MockgetCpuLimitFreqId.mockResolvedValue([{cpu: 1,maxFilterId:9 , minFilterId: 1}]) + + let MockgetCpuLimitFreqMax = sqlit.getCpuLimitFreqMax + MockgetCpuLimitFreqMax.mockResolvedValue([{maxValue: 100,filterId:9}]) + + it('spFpsChart01', function () { + expect(spFpsChart.init()).toBeDefined(); + }); +}) diff --git a/host/ide/test/trace/component/chart/SpHiPerf.test.ts b/host/ide/test/trace/component/chart/SpHiPerf.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..5456958b1763f8d5868503ce1276ea1d2700ed0a --- /dev/null +++ b/host/ide/test/trace/component/chart/SpHiPerf.test.ts @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpHiPerf} from "../../../../dist/trace/component/chart/SpHiPerf.js"; +import { + queryHiPerfCpuMergeData2, + queryHiPerfEventList, + queryPerfThread +} from "../../../../src/trace/database/SqlLite.js"; +// @ts-ignore +import {SpChartManager} from "../../../../dist/trace/component/chart/SpChartManager.js"; +const sqlit = require("../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe('SpHiPerf Test', ()=> { + let queryPerfCmdline = sqlit.queryPerfCmdline; + queryPerfCmdline.mockResolvedValue([ + { + report_value: 'hiperf record --control prepare -o /data/local/tmp…e sched:sched_waking -a -s dwarf -f 1000 --offcpu' + } + ]) + + let queryPerfThread = sqlit.queryPerfThread; + queryPerfThread.mockResolvedValue([ + { + tid: 2, + threadName: "threadName", + pid: 2, + processName: "processName" + }, + { + tid: 1, + threadName: "threadName111", + pid: 1, + processName: "processNam111e" + } + ]) + + let queryHiPerfEventList = sqlit.queryHiPerfEventList; + queryHiPerfEventList.mockResolvedValue([ + { + id: 0, + report_value: "sched:sched_waking" + }, + { + id: 1, + report_value: "sched:sched_switch" + } + ]) + + let queryHiPerfCpuMergeData2 = sqlit.queryHiPerfCpuMergeData2; + queryHiPerfCpuMergeData2.mockResolvedValue([ + { + id: 0, + callchain_id: 1, + timestamp: 3468360924674, + thread_id: 2469, + event_count: 1, + event_type_id: 0, + timestamp_trace: 3468360965799, + cpu_id: 2, + thread_state: "Running", + startNS: 0 + }, + { + id: 4, + callchain_id: 1, + timestamp: 3468361000799, + thread_id: 2469, + event_count: 1, + event_type_id: 0, + timestamp_trace: 3468361041924, + cpu_id: 2, + thread_state: "Running", + startNS: 76125 + }, + { + id: 8, + callchain_id: 1, + timestamp: 3468361045716, + thread_id: 2469, + event_count: 1, + event_type_id: 0, + timestamp_trace: 3468361086841, + cpu_id: 2, + thread_state: "Running", + startNS: 121042 + }, + { + id: 9, + callchain_id: 4, + timestamp: 3468361054466, + thread_id: 1336, + event_count: 1, + event_type_id: 1, + timestamp_trace: 3468361095591, + cpu_id: 3, + thread_state: "Suspend", + startNS: 129792 + } + ]) + let ss = new SpChartManager(); + let spHiPerf = new SpHiPerf(ss); + it('SpHiPerf01', function () { + spHiPerf.init() + expect(spHiPerf).toBeDefined(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/chart/SpHiSysEventChart.test.ts b/host/ide/test/trace/component/chart/SpHiSysEventChart.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..d570330849caa5ef69cdebee8226fa4e4e1dc432 --- /dev/null +++ b/host/ide/test/trace/component/chart/SpHiSysEventChart.test.ts @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpHiSysEventChart} from "../../../../dist/trace/component/chart/SpHiSysEventChart.js" +import "../../../../dist/trace/component/chart/SpHiSysEventChart.js"; +// @ts-ignore +import {SpChartManager} from "../../../../dist/trace/component/chart/SpChartManager.js"; +import "../../../../dist/trace/component/chart/SpChartManager.js"; +// @ts-ignore +import {SpSystemTrace} from "../../../../dist/trace/component/SpSystemTrace.js"; +import "../../../../dist/trace/component/SpSystemTrace.js"; +// @ts-ignore +import {LitPopover} from "../../../../dist/base-ui/popover/LitPopoverV.js"; +import { + querySystemLocationData, + querySystemLockData, + querySystemSchedulerData +} from "../../../../src/trace/database/SqlLite.js"; + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +const sqlite = require("../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../dist/trace/database/SqlLite.js"); + +describe('SpHiSysEventChart Test', () => { + let ss = new SpChartManager(); + let spHiSysEventChart = new SpHiSysEventChart(ss); + + let htmlDivElement = document.createElement("div"); + htmlDivElement.setAttribute("id", "appNameList") + + let anomalyData = sqlite.queryAnomalyData; + anomalyData.mockResolvedValue([]) + + let maxStateValue = sqlite.queryMaxStateValue; + let max = [{ + maxValue: 200, + type: "state" + }, { + maxValue: 300, + type: "sensor" + }] + maxStateValue.mockResolvedValue(max) + let MockExits = sqlite.queryHisystemEventExits + MockExits.mockResolvedValue(["trace_hisys_event"]) + let powerData = sqlite.queryPowerData; + let power = [ + { + startNS: 5999127353, + eventName: "POWER_IDE_AUDIO", + appKey: "APPNAME", + eventValue: "com.example.himusicdemo,com.example.himusicdemo_js,com.example.himusicdemo_app", + }, { + startNS: 5999127353, + eventName: "POWER_IDE_AUDIO", + appKey: "BACKGROUND_ENERGY", + eventValue: "854,258,141", + } + ] + powerData.mockResolvedValue(power) + + let stateData = sqlite.queryStateData; + stateData.mockResolvedValue([]) + + let sysEventAppName = sqlite.querySyseventAppName; + let appName = [{ + string_value: "app_name" + }] + sysEventAppName.mockResolvedValue(appName) + + let querySystemLocationData = sqlite.querySystemLocationData; + let querySystemLockData = sqlite.querySystemLockData; + let querySystemSchedulerData = sqlite.querySystemSchedulerData; + let location = [ + { + ts: 1005938319, + eventName: "GNSS_STATE", + appKey: "TYPE", + Value: "1", + }, { + ts: 3005933657, + eventName: "GNSS_STATE", + appKey: "TAG", + Value: "2", + } + ] + + let lock = [ + { + ts: 1005938319, + eventName: "POWER_RUNNINGLOCK", + appKey: "TYPE", + Value: "1", + }, { + ts: 3005933657, + eventName: "POWER_RUNNINGLOCK", + appKey: "TAG", + Value: "2", + } + ] + + let work = [ + { + ts: 1005938319, + eventName: "WORK_ADD", + appKey: "TYPE", + Value: "1", + }, { + ts: 3005933657, + eventName: "WORK_STOP", + appKey: "TAG", + Value: "2", + } + ] + querySystemLocationData.mockResolvedValue(location); + querySystemLockData.mockResolvedValue(lock); + querySystemSchedulerData.mockResolvedValue(work); + + it('spHiSysEventChartTest01', function () { + spHiSysEventChart.init(); + expect(SpHiSysEventChart.app_name).toBeUndefined(); + }); + + it('spHiSysEventChartTest02', function () { + let result = [ + { + ts: 1005938319, + eventName: "WORK_START", + appKey: "TYPE", + Value: "1", + }, { + ts: 3005933657, + eventName: "POWER_RUNNINGLOCK", + appKey: "TAG,", + Value: "DUBAI_TAG_RUNNINGLOCK_REMOVE", + }, { + ts: 4005938319, + eventName: "GNSS_STATE", + appKey: "STATE", + Value: "stop", + }, { + ts: 5005933657, + eventName: "POWER_RUNNINGLOCK", + appKey: "TAG", + Value: "DUBAI_TAG_RUNNINGLOCK_ADD", + }, { + ts: 6005938319, + eventName: "GNSS_STATE", + appKey: "STATE", + Value: "start", + }, { + ts: 9005938319, + eventName: "WORK_STOP", + appKey: "TYPE", + Value: "1", + }, { + ts: 10005938319, + eventName: "WORK_REMOVE", + appKey: "TYPE", + Value: "1", + } + ] + expect(spHiSysEventChart.getSystemData([result, result, result])).toEqual({"0": [{"count": 1, "startNs": 5005933657, "token": undefined, "type": 1}, + {"count": 0, "startNs": 6005938319, "token": undefined, "type": 1}], + "1": [{"count": 1, "startNs": 1005938319, "state": "start", "type": 2}, + {"count": 2, "startNs": 3005933657, "state": "start", "type": 2}, + {"count": 1, "startNs": 4005938319, "state": "stop", "type": 2}, + {"count": 2, "startNs": 5005933657, "state": "start", "type": 2}, + {"count": 3, "startNs": 6005938319, "state": "start", "type": 2}, + {"count": 4, "startNs": 9005938319, "state": "start", "type": 2}, + {"count": 5, "startNs": 10005938319, "state": "start", "type": 2}], + "2": [{"count": 1, "startNs": 1005938319, "type": 0}, {"count": 0, "startNs": undefined, "type": 0}]}); + }); + + it('spHiSysEventChartTest03', function () { + expect(spHiSysEventChart.getSystemData([]).length).toBeUndefined(); + }); + + it('spHiSysEventChartTest04', function () { + let result = [ + { + startNS: 5999127353, + eventName: "POWER_IDE_AUDIO", + appKey: "APPNAME", + eventValue: "com.example.himusicdemo,com.example.himusicdemo_js,com.example.himusicdemo_app", + }, { + startNS: 5999127353, + eventName: "POWER_IDE_AUDIO", + appKey: "BACKGROUND_ENERGY", + eventValue: "854,258,141", + }, { + startNS: 5999127353, + eventName: "POWER_IDE_BLUETOOTH", + appKey: "APPNAME", + eventValue: "com.ohos.settings,bt_switch,bt_switch_js,bt_switch_app", + }, { + startNS: 5999127353, + eventName: "POWER_IDE_BLUETOOTH", + appKey: "BACKGROUND_ENERGY", + eventValue: "76,12,43,431", + }, { + startNS: 5999127388, + eventName: "POWER_IDE_CAMERA", + appKey: "APPNAME", + eventValue: "com.ohos.camera,com.ohos.camera_app,com.ohos.camera_js,com.ohos.camera_ts", + }, { + startNS: 5999127388, + eventName: "POWER_IDE_CAMERA", + appKey: "BACKGROUND_ENERGY", + eventValue: "375,475,255,963", + } + ] + expect(spHiSysEventChart.getPowerData(result)).toStrictEqual(Promise.resolve()); + }); + + it('spHiSysEventChartTest05', function () { + expect(spHiSysEventChart.getPowerData([])).toStrictEqual(Promise.resolve()); + }); + + it('spHiSysEventChartTest6', function () { + expect(spHiSysEventChart.initHtml).toMatchInlineSnapshot(`undefined`); + }); + + it('spHiSysEventChartTest7', function () { + // expect(htmlDivElement.onMouseClick({button:2})).toBeUndefined(); + expect(htmlDivElement.onclick).toBe(null); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneBoxChild.test.ts b/host/ide/test/trace/component/chart/SpMpsChart.test.ts similarity index 40% rename from host/ide/test/trace/component/trace/sheet/TabPaneBoxChild.test.ts rename to host/ide/test/trace/component/chart/SpMpsChart.test.ts index 8304782e909c6005ba933a5ec7000dfada5e64d3..f9c9d92caadb68f89dfdbfb077c0c59363eab42c 100644 --- a/host/ide/test/trace/component/trace/sheet/TabPaneBoxChild.test.ts +++ b/host/ide/test/trace/component/chart/SpMpsChart.test.ts @@ -14,52 +14,37 @@ */ // @ts-ignore -// import { it } from "mocha" -import {TabPaneBoxChild} from "../../../../../dist/trace/component/trace/sheet/TabPaneBoxChild.js" +import {SmpsChart} from "../../../../dist/trace/component/chart/SmpsChart.js" +// @ts-ignore +import {SpChartManager} from "../../../../dist/trace/component/chart/SpChartManager.js"; +import {querySmapsDataMax} from "../../../../src/trace/database/SqlLite.js"; + +const sqlit = require("../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../dist/trace/database/SqlLite.js"); + window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ disconnect: jest.fn(), observe: jest.fn(), unobserve: jest.fn(), - })); -describe('TabPaneBoxChild Test', () => { - let tabPaneBoxChild = new TabPaneBoxChild(); - tabPaneBoxChild.parentElement= jest.fn(()=> { - return {clientHeight:56} - }) - tabPaneBoxChild.parentElement.clientHeight= jest.fn(()=>100) - tabPaneBoxChild.data = { - cpus: [], - threadIds: [], - trackIds: [], - funTids: [], - heapIds:[], - leftNs: 0, - rightNs: 0, - hasFps: false, - // parentElement:{ - // clientHeight:0, - // } - } - // tabPaneBoxChild.parentElement = { - // clientHeight:0, - // } - - it('TabPaneBoxChildTest01', function () { +describe('SpMpsChart Test', () => { + let MockquerySmapsExits = sqlit.querySmapsExits; + MockquerySmapsExits.mockResolvedValue([{ + event_name: "trace_smaps", + stat_type: "received", + count: 1 + }]) - expect(tabPaneBoxChild.sortByColumn({ - key: 'name', - sort: () => { - } - })).toBeUndefined(); + let MockquerySmapsDataMax = sqlit.querySmapsDataMax + MockquerySmapsDataMax.mockResolvedValue([{ + max_value: 11111, + }]) + let trace = new SpChartManager(); + let spMapsChart = new SmpsChart(trace); + it('SpMpsChart01', function () { + spMapsChart.init() + expect(SmpsChart).toBeInstanceOf(Function); }); - // it('TabPaneBoxChildTest02',function(){ - // TabPaneBoxChild.parentElement= jest.fn(()=> { - // return {clientHeight:56} - // }) - // // TabPaneBoxChild.parentElement.clientHeight= jest.fn(()=>100) - // expect(tabPaneBoxChild.data).toBeUndefined(); - // }) - -}) + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/TabPanePTS.test.ts b/host/ide/test/trace/component/chart/SpNativeMemoryChart.test.ts similarity index 39% rename from host/ide/test/trace/component/trace/sheet/TabPanePTS.test.ts rename to host/ide/test/trace/component/chart/SpNativeMemoryChart.test.ts index 76a843cc06432f87b75151cf38e95e87fa000bbd..8f03a9207c9e778abf79ec7c5f9523295fad0f40 100644 --- a/host/ide/test/trace/component/trace/sheet/TabPanePTS.test.ts +++ b/host/ide/test/trace/component/chart/SpNativeMemoryChart.test.ts @@ -14,46 +14,35 @@ */ // @ts-ignore -import {TabPanePTS} from "../../../../../dist/trace/component/trace/sheet/TabPanePTS.js" -window.ResizeObserver = window.ResizeObserver ||jest.fn().mockImplementation(() => ({ +import {SpSystemTrace} from "../../../../dist/trace/component/SpSystemTrace.js"; +// @ts-ignore +import {SpNativeMemoryChart} from "../../../../dist/trace/component/chart/SpNativeMemoryChart.js"; + +const sqlit = require("../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ disconnect: jest.fn(), observe: jest.fn(), unobserve: jest.fn(), })); -describe('TabPanePTS Test', () => { - let tabPanePTS = new TabPanePTS(); - +describe('SpNativeMemoryChart Test', () => { + let spNativeMemoryChart = new SpNativeMemoryChart(new SpSystemTrace()) - let dataArray = [{ - id: "", - pid: "", - title: "", - children: [], - process: "", - processId: 0, - thread: "", - threadId: 0, - state: "", - wallDuration: 0, - avgDuration: "", - count: 0, - minDuration: 0, - maxDuration: 0, - stdDuration: "", - }] + let nativeHookProcess = sqlit.queryNativeHookProcess; + nativeHookProcess.mockResolvedValue([{ + ipid: 0, + pid: 0, + name: "name" + }]) - it('TabPanePTSTest01', function () { - let result = tabPanePTS.groupByProcessThreadToMap(dataArray); - expect(result.get(0).length).toBeUndefined(); - }); - - it('TabPanePTSTest02', function () { - let result = tabPanePTS.groupByProcessToMap(dataArray) - expect(result.get(0).length).toBe(1); - }); + let heapGroupByEvent = sqlit.queryHeapGroupByEvent; + heapGroupByEvent.mockResolvedValue([{ + eventType: "AllocEvent", + sumHeapSize: 10 + }]) - it('TabPanePTSTest03', function () { - let result = tabPanePTS.groupByThreadToMap(dataArray) - expect(result.get(0).length).toBe(1); + it('SpNativeMemoryChart01', function () { + expect(spNativeMemoryChart.initChart()).toBeDefined(); }); }) diff --git a/host/ide/test/trace/component/chart/SpProcessChart.test.ts b/host/ide/test/trace/component/chart/SpProcessChart.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..b39b8365d96100656cfb8820b918d9112858a1b2 --- /dev/null +++ b/host/ide/test/trace/component/chart/SpProcessChart.test.ts @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpProcessChart} from "../../../../dist/trace/component/chart/SpProcessChart.js"; +// @ts-ignore +import {SpSystemTrace} from "../../../../dist/trace/component/SpSystemTrace.js"; +import { + queryProcess, + queryProcessAsyncFunc, + queryProcessContentCount, queryProcessMem, + queryProcessThreads, queryProcessThreadsByTable +} from "../../../../src/trace/database/SqlLite.js"; +const sqlit = require("../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe('SpProcessChart Test', ()=> { + let MockqueryProcessAsyncFunc = sqlit.queryProcessAsyncFunc; + MockqueryProcessAsyncFunc.mockResolvedValue([ + { + tid: 1, + pid: 2, + threadName: "1", + track_id: 3, + startTs: 1111, + dur: 2000000, + funName: "func", + parent_id: 4, + id: 5, + cookie: "ff", + depth: 5, + argsetid: 6 + } + ]) + let processContentCount = sqlit.queryProcessContentCount; + processContentCount.mockResolvedValue([ + { + pid: 1, + switch_count: 2, + thread_count: 3, + slice_count: 4, + mem_count: 5 + } + ]) + let queryProcessThreads = sqlit.queryProcessThreads; + queryProcessThreads.mockResolvedValue([ + { + utid: 1, + hasSched: 0, + pid: 3, + tid: 4, + processName: "process", + threadName: "thread" + } + ]) + let queryProcessThreadsByTable = sqlit.queryProcessThreadsByTable; + queryProcessThreadsByTable.mockResolvedValue([ + { + pid: 1, + tid: 0, + processName: "process", + threadName: "thread" + } + ]) + let getAsyncEvents = sqlit.getAsyncEvents; + getAsyncEvents.mockResolvedValue([ + { + pid: 1, + startTime: 100000 + } + ]) + let queryProcessMem = sqlit.queryProcessMem; + queryProcessMem.mockResolvedValue([ + { + trackId: 1, + trackName: "trackName", + upid: 2, + pid: 3, + processName: "processName" + } + ]) + let queryEventCountMap = sqlit.queryEventCountMap; + queryEventCountMap.mockResolvedValue([ + { + eventName: "eventName", + count: 1 + } + ]) + let queryProcess = sqlit.queryProcess; + queryProcess.mockResolvedValue([ + { + pid: 1, + processName: "processName" + } + ]) + + let queryProcessByTable = sqlit.queryProcessByTable; + queryProcessByTable.mockResolvedValue([ + { + pid: 2, + processName: "processName" + } + ]) + + let spSystemTrace = new SpSystemTrace(); + let spProcessChart = new SpProcessChart(spSystemTrace); + it('SpProcessChart01', function () { + spProcessChart.init() + expect(spProcessChart).toBeDefined(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/chart/SpSdkChart.test.ts b/host/ide/test/trace/component/chart/SpSdkChart.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..439f1a1cb0bf319c7a68f4dd8b00e61a857828d2 --- /dev/null +++ b/host/ide/test/trace/component/chart/SpSdkChart.test.ts @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpSdkChart} from "../../../../dist/trace/component/chart/SpSdkChart.js" +const sqlit = require("../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), +})); + +describe('SpSdkChart Test', ()=> { + let spSdkChart = new SpSdkChart(); + let MockStartTime = sqlit.queryStartTime; + MockStartTime.mockResolvedValue([{ + start_ts:0 + }]) + it('SpSdkChartTest01', function () { + let showType = { + columns:[{showType: 'counter'}] + } + expect(spSdkChart.getTableType(showType)).toBe(""); + }); + + it('SpSdkChartTest02', function () { + expect(spSdkChart.createSliceSql(10,8,[{length:5}],"")).toBe("select undefined from 8 "); + }); + + it('SpSdkChartTest03', function () { + expect(spSdkChart.createMaxValueSql("","")).toBe("select max(value) as max_value from "); + }); + + it('SpSdkChartTest04', function () { + expect(spSdkChart.createMaxValueSql("a","c")).toBe("select max(value) as max_value from a c"); + }); + + it('SpSdkChartTest06', function () { + expect(spSdkChart.createSql(3,"c",[{length:3}],"a")).toBe("select undefined from c a"); + }); + + it('SpSdkChartTest07', function () { + expect(spSdkChart.createSql(0,"c",[{length:3}],"")).toBe("select undefined from c "); + }); + + it('SpSdkChartTest08', function () { + spSdkChart.init() + expect(spSdkChart).toBeDefined(); + }); + + it('SpSdkChartTest09', function () { + let showType = { + columns:[{showType: 'slice'}] + } + expect(spSdkChart.getTableType(showType)).toBe(""); + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/chart/SpVirtualMemChart.test.ts b/host/ide/test/trace/component/chart/SpVirtualMemChart.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..d5b1656aa444580fb4c00e59313132635bc8b5f0 --- /dev/null +++ b/host/ide/test/trace/component/chart/SpVirtualMemChart.test.ts @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpVirtualMemChart} from "../../../../dist/trace/component/chart/SpVirtualMemChart.js" +// @ts-ignore +import {SpSystemTrace} from "../../../../dist/trace/component/SpSystemTrace.js"; +// @ts-ignore +import {TraceRow} from "../../../../dist/trace/component/trace/base/TraceRow.js"; + +const sqlit = require("../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), +})); + +describe('SpVirtualMemChart Test', () => { + let spVirtualMemChart = new SpVirtualMemChart(new SpSystemTrace()) + let MockVirtualMemory = sqlit.queryVirtualMemory; + MockVirtualMemory.mockResolvedValue([{ + id:0, + name:"name" + }]) + + let MockVirtualMemoryData = sqlit.queryVirtualMemoryData; + MockVirtualMemoryData.mockResolvedValue([{ + startTime:0, + value:20, + filterID:0 + }]) + + it('SpVirtualMemChart01', function () { + spVirtualMemChart.init() + expect(spVirtualMemChart).toBeDefined(); + }); + + it('SpVirtualMemChart02', function () { + let folder = new TraceRow({ + canvasNumber: 1, + alpha: false, + contextId: '2d', + isOffScreen: SpSystemTrace.isCanvasOffScreen + }); + spVirtualMemChart.initVirtualMemoryRow(folder,2,"name",2) + expect(spVirtualMemChart).toBeDefined(); + }); +}) diff --git a/host/ide/test/trace/component/metrics/CpuStrategy.test.ts b/host/ide/test/trace/component/metrics/CpuStrategy.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..b8d6a5e52f2f6d553da211ba2b581ebe24b28b57 --- /dev/null +++ b/host/ide/test/trace/component/metrics/CpuStrategy.test.ts @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {initTest,initCpuStrategyData} from "../../../../dist/trace/component/metrics/CpuStrategy.js"; + +describe('CpuStrategy Test', () => { + const metricData=[{ + length:1, + event_name:"name", + stat_type:1, + count:1, + source:1, + serverity:0, + avg_frequency:null, + cpu:1, + min_freq:"", + max_freq:"", + duration:1, + process_name:"", + thread_name:"" + }] + + it('initTestTest01', () => { + expect(initTest(metricData)).toBeTruthy(); + }); + + it('initCpuStrategyDataTest02', () => { + expect(initCpuStrategyData(metricData)).toBeTruthy(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/metrics/DistributeTermStrategy.test.ts b/host/ide/test/trace/component/metrics/DistributeTermStrategy.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..f765314d7618ae922736291c3ce7e256dd92e231 --- /dev/null +++ b/host/ide/test/trace/component/metrics/DistributeTermStrategy.test.ts @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {initDistributedTermData} from "../../../../dist/trace/component/metrics/DistributeTermStrategy.js"; + +describe('DistributeTermStrategy Test', () => { + let metricData=[{ + length:1, + funName:"name", + ts:"ts", + dur:"", + flag: 'fd,fdsf.fds', + trace_name:"name1", + chainId:"1", + spanId:"span", + parentSpanId:"", + processId:"", + threadId:"", + threadName:"", + processName:"" + }] + it('initDistributedTermDataTest01', () => { + expect(initDistributedTermData(metricData)).toBeTruthy(); + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/metrics/MemAggStrategy.test.ts b/host/ide/test/trace/component/metrics/MemAggStrategy.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..552f5205645d65317e6e46a7a7471c4373b3eb7d --- /dev/null +++ b/host/ide/test/trace/component/metrics/MemAggStrategy.test.ts @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {initMemoryAggStrategy} from "../../../../dist/trace/component/metrics/MemAggStrategy.js"; + +describe('MemAggStrategy Test', () => { + + it('initMemoryAggStrategyTest01', () => { + const metricData=[{ + length:1, + processName:"name", + name:"oom_score_adj", + value:"", + ts:"" + }] + expect(initMemoryAggStrategy(metricData)).toBeTruthy(); + }); + + it('initMemoryAggStrategyTest02', () => { + const metricData=[{ + length:1, + processName:"name", + name:"mem.rss.anon", + value:"", + ts:"" + }] + expect(initMemoryAggStrategy(metricData)).toBeTruthy(); + }); + + it('initMemoryAggStrategyTest03', () => { + const metricData=[{ + length:1, + processName:"name", + name:"mem.swap", + value:"", + ts:"" + }] + expect(initMemoryAggStrategy(metricData)).toBeTruthy(); + }); + + it('initMemoryAggStrategyTest04', () => { + const metricData=[{ + length:1, + processName:"name", + name:"mem.rss.file", + value:"", + ts:"" + }] + expect(initMemoryAggStrategy(metricData)).toBeTruthy(); + }); + + it('initMemoryAggStrategyTest05', () => { + const metricData=[{ + length:1, + processName:"name", + name:"oom_score_adj", + value:"", + ts:"" + }] + expect(initMemoryAggStrategy(metricData)).toBeTruthy(); + }) +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/metrics/MemStrategy.test.ts b/host/ide/test/trace/component/metrics/MemStrategy.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..e701f50100f44acbff601ec448ba8d6fe0e768dc --- /dev/null +++ b/host/ide/test/trace/component/metrics/MemStrategy.test.ts @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {initMemoryStrategy} from "../../../../dist/trace/component/metrics/MemStrategy.js"; + +describe('MemStrategy Test', () => { + const metricData=[{ + length:1, + minNum:"name", + maxNum:"", + avgNum:"", + processName:"" + }] + + it('initMemoryStrategyTest01', () => { + expect(initMemoryStrategy(metricData)).toBeTruthy(); + + }) + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/metrics/MetaDataStrategy.test.ts b/host/ide/test/trace/component/metrics/MetaDataStrategy.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..7e813384d28f317d09878e025a48705213b3a4a1 --- /dev/null +++ b/host/ide/test/trace/component/metrics/MetaDataStrategy.test.ts @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {initMetaDataStrategy} from "../../../../dist/trace/component/metrics/MetaDataStrategy.js"; + +describe('MetaDataStrategy Test', () => { + const metricData=[{ + length:1, + name:"name", + valueText:"", + }] + + it('initMetaDataStrategyTest01', () => { + expect(initMetaDataStrategy(metricData)).toBeTruthy(); + + }) + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/metrics/SysCallsStrategy.test.ts b/host/ide/test/trace/component/metrics/SysCallsStrategy.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..eb8dd09c955dbf409199c587f852100655915988 --- /dev/null +++ b/host/ide/test/trace/component/metrics/SysCallsStrategy.test.ts @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {initSysCallsStrategy} from "../../../../dist/trace/component/metrics/SysCallsStrategy.js"; + +describe('SysCallsStrategy Test', () => { + const metricData=[{ + length:1, + funName:"name", + maxDur:"", + minDur:"", + avgDur:"" + }] + + it('initMetaDataStrategyTest01', () => { + expect(initSysCallsStrategy(metricData)).toBeTruthy(); + + }) + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/metrics/SysCallsTopStrategy.test.ts b/host/ide/test/trace/component/metrics/SysCallsTopStrategy.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..2e812163eba40ae91a03964b0845e3ed01d97332 --- /dev/null +++ b/host/ide/test/trace/component/metrics/SysCallsTopStrategy.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {initSysCallsTopStrategy} from "../../../../dist/trace/component/metrics/SysCallsTopStrategy.js"; + +describe('SysCallsTopStrategy Test', () => { + const metricData=[{ + length:1, + pid:"pi", + tid:"ti", + process_name:"", + maxDur:"name", + minDur:"", + avgDur:"", + funName:"" + }] + + it('initSysCallsTopStrategyTest01', () => { + expect(initSysCallsTopStrategy(metricData)).toBeTruthy(); + + }) + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/metrics/TraceStatsStrategy.test.ts b/host/ide/test/trace/component/metrics/TraceStatsStrategy.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..38c66a50d54c18e39dbaf123114cd8601ee4c656 --- /dev/null +++ b/host/ide/test/trace/component/metrics/TraceStatsStrategy.test.ts @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {initTraceStateStrategy} from "../../../../dist/trace/component/metrics/TraceStatsStrategy.js"; + +describe('TraceTaskStrategy Test', () => { + let metricData=[{ + length:1, + event_name:"name", + count:1, + source:1, + serverity:0, + }] + it('initTraceStateStrategyTest01', () => { + expect(initTraceStateStrategy(metricData)).toBeTruthy(); + }) + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/metrics/TraceTaskStrategy.test.ts b/host/ide/test/trace/component/metrics/TraceTaskStrategy.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..be12008f2e5b668633ba0db12c37dfb3d59a2b15 --- /dev/null +++ b/host/ide/test/trace/component/metrics/TraceTaskStrategy.test.ts @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {initTraceTaskStrategy} from "../../../../dist/trace/component/metrics/TraceTaskStrategy.js"; + + +describe('TraceTaskStrategy Test', () => { + let metricData=[{ + length:1, + process_name:"", + thread_name:"", + pid:3 + + }] + it('initTraceTaskStrategyTest01', () => { + expect(initTraceTaskStrategy(metricData)).toBeTruthy(); + }) + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/setting/SpAllocations.test.ts b/host/ide/test/trace/component/setting/SpAllocations.test.ts index b4de0f617d6ef4167b895eae2bef99f4de28a2ed..9a97a85d9c766279abe4d2f3932e3ea09e12c2bd 100644 --- a/host/ide/test/trace/component/setting/SpAllocations.test.ts +++ b/host/ide/test/trace/component/setting/SpAllocations.test.ts @@ -22,16 +22,23 @@ describe('SpAllocations Test', ()=>{ ` }) - it('new SpAllocations', function () { - expect(new SpAllocations()).not.toBeUndefined(); - }); it(' SpAllocations get Default attrValue', function () { let spEle = document.querySelector("#sp") as SpAllocations + spEle.unwindEL = jest.fn(()=>true) + spEle.unwindEL.value = jest.fn(()=>true) + spEle.shareMemory = jest.fn(()=>true) + spEle.shareMemory.value = jest.fn(()=>true) + spEle.shareMemoryUnit = jest.fn(()=>true) + spEle.shareMemoryUnit.value = jest.fn(()=>true) + spEle.filterMemory = jest.fn(()=>true) + spEle.filterMemory.value = jest.fn(()=>true) + spEle.filterMemoryUnit = jest.fn(()=>true) + spEle.filterMemoryUnit.value = jest.fn(()=>true) expect(spEle.pid).toEqual(undefined) - expect(spEle.unwind).toEqual(10) - expect(spEle.shared).toEqual(2048) - expect(spEle.filter).toEqual(0) + expect(spEle.unwind).toBeNaN() + expect(spEle.shared).toBe(16384) + expect(spEle.filter).toBeNaN() }); it(' SpAllocations set attrValue', function () { @@ -44,38 +51,205 @@ describe('SpAllocations Test', ()=>{ spEle.filterMemoryUnit.value = "MB" expect(spEle.pid).toEqual(undefined) expect(spEle.unwind).toEqual(111) - expect(spEle.shared).toEqual(0) - expect(spEle.filter).toEqual(28416) + expect(spEle.shared).toEqual(222) + expect(spEle.filter).toEqual(111) + }); - it(' SpAllocations set attrValue', function () { + it(' SpAllocations set attrValue2', function () { let spEle = document.querySelector("#sp") as SpAllocations spEle.processId.value ="3" spEle.unwindEL.value = "1121" - spEle.shareMemory.value = "222" + spEle.shareMemory!.value = "222" spEle.shareMemoryUnit.value = "KB" spEle.filterMemory.value = "111" spEle.filterMemoryUnit.value = "KB" expect(spEle.pid).toEqual(undefined) expect(spEle.unwind).toEqual(1121) - expect(spEle.shared).toEqual(55) + expect(spEle.shared).toEqual(222) expect(spEle.filter).toEqual(111) }); it(' SpAllocations set attrValue03', function () { - let spEle = document.querySelector("#sp") as SpAllocations + let spEle = new SpAllocations(); spEle.processId.value ="3" spEle.unwindEL.value = "1121" spEle.shareMemory.value = "222" - spEle.shareMemoryUnit.value = "G" spEle.filterMemory.value = "111" - spEle.filterMemoryUnit.value = "G" expect(spEle.pid).toEqual(undefined) expect(spEle.unwind).toEqual(1121) - expect(spEle.shared).toEqual(0) + expect(spEle.shared).toEqual(222) expect(spEle.filter).toEqual(111) }); - // it('CpuStructTest02', function () { - // expect(FpsStruct.equals({}, data)).toBeTruthy(); - // }); + + it('SpAllocations test04', function () { + let spEle = document.querySelector("#sp") as SpAllocations; + expect(spEle.initHtml()).toMatchInlineSnapshot(` +" + +
+
+ Native Memory +
+
+ ProcessId or ProcessName : + + +
+
+ Max unwind level : + 30) this.value = '30'\\" onkeyup=\\"this.value=this.value.replace(/\\\\D/g,'')\\" value=\\"10\\"> +
+
+ Shared Memory Size (One page equals 4 KB) : +
+ 2147483647) this.value = ''\\" onkeyup=\\"this.value=this.value.replace(/\\\\D/g,'')\\" value=\\"16384\\"> + Page +
+
+
+ Filter Memory Size : +
+ 65535) this.value = ''\\" onkeyup=\\"this.value=this.value.replace(/\\\\\\\\D/g,'')\\" value=\\"4096\\"> + Byte +
+
+
+ Use Fp Unwind : + +
+
+ " +`); + }); + + it('SpAllocations test05', function () { + let spAllocations = document.querySelector("#sp") as SpAllocations; + expect(spAllocations.appProcess).toBe("3") + }); + + it('SpAllocations test06', function () { + let spAllocations = document.querySelector("#sp") as SpAllocations; + expect(spAllocations.convertToValue("0","MB")).toBe(0); + }); + + it('SpAllocations test07', function () { + let spAllocations = document.querySelector("#sp") as SpAllocations; + expect(spAllocations.convertToValue("1","KB")).toBe(16384); + }); + + it('SpAllocations test08', function () { + let spAllocations = document.querySelector("#sp") as SpAllocations; + expect(spAllocations.convertToValue("1","")).toBe(0); + }); + it('SpAllocations test09', function () { + let spAllocations = document.querySelector("#sp") as SpAllocations; + expect(spAllocations.fp_unwind).toBeTruthy() + }); }) \ No newline at end of file diff --git a/host/ide/test/trace/component/setting/SpCheckDesBox.test.ts b/host/ide/test/trace/component/setting/SpCheckDesBox.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..f475a534c7a0d6d9f98fcaf274b54909e6c35b98 --- /dev/null +++ b/host/ide/test/trace/component/setting/SpCheckDesBox.test.ts @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//@ts-ignore +import {SpCheckDesBox} from "../../../../dist/trace/component/setting/SpCheckDesBox.js"; + +describe('SpCheckDesBox Test', () => { + let spCheckDesBox = new SpCheckDesBox(); + + it('SpCheckDesBoxTest01', function () { + expect(spCheckDesBox.value).toBe(''); + }); + + it('SpCheckDesBoxTest02', function () { + expect(spCheckDesBox.attributeChangedCallback('checked',"","")).toBeUndefined(); + }); + + it('SpCheckDesBoxTest03', function () { + expect(spCheckDesBox.attributeChangedCallback('value',"","")).toBeUndefined(); + }); + + it('SpCheckDesBoxTest04', function () { + expect(spCheckDesBox.attributeChangedCallback('des',"","")).toBeUndefined(); + }); + + it('SpCheckDesBoxTest05', function () { + spCheckDesBox.checked = false; + expect(spCheckDesBox.checked).toBeFalsy(); + }); + + it('SpCheckDesBoxTest07', function () { + spCheckDesBox.checked = true; + expect(spCheckDesBox.checked).toBeTruthy(); + }); + + it('SpCheckDesBoxTest06 ', function () { + expect(spCheckDesBox.connectedCallback()).toBeUndefined() + + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/setting/SpFileSystem.test.ts b/host/ide/test/trace/component/setting/SpFileSystem.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..a55d4fe882242cb5139525f7768130669a524139 --- /dev/null +++ b/host/ide/test/trace/component/setting/SpFileSystem.test.ts @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//@ts-ignore +import { SpFileSystem } from "../../../../dist/trace/component/setting/SpFileSystem"; + +describe('spFileSystem Test', () => { + let spFileSystem = new SpFileSystem(); + it('SpFileSystemTest01', function () { + spFileSystem.startSamp = true; + expect(spFileSystem.startSamp).toBeTruthy(); + }); + + it('SpFileSystemTest02', function () { + spFileSystem.startSamp = false; + expect(spFileSystem.startSamp).toBeFalsy(); + }); + + it('SpFileSystemTest03', function () { + expect(spFileSystem.getSystemConfig()).toStrictEqual({"process": ""}) + }); + + it('SpFileSystemTest04', function () { + expect(spFileSystem.unDisable()).toBeUndefined(); + }); + + it('SpFileSystemTest05', function () { + expect(spFileSystem.disable()).toBeUndefined(); + }); + + it('SpFileSystemTest06', function () { + expect(spFileSystem.initConfigList()).toBeUndefined(); + }); + + it('SpFileSystemTest07', function () { + spFileSystem.startRecord = true; + expect(spFileSystem.startRecord).toBeTruthy(); + }); + + it('SpFileSystemTest08', function () { + spFileSystem.startRecord = false; + expect(spFileSystem.startRecord).toBeFalsy(); + }); + + it('SpFileSystemTest09', function () { + spFileSystem.startFileSystem = true; + expect(spFileSystem.startFileSystem).toBeTruthy(); + }); + + it('SpFileSystemTest10', function () { + spFileSystem.startFileSystem = false; + expect(spFileSystem.startFileSystem).toBeFalsy(); + }); + + it('SpFileSystemTest11', function () { + spFileSystem.startVirtualMemory = true; + expect(spFileSystem.startVirtualMemory).toBeTruthy(); + }); + + it('SpFileSystemTest12', function () { + spFileSystem.startVirtualMemory = false; + expect(spFileSystem.startVirtualMemory).toBeFalsy(); + }); + + it('SpFileSystemTest13', function () { + spFileSystem.startIo = true; + expect(spFileSystem.startIo).toBeTruthy(); + }); + + it('SpFileSystemTest14', function () { + spFileSystem.startIo = false; + expect(spFileSystem.startIo).toBeFalsy(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/setting/SpProbesConfig.test.ts b/host/ide/test/trace/component/setting/SpProbesConfig.test.ts index c105faf75f0266e24e02009f3d4533841cec92c4..dc10cc7b94a251b337e026f45e93c299b03fbd26 100644 --- a/host/ide/test/trace/component/setting/SpProbesConfig.test.ts +++ b/host/ide/test/trace/component/setting/SpProbesConfig.test.ts @@ -15,6 +15,7 @@ // @ts-ignore import {SpProbesConfig} from "../../../../dist/trace/component/setting/SpProbesConfig.js"; +import {LitCheckBox} from "../../../../src/base-ui/checkbox/LitCheckBox"; describe('SpProbesConfig Test', ()=>{ beforeAll(() => { @@ -26,10 +27,110 @@ describe('SpProbesConfig Test', ()=>{ expect(new SpProbesConfig()).not.toBeNull(); }); - it(' SpProbesConfig get Default attrValue', function () { + it(' SpProbesConfig get Default attrValue', function () { let spEle = document.querySelector("#spconfig") as SpProbesConfig expect(spEle.traceConfig).toEqual([]) expect(spEle.traceEvents).toEqual([]) expect(spEle.memoryConfig).toEqual([]) }); + + it(' SpProbesConfig test', function () { + let spEle = document.querySelector("#spconfig") as SpProbesConfig + expect(spEle.initHtml()).toMatchInlineSnapshot(` +" + +
+
Record mode
+
+
+
+
+ + +
+ +
+
+
+
+
+ Memory Config +
+
+
+
+ " +`); + }); }) \ No newline at end of file diff --git a/host/ide/test/trace/component/setting/SpRecordPerf.test.ts b/host/ide/test/trace/component/setting/SpRecordPerf.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..accfb6ed706b48498d12d44e66584919579deaf4 --- /dev/null +++ b/host/ide/test/trace/component/setting/SpRecordPerf.test.ts @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpRecordPerf} from "../../../../dist/trace/component/setting/SpRecordPerf.js"; + +describe('SpRecordPerf Test', ()=>{ + + let spRecordPerf = new SpRecordPerf(); + it('SpRecordPerfTest01', function () { + expect(spRecordPerf).not.toBeUndefined(); + }); + + it('SpRecordPerfTest02', function () { + expect(spRecordPerf.show).toBeFalsy(); + }); + + it('SpRecordPerfTest03', function () { + spRecordPerf.show = true; + expect(spRecordPerf.show).toBeTruthy(); + }); + + it('SpRecordPerfTest08', function () { + spRecordPerf.show = false; + expect(spRecordPerf.show).toBeFalsy(); + }); + + it('SpRecordPerfTest09', function () { + expect(spRecordPerf.startSamp).toBeFalsy(); + }); + + it('SpRecordPerfTest10', function () { + spRecordPerf.startSamp = true; + expect(spRecordPerf.startSamp).toBeTruthy(); + }); + + it('SpRecordPerfTest11', function () { + spRecordPerf.startSamp = false; + expect(spRecordPerf.startSamp).toBeFalsy(); + }); + + it('SpRecordPerfTest05', function () { + expect(spRecordPerf.unDisable()).toBeUndefined(); + }); + + + it('SpRecordPerfTest04', function () { + expect(spRecordPerf.initHtml()).toMatchInlineSnapshot(` +" + +
+
+
+ +
+ " +`); + }); + + it('SpRecordPerfTest06', function () { + expect(spRecordPerf.startSamp).toBeFalsy(); + }); + + it('SpRecordPerfTest07', function () { + spRecordPerf.startSamp = true + expect(spRecordPerf.startSamp).toBeTruthy(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/setting/SpRecordSetting.test.ts b/host/ide/test/trace/component/setting/SpRecordSetting.test.ts index 0832660f298291cf038c54b4fb6e119c663fbd7d..125bb46940592ff93866d7444605edae73d02066 100644 --- a/host/ide/test/trace/component/setting/SpRecordSetting.test.ts +++ b/host/ide/test/trace/component/setting/SpRecordSetting.test.ts @@ -33,4 +33,202 @@ describe('SpRecordSetting Test', ()=>{ expect(spEle.maxDur).toEqual(50) }); + it(' SpRecordSetting test', function () { + let spEle = document.querySelector("#setting") as SpRecordSetting + expect(spEle.initHtml()).toMatchInlineSnapshot(` +" + +
+
+ Record mode + Stop when full +
+
+ output file path +
+ /data/local/tmp/ + = 100 ? this.value = this.value.substring(0,99): 0\\" oninput=\\"this.value= this.value.replace('__','_')\\" onkeyup=\\"this.value=this.value.replace(/[^\\\\w\\\\.]/g,'')\\"> +
+
+
+
+ In-memory buffer size + (max memory buffer size is 512 MB) +
+ + +
+ + MB +
+
+
+
+ Max duration + (max duration value is 01:00:00) +
+ + +
+ + h:m:s +
+ +
+
+ " +`); + }); + it(' SpRecordSettingTest04', function () { + let spEle = document.querySelector("#setting") as SpRecordSetting + expect(spEle.resetValue()).toBeUndefined(); + }); + }) \ No newline at end of file diff --git a/host/ide/test/trace/component/setting/SpSdkConfig.test.ts b/host/ide/test/trace/component/setting/SpSdkConfig.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..9319925f2bd3e839edf8bd4e7cf635c3a4cab707 --- /dev/null +++ b/host/ide/test/trace/component/setting/SpSdkConfig.test.ts @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//@ts-ignore +import { SpSdkConfig } from "../../../../dist/trace/component/setting/SpSdkConfig.js"; + +describe('spSdkConfig Test', () => { + let spSdkConfig = new SpSdkConfig(); + it('spSdkConfigTest01', function () { + spSdkConfig.show = true; + expect(spSdkConfig.show).toBeTruthy(); + }); + + it('spSdkConfigTest02', function () { + spSdkConfig.show = false; + expect(spSdkConfig.show).toBeFalsy(); + }); + + it('spSdkConfigTest03', function () { + spSdkConfig.startSamp = true; + expect(spSdkConfig.startSamp).toBeTruthy(); + }); + + it('spSdkConfigTest04', function () { + spSdkConfig.startSamp = false; + expect(spSdkConfig.startSamp).toBeFalsy(); + }); + + it('spSdkConfigTest05', function () { + spSdkConfig.configName = ''; + expect(spSdkConfig.configName).toBeDefined(); + }); + + it('spSdkConfigTest06', function () { + spSdkConfig.configName = 'configName'; + expect(spSdkConfig.configName).toBeDefined(); + }); + + it('spSdkConfigTest07', function () { + spSdkConfig.type = ''; + expect(spSdkConfig.type).toBeDefined(); + }); + + it('spSdkConfigTest08', function () { + spSdkConfig.type = 'configName'; + expect(spSdkConfig.type).toBeDefined(); + }); + + it('spSdkConfigTest09', function () { + expect(spSdkConfig.getPlugName()).not.toBeUndefined(); + }); + + it('spSdkConfigTest10', function () { + expect(spSdkConfig.getSampleInterval()).not.toBeUndefined(); + }); + + it('spSdkConfigTest11', function () { + expect(spSdkConfig.getGpuConfig()).not.toBeUndefined(); + }); + + it('spSdkConfigTest12', function () { + expect(spSdkConfig.checkIntegerInput('')).not.toBeUndefined(); + }); + + it('spSdkConfigTest13', function () { + expect(spSdkConfig.checkIntegerInput('checkIntegerInput')).not.toBeUndefined(); + }); + + it('spSdkConfigTest14', function () { + expect(spSdkConfig.checkFloatInput('checkFloatInput')).not.toBeUndefined(); + }); + + it('spSdkConfigTest15', function () { + expect(spSdkConfig.isAbleShowConfig(false)).toBeUndefined(); + }); + + it('spSdkConfigTest16', function () { + expect(spSdkConfig.isAbleShowConfig(true)).toBeUndefined(); + }); + + it('spSdkConfigTest17', function () { + expect(spSdkConfig.initConfigList()).toBeUndefined(); + }); + it('spSdkConfigTest18', function () { + spSdkConfig.configList = + { + "name": "", + "configuration": { + "ss": { + "type": "string", + "default": "strsadsa", + "description": "xxxx", + }, + "aa": { + "type": "string", + "default": "11", + "enum": [ + "consistent", + "11", + "delegated" + ] + }, + "cc": { + "type": "number", + "description": "number1111", + }, + "ee": { + "type": "integer", + "default": "12", + "description": "integer1222", + }, + "ff": { + "type": "boolean", + "description": "switchhh", + } + } + }; + expect(spSdkConfig.initConfig()).toBeUndefined(); + }); + it('spSdkConfigTest19', function () { + expect(spSdkConfig.getGpuConfig()).toStrictEqual({"aa": "11", "cc": 0, "ee": 12, "ff": true, "ss": "strsadsa",}); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/setting/SpTraceCommand.test.ts b/host/ide/test/trace/component/setting/SpTraceCommand.test.ts index 6695556c535da9b7b54fa06e4d7c27a0426e4d1e..374ce170eba7c270f039c959f894d0bd3aa902f4 100644 --- a/host/ide/test/trace/component/setting/SpTraceCommand.test.ts +++ b/host/ide/test/trace/component/setting/SpTraceCommand.test.ts @@ -14,7 +14,6 @@ */ // @ts-ignore - import {SpTraceCommand} from "../../../../dist/trace/component/setting/SpTraceCommand.js"; describe('SPTraceCommand Test', ()=>{ @@ -34,8 +33,135 @@ describe('SPTraceCommand Test', ()=>{ it(' SpAllocations set attrValue', function () { let spEle = document.querySelector("#command") as SpTraceCommand - spEle.hdcCommon = "aaaaaaaaaa" - expect(spEle.hdcCommon).toEqual("aaaaaaaaaa"); + spEle.hdcCommon = "test" + expect(spEle.hdcCommon).toEqual("test"); }); + it(' SpTraceCommand test', function () { + let spEle = document.querySelector("#command") as SpTraceCommand + expect(spEle.initHtml()).toMatchInlineSnapshot(` +" + +
+ + + +
+ " +`) + }); + it(' SpTraceCommandtest01', function () { + let spEle = document.querySelector("#command") as SpTraceCommand + spEle.show = false + expect(spEle.show).toBeFalsy() + }) + it(' SpTraceCommandtest02', function () { + let spEle = document.querySelector("#command") as SpTraceCommand + spEle.show = true + expect(spEle.show).toBeTruthy() + }) + it(' SpTraceCommandtest03', function () { + let spEle = document.querySelector("#command") as SpTraceCommand + expect(spEle.disconnectedCallback()).toBeUndefined() + }) }) \ No newline at end of file diff --git a/host/ide/test/trace/component/setting/SpVmTracker.test.ts b/host/ide/test/trace/component/setting/SpVmTracker.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..2bdd4a900b079c7961b428cfc53b98089ceb0c54 --- /dev/null +++ b/host/ide/test/trace/component/setting/SpVmTracker.test.ts @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpVmTracker} from "../../../../dist/trace/component/setting/SpVmTracker.js"; + +describe('SpVmTracker Test', () => { + let spVmTracker = new SpVmTracker(); + it('SpVmTrackerTest01', function () { + spVmTracker.startSamp = true; + expect(spVmTracker.startSamp).toBeTruthy(); + }); + + it('SpVmTrackerTest02', function () { + spVmTracker.startSamp = false; + expect(spVmTracker.startSamp).toBeFalsy(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/setting/utils/PluginConvertUtils.test.ts b/host/ide/test/trace/component/setting/utils/PluginConvertUtils.test.ts index 1a3a73a3f2eacde8d1e88cfda66355d4962914ee..aa3428527cec641c91f665a13108ccad2af93292 100644 --- a/host/ide/test/trace/component/setting/utils/PluginConvertUtils.test.ts +++ b/host/ide/test/trace/component/setting/utils/PluginConvertUtils.test.ts @@ -109,7 +109,7 @@ describe('PlugConvertUtils Test', ()=>{ }); it('PlugConvertUtils03', function () { - expect(PluginConvertUtils.BeanToCmdTxt(request, false)).not.toBeNull() + expect(PluginConvertUtils.BeanToCmdTxtWithObjName(request, false,'',1)).not.toBeNull() }); }) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/TimerShaftElement.test.ts b/host/ide/test/trace/component/trace/TimerShaftElement.test.ts index d4f37f42f5e1a117a70e7e0d7f99616367aded3e..3802f8be998cef3041973fb7d7ae5c7c10315853 100644 --- a/host/ide/test/trace/component/trace/TimerShaftElement.test.ts +++ b/host/ide/test/trace/component/trace/TimerShaftElement.test.ts @@ -14,8 +14,9 @@ */ // @ts-ignore -import {TimerShaftElement} from "../../../../dist/trace/component/trace/TimerShaftElement.js" - +import {TimerShaftElement,ns2s,ns2x} from "../../../../dist/trace/component/trace/TimerShaftElement.js"; +// @ts-ignore +import {Rect} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerCommon"; describe('TimerShaftElement Test', () => { let timerShaftElement = new TimerShaftElement(); @@ -28,68 +29,18 @@ describe('TimerShaftElement Test', () => { expect(timerShaftElement.cpuUsage).toBeUndefined(); }); - it('TimerShaftElementTest02', function () { - timerShaftElement.rangeRuler = jest.fn(() => false) - timerShaftElement.loadComplete = jest.fn(() => false) - timerShaftElement.rangeRuler.markA = jest.fn(() => true) - timerShaftElement.rangeRuler.markB = jest.fn(() => true) - timerShaftElement.rangeRuler.markA.frame = jest.fn(() => true) - timerShaftElement.rangeRuler.markB.frame = jest.fn(() => true) - timerShaftElement.rangeRuler.markA.frame.x = jest.fn(() => 0) - timerShaftElement.rangeRuler.markB.frame.x = jest.fn(() => true) - timerShaftElement.rangeRuler.frame = jest.fn(() => true) - timerShaftElement.rangeRuler.frame.width = jest.fn(() => 8) - timerShaftElement.rangeRuler.cpuUsage = jest.fn(() => []) - timerShaftElement.sportRuler = jest.fn(() => true) - timerShaftElement.sportRuler.flagList = jest.fn(() => false) - timerShaftElement.sportRuler.flagList.length = jest.fn(() =>0) - timerShaftElement.totalNS =jest.fn(()=>false); - timerShaftElement.sportRuler.isRangeSelect = jest.fn(() => false) - expect(timerShaftElement.reset()).toBeUndefined(); - }); - - it('spApplicationTest10',function (){ - expect(timerShaftElement.reset()).not.toBeUndefined() - }); - - it('TimerShaftElementTest03', function () { timerShaftElement.timeRuler = jest.fn(() => false) - timerShaftElement.sportRuler = jest.fn(() => false) timerShaftElement.rangeRuler = jest.fn(() => false) timerShaftElement.timeRuler.frame = jest.fn(() => { return document.createElement('canvas') as HTMLCanvasElement }) - - timerShaftElement.sportRuler.frame = jest.fn(() => { - return document.createElement('canvas') as HTMLCanvasElement - }) - timerShaftElement.rangeRuler.frame = jest.fn(() => { return document.createElement('canvas') as HTMLCanvasElement }) expect(timerShaftElement.connectedCallback()).toBeUndefined(); }); - it('TimerShaftElementTest04', function () { - timerShaftElement.canvas = jest.fn(()=> { - return { - width: 20, - height: 20, - style: { - width: 30, - height: 30, - } - } - }) - timerShaftElement.canvas.style = jest.fn(() => true) - timerShaftElement.rangeRuler.fillX = jest.fn(() => true) - timerShaftElement.timeRuler.draw = jest.fn(() => true) - timerShaftElement.rangeRuler.draw = jest.fn(() => true) - timerShaftElement.sportRuler.draw = jest.fn(() => true) - expect(timerShaftElement.updateWidth(2)).toBeUndefined(); - }); - it('TimerShaftElementTest05', function () { expect(timerShaftElement.disconnectedCallback()).toBeUndefined(); }); @@ -97,15 +48,6 @@ describe('TimerShaftElement Test', () => { it('TimerShaftElementTest06', function () { expect(timerShaftElement.totalNS).toBe(10000000000); }); - it('TimerShaftElementTest10', function () { - timerShaftElement.totalNS = 10000000000; - expect(timerShaftElement.totalNS).toBe(10000000000); - }); - - it('TimerShaftElementTest07', function () { - // timerShaftElement._sportRuler.modifyFlagList = jest.fn(() => true) - expect(timerShaftElement.modifyFlagList()).toBeUndefined(); - }); it('TimerShaftElementTest08', function () { timerShaftElement.startNS = 'startNS' @@ -117,14 +59,187 @@ describe('TimerShaftElement Test', () => { expect(timerShaftElement.endNS).toBe('endNS'); }); - it('TimerShaftElementTest11', function () { - expect(timerShaftElement.render()).toBe(undefined); + it('TimerShaftElementTest14', function () { + expect(ns2s(1_000_0000)).toBe("10.0 ms"); + }); + + it('TimerShaftElementTest15', function () { + expect(timerShaftElement.initHtml()).toMatchInlineSnapshot(` +" + +
+
+
+
+ 10 + 0 +
+
+ +
+ " +`); + }); + + it('TimerShaftElementTest16', function () { + expect(ns2s(1)).toBe("1.0 ns"); + }); + + it('TimerShaftElementTest17', function () { + expect(ns2s(1_000)).toBe("1.0 μs"); + }); + + it('TimerShaftElementTest18', function () { + expect(ns2x(1,3,4,4,{width:1})).toBe(0); + }); + + it('TimerShaftElementTest19', function () { + expect(timerShaftElement.sportRuler).not.toBeUndefined(); + }); + + it('TimerShaftElementTest20', function () { + expect(timerShaftElement.isScaling()).toBeFalsy(); + }); + + it('TimerShaftElementTest21', function () { + timerShaftElement.rangeRuler = jest.fn(()=>undefined) + timerShaftElement.rangeRuler.setRangeNS = jest.fn(()=>true) + expect(timerShaftElement.setRangeNS()).toBeFalsy(); + }); + + it('TimerShaftElementTest22', function () { + timerShaftElement.rangeRuler = jest.fn(()=>undefined) + timerShaftElement.rangeRuler.getRange = jest.fn(()=>true) + expect(timerShaftElement.getRange()).toBeTruthy(); + }); + + it('TimerShaftElementTest23', function () { + timerShaftElement.rangeRuler = jest.fn(()=>undefined) + timerShaftElement.rangeRuler.frame = jest.fn(()=>Rect) + timerShaftElement.rangeRuler.frame.width = jest.fn(()=>1) + timerShaftElement._sportRuler = jest.fn(()=>undefined) + timerShaftElement._sportRuler.frame = jest.fn(()=>Rect) + timerShaftElement._sportRuler.frame.width = jest.fn(()=>1) + timerShaftElement.timeRuler = jest.fn(()=>undefined) + timerShaftElement.timeRuler.frame = jest.fn(()=>Rect) + timerShaftElement.timeRuler.frame.width = jest.fn(()=>1) + timerShaftElement.rangeRuler.fillX = jest.fn(()=>true) + timerShaftElement.render = jest.fn(()=>true) + expect(timerShaftElement.updateWidth()).toBeUndefined(); + }); + + it('TimerShaftElementTest24', function () { + timerShaftElement._sportRuler = jest.fn(()=>undefined) + timerShaftElement._sportRuler.modifyFlagList = jest.fn(()=>true) + expect(timerShaftElement.modifyFlagList()).toBeUndefined(); + }); + + it('TimerShaftElementTest25', function () { + timerShaftElement._sportRuler = jest.fn(()=>undefined) + timerShaftElement._sportRuler.drawTriangle = jest.fn(()=>true) + expect(timerShaftElement.drawTriangle()).toBeTruthy(); + }); + + it('TimerShaftElementTest26', function () { + timerShaftElement._sportRuler = jest.fn(()=>undefined) + timerShaftElement._sportRuler.removeTriangle = jest.fn(()=>true) + expect(timerShaftElement.removeTriangle()).toBeUndefined(); + }); + + it('TimerShaftElementTest27', function () { + timerShaftElement._sportRuler = jest.fn(()=>undefined) + timerShaftElement._sportRuler.setSlicesMark = jest.fn(()=>true) + expect(timerShaftElement.setSlicesMark()).toBeUndefined(); + }); + + + it('TimerShaftElementTest28', function () { + timerShaftElement.rangeRuler = jest.fn(()=>undefined) + timerShaftElement.rangeRuler.render = jest.fn(()=>true) + expect(timerShaftElement.render()).not.toBeUndefined(); }); - it('TimerShaftElementTest12', function () { - timerShaftElement.ctx = jest.fn(()=>true) - timerShaftElement.ctx.fillStyle = jest.fn(()=>'transparent') - timerShaftElement.ctx.fillRect = jest.fn(()=>true) - expect(timerShaftElement.render()).toBe(undefined); + it('TimerShaftElementTest29', function () { + expect(ns2x(1,3,0,4,{width:1})).toBe(0); }); + + it('TimerShaftElementTest30', function () { + timerShaftElement.rangeRuler = jest.fn(() => true); + timerShaftElement.rangeRuler.cpuUsage = jest.fn(() => true); + expect(timerShaftElement.cpuUsage).toBe(undefined); + }); + + it('TimerShaftElementTest31', function () { + timerShaftElement.timeRuler = jest.fn(() => true); + expect(timerShaftElement.totalNS).toBe(10000000000); + }); + + it('TimerShaftElementTest32', function () { + timerShaftElement.rangeRuler = jest.fn(() => true); + expect(timerShaftElement.totalNS).toBe(10000000000); + }); + + it('TimerShaftElementTest33', function () { + timerShaftElement.timeTotalEL = jest.fn(() => true); + expect(timerShaftElement.totalNS).toBe(10000000000); + }); + + it('TimerShaftElementTest35', function () { + timerShaftElement.rangeRuler =jest.fn(()=>undefined) + timerShaftElement.rangeRuler.cancelPressFrame =jest.fn(()=>undefined) + expect(timerShaftElement.cancelPressFrame()).toBeUndefined(); + }); + + it('TimerShaftElementTest36', function () { + timerShaftElement.rangeRuler =jest.fn(()=>undefined) + timerShaftElement.rangeRuler.cancelUpFrame =jest.fn(()=>undefined) + expect(timerShaftElement.cancelUpFrame()).toBeUndefined(); + }); + }) diff --git a/host/ide/test/trace/component/trace/base/ColorUtils.test.ts b/host/ide/test/trace/component/trace/base/ColorUtils.test.ts index 5b49ac2c6099513e26f2016ea82fc40a4a4ad9bf..3d618da0895078664167f1c1ba1a833fef1af966 100644 --- a/host/ide/test/trace/component/trace/base/ColorUtils.test.ts +++ b/host/ide/test/trace/component/trace/base/ColorUtils.test.ts @@ -20,7 +20,7 @@ describe("testColorUtils Test", () => { beforeAll(() => { }) it('testColorUtils01', () => { - expect(ColorUtils.hash("mm",ColorUtils.MD_PALETTE.length)).toBe(6); + expect(ColorUtils.hash("mm",ColorUtils.MD_PALETTE.length)).toBe(0); }); it('testColorUtils02', () => { // @ts-ignore @@ -30,7 +30,7 @@ describe("testColorUtils Test", () => { it('testColorUtils03', () => { // @ts-ignore let thread = {processId:1} - expect(ColorUtils.colorForThread(thread)).toEqual("#fbbf00"); + expect(ColorUtils.colorForThread(thread)).toEqual("#7AD7E6"); }); it('testColorUtils03', () => { @@ -39,7 +39,7 @@ describe("testColorUtils Test", () => { processId:0, tid:1 } - expect(ColorUtils.colorForThread(thread)).toEqual("#fbbf00"); + expect(ColorUtils.colorForThread(thread)).toEqual("#7AD7E6"); }); it('testColorUtils04', () => { diff --git a/host/ide/test/trace/component/trace/base/RangeSelect.test.ts b/host/ide/test/trace/component/trace/base/RangeSelect.test.ts index 2e84cc0e2f9869470581840a4a1c3709c38a392c..74be6f4636023761a543f5f5b5b67fb9a374bca2 100644 --- a/host/ide/test/trace/component/trace/base/RangeSelect.test.ts +++ b/host/ide/test/trace/component/trace/base/RangeSelect.test.ts @@ -147,6 +147,11 @@ describe("RangeSelect Test", () => { rangeSelect.timerShaftDragEL.timerShaftDragEL = jest.fn(()=>0) rangeSelect.spacerEL = jest.fn(()=>true) rangeSelect.spacerEL.offsetTop = jest.fn(()=>1) + rangeSelect.ns2x = jest.fn(()=> 1) + rangeSelect.mouseX = jest.fn(()=> 10) + rangeSelect.markA = jest.fn( ()=> 8) + rangeSelect.markB = jest.fn( ()=> 9) + expect(rangeSelect.mouseMove(rowsEL,mouseEvent)).toBeUndefined(); }); @@ -176,4 +181,22 @@ describe("RangeSelect Test", () => { rangeSelect.timerShaftDragEL.timerShaftDragEL = jest.fn(()=>0) expect(rangeSelect.isTouchMark(mouseEvent)).toBeFalsy(); }); + + it('Utils Test06', () => { + let rangeSelect = new RangeSelect(); + rangeSelect.isHover = true; + let mouseEvent = new MouseEvent("mousedown",{ + // @ts-ignore + offsetY:1, + offsetX:1, + button: 0, + buttons: 0, + clientX: 2, + clientY: 100, + screenX: 255, + screenY: 325 + }); + expect(rangeSelect.mouseDown(mouseEvent)).toBeUndefined(); + }); + }) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/base/TraceRow.test.ts b/host/ide/test/trace/component/trace/base/TraceRow.test.ts index da8ecac2169bd0b124c37c7d2f216c7cc568cb7b..3d7c0e27b27a53f70e50ff2076758a3baac3fd0b 100644 --- a/host/ide/test/trace/component/trace/base/TraceRow.test.ts +++ b/host/ide/test/trace/component/trace/base/TraceRow.test.ts @@ -15,111 +15,56 @@ // @ts-ignore import {TraceRow} from "../../../../../dist/trace/component/trace/base/TraceRow.js"; +// @ts-ignore +import {Sptext} from "../../../../../dist/trace/component/Sptext.js"; + describe("TraceRow Test", () => { beforeAll(() => { }) + const ctx = { + lineWidth:1, + strokeStyle:true + } it('TraceRow Test01', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); expect(traceRow).not.toBeUndefined(); }); it('TraceRow Test02', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); expect(traceRow.sleeping).toBeFalsy(); }); it('TraceRow Test03', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); traceRow.sleeping = true expect(traceRow.sleeping).toBeTruthy(); }); it('TraceRow Test04', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); traceRow.sleeping = false expect(traceRow.sleeping).toBeFalsy(); }); it('TraceRow Test05', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); expect(traceRow.rangeSelect).toBeFalsy(); }); it('TraceRow Test06', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); traceRow.rangeSelect = true expect(traceRow.rangeSelect).toBeTruthy(); }); - it('TraceRow Test07', () => { - const canvas = document.createElement('canvas'); - canvas.width = 1; - canvas.height = 1; - const ctx = canvas.getContext('2d'); - let traceRow = new TraceRow(); - //transferControlToOffscreen() - traceRow.canvas = jest.fn(()=>true) - traceRow.args = jest.fn(()=>true) - traceRow.args.isOffScreen = jest.fn(()=>true) - // @ts-ignore - traceRow.canvas.transferControlToOffscreen = jest.fn(()=>true) - traceRow.dataList = { - supplier:true, - isLoading:false, - } - traceRow.args={ - isOffScreen:true, - } - traceRow.supplier = true; - traceRow.isLoading = false; - traceRow.name = "111" - traceRow.height = 20 - traceRow.height = 30 - expect(traceRow.initCanvas()).toBeUndefined(); - }); - - it('TraceRow Test08', () => { - const canvas = document.createElement('canvas'); - canvas.width = 1; - canvas.height = 1; - const ctx = canvas.getContext('2d'); - let traceRow = new TraceRow(); - traceRow.dataList = { - supplier:true, - isLoading:false, - } - traceRow.supplier = true; - traceRow.isLoading = false; - traceRow.name = "111" - traceRow.height = 20 - traceRow.height = 30 - expect(traceRow.drawObject()).toBeUndefined(); - }); - - it('TraceRow Test09', () => { - const canvas = document.createElement('canvas'); - canvas.width = 1; - canvas.height = 1; - const ctx = canvas.getContext('2d'); - let traceRow = new TraceRow(); - traceRow.dataList = { - supplier:true, - isLoading:false, - } - traceRow.supplier = true; - traceRow.isLoading = false; - traceRow.name = "111" - traceRow.height = 20 - traceRow.height = 30 - expect(traceRow.drawObject()).toBeUndefined(); - }); it('TraceRow Test10', () => { const canvas = document.createElement('canvas'); canvas.width = 1; canvas.height = 1; const ctx = canvas.getContext('2d'); - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); traceRow.dataList = { supplier:true, isLoading:false, @@ -129,7 +74,7 @@ describe("TraceRow Test", () => { traceRow.name = "111" traceRow.height = 20 traceRow.height = 30 - expect(traceRow.clearCanvas()).toBeUndefined(); + expect(traceRow.clearCanvas(ctx)).toBeUndefined(); }); it('TraceRow Test11', () => { @@ -137,7 +82,7 @@ describe("TraceRow Test", () => { canvas.width = 1; canvas.height = 1; const ctx = canvas.getContext('2d'); - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); traceRow.dataList = { supplier:true, isLoading:false, @@ -147,7 +92,7 @@ describe("TraceRow Test", () => { traceRow.name = "111" traceRow.height = 20 traceRow.height = 30 - expect(traceRow.drawLines()).toBeUndefined(); + expect(traceRow.drawLines(ctx)).toBeUndefined(); }); it('TraceRow Test12', () => { @@ -155,7 +100,7 @@ describe("TraceRow Test", () => { canvas.width = 1; canvas.height = 1; const ctx = canvas.getContext('2d'); - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); traceRow.dataList = { supplier:true, isLoading:false, @@ -165,156 +110,557 @@ describe("TraceRow Test", () => { traceRow.name = "111" traceRow.height = 20 traceRow.height = 30 - expect(traceRow.drawSelection()).toBeUndefined(); + expect(traceRow.drawSelection(ctx)).toBeUndefined(); }); it('TraceRow Test13', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); expect(traceRow.collect).toBeFalsy(); }); it('TraceRow Test14', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); traceRow.collect = true; expect(traceRow.collect).toBeTruthy(); }); it('TraceRow Test15', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); expect(traceRow.rowType).toBeFalsy(); }); it('TraceRow Test16', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); traceRow.rowType = true; expect(traceRow.rowType).toBeTruthy(); }); it('TraceRow Test17', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); expect(traceRow.rowId).toBeFalsy(); }); it('TraceRow Test18', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); traceRow.rowId = true; expect(traceRow.rowId).toBeTruthy(); }); it('TraceRow Test19', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); expect(traceRow.rowParentId).toBeFalsy(); }); it('TraceRow Test20', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); traceRow.rowParentId = true; expect(traceRow.rowParentId).toBeTruthy(); }); it('TraceRow Test21', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); traceRow.rowHidden = true; expect(traceRow.rowHidden).toBeUndefined(); }); + it('TraceRow Test22', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); expect(traceRow.name).toBeFalsy(); }); it('TraceRow Test23', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.folder = false; expect(traceRow.folder).toBeFalsy(); }); it('TraceRow Test24', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); traceRow.folder = true; expect(traceRow.folder).toBeTruthy(); }); it('TraceRow Test25', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.expansion = false; expect(traceRow.expansion).toBeFalsy(); }); it('TraceRow Test26', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); traceRow.expansion = true; expect(traceRow.expansion).toBeTruthy(); }); it('TraceRow Test27', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); traceRow.tip = true; expect(traceRow.tip).toBeUndefined(); }); it('TraceRow Test28', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); expect(traceRow.frame).not.toBeUndefined(); }); it('TraceRow Test29', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); traceRow.frame = [0,0,0]; expect(traceRow.frame).toBeTruthy(); }); + it('TraceRow Test60', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + expect(traceRow.disabledCheck).not.toBeUndefined(); + }); + + it('TraceRow Test61', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.disabledCheck = true; + expect(traceRow.disabledCheck).toBeTruthy(); + }); + + it('TraceRow Test62', () => { + let traceRow = new TraceRow({canvasNumber: 1, alpha: true, contextId: '2d', isOffScreen: true}); + expect(traceRow.folderPaddingLeft).toBeUndefined(); + }); + it('TraceRow Test30', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); expect(traceRow.checkType).not.toBeUndefined(); }); it('TraceRow Test31', () => { - let traceRow = new TraceRow(); - traceRow.checkType = true; + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.checkType = "-1"; expect(traceRow.checkType).toBeTruthy(); }); it('TraceRow Test32', () => { - let traceRow = new TraceRow(); - expect(traceRow.drawType).toBeUndefined(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + expect(traceRow.drawType).toBe(0); }); it('TraceRow Test33', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); traceRow.drawType = true; expect(traceRow.drawType).toBeTruthy(); }); it('TraceRow Test34', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); traceRow.args = jest.fn(()=>true) traceRow.args.isOffScreen = jest.fn(()=>null) expect(traceRow.updateWidth(1)).toBeUndefined(); }); - it('TraceRow Test35', () => { - let traceRow = new TraceRow(); - expect(traceRow.setCheckBox()).toBeUndefined(); - }); - it('TraceRow Test36', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); expect(traceRow.onMouseHover()).toBeFalsy(); }); it('TraceRow Test37', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); expect(traceRow.setTipLeft(1,null)).toBeFalsy(); }); it('TraceRow Test38', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); expect(traceRow.onMouseLeave(1,1)).toBeFalsy(); }); it('TraceRow Test39', () => { - let traceRow = new TraceRow(); + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); expect(traceRow.draw(false)).toBeFalsy(); }); + it('TraceRow Test40', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.collect = 1 + expect(traceRow.collect).toBeTruthy(); + }); + + it('TraceRow Test41', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.collect = 0 + expect(traceRow.collect).toBeFalsy(); + }); + + it('TraceRow Test42', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.checkType = "0"; + expect(traceRow.checkType).toBe("0"); + }); + + it('TraceRow Test43', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.checkType = "1"; + expect(traceRow.checkType).toBe("1"); + }); + + it('TraceRow Test44', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.checkType = "2"; + expect(traceRow.checkType).toBe("2"); + }); + + + it('TraceRow Test45', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.checkType = 0; + expect(traceRow.checkType).toBe(""); + }); + + it('TraceRow Test46', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.rowHidden = false; + expect(traceRow.rowHidden).toBeUndefined(); + }); + + it('TraceRow Test47', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.highlight = false; + expect(traceRow.highlight).toBeFalsy(); + }); + + it('TraceRow Test48', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.highlight = true; + expect(traceRow.highlight).toBeFalsy(); + }); + + it('TraceRow Test49', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.setCheckBox = true; + expect(traceRow.highlight).toBeFalsy(); + }); + it('TraceRow Test50', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.initCanvas = jest.fn(()=>null) + expect(traceRow.connectedCallback()).toBeUndefined(); + }); + + it('TraceRow Test51', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + expect(traceRow.isInTimeRange()).toBe(false); + }); + + it('TraceRow Test52', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + expect(traceRow.getLineColor()).toBe(""); + }); + + it('TraceRow Test53', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + let value = traceRow.attributeChangedCallback("name") + expect(value).toBe(undefined); + }); + + it('TraceRow Test54', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + let value = traceRow.attributeChangedCallback("height","1","2") + expect(value).toBe(undefined); + }); + + it('TraceRow Test55', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + let value = traceRow.attributeChangedCallback("check-type","1","check") + expect(value).toBe(undefined); + }); + + it('TraceRow Test56', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + expect(traceRow.initHtml()).toMatchInlineSnapshot(` +" + +
+
+ + + + +
+
+ Current Bytes
+
+ Native Memory Density
+
+ +
+ +
+
+ +
+ +
+
+
+ P:process [1573]
+ T:Thread [675] +
+
+
+ " +`); + }); + it('TraceRow Test57', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + expect(traceRow.rowDiscard).toBeFalsy() + }); + it('TraceRow Test58', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.rowDiscard =true + expect(traceRow.rowDiscard).toBeTruthy() + }); + it('TraceRow Test58', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.rowDiscard = false + expect(traceRow.rowDiscard).toBeFalsy() + }); + it('TraceRow Test59', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.disabledCheck = false + expect(traceRow.disabledCheck).toBeFalsy() + }); + it('TraceRow Test64', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + traceRow.folderPaddingLeft = 1 + expect(traceRow.folderPaddingLeft).toBeUndefined() + }); + it('TraceRow Test65', () => { + let traceRow = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + expect(traceRow.getTransferArray()).toStrictEqual([undefined]) + }); }) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/base/TraceRowRecyclerView.test.ts b/host/ide/test/trace/component/trace/base/TraceRowRecyclerView.test.ts index 6aa8c61cb54897f6a729de2ada5607dc10c3fd6c..3185d3befb0987fa7096a8774a401d26fc3aa449 100644 --- a/host/ide/test/trace/component/trace/base/TraceRowRecyclerView.test.ts +++ b/host/ide/test/trace/component/trace/base/TraceRowRecyclerView.test.ts @@ -32,7 +32,8 @@ describe("TraceRow Test", () => { it('Test03', function () { let traceRow = new TraceRowRecyclerView(); - traceRow.dataSource=false + traceRow.measureHeight = jest.fn(()=>true) + traceRow.dataSource = true expect(traceRow.dataSource).toBeTruthy(); }); @@ -49,22 +50,84 @@ describe("TraceRow Test", () => { it('Test06', function () { let traceRow = new TraceRowRecyclerView(); - expect(traceRow.refreshRow()).toBeUndefined(); - }); + const obj={ + folder:false, + top:0, + name:"", + children:false, + rowId:"", + rowType:"", + rowParentId:"1", + expansion:false, + rowHidden:false, + rowHeight:40 + } + const el={ + obj:undefined, + style:{top:1,visibility:'visible'}, + name:"", + rowId:"", + rowType:"", + rowParentId:"1", + expansion:false, + rowHidden:false, + setAttribute:"", + removeAttribute:"" - it('Test07', function () { - let traceRow = new TraceRowRecyclerView(); - traceRow.dataSource = jest.fn(()=>true) - traceRow.dataSource.filter = jest.fn(()=>true) - expect(traceRow.measureHeight()).toBeUndefined(); + } + expect(traceRow.refreshRow(el,!obj)).toBeUndefined(); }); it('Test08', function () { let traceRow = new TraceRowRecyclerView(); expect(traceRow.initUI()).toBeUndefined(); }); + it('Test09', function () { let traceRow = new TraceRowRecyclerView(); expect(traceRow.initUI()).toBeUndefined(); }); + + it('Test09', function () { + let traceRow = new TraceRowRecyclerView(); + expect(traceRow.initHtml()).toMatchInlineSnapshot(` +" + +
+
+
+ + " +`) + }); }) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/base/TraceSheet.test.ts b/host/ide/test/trace/component/trace/base/TraceSheet.test.ts index 39ef4ca48217c030d92e11aed1bf6d7a1e8fe608..51088576b8bfd2a5de8c2d5f834c1e0b324e5924 100644 --- a/host/ide/test/trace/component/trace/base/TraceSheet.test.ts +++ b/host/ide/test/trace/component/trace/base/TraceSheet.test.ts @@ -15,6 +15,7 @@ // @ts-ignore import {TraceSheet} from "../../../../../dist/trace/component/trace/base/TraceSheet.js"; + window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ disconnect: jest.fn(), @@ -25,70 +26,90 @@ window.ResizeObserver = window.ResizeObserver || describe("TraceSheet Test", () => { beforeAll(() => { }) -let val=[{ - cpus:{length:1,}, - threadIds:{length: 2}, - funTids:{length: 2}, - trackIds:{length: 2}, - hasFps:0, - heapIds:{length: 0}, - nativeMemory:{length: 1} -}] - it('TraceSheet Test01', () => { - let traceRow = new TraceSheet(); - expect(traceRow).not.toBeUndefined() - }); - - it('TraceSheet Test02', () => { - let traceRow = new TraceSheet(); - expect(traceRow.recoveryBoxSelection).not.toBeUndefined() - }); + let val = { + hasFps: 1, + cpus:{length:1}, + threadIds:[{length:2}], + funTids:{length:1}, + trackIds: {length:1}, + heapIds: {length:1}, + nativeMemory: {length:1}, + cpuAbilityIds:{length:1}, + memoryAbilityIds:{length:1}, + diskAbilityIds:{length:1}, + networkAbilityIds:{length:1}, + } + let e = {detail:{ + title:1, + state:0, + threadId:1, + processId:2 + }} + let selection ={ + hasFps: 1, + cpus:{length:1}, + threadIds:[{length:2}], + funTids:{length:1}, + trackIds: {length:1}, + heapIds: {length:1}, + nativeMemory: {length:1}, + cpuAbilityIds:{length:0}, + memoryAbilityIds:{length:0}, + diskAbilityIds:{length:0}, + networkAbilityIds:{length:0}, + perfSampleIds:{length:0}, + processTrackIds:{length:0}, + fileSystemType:{length:0}, + virtualTrackIds:{length:0}, + sdkCounterIds:[{ + length:0 + }], + sdkSliceIds:[{ + length:0 + }] - - - it('TraceSheet Test03', () => { - let traceRow = new TraceSheet(); - expect(traceRow.hideBoxTab()).toBeUndefined() - }); - - /* it('TraceSheet Test04', () => { - let traceRow = new TraceSheet(); - expect(traceRow.hideOtherBoxTab("11")).not.toBeUndefined() - }); - - - it('TraceSheet Test05', () => { - let traceRow = new TraceSheet(); - expect(traceRow.hideOtherBoxTab("12")).not.toBeUndefined() - }); - - - it('TraceSheet Test06', () => { - let traceRow = new TraceSheet(); - expect(traceRow.hideOtherBoxTab("13")).not.toBeUndefined() + } + it('TraceSheet Test01', () => { + let traceSheet = new TraceSheet(); + expect(traceSheet).not.toBeUndefined() }); - it('TraceSheet Test07', () => { - let traceRow = new TraceSheet(); - expect(traceRow.hideOtherBoxTab("14")).not.toBeUndefined() - });*/ - it('TraceSheet Test08', () => { - let traceRow = new TraceSheet(); - expect(traceRow.connectedCallback()).toBeUndefined() + let traceSheet = new TraceSheet(); + expect(traceSheet.connectedCallback()).toBeUndefined() }); it('TraceSheet Test09', () => { - let traceRow = new TraceSheet(); - expect(traceRow.loadTabPaneData()).toBeUndefined() - }); - - it('TraceSheet Test10', () => { - let traceRow = new TraceSheet(); - expect(traceRow.clear()).toBeUndefined() + let traceSheet = new TraceSheet(); + expect(traceSheet.loadTabPaneData()).toBeUndefined() }); - it('TraceSheet Test11', () => { - let traceRow = new TraceSheet(); - expect(traceRow.boxSelection(val)).toBeUndefined() + it('TraceSheet Test19', () => { + let traceSheet = new TraceSheet(); + expect(traceSheet.initHtml()).toMatchInlineSnapshot(` +" + +
+ +
+ + + + +
+
+
" +`) }); }) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/base/Utils.test.ts b/host/ide/test/trace/component/trace/base/Utils.test.ts index 0b70b4d7124f07fc83df773fcada772b0bad0614..c7ad70dece48253981174301da63d1b09a209c9c 100644 --- a/host/ide/test/trace/component/trace/base/Utils.test.ts +++ b/host/ide/test/trace/component/trace/base/Utils.test.ts @@ -68,21 +68,208 @@ describe("Utils Test", () => { }); it('Utils Test11', () => { - expect(Utils.getByteWithUnit(1_000_000_001)).toBe("1.00 Gb") + expect(Utils.getByteWithUnit(2_000_000_000)).toBe("1.86 Gb") }); it('Utils Test12', () => { - expect(Utils.getByteWithUnit(1_000_000_000)).toBe("1000.00 Mb") + expect(Utils.getByteWithUnit(1_000_000_000)).toBe("953.67 Mb") + }); + + it('Utils Test13', () => { + expect(Utils.getByteWithUnit(1000_000)).toBe("976.56 Kb") + }); + + it('Utils Test23', () => { + expect(Utils.getByteWithUnit(-2_000)).toBe("-1.95 Kb") }); it('Utils Test14', () => { - expect(Utils.getByteWithUnit(1000_000)).toBe("1000.00 kb") + expect(Utils.getTimeString( 1_000_000_000_000)).toBe("16m 40s ") }); - it('Utils Test13', () => { + it('Utils Test15', () => { + expect(Utils.getTimeString( 2_000_000)).toBe("2ms ") + }); + + it('Utils Test16', () => { + expect(Utils.getTimeString( 3_000)).toBe("3μs ") + }); + + it('Utils Test17', () => { + expect(Utils.getTimeString( 300)).toBe("300ns ") + }); + + it('Utils Test18', () => { expect(Utils.getTimeStringHMS(5900_000_000_000)).toBe("1:38:") }); + it('Utils Test19', () => { + expect(Utils.getTimeStringHMS(3_000_000_000)).toBe("3:") + }); + + it('Utils Test20', () => { + expect(Utils.getTimeStringHMS(2_000_000)).toBe("2.") + }); + + it('Utils Test21', () => { + expect(Utils.getTimeStringHMS(5_000)).toBe("5.") + }); + + it('Utils Test22', () => { + expect(Utils.getTimeStringHMS(90)).toBe("90") + }); + + it('Utils Test24', () => { + expect(Utils.getBinaryByteWithUnit(0)).toBe("0Bytes") + }); + + it('Utils Test25', () => { + expect(Utils.getBinaryByteWithUnit(3_000_000_000)).toBe("2.79Gib") + }); + + it('Utils Test26', () => { + expect(Utils.getBinaryByteWithUnit(2_000_000)).toBe("1.91Mib") + }); + + it('Utils Test27', () => { + expect(Utils.getBinaryByteWithUnit(2_000)).toBe("1.95kib") + }); + + it('Utils Test28', () => { + expect(Utils.getTimeStampHMS(3900_000_000_000)).toBe("01:05:00:000.000") + }); + + it('Utils Test29', () => { + expect(Utils.getTimeStampHMS(70_000_000_000)).toBe("01:10:000.000") + }); + + it('Utils Test30', () => { + expect(Utils.getTimeStampHMS(2_000_000_000)).toBe("02:000.000") + }); + + it('Utils Test31', () => { + expect(Utils.getTimeStampHMS(2_000_000)).toBe("00:002.000") + }); + + it('Utils Test32', () => { + expect(Utils.getTimeStampHMS(2_000)).toBe("00:000.002.") + }); + + it('Utils Test33', () => { + expect(Utils.getTimeStampHMS(1)).toBe("00:000.000001") + }); + + it('Utils Test40', () => { + expect(Utils.getDurString(61_000_000_000)).toBe("61.000 s ") + }); + + it('Utils Test34', () => { + expect(Utils.getDurString(2_000_000_000)).toBe("2.000 s ") + }); + + it('Utils Test35', () => { + expect(Utils.getDurString(1_800_000)).toBe("1 ms ") + }); + + it('Utils Test36', () => { + expect(Utils.timeMsFormat2p(3800_000)).toBe("1.00h") + }); + + it('Utils Test37', () => { + expect(Utils.timeMsFormat2p(90_000)).toBe("1.00min") + }); + + it('Utils Test38', () => { + expect(Utils.timeMsFormat2p(2_000)).toBe("2.00s") + }); + + it('Utils Test39', () => { + expect(Utils.timeMsFormat2p(1)).toBe("1.00ms") + }); + + it('Utils Test41', () => { + expect(Utils.getProbablyTime(3600_000_000_000)).toBe("1.00h "); + }); + + it('Utils Test42', () => { + expect(Utils.getProbablyTime(60_000_000_000)).toBe("1.00m "); + }); + + it('Utils Test43', () => { + expect(Utils.getProbablyTime(1_000_000_000)).toBe("1.00s "); + }); + + it('Utils Test44', () => { + expect(Utils.getProbablyTime(1_000_000)).toBe("1.00ms "); + }); + + it('Utils Test45', () => { + expect(Utils.getProbablyTime(1_000)).toBe("1.00μs "); + }); + + it('Utils Test46', () => { + expect(Utils.getProbablyTime(0)).toBe("0"); + }); + + it('Utils Test47', () => { + expect(Utils.groupByMap([],'')).not.toBeUndefined(); + }); + + it('Utils Test48', () => { + expect(Utils.uuid).not.toBeUndefined(); + }); + + it('Utils Test49', () => { + expect(Utils.removeDuplicates([10],[11],"pid")).not.toBeUndefined(); + }); + + it('Utils Test50', () => { + expect(Utils.groupBy([],'')).not.toBeUndefined(); + }); + + it('Utils Test51', () => { + expect(Utils.getTimeStringHMS(0)).toBe("0"); + }); + + it('Utils Test52', () => { + expect(Utils.timeMsFormat2p(0)).toBe("0s"); + }); + + it('Utils Test53', () => { + expect(Utils.getBinaryByteWithUnit(1)).toBe("1.00Bytes"); + }); + + it('Utils Test54', () => { + expect(Utils.getTimeStampHMS(0)).toBe("00:000.000"); + }); + + it('Utils Test55', () => { + expect(Utils.getDurString(1)).toBe("1") + }); + + it('Utils Test56', () => { + expect(Utils.getCompletionTime(300,3)).toBe('300'); + }); + + it('Utils Test57', () => { + expect(Utils.getCompletionTime(30,3)).toBe('030'); + }); + + it('Utils Test58', () => { + expect(Utils.getCompletionTime(0,0)).toBe('0'); + }); + + it('Utils Test59', () => { + expect(Utils.groupByMap([10],'pid')).not.toBeUndefined(); + }); + + it('Utils Test60', () => { + expect(Utils.getProbablyTime(1)).toBe("1ns "); + }); + + it('Utils Test61', () => { + expect(Utils.groupBy([10],'pid')).not.toBeUndefined(); + }); afterAll(() => { // 后处理操作 diff --git a/host/ide/test/trace/component/trace/search/Search.test.ts b/host/ide/test/trace/component/trace/search/Search.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..0f52ce524b7d12adea25716d5042f4ce09c4324f --- /dev/null +++ b/host/ide/test/trace/component/trace/search/Search.test.ts @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitSearch} from "../../../../../dist/trace/component/trace/search/Search.js"; + +describe(" SearchTest", () => { + beforeAll(() => { + }) + it('Search Test01', () => { + let search = new LitSearch(); + expect(search).not.toBeUndefined() + }); + + it('Search Test02', () => { + let search = new LitSearch(); + search.list = ["1"]; + expect(search.list[0]).toBe("1"); + }); + + it('Search Test03', () => { + let search = new LitSearch(); + search.index = 1; + expect(search.index).toBe(1); + }); + + it('Search Test04', () => { + let search = new LitSearch(); + search.index = 1; + expect(search.total).toBe(0); + }); + + it('Search Test05', () => { + let search = new LitSearch(); + search.index = 1; + expect(search.setPercent("1",2)).toBeUndefined(); + }); + + it('Search Test06', () => { + let search = new LitSearch(); + search.index = 1; + expect(search.setPercent("1",101)).toBeUndefined(); + }); + + it('Search Test07', () => { + let search = new LitSearch(); + search.index = 1; + expect(search.setPercent("1",-1)).toBeUndefined(); + }); + + it('Search Test08', () => { + let search = new LitSearch(); + search.index = 1; + expect(search.setPercent("1",-2)).toBeUndefined(); + }); + + it('Search Test09', () => { + let search = new LitSearch(); + expect(search.clear()).toBeUndefined(); + }); + + it('Search Test11', function () { + let search = new LitSearch(); + search.search = jest.fn(()=>undefined) + search.search.blur = jest.fn(()=>true) + expect(search.blur()).toBeUndefined(); + }); + + it('Search Test10', () => { + let search = new LitSearch(); + expect(search.initHtml()).toMatchInlineSnapshot(` +" + +
+ + + +
+ 0/0 + + + | + + +
+
+ " +`); + }); + + it('Search Test12', () => { + let search = new LitSearch(); + expect(search.searchValue).toBe(''); + }); + + it('Search Test13', () => { + let search = new LitSearch(); + expect(search.isLoading).toBeFalsy(); + }); + +}); \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneCurrentSelection.test.ts b/host/ide/test/trace/component/trace/sheet/TabPaneCurrentSelection.test.ts index 5ecf5f1719d90fc6ba210676b7daa274b8f6afba..2d26e247faccdaaf0d05b7f36f48e5c6e3b3d4ad 100644 --- a/host/ide/test/trace/component/trace/sheet/TabPaneCurrentSelection.test.ts +++ b/host/ide/test/trace/component/trace/sheet/TabPaneCurrentSelection.test.ts @@ -29,6 +29,7 @@ describe('TabPaneCurrentSelection Test', () => { const canvas = document.createElement('canvas'); canvas.width = 1; canvas.height = 1; + let context = canvas.getContext("2d"); let cpuData = [{ cpu: 1, @@ -121,6 +122,28 @@ describe('TabPaneCurrentSelection Test', () => { state: "S", type: "thread", + }] + let scrollWakeUp = [{ + startTime:0, + pid:11, + tid:22, + + }] + let data = [{ + cpu: 1, + dur: 1, + end_state: 'string', + id: 12, + name: 'name', + priority: 11, + processCmdLine: 'processCmdLine', + processId: 111, + processName: 'processName', + schedId: 22, + startTime: 0, + tid: 100, + type: 'type', + }] tabPaneCurrentSelection.queryWakeUpData = jest.fn(()=> 'WakeUpData') @@ -138,49 +161,118 @@ describe('TabPaneCurrentSelection Test', () => { expect(result).toBeUndefined(); }); - it('TabPaneCurrentSelectionTest12', function () { - let result = tabPaneCurrentSelection.queryWakeUpData(queryData) - expect(result).toBeTruthy(); - }); - it('TabPaneCurrentSelectionTest03', function () { - let result = tabPaneCurrentSelection.setThreadData(threadData) - expect(result).toBeUndefined(); + let result = getTimeString(3600_000_000_002) + expect(result).toBe('1h 2ns '); }); it('TabPaneCurrentSelectionTest04', function () { - let result = tabPaneCurrentSelection.drawRight(canvas, wakeupBean) - expect(result).toBeUndefined(); - }); - - it('TabPaneCurrentSelectionTest06', function () { - let result = getTimeString(3600000000001) - expect(result).toBe('1h 1ns '); - }); - - it('TabPaneCurrentSelectionTest07', function () { let result = getTimeString(60000000001) expect(result).toBe('1m 1ns '); }); - it('TabPaneCurrentSelectionTest08', function () { + it('TabPaneCurrentSelectionTest05', function () { let result = getTimeString(1000000001) expect(result).toBe('1s 1ns '); }); - it('TabPaneCurrentSelectionTest9', function () { + it('TabPaneCurrentSelectionTest06', function () { let result = getTimeString(1000001) expect(result).toBe('1ms 1ns '); }); - it('TabPaneCurrentSelectionTest10', function () { + it('TabPaneCurrentSelectionTest07', function () { let result = getTimeString(1001) expect(result).toBe('1μs 1ns '); }); - it('TabPaneCurrentSelectionTest11', function () { + it('TabPaneCurrentSelectionTest08', function () { let result = getTimeString(101) expect(result).toBe('101ns '); }); + it('TabPaneCurrentSelectionTest09',function(){ + tabPaneCurrentSelection.setCpuData = jest.fn(()=>true); + tabPaneCurrentSelection.data = jest.fn(()=>true); + expect(tabPaneCurrentSelection.data).toBeUndefined(); + }); + + it('TabPaneCurrentSelectionTest10',function(){ + expect(tabPaneCurrentSelection.setCpuData(cpuData,undefined,1)).toBeTruthy(); + }); + + it('TabPaneCurrentSelectionTest13', function () { + expect(tabPaneCurrentSelection.initCanvas()).not.toBeUndefined(); + }); + + it('TabPaneCurrentSelectionTest14', function () { + let str = { + length:0 + } + expect(tabPaneCurrentSelection.transferString(str)).toBe(""); + }); + + it('TabPaneCurrentSelectionTest15', function () { + expect(tabPaneCurrentSelection.transferString("&")).not.toBeUndefined(); + }); + + it('TabPaneCurrentSelectionTest16', function () { + expect(tabPaneCurrentSelection.drawRight(null)).toBeUndefined(); + }); + + it('TabPaneCurrentSelectionTest11',function(){ + expect(tabPaneCurrentSelection.initHtml()).toMatchInlineSnapshot(` +" + +
+
+

+

Scheduling Latency

+
+
+
+ + + + + + + + +
+
+ +
+
+
+ " +`); + }); }) diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneFilter.test.ts b/host/ide/test/trace/component/trace/sheet/TabPaneFilter.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..26d309cda403ecad26047b3b08b20eafd86862c1 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/TabPaneFilter.test.ts @@ -0,0 +1,346 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneFilter} from "../../../../../dist/trace/component/trace/sheet/TabPaneFilter.js" + +describe('TabPaneFilter Test', () => { + let tabPaneFilter = new TabPaneFilter(); + + it('TabPaneFilterTest01', function () { + expect(tabPaneFilter.firstSelect).toBe(""); + }); + + it('TabPaneFilterTest02', function () { + expect(tabPaneFilter.secondSelect).toBe(""); + }); + + it('TabPaneFilterTest03', function () { + expect(tabPaneFilter.filterValue).toBe(""); + }); + + it('TabPaneFilterTest04', function () { + tabPaneFilter.filterValue = true + expect(tabPaneFilter.filterValue).toBeTruthy(); + }); + + it('TabPaneFilterTest05', function () { + expect(tabPaneFilter.icon).toBe("tree"); + }); + + it('TabPaneFilterTest08', function () { + tabPaneFilter.iconEL.name = "menu" + expect(tabPaneFilter.icon).toBe("block"); + }); + + it('TabPaneFilterTest09', function () { + tabPaneFilter.iconEL.name = "" + expect(tabPaneFilter.icon).toBe(""); + }); + + it('TabPaneFilterTest06', function () { + tabPaneFilter.icon = true + expect(tabPaneFilter.icon).toBe(""); + }); + + it('TabPaneFilterTest010', function () { + tabPaneFilter.icon = "block" + expect(tabPaneFilter.icon).toBe("block"); + }); + + it('TabPaneFilterTest011', function () { + tabPaneFilter.icon = "tree" + expect(tabPaneFilter.icon).toBe("tree"); + }); + + it('TabPaneFilterTest07', function () { + expect(tabPaneFilter.initHtml()).toMatchInlineSnapshot(` +" + + + Input Filter + + +
+ +
+ +
+
Invert
+
Hide System so
+
+ Options +
+ +
+ + + +
+
Constraints:Only enabled with data and while stopped;
+
filters data to thresholds.
+
+ +
+
+ Sample Count Filter +
+ +
+
+ +
+
+
Reset
+
+
+ Symbol Filter +
+ +
+
+ +
+
+
Reset
+
+
+ Library Filter +
+
+ +
Statistics by Thread
+
+ " +`); + }); + + it('TabPaneFilterTest10', function () { + expect(tabPaneFilter.addDataMining({name:""},"")).toBe(-1); + }); + + it('TabPaneFilterTest11', function () { + expect(tabPaneFilter.getFilterTreeData()).not.toBeUndefined(); + }); + + it('TabPaneFilterTest12', function () { + expect(tabPaneFilter.initializeFilterTree(true,true,true)).toBeUndefined(); + }); + + it('TabPaneFilterTest13', function () { + expect(tabPaneFilter.disabledMining).toBeFalsy(); + }); + + it('TabPaneFilterTest14', function () { + tabPaneFilter.disabledMining = true + expect(tabPaneFilter.disabledMining).toBeTruthy(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/ability/TabPaneCpuAbility.test.ts b/host/ide/test/trace/component/trace/sheet/ability/TabPaneCpuAbility.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..30e43f941d7c70b5daae274004cf5331bbe8c4e8 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/ability/TabPaneCpuAbility.test.ts @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {TabPaneCpuAbility} from "../../../../../../dist/trace/component/trace/sheet/ability/TabPaneCpuAbility.js" + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe('TabPaneCpuAbility Test', () => { + let tabPaneCpuAbility = new TabPaneCpuAbility(); + + it('TabPaneCpuAbilityTest01', function () { + tabPaneCpuAbility.queryResult.length = 2; + expect(tabPaneCpuAbility.filterData()).toBeUndefined(); + }); + + it('TabPaneCpuAbilityTest02', function () { + const systemCpuSummary = { + startTimeStr:"", + durationStr:"", + totalLoadStr:"", + userLoadStr:"", + systemLoadStr:"", + threadsStr:"" + } + expect(tabPaneCpuAbility.toCpuAbilityArray(systemCpuSummary)).not.toBeUndefined(); + }); + + it('TabPaneCpuAbilityTest03 ', function () { + expect(tabPaneCpuAbility.sortByColumn({ + key:'startTime', + })).toBeUndefined(); + }); + + it('TabPaneCpuAbilityTest04 ', function () { + expect(tabPaneCpuAbility.sortByColumn({ + key:!'startTime', + })).toBeUndefined(); + }); + + it('TabPaneCpuAbilityTest05 ', function () { + expect(tabPaneCpuAbility.sortByColumn({ + key:'totalLoadStr', + })).toBeUndefined(); + }); + + it('TabPaneCpuAbilityTest06 ', function () { + expect(tabPaneCpuAbility.sortByColumn({ + key:'userLoadStr', + })).toBeUndefined(); + }); + + it('TabPaneCpuAbilityTest07 ', function () { + expect(tabPaneCpuAbility.sortByColumn({ + key:'systemLoadStr', + })).toBeUndefined(); + }); + + it('TabPaneCpuAbilityTest08 ', function () { + expect(tabPaneCpuAbility.sortByColumn({ + key:'durationStr', + })).toBeUndefined(); + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/ability/TabPaneDiskAbility.test.ts b/host/ide/test/trace/component/trace/sheet/ability/TabPaneDiskAbility.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..e4f55489fbb51acf1d283d6c6570be12122e5121 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/ability/TabPaneDiskAbility.test.ts @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//@ts-ignore +import {TabPaneDiskAbility} from "../../../../../../dist/trace/component/trace/sheet/ability/TabPaneDiskAbility.js"; +window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(()=>({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), +})) + +describe('TabPaneDiskAbility Test', ()=>{ + + let tabPaneDiskAbility = new TabPaneDiskAbility(); + it('TabPaneDiskAbilityTest01',()=>{ + tabPaneDiskAbility.queryResult.length = 1; + expect(tabPaneDiskAbility.filterData()).toBeUndefined(); + }); + + it('TabPaneDiskAbilityTest02 ', function () { + const val = { + startTimeStr:"", + durationStr:"", + dataReadStr:"", + dataReadSecStr:"", + dataWriteStr:"", + readsInStr:"", + readsInSecStr:"", + writeOutStr:"", + writeOutSecStr:"" + } + expect(tabPaneDiskAbility.toDiskAbilityArray(val)).not.toBeUndefined(); + }); + + it('TabPaneDiskAbilityTest03 ', function () { + expect(tabPaneDiskAbility.sortByColumn({ + key:'startTime', + })).toBeUndefined(); + }); + + it('TabPaneDiskAbilityTest04 ', function () { + expect(tabPaneDiskAbility.sortByColumn({ + key:!'startTime', + })).toBeUndefined(); + }); + + it('TabPaneDiskAbilityTest05 ', function () { + expect(tabPaneDiskAbility.sortByColumn({ + key:'durationStr', + })).toBeUndefined(); + }); + + it('TabPaneDiskAbilityTest06 ', function () { + expect(tabPaneDiskAbility.sortByColumn({ + key:'dataReadStr', + })).toBeUndefined(); + }); + + it('TabPaneDiskAbilityTest07 ', function () { + expect(tabPaneDiskAbility.sortByColumn({ + key:'dataReadSecStr', + })).toBeUndefined(); + }); + + it('TabPaneDiskAbilityTest08 ', function () { + expect(tabPaneDiskAbility.sortByColumn({ + key:'dataWriteStr', + })).toBeUndefined(); + }); + + it('TabPaneDiskAbilityTest09 ', function () { + expect(tabPaneDiskAbility.sortByColumn({ + key:'dataWriteSecStr', + })).toBeUndefined(); + }); + + it('TabPaneDiskAbilityTest10 ', function () { + expect(tabPaneDiskAbility.sortByColumn({ + key:'readsInStr', + })).toBeUndefined(); + }); + + it('TabPaneDiskAbilityTest11 ', function () { + expect(tabPaneDiskAbility.sortByColumn({ + key:'readsInSecStr', + })).toBeUndefined(); + }); + + it('TabPaneDiskAbilityTest12', function () { + expect(tabPaneDiskAbility.sortByColumn({ + key:'writeOutStr', + })).toBeUndefined(); + }); + + it('TabPaneDiskAbilityTest13', function () { + expect(tabPaneDiskAbility.sortByColumn({ + key:'writeOutSecStr', + })).toBeUndefined(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/ability/TabPaneHistoryProcesses.test.ts b/host/ide/test/trace/component/trace/sheet/ability/TabPaneHistoryProcesses.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..b2da252e6b475ae5aa9d8068f856a7a48d2098ca --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/ability/TabPaneHistoryProcesses.test.ts @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//@ts-ignore +import {TabPaneHistoryProcesses} from "../../../../../../dist/trace/component/trace/sheet/ability/TabPaneHistoryProcesses.js"; +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe('TabPaneHistoryProcesses Test', function () { + + let tabPaneHistoryProcesses = new TabPaneHistoryProcesses(); + it('TabPaneHistoryProcessesTest01 ', function () { + tabPaneHistoryProcesses.queryResult.length = 1; + expect(tabPaneHistoryProcesses.filterData()).toBeUndefined(); + }); + + it('TabPaneHistoryProcessesTest02 ', function () { + const val = { + processId:-1, + processName:"", + alive:"", + firstSeen:"", + lastSeen:"", + responsibleProcess:"", + userName:"", + cpuTime:"" + } + expect(tabPaneHistoryProcesses.toProcessHistoryArray(val)).not.toBeUndefined(); + }); + + it('TabPaneHistoryProcessesTest03 ', function () { + expect(tabPaneHistoryProcesses.sortByColumn({ + key:'startTime', + })).toBeUndefined(); + }); + + it('TabPaneHistoryProcessesTest04 ', function () { + expect(tabPaneHistoryProcesses.sortByColumn({ + key:'alive', + })).toBeUndefined(); + }); + + it('TabPaneHistoryProcessesTest11 ', function () { + expect(tabPaneHistoryProcesses.sortByColumn({ + key:!'startTime'&&!'alive', + })).toBeUndefined(); + }); + + it('TabPaneHistoryProcessesTest04 ', function () { + expect(tabPaneHistoryProcesses.sortByColumn({ + key:'cpuTime', + })).toBeUndefined(); + }); + + it('TabPaneHistoryProcessesTest06', function () { + expect(tabPaneHistoryProcesses.timeFormat(3600001)).toBe("1 h 1 ms ") + }); + + it('TabPaneHistoryProcessesTest07', function () { + expect(tabPaneHistoryProcesses.timeFormat(60001)).toBe("1 min 1 ms ") + }); + + it('TabPaneHistoryProcessesTest08', function () { + expect(tabPaneHistoryProcesses.timeFormat(1001)).toBe("1 s 1 ms ") + }); + + it('TabPaneHistoryProcessesTest09', function () { + expect(tabPaneHistoryProcesses.timeFormat(1)).toBe("1 ms ") + }); + + it('TabPaneHistoryProcessesTest10', function () { + expect(tabPaneHistoryProcesses.timeFormat(0)).toBe("0 ms ") + }); + +}); \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/ability/TabPaneLiveProcesses.test.ts b/host/ide/test/trace/component/trace/sheet/ability/TabPaneLiveProcesses.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..3fa3b8331dd23dba7cacd822aefa0625c2eef6a9 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/ability/TabPaneLiveProcesses.test.ts @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//@ts-ignore +import {TabPaneLiveProcesses} from "../../../../../../dist/trace/component/trace/sheet/ability/TabPaneLiveProcesses.js"; +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe('TabPaneLiveProcesses Test',function (){ + let tabPaneLiveProcesses = new TabPaneLiveProcesses(); + + it('TabPaneLiveProcessesTest01 ', function () { + tabPaneLiveProcesses.queryResult.length = 1; + expect(tabPaneLiveProcesses.filterData()).toBeUndefined(); + }); + + it('TabPaneLiveProcessesTest02 ', function () { + const live={ + processId:1, + processName:"", + responsibleProcess:"", + userName:"", + cpu:"1", + threads:-1, + memory:'', + diskReads:-1, + diskWrite:-1 + } + expect(tabPaneLiveProcesses.toLiveProcessArray(live)).not.toBeUndefined(); + }); + + it('TabPaneLiveProcessesTest03 ', function () { + expect(tabPaneLiveProcesses.sortByColumn({ + key:'startTime', + })).toBeUndefined(); + }); + + it('TabPaneLiveProcessesTest07 ', function () { + expect(tabPaneLiveProcesses.sortByColumn({ + key:'cpuTime', + })).toBeUndefined(); + }); + + it('TabPaneLiveProcessesTest04 ', function () { + expect(tabPaneLiveProcesses.sortByColumn({ + key:!'startTime'|| !'cpuTime', + })).toBeUndefined(); + }); + + it('TabPaneLiveProcessesTest09 ', function () { + expect(tabPaneLiveProcesses.sortByColumn({ + key:'memory', + })).toBeUndefined(); + }); + + it('TabPaneLiveProcessesTest05', function () { + expect(tabPaneLiveProcesses.timeFormat(70000)).toBe("1 min 10 s 0 ms "); + }); + + it('TabPaneLiveProcessesTest06', function () { + expect(tabPaneLiveProcesses.timeFormat(2000)).toBe("2 s 0 ms "); + }); + + it('TabPaneLiveProcessesTest07', function () { + expect(tabPaneLiveProcesses.timeFormat(3600002)).toBe("1 h 2 ms "); + }); + + it('TabPaneLiveProcessesTest08', function () { + expect(tabPaneLiveProcesses.timeFormat(10)).toBe("10 ms "); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/ability/TabPaneMemoryAbility.test.ts b/host/ide/test/trace/component/trace/sheet/ability/TabPaneMemoryAbility.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..8cb714eb8417ad6c9af9647edea8b1441bc2a302 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/ability/TabPaneMemoryAbility.test.ts @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//@ts-ignore +import {TabPaneMemoryAbility} from "../../../../../../dist/trace/component/trace/sheet/ability/TabPaneMemoryAbility.js"; + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +describe('TabPaneMemoryAbility Test', () => { + let tabPaneMemoryAbility = new TabPaneMemoryAbility(); + let queryStartTime = sqlit.queryStartTime; + queryStartTime.mockResolvedValue([{ + start_ts: 0 + }]) + + let queryMemoryAbilityData = sqlit.getTabMemoryAbilityData; + queryMemoryAbilityData.mockResolvedValue([{ + startTime: 0, + name: "s", + value: "d,ds,f" + },{ + startTime: 10000, + name: "s", + value: "d,ds,f" + },{ + startTime: 20000, + name: "s", + value: "d,ds,f" + }]) + + + tabPaneMemoryAbility.tbl = jest.fn(() => true) + tabPaneMemoryAbility.tbl.recycleDataSource = jest.fn(() => []) + tabPaneMemoryAbility.data = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds: [], + nativeMemory: [], + cpuAbilityIds: [], + memoryAbilityIds: [], + diskAbilityIds: [], + networkAbilityIds: [], + leftNs: 0, + rightNs: 1000, + hasFps: false, + statisticsSelectData: undefined, + perfSampleIds: [], + perfCpus: [], + perfProcess: [], + perfThread: [], + perfAll: false, + systemEnergy: [0, 1, 2], + powerEnergy: [0, 1, 2], + anomalyEnergy: [0, 1, 2] + } + + it('TabPaneMemoryAbilityTest01', function () { + tabPaneMemoryAbility.queryResult.length = 1; + expect(tabPaneMemoryAbility.filterData()).toBeUndefined(); + }); + + it('TabPaneMemoryAbilityTest02', function () { + const systemMemorySummary = [{ + startTimeStr: "1", + durationStr: "1", + cached: "1", + swapTotal: "1" + }] + expect(tabPaneMemoryAbility.toMemoryAbilityArray(systemMemorySummary)).not.toBeUndefined(); + }); + + it('TabPaneMemoryAbilityTest03', function () { + expect(tabPaneMemoryAbility.sortByColumn({ + key: 'startTime' + })).toBeUndefined(); + }); + + it('TabPaneMemoryAbilityTest04', function () { + expect(tabPaneMemoryAbility.sortByColumn({ + key: !'startTime' + })).toBeUndefined(); + }); + + it('TabPaneMemoryAbilityTest05', function () { + expect(tabPaneMemoryAbility.sortByColumn({ + key: 'durationStr' + })).toBeUndefined(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/ability/TabPaneNetworkAbility.test.ts b/host/ide/test/trace/component/trace/sheet/ability/TabPaneNetworkAbility.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..97ab1a7513220adf56cb2bc8dffd2fe33db5f629 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/ability/TabPaneNetworkAbility.test.ts @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//@ts-ignore +import {TabPaneNetworkAbility} from "../../../../../../dist/trace/component/trace/sheet/ability/TabPaneNetworkAbility.js"; +import "../../../../../../dist/trace/component/trace/sheet/ability/TabPaneNetworkAbility.js"; + +window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(()=>({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), +})) + +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +describe('TabPaneNetworkAbility Test', ()=>{ + let tabPaneNetworkAbility = new TabPaneNetworkAbility(); + let tabNetworkAbilityData = sqlit.getTabNetworkAbilityData; + + tabNetworkAbilityData.mockResolvedValue([{ + startTime: 1000, + duration: 200, + dataReceived: 100.00, + dataReceivedSec: 100.00, + dataSend: 200.00, + dataSendSec: 100.00, + packetsIn: 100.00, + packetsInSec: 100.00, + packetsOut: 200.00, + packetsOutSec: 100.00 + }]) + + tabPaneNetworkAbility.data = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds: [], + nativeMemory: [], + cpuAbilityIds: [], + memoryAbilityIds: [], + diskAbilityIds: [], + networkAbilityIds: [], + leftNs: 0, + rightNs: 1000, + hasFps: false, + statisticsSelectData: undefined, + perfSampleIds: [], + perfCpus: [], + perfProcess: [], + perfThread: [], + perfAll: false, + systemEnergy: [0, 1, 2], + powerEnergy: [0, 1, 2], + anomalyEnergy: [0, 1, 2] + } + + it('TabPaneNetworkAbilityTest01',()=>{ + tabPaneNetworkAbility.queryResult.length = 1; + let queryResult = [{ + startTimeStr: "s", + durationStr: "s", + dataReceivedStr: "s", + dataReceivedSecStr: "s", + dataSendSecStr: "s", + dataSendStr: "s", + packetsIn: "s", + packetsOut: "s", + packetsOutSec: "s" + }] + tabPaneNetworkAbility.search = jest.fn(()=>"s") + tabPaneNetworkAbility.queryResult = jest.fn(()=>queryResult) + expect(tabPaneNetworkAbility.filterData()).toBeUndefined(); + }); + + it('TabPaneNetworkAbilityTest02 ', function () { + const val = { + startTimeStr:"", + durationStr:"", + dataReceivedStr:"", + dataReceivedSecStr:"", + dataSendSecStr:"", + dataSendStr:"", + packetsIn:-1, + packetsOut:-1, + packetsOutSec:-1 + } + expect(tabPaneNetworkAbility.toNetWorkAbilityArray(val)).not.toBeUndefined(); + }); + + it('TabPaneNetworkAbilityTest03 ', function () { + expect(tabPaneNetworkAbility.sortByColumn({ + key:'startTime', + })).toBeUndefined(); + }); + + it('TabPaneNetworkAbilityTest04 ', function () { + expect(tabPaneNetworkAbility.sortByColumn({ + key:!'startTime', + })).toBeUndefined(); + }); + + it('TabPaneNetworkAbilityTest05 ', function () { + expect(tabPaneNetworkAbility.sortByColumn({ + key:'dataSendSecStr', + })).toBeUndefined(); + }); + + it('TabPaneNetworkAbilityTest06 ', function () { + expect(tabPaneNetworkAbility.sortByColumn({ + key:'packetsInStr', + })).toBeUndefined(); + }); + + it('TabPaneNetworkAbilityTest07 ', function () { + expect(tabPaneNetworkAbility.sortByColumn({ + key:'packetsInSecStr', + })).toBeUndefined(); + }); + + it('TabPaneNetworkAbilityTest08 ', function () { + expect(tabPaneNetworkAbility.sortByColumn({ + key:'packetsOutStr', + })).toBeUndefined(); + }); + + it('TabPaneNetworkAbilityTest09 ', function () { + expect(tabPaneNetworkAbility.sortByColumn({ + key:'packetsOutSecStr', + })).toBeUndefined(); + }); + + it('TabPaneNetworkAbilityTest10 ', function () { + expect(tabPaneNetworkAbility.sortByColumn({ + key:'dataSendStr', + })).toBeUndefined(); + }); + + it('TabPaneNetworkAbilityTest11 ', function () { + expect(tabPaneNetworkAbility.sortByColumn({ + key:'dataReceivedSecStr', + })).toBeUndefined(); + }); + + it('TabPaneNetworkAbilityTest12 ', function () { + expect(tabPaneNetworkAbility.sortByColumn({ + key:'durationStr', + })).toBeUndefined(); + }); + + it('TabPaneNetworkAbilityTest13 ', function () { + expect(tabPaneNetworkAbility.sortByColumn({ + key:'dataReceivedStr', + })).toBeUndefined(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/cpu/TabPaneBoxChild.test.ts b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneBoxChild.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..457a3d87d8c32d68663196fb8bb0eacc7dd6046e --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneBoxChild.test.ts @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +// import { it } from "mocha" +import {TabPaneBoxChild} from "../../../../../../dist/trace/component/trace/sheet/cpu/TabPaneBoxChild.js" +import {getTabBoxChildData} from "../../../../../../src/trace/database/SqlLite"; + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + + })); + +describe('TabPaneBoxChild Test', () => { + document.body.innerHTML = `
` + let element = document.querySelector("#div") as HTMLDivElement; + let tabPaneBoxChild = new TabPaneBoxChild(); + element.appendChild(tabPaneBoxChild) + tabPaneBoxChild.loadDataInCache = true + tabPaneBoxChild.data = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds:[], + leftNs: 0, + rightNs: 0, + hasFps: false, + } + let val={ + leftNs:2, + rightNs:1, + state:"1", + processId:0, + threadId:1 + } + + it('TabPaneBoxChildTest01', function () { + expect(tabPaneBoxChild.sortByColumn({ + key: 'number', + })).toBeUndefined(); + }); + + it('TabPaneCounterTest02', function () { + expect(tabPaneBoxChild.sortByColumn({ + sort: () => { + } + })).toBeUndefined(); + }); + + it('TabPaneCounterTest03', function () { + expect(tabPaneBoxChild.initHtml()).toMatchInlineSnapshot(` +" + + + + + + + + + + + + + + + + + + + " +`); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/cpu/TabPaneContextSwitch.test.ts b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneContextSwitch.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..3896d1396a750d52b9882a4b4ce2134c407d08e1 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneContextSwitch.test.ts @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneContextSwitch} from "../../../../../../dist/trace/component/trace/sheet/cpu/TabPaneContextSwitch.js" +// @ts-ignore +import {LitTable} from "../../../../../../dist/base-ui/table/lit-table.js"; +// @ts-ignore +import {SpSystemTrace} from "../../../../../../dist/trace/component/SpSystemTrace.js"; + +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); +describe('TabPaneContextSwitch Test', () => { + document.body.innerHTML = `
` + let tab = document.querySelector('.ddd') as HTMLDivElement; + let tabPaneContextSwitch = new TabPaneContextSwitch(); + tabPaneContextSwitch.tbl = jest.fn(() => tab); + tabPaneContextSwitch.tbl.treeElement = jest.fn(() => tab); + tabPaneContextSwitch.tbl.tableElement = jest.fn(() => tab); + SpSystemTrace.SPT_DATA = [{ + process: "", + processId: 0, + thread: "", + threadId: 0, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + }, { + process: "", + processId: 1, + thread: "", + threadId: 1, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + }, { + process: "", + processId: 2, + thread: "", + threadId: 2, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + }] + + let dataArray = { + id: "", + pid: "", + title: "", + children: [], + process: "", + processId: 0, + thread: "", + threadId: 0, + state: "", + wallDuration: 0, + avgDuration: "", + count: 0, + minDuration: 0, + maxDuration: 0, + stdDuration: "", + } + + it('TabPaneContextSwitchTest01', function () { + expect(tabPaneContextSwitch).not.toBeUndefined(); + }); + + it('TabPanePTSTest02', function () { + expect(tabPaneContextSwitch.getDataBySPT(0, 0, [])).toBeUndefined() + }); + + it('TabPaneContextSwitchTest03', function () { + let mockgetProcessThreadDataByRange = sqlit.getStatesProcessThreadDataByRange + mockgetProcessThreadDataByRange.mockResolvedValue([{ + process: "process", + processId: 1, + thread: "thread", + state: "state", + threadId: 1, + dur: 1000, + end_ts: 2000, + start_ts: 2000, + cpu: 1111 + }] + ) + expect(tabPaneContextSwitch.data = dataArray).toBeTruthy(); + }); + + it('TabPaneContextSwitchTest04', function () { + expect(tabPaneContextSwitch.initHtml()).toMatchInlineSnapshot(` +" + + + + + + + + + " +`); + }); + + + it('TabPaneContextSwitchTest04', function () { + document.body.innerHTML = `` + let tabPaneContextSwitch = document.querySelector('#Switch') as TabPaneContextSwitch + expect(tabPaneContextSwitch.data).toBe(tabPaneContextSwitch.dataArray); + }); + + it('TabPaneContextSwitchTest05', function () { + document.body.innerHTML = `` + let tabPaneContextSwitch = document.querySelector('#Switch') as TabPaneContextSwitch + tabPaneContextSwitch.loadDataInCache = false; + expect(tabPaneContextSwitch.data).toBe(tabPaneContextSwitch.dataArray); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/cpu/TabPaneCounterSample.test.ts b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneCounterSample.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..1e6c1dc1674f35ebb8be12baec81aaa952c2ab9a --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneCounterSample.test.ts @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneCounterSample} from "../../../../../../dist/trace/component/trace/sheet/cpu/TabPaneCounterSample.js" +// @ts-ignore +import {SpSystemTrace} from "../../../../../../dist/trace/component/SpSystemTrace.js"; + +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe('TabPaneCounterSample Test', () => { + document.body.innerHTML = `
` + let tab = document.querySelector('.ddd') as HTMLDivElement; + let tabPaneCounterSample = new TabPaneCounterSample(); + tabPaneCounterSample.tbl = jest.fn(() => tab); + tabPaneCounterSample.tbl.treeElement = jest.fn(() => tab); + tabPaneCounterSample.tbl.tableElement = jest.fn(() => tab); + SpSystemTrace.SPT_DATA = [{ + process: "", + processId: 0, + thread: "", + threadId: 0, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + }, { + process: "", + processId: 1, + thread: "", + threadId: 1, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + }, { + process: "", + processId: 2, + thread: "", + threadId: 2, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + }] + + let dataArray = { + id: "", + pid: "", + title: "", + children: [], + process: "", + processId: 0, + thread: "", + threadId: 0, + state: "", + wallDuration: 0, + avgDuration: "", + count: 0, + minDuration: 0, + maxDuration: 0, + stdDuration: "", + cpuStateFilterIds: [1,2,3] + } + + it('TabPaneCounterSampleTest01', function () { + let getTabPaneCounterSampleData = sqlit.getTabPaneCounterSampleData + getTabPaneCounterSampleData.mockResolvedValue([{ + value: "process", + filterId: 1, + ts: 1000, + cpu: "cpu" + }] + ) + tabPaneCounterSample.tbl.recycleDataSource = jest.fn(() => dataArray) + expect(tabPaneCounterSample.data = dataArray).toBeTruthy(); + + }); + + it('TabPaneCounterSampleTest02', function () { + expect(tabPaneCounterSample.initElements()).toBeUndefined(); + }); + + it('TabPaneCounterSampleTest03', function () { + expect(tabPaneCounterSample.initHtml()).toMatchInlineSnapshot(` +" + + + + + + + + + + +
+ " +`); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/cpu/TabPaneCpuByProcess.test.ts b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneCpuByProcess.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..d7ddb9540150e5825a64238238e9826cf44ec187 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneCpuByProcess.test.ts @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneCpuByProcess} from "../../../../../../dist/trace/component/trace/sheet/cpu/TabPaneCpuByProcess.js" + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); +describe('TabPaneCpuByProcess Test', () => { + let tabPaneCpuByProcess = new TabPaneCpuByProcess(); + // tabPaneCpuByProcess.sortByColumn = jest.fn(()=> true) + + it('TabPaneCpuByProcessTest01', function () { + expect(tabPaneCpuByProcess.sortByColumn({ + key: 'number', + })).toBeUndefined(); + }); + + it('TabPaneCpuByProcessTest05', function () { + expect(tabPaneCpuByProcess.sortByColumn({ + sort: () => { + } + })).toBeUndefined(); + }); + + it('TabPaneCpuByProcessTest04', function () { + expect(tabPaneCpuByProcess.sortByColumn({ + key: 'pid'||'wallDuration'||'avgDuration'||'occurrences', + })).toBeUndefined(); + }); + + it('TabPaneCpuByProcessTest04', function () { + expect(tabPaneCpuByProcess.initHtml()).toMatchInlineSnapshot(` +" + + + + + + + + + + + + + + + " +`) + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/cpu/TabPaneCpuByThread.test.ts b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneCpuByThread.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..d1cd9696efbb1e45cb9cf80394c0c14e556cd9d7 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneCpuByThread.test.ts @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneCpuByThread} from "../../../../../../dist/trace/component/trace/sheet/cpu/TabPaneCpuByThread.js" + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +describe('TabPaneCpuByThread Test', () => { + let tabPaneCpuByThread = new TabPaneCpuByThread(); + + it('TabPaneCpuByThreadTest01', function () { + expect(tabPaneCpuByThread.sortByColumn({ + key: 'number', + sort: () => { + } + })).toBeUndefined(); + }); + + it('TabPaneCpuByThreadTest02', function () { + expect(tabPaneCpuByThread.sortByColumn({ + key: 'pid'||'wallDuration'||'avgDuration'||'occurrences', + })).toBeUndefined(); + }); + + it('TabPaneCpuByThreadTest03', function () { + let mockgetTabCpuByThread = sqlit.getTabCpuByThread + mockgetTabCpuByThread.mockResolvedValue([{process : "test", + wallDuration: 10, + occurrences: 10, + thread:"" + }, + {process : "test2", + wallDuration: 11, + occurrences: 11, + thread:"" + }] + ) + let a = {rightNs: 1, cpus: [11, 12, 13]} + expect(tabPaneCpuByThread.data = a).toBeTruthy(); + }); + + it('TabPaneCpuByThreadTest04', function () { + let mockgetTabCpuByThread = sqlit.getTabCpuByThread + mockgetTabCpuByThread.mockResolvedValue([]) + let a = {rightNs: 1, cpus: [11, 12, 13]} + expect(tabPaneCpuByThread.data = a).toBeTruthy(); + }); + + it('TabPaneCpuByThreadTest05', function () { + expect(tabPaneCpuByThread.initHtml()).toMatchInlineSnapshot(` +" + + + + + + + + + + + + + + + + + + + " +`); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneCpuUsage.test.ts b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneCpuUsage.test.ts similarity index 35% rename from host/ide/test/trace/component/trace/sheet/TabPaneCpuUsage.test.ts rename to host/ide/test/trace/component/trace/sheet/cpu/TabPaneCpuUsage.test.ts index d70e77feda656ac03d080bf3159592143e2bf2a5..39d399af66d987d3defa9614adde9ee3a98b45db 100644 --- a/host/ide/test/trace/component/trace/sheet/TabPaneCpuUsage.test.ts +++ b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneCpuUsage.test.ts @@ -14,11 +14,65 @@ */ // @ts-ignore -import {TabPaneCpuUsage} from "../../../../../dist/trace/component/trace/sheet/TabPaneCpuUsage.js" +import {TabPaneCpuUsage} from "../../../../../../dist/trace/component/trace/sheet/cpu/TabPaneCpuUsage.js" +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + describe('TabPaneCpuUsage Test', () => { let tabPaneCpuUsage = new TabPaneCpuUsage(); + let mockGetTabCpuUsage = sqlit.getTabCpuUsage + let mockGetTabCpuFreq = sqlit.getTabCpuFreq + + mockGetTabCpuUsage.mockResolvedValue([]) + mockGetTabCpuFreq.mockResolvedValue([]) + + let selectionData = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds: [], + nativeMemory: [], + cpuAbilityIds: [], + memoryAbilityIds: [], + diskAbilityIds: [], + networkAbilityIds: [], + leftNs: 0, + rightNs: 0, + hasFps: false, + statisticsSelectData: undefined, + perfSampleIds: [], + perfCpus: [], + perfProcess: [], + perfThread: [], + perfAll: false, + } + + it('TabPaneCpuUsageTest01', function () { + expect(tabPaneCpuUsage.sortTable([[1,2,3,9,6,4],[5,2,1,4,9,6]],0,true)).toBeUndefined(); + }); + + it('TabPaneCpuUsageTest08', function () { + expect(tabPaneCpuUsage.sortTable([[1,2,3,9,6,4],[5,2,1,4,9,6]],0,false)).toBeUndefined(); + }); + + it('TabPaneCpuUsageTest09', function () { + expect(tabPaneCpuUsage.sortTable([[1,2,3,9,6,4],[5,2,1,4,9,6]],2,true)).toBeUndefined(); + }); + + it('TabPaneCpuUsageTest10', function () { + expect(tabPaneCpuUsage.sortTable([[1,2,3,9,6,4],[5,2,1,4,9,6]],2,false)).toBeUndefined(); + }); + it('TabPaneCpuUsageTest02', function () { expect(tabPaneCpuUsage.sortTable([[1,2,3,9,6,4],[5,2,1,4,9,6]],1,true)).toBeUndefined(); }); @@ -70,4 +124,43 @@ describe('TabPaneCpuUsage Test', () => { }]) expect(result.get(0).length).toBe(1); }); + + it('TabPaneCurrentSelectionTest07',function(){ + expect(tabPaneCpuUsage.initHtml()).toMatchInlineSnapshot(` +" + + + + + + + + + + + + + + + + + + + + + " +`); + }); + + it('TabPaneCpuUsageTest11', function () { + document.body.innerHTML = `
` + let tabPaneCpuUsage = document.querySelector("#CpuUsage") as TabPaneCpuUsage; + expect(tabPaneCpuUsage.sortFreq).toBe(undefined); + }); }) diff --git a/host/ide/test/trace/component/trace/sheet/cpu/TabPaneFrequencySample.test.ts b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneFrequencySample.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..005f58468210af03370890eff62708e7c2a086ce --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneFrequencySample.test.ts @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneFrequencySample} from "../../../../../../dist/trace/component/trace/sheet/cpu/TabPaneFrequencySample.js" +// @ts-ignore +import {SpSystemTrace} from "../../../../../../dist/trace/component/SpSystemTrace.js"; + +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe('TabPaneFrequencySample Test', () => { + document.body.innerHTML = `
` + let tab = document.querySelector('.ddd') as HTMLDivElement; + let tabPaneFreSample = new TabPaneFrequencySample(); + tabPaneFreSample.tbl = jest.fn(() => tab); + tabPaneFreSample.tbl.treeElement = jest.fn(() => tab); + tabPaneFreSample.tbl.tableElement = jest.fn(() => tab); + SpSystemTrace.SPT_DATA = [{ + process: "", + processId: 0, + thread: "", + threadId: 0, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + }, { + process: "", + processId: 1, + thread: "", + threadId: 1, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + }, { + process: "", + processId: 2, + thread: "", + threadId: 2, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + }] + + let dataArray = { + id: "", + pid: "", + title: "", + children: [], + process: "", + processId: 0, + thread: "", + threadId: 0, + state: "", + wallDuration: 0, + avgDuration: "", + count: 0, + minDuration: 0, + maxDuration: 0, + stdDuration: "", + cpuFreqFilterIds: [1,2,3] + } + + it('TabPaneCounterSampleTest01', function () { + let getTabPaneFrequencySampleData = sqlit.getTabPaneFrequencySampleData + getTabPaneFrequencySampleData.mockResolvedValue([{ + value: "process", + filterId: 1, + ts: 1000, + cpu: "cpu" + }] + ) + tabPaneFreSample.tbl.recycleDataSource = jest.fn(() => dataArray) + expect(tabPaneFreSample.data = dataArray).toBeTruthy(); + + }); + + it('TabPaneCounterSampleTest02', function () { + expect(tabPaneFreSample.initElements()).toBeUndefined(); + }); + + it('TabPaneCounterSampleTest03', function () { + expect(tabPaneFreSample.initHtml()).toMatchInlineSnapshot(` +" + + + + + + + + + + +
+ " +`); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/cpu/TabPanePTS.test.ts b/host/ide/test/trace/component/trace/sheet/cpu/TabPanePTS.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..2c612cd61f35e6f2b6b4482de051788938380894 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/cpu/TabPanePTS.test.ts @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPanePTS} from "../../../../../../dist/trace/component/trace/sheet/cpu/TabPanePTS.js" +// @ts-ignore +import {SpSystemTrace} from "../../../../../../dist/trace/component/SpSystemTrace.js"; +// @ts-ignore +import {LitTable} from "../../../../../../dist/base-ui/table/lit-table.js"; + +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), +})); +describe('TabPanePTS Test', () => { + document.body.innerHTML = `` + let tab = document.querySelector('#tb-states') as LitTable; + + document.body.innerHTML = `
` + let tabPane = document.querySelector('.pts') as TabPanePTS; + let tabPanePTS = new TabPanePTS(); + + tabPanePTS.tbl = jest.fn(() => tab) + + SpSystemTrace.SPT_DATA = [{ + process: "", + processId: 0, + thread: "", + threadId: 0, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + }, { + process: "", + processId: 1, + thread: "", + threadId: 1, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + }, { + process: "", + processId: 2, + thread: "", + threadId: 2, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + }] + + let dataArray = [{ + id: "", + pid: "", + title: "", + children: [], + process: "", + processId: 0, + thread: "", + threadId: 0, + state: "", + wallDuration: 0, + avgDuration: "", + count: 0, + minDuration: 0, + maxDuration: 0, + stdDuration: "", + }] + + it('TabPanePTSTest01', function () { + expect(tabPane.getDataBySPT(0, 0, [])).toBeUndefined() + }); + + it('TabPanePTSTest02', function () { + let source = [ + { + process: "", + processId: 10, + thread: "", + threadId: 10, + state: "", + dur: 1000, + start_ts: 100_0000, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + } + ] + expect(tabPane.getDataBySPT(10, 100_000, source)).toBeUndefined() + }); + + it('TabPaneSPTTest03', function () { + let mockgetProcessThreadDataByRange = sqlit.getStatesProcessThreadDataByRange + mockgetProcessThreadDataByRange.mockResolvedValue([{ + process: "process", + processId: 1, + thread: "thread", + state: "state", + threadId: 1, + dur: 1000, + end_ts: 2000, + start_ts: 2000, + cpu: 1111 + }] + ) + tabPanePTS.tbl.recycleDataSource = jest.fn(() => dataArray) + expect(tabPanePTS.data = dataArray).toBeTruthy(); + }); + + it('TabPanePTSTest04', function () { + expect(tabPanePTS.initHtml()).toMatchInlineSnapshot(` +" + + + + + + + + + + + + + + + + + " +`); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/cpu/TabPaneSPT.test.ts b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneSPT.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..4a4107021d82738c49c2f3d9c9988eccb43977d8 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneSPT.test.ts @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneSPT} from "../../../../../../dist/trace/component/trace/sheet/cpu/TabPaneSPT.js" +// @ts-ignore +import {SpSystemTrace} from "../../../../../../dist/trace/component/SpSystemTrace.js"; +// @ts-ignore +import {LitTable} from "../../../../../../dist/base-ui/table/lit-table.js"; + + +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe('TabPaneSPT Test', () => { + document.body.innerHTML = `` + let tab = document.querySelector('#tb-states') as LitTable; + + document.body.innerHTML = `
` + let tabPane = document.querySelector('.SPT') as TabPaneSPT; + let tabPaneSPT = new TabPaneSPT(); + tabPaneSPT.tbl = jest.fn(() => tab) + SpSystemTrace.SPT_DATA = [{ + process: "", + processId: 0, + thread: "", + threadId: 0, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + },{ + process: "", + processId: 1, + thread: "", + threadId: 1, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + },{ + process: "", + processId: 2, + thread: "", + threadId: 2, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + }] + + let dataList = [{ + id: "", + pid: "", + title: "", + children: [], + process: "", + processId: 0, + thread: "", + threadId: 0, + state: "", + wallDuration: 0, + avgDuration: "", + count: 0, + minDuration: 0, + maxDuration: 0, + stdDuration: "", + }] + + let dataArray = [{ + id: "", + pid: "", + title: "", + children: [], + process: "", + processId: 0, + thread: "", + threadId: 0, + state: "", + wallDuration: 0, + avgDuration: "", + count: 0, + minDuration: 0, + maxDuration: 0, + stdDuration: "", + }] + + it('TabPaneSPTTest01', function () { + expect(tabPane.getDataBySPT(0,0,[])).toBeUndefined(); + }); + + it('TabPaneSPTTest02', function () { + let source = [ + { + process: "", + processId: 10, + thread: "", + threadId: 10, + state: "", + dur: 1000, + start_ts: 100_0000, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + } + ] + expect(tabPane.getDataBySPT(10,100_000,source)).toBeUndefined(); + }); + + it('TabPaneSPTTest03', function () { + let mockgetProcessThreadDataByRange = sqlit.getStatesProcessThreadDataByRange + mockgetProcessThreadDataByRange.mockResolvedValue([{ + process: "process", + processId: 1, + thread: "thread", + state: "state", + threadId: 1, + dur: 1000, + end_ts: 2000, + start_ts: 2000, + cpu:1111 + }] + ) + tabPaneSPT.tbl.recycleDataSource = jest.fn(() => dataList) + + expect(tabPaneSPT.data = dataList).toBeTruthy(); + }); + + it('TabPaneSPTTest04', function () { + expect(tabPaneSPT.initHtml()).toMatchInlineSnapshot(` +" + + + + + + + + + + + + + + + + + " +`); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/cpu/TabPaneThreadSwitch.test.ts b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneThreadSwitch.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..2cb015d16109da36c5fe95041b507e438b9926ec --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/cpu/TabPaneThreadSwitch.test.ts @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneThreadSwitch} from "../../../../../../dist/trace/component/trace/sheet/cpu/TabPaneThreadSwitch.js" +// @ts-ignore +import {LitTable} from "../../../../../../dist/base-ui/table/lit-table.js"; +// @ts-ignore +import {SpSystemTrace} from "../../../../../../dist/trace/component/SpSystemTrace.js"; + +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe('TabPaneContextSwitch Test', () => { + document.body.innerHTML = `
` + let tab = document.querySelector('.ddd') as HTMLDivElement; + let tabPaneThreadSwitch = new TabPaneThreadSwitch(); + tabPaneThreadSwitch.tbl = jest.fn(() => tab); + tabPaneThreadSwitch.tbl.treeElement = jest.fn(() => tab); + tabPaneThreadSwitch.tbl.tableElement = jest.fn(() => tab); + SpSystemTrace.SPT_DATA = [{ + process: "", + processId: 0, + thread: "", + threadId: 0, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + }, { + process: "", + processId: 1, + thread: "", + threadId: 1, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + }, { + process: "", + processId: 2, + thread: "", + threadId: 2, + state: '', + dur: 0, + start_ts: 0, + end_ts: 0, + cpu: 0, + priority: "-", + note: "-", + }] + + let dataArray = { + id: "", + pid: "", + title: "", + children: [], + process: "", + processId: 0, + thread: "", + threadId: 0, + state: "", + wallDuration: 0, + avgDuration: "", + count: 0, + minDuration: 0, + maxDuration: 0, + stdDuration: "", + } + + it('TabPaneThreadSwitchTest03', function () { + expect(tabPaneThreadSwitch.getDataBySPT(0, 0, [])).toBeUndefined(); + }); + + it('TabPaneThreadSwitchTest04', function () { + let mockgetProcessThreadDataByRange = sqlit.getStatesProcessThreadDataByRange + mockgetProcessThreadDataByRange.mockResolvedValue([{ + process: "process", + processId: 1, + thread: "thread", + state: "state", + threadId: 1, + dur: 1000, + end_ts: 2000, + start_ts: 2000, + cpu: 1111 + }] + ) + tabPaneThreadSwitch.tbl.recycleDataSource = jest.fn(() => dataArray) + expect(tabPaneThreadSwitch.data = dataArray).toBeTruthy(); + + }); + + it('TabPaneThreadSwitchTest05', function () { + expect(tabPaneThreadSwitch.initElements()).toBeUndefined(); + }); + + it('TabPaneThreadSwitchTest06', function () { + expect(tabPaneThreadSwitch.initHtml()).toMatchInlineSnapshot(` +" + + + + + + + + + " +`); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/energy/TabPaneEnergyAnomaly.test.ts b/host/ide/test/trace/component/trace/sheet/energy/TabPaneEnergyAnomaly.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..e0f16ee9a70dac260f67fb028771d868f6bfedab --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/energy/TabPaneEnergyAnomaly.test.ts @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneEnergyAnomaly} from "../../../../../../dist/trace/component/trace/sheet/energy/TabPaneEnergyAnomaly.js" +import "../../../../../../dist/trace/component/trace/sheet/energy/TabPaneEnergyAnomaly.js" + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +describe('TabPanePowerBattery Test', () => { + it('TabPaneEnergyAnomalyTest01', function () { + let tabPaneEnergyAnomaly = new TabPaneEnergyAnomaly(); + let MockAnomalyDetailedData = sqlit.queryAnomalyDetailedData; + let battery = [ + { + ts: 11611696002, + eventName: "ANOMALY_SCREEN_OFF_ENERGY", + appKey: "BATTERY_DRAIN", + Value: "10" + }, { + ts: 11611696002, + eventName: "ANOMALY_SCREEN_OFF_ENERGY", + appKey: "BATTERY_GAS_GUAGE", + Value: "980" + }, { + ts: 15612568649, + eventName: "ANOMALY_RUNNINGLOCK", + appKey: "APPNAME", + Value: "com.example.powerhap" + }, { + ts: 15612568649, + eventName: "ANOMALY_RUNNINGLOCK", + appKey: "COUNT", + Value: "1" + }, { + ts: 17611804002, + eventName: "ANORMALY_APP_ENERGY", + appKey: "APPNAME", + Value: "*dpm_others*,*dpm_rom*,/system/bin/hilogd," + + "/system/bin/render_service," + + "/system/bin/wifi_hal_service," + + "bluetooth_servi,com.example.baseanimation," + + "com.example.ohos_location_js," + + "com.ohos.launcher,com.ohos.settings," + + "hidumper_servic,hwc_host," + + "kernel_kworker,softbus_server" + }, { + ts: 17611804002, + eventName: "ANORMALY_APP_ENERGY", + appKey: "BGENERGY", + Value: "11726,79745,6209,249329,1680,8694,3061,457,402,17064,4087,16403,32965,2895" + }] + MockAnomalyDetailedData.mockResolvedValue(battery) + let tabPaneAnomalyDetailedData = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds: [], + nativeMemory: [], + cpuAbilityIds: [], + memoryAbilityIds: [], + diskAbilityIds: [], + networkAbilityIds: [], + leftNs: 0, + rightNs: 1000, + hasFps: false, + statisticsSelectData: undefined, + perfSampleIds: [], + perfCpus: [], + perfProcess: [], + perfThread: [], + perfAll: false, + systemEnergy: [0, 1, 2], + powerEnergy: [0, 1, 2], + anomalyEnergy: [0, 1, 2] + } + + tabPaneEnergyAnomaly.data = tabPaneAnomalyDetailedData + }) + + + it('TabPaneEnergyAnomalyTest02', function () { + let tabPaneEnergyAnomaly = new TabPaneEnergyAnomaly(); + expect(tabPaneEnergyAnomaly.initHtml()).toMatchInlineSnapshot(` +" + +
+
+

+
+
+
+ + + + + + +
+
+
+ " +`); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/energy/TabPanePowerBattery.test.ts b/host/ide/test/trace/component/trace/sheet/energy/TabPanePowerBattery.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..c923479366757d28dc3acca305a90bfa14b8ad14 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/energy/TabPanePowerBattery.test.ts @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPanePowerBattery} from "../../../../../../dist/trace/component/trace/sheet/energy/TabPanePowerBattery.js" +import "../../../../../../dist/trace/component/trace/sheet/energy/TabPanePowerBattery.js" +// @ts-ignore +import {LitTable} from "../../../../../../dist/base-ui/table/lit-table.js"; + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +describe('TabPanePowerBattery Test', () => { + it('TabPanePowerBatteryTest01', function () { + document.body.innerHTML= `` + let litTable = document.querySelector("#tb-power-battery-energy") as LitTable + let tabPanePowerBattery = new TabPanePowerBattery(); + tabPanePowerBattery.tbl = jest.fn(() => litTable) + let MockPowerBatteryData = sqlit.getTabPowerBatteryData; + let battery = [ + { + ts: 1000, + eventName: "POWER_IDE_BATTERY", + appKey: "appname", + eventValue: "POWER_IDE,POWER_IDE,POWER_IDE,POWER_IDE" + }, { + ts: 1000, + eventName: "POWER_IDE_BATTERY", + appKey: "appname", + eventValue: "POWER_IDE,POWER_IDE,POWER_IDE,POWER_IDE" + }] + MockPowerBatteryData.mockResolvedValue(battery) + let tabPanePowerBatteryData = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds: [], + nativeMemory: [], + cpuAbilityIds: [], + memoryAbilityIds: [], + diskAbilityIds: [], + networkAbilityIds: [], + leftNs: 0, + rightNs: 1000, + hasFps: false, + statisticsSelectData: undefined, + perfSampleIds: [], + perfCpus: [], + perfProcess: [], + perfThread: [], + perfAll: false, + systemEnergy: [0, 1, 2], + powerEnergy: [0, 1, 2], + anomalyEnergy: [0, 1, 2] + } + tabPanePowerBattery.tbl.recycleDataSource = jest.fn(() => tabPanePowerBatteryData) + tabPanePowerBattery.data = tabPanePowerBatteryData + }) + + + it('TabPanePowerBatteryTest02', function () { + let tabPanePowerBattery = new TabPanePowerBattery(); + expect(tabPanePowerBattery.initHtml()).toMatchInlineSnapshot(` +" + +
+
+
+ + + + +
+
+
+ " +`); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/energy/TabPanePowerDetails.test.ts b/host/ide/test/trace/component/trace/sheet/energy/TabPanePowerDetails.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..c8318264a1431ef447dac5bcc5f77945324ba92b --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/energy/TabPanePowerDetails.test.ts @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPanePowerDetails} from "../../../../../../dist/trace/component/trace/sheet/energy/TabPanePowerDetails.js" +import "../../../../../../dist/trace/component/trace/sheet/energy/TabPanePowerDetails.js" + +// @ts-ignore +import {LitTable} from "../../../../../../dist/base-ui/table/lit-table.js"; + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js"); +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +describe('TabPanePowerDetails Test', () => { + document.body.innerHTML= `` + let litTable = document.querySelector("#tb-power-details-energy") as LitTable + it('TabPanePowerDetailsTest01', function () { + let tabPanePowerDetails = new TabPanePowerDetails(); + tabPanePowerDetails.tbl = jest.fn(() => litTable) + let MockPowerDetailsData = sqlit.getTabPowerDetailsData + let detail = [ + { + ts: 5999127353, + eventName: "POWER_IDE_AUDIO", + appKey: "APPNAME", + eventValue: "com.example.himusicdemo,com.example.himusicdemo_js,com.example.himusicdemo_app" + }, { + ts: 5999127353, + eventName: "POWER_IDE_AUDIO", + appKey: "BACKGROUND_DURATION", + eventValue: "524,854,612", + }, { + ts: 5999127353, + eventName: "POWER_IDE_BLUETOOTH", + appKey: "APPNAME", + eventValue: "com.ohos.settings,bt_switch,bt_switch_js,bt_switch_app" + }, { + ts: 5999127353, + eventName: "POWER_IDE_BLUETOOTH", + appKey: "BACKGROUND_DURATION", + eventValue: "325,124,51,52" + }, { + ts: 5999127353, + eventName: "POWER_IDE_CAMERA", + appKey: "APPNAME", + eventValue: "com.ohos.camera,com.ohos.camera_app,com.ohos.camera_js,com.ohos.camera_ts" + }, { + ts: 5999127353, + eventName: "POWER_IDE_CAMERA", + appKey: "BACKGROUND_DURATION", + eventValue: "356,325,854,365" + } + ] + MockPowerDetailsData.mockResolvedValue(detail) + let list = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds: [], + nativeMemory: [], + cpuAbilityIds: [], + memoryAbilityIds: [], + diskAbilityIds: [], + networkAbilityIds: [], + leftNs: 0, + rightNs: 1000, + hasFps: false, + statisticsSelectData: undefined, + perfSampleIds: [], + perfCpus: [], + perfProcess: [], + perfThread: [], + perfAll: false, + systemEnergy: [0, 1, 2], + powerEnergy: [0, 1, 2], + anomalyEnergy: [0, 1, 2] + } + tabPanePowerDetails.tbl.recycleDataSource = jest.fn(() => list) + tabPanePowerDetails.data = list + expect(tabPanePowerDetails.data).toBeUndefined() + }) + + it('TabPanePowerDetailsTest02', function () { + let tabPanePowerDetails = new TabPanePowerDetails(); + expect(tabPanePowerDetails.initHtml()).toMatchInlineSnapshot(` +" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + " +`); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/energy/TabPaneSystemDetails.test.ts b/host/ide/test/trace/component/trace/sheet/energy/TabPaneSystemDetails.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..e50ba367f9aa90a121aee9f9742f2712d5618cba --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/energy/TabPaneSystemDetails.test.ts @@ -0,0 +1,432 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneSystemDetails} from "../../../../../../dist/trace/component/trace/sheet/energy/TabPaneSystemDetails.js" +import "../../../../../../dist/trace/component/trace/sheet/energy/TabPaneSystemDetails.js" + +import {querySysLocationDetailsData, querySysLockDetailsData} from "../../../../../../src/trace/database/SqlLite.js"; +// @ts-ignore +import {SpHiSysEventChart} from "../../../../../../dist/trace/component/chart/SpHiSysEventChart.js"; +import "../../../../../../dist/trace/component/chart/SpHiSysEventChart.js"; + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +describe('TabPanePowerBattery Test', () => { + it('TabPaneSystemDetailsTest01', function () { + let tabPaneSystemDetails = new TabPaneSystemDetails(); + tabPaneSystemDetails.tbl = jest.fn(()=>true) + tabPaneSystemDetails.detailsTbl = jest.fn(() => true) + tabPaneSystemDetails.tbl!.recycleDataSource = jest.fn(() => []) + tabPaneSystemDetails.detailsTbl!.recycleDataSource = jest.fn(() => []) + let MockquerySystemWorkData = sqlit.querySystemWorkData; + SpHiSysEventChart.app_name = "111" + + let querySystemWorkData = [ + { + ts: 0, + eventName: "WORK_ADD", + appKey: "workid", + appValue: "1" + }, { + ts: 1005938319, + eventName: "WORK_ADD", + appKey: "name", + appValue: "nnnn" + },{ + ts: 3005938319, + eventName: "WORK_START", + appKey: "workid", + appValue: "1" + },{ + ts: 3005938319, + eventName: "WORK_START", + appKey: "name", + appValue: "nnnn" + }, { + ts: 5005938319, + eventName: "WORK_STOP", + appKey: "workid", + appValue: "1" + }, { + ts: 5005938319, + eventName: "WORK_STOP", + appKey: "name", + appValue: "nnnn" + }] + MockquerySystemWorkData.mockResolvedValue(querySystemWorkData); + + let MockLockData = sqlit.querySysLockDetailsData; + let lockDetails = [ + { + ts: 1005938319, + eventName: "POWER_RUNNINGLOCK", + appKey: "tag", + appValue: "DUBAI_TAG_RUNNINGLOCK_ADD" + }, { + ts: 1005938319, + eventName: "POWER_RUNNINGLOCK", + appKey: "message", + appValue: "token=123" + }, { + ts: 3005933657, + eventName: "POWER_RUNNINGLOCK", + appKey: "tag", + appValue: "DUBAI_TAG_RUNNINGLOCK_REMOVE" + }, { + ts: 3005933657, + eventName: "POWER_RUNNINGLOCK", + appKey: "message", + appValue: "token=123" + }] + MockLockData.mockResolvedValue(lockDetails) + + let MockLocationData = sqlit.querySysLocationDetailsData; + let locationDetails = [ + { + ts: 1005938319, + eventName: "GNSS_STATE", + appKey: "state", + appValue: "start" + }, { + ts: 1005938319, + eventName: "GNSS_STATE", + appKey: "pid", + appValue: "11" + }, + { + ts: 3005933657, + eventName: "GNSS_STATE", + appKey: "state", + appValue: "stop" + }, { + ts: 3005933657, + eventName: "GNSS_STATE", + appKey: "pid", + appValue: "11" + }] + MockLocationData.mockResolvedValue(locationDetails) + + let tabPaneSystemDetailsData = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds: [], + nativeMemory: [], + cpuAbilityIds: [], + memoryAbilityIds: [], + diskAbilityIds: [], + networkAbilityIds: [], + leftNs: 0, + rightNs: 300000000000, + hasFps: false, + statisticsSelectData: undefined, + perfSampleIds: [], + perfCpus: [], + perfProcess: [], + perfThread: [], + perfAll: false, + systemEnergy: [0, 1, 2], + powerEnergy: [0, 1, 2], + anomalyEnergy: [0, 1, 2] + } + + tabPaneSystemDetails.data = tabPaneSystemDetailsData + expect(tabPaneSystemDetails.data).toBeUndefined() + }) + + it('TabPaneSystemDetailsTest02', function () { + let tabPaneSystem = new TabPaneSystemDetails(); + tabPaneSystem.tbl = jest.fn(()=>true) + tabPaneSystem.detailsTbl = jest.fn(() => true) + tabPaneSystem.tbl!.recycleDataSource = jest.fn(() => []) + tabPaneSystem.detailsTbl!.recycleDataSource = jest.fn(() => []) + let MockSystemWorkData = sqlit.querySystemWorkData; + MockSystemWorkData.mockResolvedValue([]) + let MockSystemLockData = sqlit.querySysLockDetailsData; + MockSystemLockData.mockResolvedValue([]) + let MockSystemLocationData = sqlit.querySysLocationDetailsData; + MockSystemLocationData.mockResolvedValue([]) + let tabPaneSystemDetailsData = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds: [], + nativeMemory: [], + cpuAbilityIds: [], + memoryAbilityIds: [], + diskAbilityIds: [], + networkAbilityIds: [], + leftNs: 0, + rightNs: 1000, + hasFps: false, + statisticsSelectData: undefined, + perfSampleIds: [], + perfCpus: [], + perfProcess: [], + perfThread: [], + perfAll: false, + systemEnergy: [0, 1, 2], + powerEnergy: [0, 1, 2], + anomalyEnergy: [0, 1, 2] + } + + tabPaneSystem.data = tabPaneSystemDetailsData + expect(tabPaneSystem.data).toBeUndefined() + }) + + it('TabPaneSystemDetailsTest03', function () { + let tabPaneSystemDetails = new TabPaneSystemDetails(); + tabPaneSystemDetails.tbl = jest.fn(()=>true) + tabPaneSystemDetails.detailsTbl = jest.fn(() => true) + tabPaneSystemDetails.tbl!.recycleDataSource = jest.fn(() => []) + tabPaneSystemDetails.detailsTbl!.recycleDataSource = jest.fn(() => []) + let data = { + ts: 0, + eventName: "Event Name", + type: "type", + pid: 0, + uid: 0, + state: 0, + workId: "workId", + name: "name", + interval: 0, + level: 0, + tag: "tag:", + message: "message", + log_level: "log_level", + } + + expect(tabPaneSystemDetails.convertData(data)).toBeUndefined() + }) + + it('TabPaneSystemDetailsTest04', function () { + let tabPaneSystemDetails = new TabPaneSystemDetails(); + tabPaneSystemDetails.tbl = jest.fn(()=>true) + tabPaneSystemDetails.detailsTbl = jest.fn(() => true) + tabPaneSystemDetails.tbl!.recycleDataSource = jest.fn(() => []) + tabPaneSystemDetails.detailsTbl!.recycleDataSource = jest.fn(() => []) + let data = { + ts: 0, + eventName: "GNSS_STATE", + type: "type", + pid: 0, + uid: 0, + state: 0, + workId: "workId", + name: "name", + interval: 0, + level: 0, + tag: "tag:", + message: "message", + log_level: "log_level", + } + + expect(tabPaneSystemDetails.convertData(data)).toBeUndefined() + }) + + it('TabPaneSystemDetailsTest05', function () { + let tabPaneSystemDetails = new TabPaneSystemDetails(); + tabPaneSystemDetails.tbl = jest.fn(()=>true) + tabPaneSystemDetails.detailsTbl = jest.fn(() => true) + tabPaneSystemDetails.tbl!.recycleDataSource = jest.fn(() => []) + tabPaneSystemDetails.detailsTbl!.recycleDataSource = jest.fn(() => []) + let data = { + ts: 0, + eventName: "POWER_RUNNINGLOCK", + type: "type", + pid: 0, + uid: 0, + state: 0, + workId: "workId", + name: "name", + interval: 0, + level: 0, + tag: "tag:", + message: "message", + log_level: "log_level", + } + expect(tabPaneSystemDetails.convertData(data)).toBeUndefined() + }) + + it('TabPaneSystemDetailsTest06', function () { + let tabPaneSystemDetails = new TabPaneSystemDetails(); + tabPaneSystemDetails.tbl = jest.fn(()=>true) + tabPaneSystemDetails.detailsTbl = jest.fn(() => true) + tabPaneSystemDetails.tbl!.recycleDataSource = jest.fn(() => []) + tabPaneSystemDetails.detailsTbl!.recycleDataSource = jest.fn(() => []) + let data = { + ts: 0, + eventName: "POWER", + type: "type", + pid: 0, + uid: 0, + state: 0, + workId: "workId", + name: "name", + interval: 0, + level: 0, + tag: "tag:", + message: "message", + log_level: "log_level", + } + + expect(tabPaneSystemDetails.convertData(data)).toBeUndefined() + }) + + it('TabPaneSystemDetailsTest08', function () { + let tabPaneSystemDetails = new TabPaneSystemDetails(); + let cc = [ + { + ts: -14000, + workId: 44, + name: SpHiSysEventChart.app_name, + eventName: "WORK_ADD" + }, { + ts: 10000, + workId: 11, + name: SpHiSysEventChart.app_name, + eventName: "WORK_START" + }, { + ts: 12000, + workId: 22, + name: SpHiSysEventChart.app_name, + eventName: "WORK_ADD" + }, { + ts: 14000, + workId: 44, + name: SpHiSysEventChart.app_name, + eventName: "WORK_START" + }, { + ts: 20000, + workId: 11, + name: SpHiSysEventChart.app_name, + eventName: "WORK_STOP" + }, { + ts: 22000, + workId: 22, + name: SpHiSysEventChart.app_name, + eventName: "WORK_START" + }, { + ts: 30000, + workId: 11, + name: SpHiSysEventChart.app_name, + eventName: "WORK_START" + }, { + ts: 32000, + workId: 22, + name: SpHiSysEventChart.app_name, + eventName: "WORK_STOP" + }, { + ts: 40000, + workId: 11, + name: SpHiSysEventChart.app_name, + eventName: "WORK_STOP" + }, { + ts: 42000, + workId: 22, + name: SpHiSysEventChart.app_name, + eventName: "WORK_START" + }, { + ts: 50000, + workId: 11, + name: SpHiSysEventChart.app_name, + eventName: "WORK_START" + }, { + ts: 52000, + workId: 22, + name: SpHiSysEventChart.app_name, + eventName: "WORK_STOP" + }, { + ts: 60000, + workId: 11, + name: SpHiSysEventChart.app_name, + eventName: "WORK_STOP" + }, { + ts: 62000, + workId: 22, + name: SpHiSysEventChart.app_name, + eventName: "WORK_REMOVE" + }, { + ts: 64000, + workId: 44, + name: SpHiSysEventChart.app_name, + eventName: "WORK_STOP" + }, { + ts: 70000, + workId: 11, + name: SpHiSysEventChart.app_name, + eventName: "WORK_REMOVE" + } + ] + tabPaneSystemDetails.getConvertData = jest.fn(() => cc) + let systemWorkData = tabPaneSystemDetails.getSystemWorkData(); + + expect(systemWorkData).toStrictEqual([]) + }) + + it('TabPaneSystemDetailsTest07', function () { + let tabPaneSystemDetails = new TabPaneSystemDetails(); + expect(tabPaneSystemDetails.initHtml()).toMatchInlineSnapshot(` +" + +
+
+ +
+ + + + + + +
+ + + + + + + +
+
+ +
+ " +`); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/file-system/TabPaneFileSystemCalltree.test.ts b/host/ide/test/trace/component/trace/sheet/file-system/TabPaneFileSystemCalltree.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..7ec3d305e48cd08329d1969dde55e6518645e07a --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/file-system/TabPaneFileSystemCalltree.test.ts @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabpaneFilesystemCalltree} from "../../../../../../dist/trace/component/trace/sheet/file-system/TabpaneFilesystemCalltree.js"; + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); +describe('TabpaneFilesystemCalltree Test', () => { + + document.body.innerHTML = `` + let tabpaneFilesystemCalltree = document.querySelector('#tree') + + it('TabpaneFilesystemCalltreeTest02', function () { + tabpaneFilesystemCalltree!.showButtomMenu = jest.fn(()=>'') + tabpaneFilesystemCalltree.filter = jest.fn(()=>'') + tabpaneFilesystemCalltree.filter.setAttribute = jest.fn(()=>'') + expect(tabpaneFilesystemCalltree.showButtomMenu(true)).toBe("") + }); + + it('TabpaneFilesystemCalltreeTest03', function () { + TabpaneFilesystemCalltree.getParentTree = jest.fn(()=>true); + let call = { + id: '1', + children: [], + } + let target = { + id: '1', + } + expect(tabpaneFilesystemCalltree.getParentTree([call],{target},[])).toBeFalsy(); + + }); + + it('TabpaneFilesystemCalltreeTest04', function () { + TabpaneFilesystemCalltree.getParentTree = jest.fn(()=>true); + let call = { + children: [], + } + expect(tabpaneFilesystemCalltree.getParentTree([call],'',[])).not.toBeUndefined(); + }); + + it('TabpaneFilesystemCalltreeTest05', function () { + TabpaneFilesystemCalltree.getChildTree = jest.fn(()=>true); + let call = { + id: '1', + children: [], + } + let id = '1'; + expect(tabpaneFilesystemCalltree.getChildTree([call],{id},[])).not.toBeUndefined(); + }); + + it('TabpaneFilesystemCalltreeTest06', function () { + TabpaneFilesystemCalltree.getChildTree = jest.fn(()=>true); + let call = { + children: [], + } + expect(tabpaneFilesystemCalltree.getChildTree([call],'',[])).not.toBeUndefined(); + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/file-system/TabPaneFileSystemDescHistory.test.ts b/host/ide/test/trace/component/trace/sheet/file-system/TabPaneFileSystemDescHistory.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..685c8d5f81af6f8253883335267891d376bce437 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/file-system/TabPaneFileSystemDescHistory.test.ts @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneFileSystemDescHistory} from "../../../../../../dist/trace/component/trace/sheet/file-system/TabPaneFileSystemDescHistory.js" +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); +describe('TabPaneFileSystemDescHistory Test', () => { + + document.body.innerHTML = `` + let tabPaneFileSystemDescHistory = document.querySelector('#history') + + it('TabPaneFileSystemDescHistoryTest01', function () { + expect(tabPaneFileSystemDescHistory.setProcessFilter).toBeUndefined(); + + }); + + it('TabPaneFileSystemDescHistoryTest02', function () { + expect(tabPaneFileSystemDescHistory.filterData).toBeUndefined(); + + }); + + it('TabPaneFileSystemDescHistoryTest03', function () { + expect(tabPaneFileSystemDescHistory.data).toBeUndefined(); + + }); + + }) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneThreadSwitch.test.ts b/host/ide/test/trace/component/trace/sheet/file-system/TabPaneFileSystemEvents.test.ts similarity index 34% rename from host/ide/test/trace/component/trace/sheet/TabPaneThreadSwitch.test.ts rename to host/ide/test/trace/component/trace/sheet/file-system/TabPaneFileSystemEvents.test.ts index cd1fce51cad6516ad122f5e263728871d066dbfa..2723015b6bc20b3752d9e7e32a2cee539f9578ec 100644 --- a/host/ide/test/trace/component/trace/sheet/TabPaneThreadSwitch.test.ts +++ b/host/ide/test/trace/component/trace/sheet/file-system/TabPaneFileSystemEvents.test.ts @@ -13,61 +13,52 @@ * limitations under the License. */ +import "../../../../../../dist/trace/component/trace/sheet/file-system/TabPaneFileSystemEvents.js" + +// @ts-ignore +import {TabPaneFileSystemEvents} from "../../../../../../dist/trace/component/trace/sheet/file-system/TabPaneFileSystemEvents.js" // @ts-ignore -import {TabPaneThreadSwitch} from "../../../../../dist/trace/component/trace/sheet/TabPaneThreadSwitch.js" +import {TabPaneFilter} from "../../../../../../dist/trace/component/trace/sheet/TabPaneFilter.js"; + window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ disconnect: jest.fn(), observe: jest.fn(), unobserve: jest.fn(), })); -describe('TabPaneContextSwitch Test', () => { - let tabPaneThreadSwitch = new TabPaneThreadSwitch(); - let dataArray = [{ - id: "", - pid: "", - title: "", - children: [], - process: "", - processId: 0, - thread: "", - threadId: 0, - state: "", - wallDuration: 0, - avgDuration: "", - count: 0, - minDuration: 0, - maxDuration: 0, - stdDuration: "", - }] -let val={ - leftNs:1, - rightNs:1, - -} - it('TabPaneThreadSwitchTest01', function () { - let result = tabPaneThreadSwitch.groupByStateToMap(dataArray); - expect(result.get('').length).toBe(1); +describe('TabPaneFileSystemEvents Test', () => { + document.body.innerHTML = `` + let tabPaneFileSystemEvents = document.querySelector("#files") as TabPaneFileSystemEvents + it('TabPaneFileStatisticsTest01', function () { + expect(tabPaneFileSystemEvents.sortTable("",0)).toBeUndefined(); }); - it('TabPaneThreadSwitchTest02', function () { - let result = tabPaneThreadSwitch.groupByProcessToMap(dataArray) - expect(result.get(0).length).toBe(1); + it('TabPaneFileStatisticsTest02', function () { + tabPaneFileSystemEvents.filterSource = [{startTsStr:1}] + expect(tabPaneFileSystemEvents.sortTable("startTsStr",1)).toBeUndefined(); }); - it('TabPaneThreadSwitchTest03', function () { - let result = tabPaneThreadSwitch.groupByStateProcessToMap(dataArray) - expect(result.get('').get(0).length).toBe(1); - }); + it('TabPaneFileStatisticsTest03', function () { + tabPaneFileSystemEvents.filterSource = [{durStr:1}] - it('TabPaneThreadSwitchTest04', function () { - expect(tabPaneThreadSwitch.data).toBeUndefined(); + expect(tabPaneFileSystemEvents.sortTable("durStr",1)).toBeUndefined(); }); - it('TabPaneThreadSwitchTest05', function () { - expect(tabPaneThreadSwitch.queryDataByCacheData(val)).toBeUndefined(); + it('TabPaneFileStatisticsTest04', function () { + tabPaneFileSystemEvents.filterSource = [{process:1}] + + expect(tabPaneFileSystemEvents.sortTable("process",2)).toBeUndefined(); }); + it('TabPaneFileStatisticsTest05', function () { + tabPaneFileSystemEvents.filterSource = [{thread:1}] + + expect(tabPaneFileSystemEvents.sortTable("thread",2)).toBeUndefined(); + }); + it('TabPaneFileStatisticsTest06', function () { + tabPaneFileSystemEvents.filterSource = [{typeStr:1}] -}) + expect(tabPaneFileSystemEvents.sortTable("typeStr",2)).toBeUndefined(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/file-system/TabPaneFilesystemStatistics.test.ts b/host/ide/test/trace/component/trace/sheet/file-system/TabPaneFilesystemStatistics.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..4c99fb720c4b53b0a7e23b0856b76c0ed7379d16 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/file-system/TabPaneFilesystemStatistics.test.ts @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneFileStatistics} from "../../../../../../dist/trace/component/trace/sheet/file-system/TabPaneFilesystemStatistics.js" +// @ts-ignore +import {Utils} from "../../../../../../dist/trace/component/trace/base/Utils.js"; + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); +describe('TabPaneFileStatistics Test', () => { + document.body.innerHTML = `` + let tabPaneFileStatistics = document.querySelector('#statistics') + + it('TabPaneFileStatisticsTest01', function () { + tabPaneFileStatistics.setInitDua = jest.fn(()=>true); + let item = { + allDuration: '', + minDuration: '', + avgDuration: '', + maxDuration: '', + } + expect(tabPaneFileStatistics.setInitDua(item)).toBeTruthy(); + + }); + + it('TabPaneFileStatisticsTest02', function () { + tabPaneFileStatistics.getInitData = jest.fn(()=>true); + let item = { + allDuration: '', + minDuration: '', + avgDuration: '', + maxDuration: '', + } + expect(tabPaneFileStatistics.getInitData(item)).toBeTruthy(); + + }); + + it('TabPaneFileStatisticsTest04', function () { + tabPaneFileStatistics.showButtomMenu = jest.fn(()=>true); + let isShow = { + filter: { + setAttribute: 'tree, input, inputLeftText' + } + } + expect(tabPaneFileStatistics.showButtomMenu(isShow)).toBeTruthy(); + + }); + + it('TabPaneFileStatisticsTest08', function () { + let FileStatistics = new TabPaneFileStatistics(); + let item = { + allDuration:"", + minDuration:"", + avgDuration:"", + maxDuration:"", + name:"as", + logicalWrites:"", + logicalReads:"", + otherFile:"0 Bytes", + pid:1 + } + Utils.getBinaryByteWithUnit = jest.fn(()=>true) + expect(FileStatistics.getInitData(item)).toEqual({"allDuration": "", + "avgDuration": "", "logicalReads": true, "logicalWrites": true, "maxDuration": "", + "minDuration": "", "name": "as", "node": {"allDuration": "", "avgDuration": "", + "children": [], "logicalReads": "", "logicalWrites": "", "maxDuration": "", + "minDuration": "", "name": "as", "otherFile": "0 Bytes", "pid": 1}, + "otherFile": true, "pid": 1, "title": "as(1)" + }); + }); + + it('TabPaneFileStatisticsTest09', function () { + let FileStatistics = new TabPaneFileStatistics(); + let node = { + children: [] + } + // Utils.getBinaryByteWithUnit = jest.fn(()=>true) + expect(FileStatistics.sortTable(node,'')).toBeUndefined(); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatistics.test.ts b/host/ide/test/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatistics.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..a381de816048f6625e98f127da862c9785e464e0 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatistics.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneVirtualMemoryStatistics} from "../../../../../../dist/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatistics.js"; +import "../../../../../../dist/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatistics.js"; + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); +describe('TabPaneVirtualMemoryStatistics Test', () => { + document.body.innerHTML = ` +` + let tabPaneVirtualMemoryStatistics = document.querySelector("#statistics") as TabPaneVirtualMemoryStatistics + it('TabPaneVirtualMemoryStatisticsTest01', function () { + + expect(tabPaneVirtualMemoryStatistics).toBeDefined() + + }) +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/fps/TabPaneFps.test.ts b/host/ide/test/trace/component/trace/sheet/fps/TabPaneFps.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..1fb371a9c108bcef2022cdc84bb01bc47f9c6279 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/fps/TabPaneFps.test.ts @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//@ts-ignore +import {TabPaneFps} from "../../../../../../dist/trace/component/trace/sheet/fps/TabPaneFps.js"; +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe('TabPaneFps Test', () => { + let tabPaneFps = new TabPaneFps(); + + it('TabPaneFpsTest01', function () { + let mockgetTabFps = sqlit.getTabFps + mockgetTabFps.mockResolvedValue( + [ + { leftNs : 10, + rightNs: 10, + }] + ) + let a = {rightNs: 1, leftNs:1} + expect(tabPaneFps.data = a).toBeTruthy(); + }); + + it('TabPaneFpsTest02', function () { + let mockgetTabFps = sqlit.getTabFps + mockgetTabFps.mockResolvedValue([]) + let a = {rightNs: 1, leftNs:1} + expect(tabPaneFps.data = a).toBeTruthy(); + }); + + it('TabPaneFpsTest03', function () { + expect(tabPaneFps.initHtml()).toMatchInlineSnapshot(` +" + + + + + + + + + " +`) + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/hiperf/TabPerfProfile.test.ts b/host/ide/test/trace/component/trace/sheet/hiperf/TabPerfProfile.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..f3038412168b4d12b249787017b6da69cbb1c09e --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/hiperf/TabPerfProfile.test.ts @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//@ts-ignore +import {TabpanePerfProfile} from "../../../../../../dist/trace/component/trace/sheet/hiperf/TabPerfProfile.js" + + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe('TabPerfProfile Test', () => { + + document.body.innerHTML = `` + let tabpanePerfProfile = document.querySelector('#perfprofile') as TabpanePerfProfile + + it('TabpanePerfProfileTest01 ', function () { + TabpanePerfProfile.getParentTree = jest.fn(()=>true) + let call = { + id:"1", + dur:1, + children:[] + } + let id = "1"; + expect(tabpanePerfProfile.getParentTree([call],{id},[])).not.toBeUndefined(); + }); + it('TabpanePerfProfileTest02 ', function () { + let call = { + id:"1", + dur:1, + children:[] + } + expect(tabpanePerfProfile.getChildTree([call],"1",[])).not.toBeUndefined(); + }); + + it('TabpanePerfProfileTest03 ', function () { + let call = { + id:"1", + dur:1, + children:[] + } + expect(tabpanePerfProfile.setRightTableData(call)).toBeUndefined(); + }); + it('TabpanePerfProfileTest04 ', function () { + expect(tabpanePerfProfile.showButtomMenu()).toBeUndefined(); + }); + it('TabpanePerfProfileTest05 ', function () { + let isShow = 1; + expect(tabpanePerfProfile.showButtomMenu(isShow)).toBeUndefined(); + }); + it('TabpanePerfProfileTest06 ', function () { + TabpanePerfProfile.getParentTree = jest.fn(()=>true) + let call = { + id:"1", + dur:1, + children:[] + } + let id = "2"; + + expect(tabpanePerfProfile.getParentTree([call],{id},[])).not.toBeUndefined(); + }); + it('TabpanePerfProfileTest08 ', function () { + let data = { + icon:"tree", + }; + tabpanePerfProfile.tbl!.reMeauseHeight = jest.fn(()=>true) + expect(tabpanePerfProfile.switchFlameChart(data)).toBeUndefined() + }); + it('TabpanePerfProfileTest07 ', function () { + let data = { + icon:1, + }; + expect(tabpanePerfProfile.switchFlameChart(data)).toBeUndefined() + }); + it('TabpanePerfProfileTest09 ', function () { + tabpanePerfProfile.sortTree = jest.fn(()=>true) + tabpanePerfProfile.sortTree.sort = jest.fn(()=>true) + expect(tabpanePerfProfile.setLTableData()).toBeUndefined() + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/native-memory/TabPaneNMCallInfo.test.ts b/host/ide/test/trace/component/trace/sheet/native-memory/TabPaneNMCallInfo.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..68e6fb8252fa4e6a04b0d47884f5569a29908e09 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/native-memory/TabPaneNMCallInfo.test.ts @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneNMCallInfo} from "../../../../../../dist/trace/component/trace/sheet/native-memory/TabPaneNMCallInfo.js" +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), +})); + +describe('TabPaneNMCallInfo Test', () => { + document.body.innerHTML = '' + let tabPaneNMCallInfo = document.querySelector('#ddd') + + let nativeHookData = [ + { + eventId: 0, + eventType: "", + subType: "", + heapSize: 0, + addr: "", + startTs: 0, + endTs: 0, + sumHeapSize: 0, + max: 0, + count: 0, + tid: 0, + isSelected: false, + }, + { + eventId: 0, + eventType: "", + subType: "", + heapSize: 0, + addr: "", + startTs: 0, + endTs: 0, + sumHeapSize: 0, + max: 0, + count: 0, + tid: 0, + isSelected: false, + }, + ] + + tabPaneNMCallInfo.currentSelection = jest.fn(()=>true) + TabPaneNMCallInfo.data = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds: [], + nativeMemory: [], + leftNs: 0, + rightNs: 0, + hasFps: false, + statisticsSelectData: undefined + } + + it('TabPaneNMCallInfoTest08', function () { + let hookLeft = { + id: "", + pid: '', + library: "", + title: "", + count: 0, + children: [], + depth: 0, + frame: undefined, + isHover: false, + parent: undefined, + size: 2, + symbol: "", + type: 0, + heapSize: 0, + heapSizeStr: "", + eventId: 0, + threadId: 0 + } + let groupByWithTid = tabPaneNMCallInfo.setRightTableData(hookLeft); + expect(groupByWithTid).toBeUndefined() + }); + + it('TabPaneNMCallInfoTest10', function () { + expect(tabPaneNMCallInfo.sortTreeByColumn()).toBeUndefined(); + }); + + it('TabPaneNMCallInfoTest11', function () { + let tab = new TabPaneNMCallInfo() + let MockqueryNativeHookEventTid = sqlit.queryNativeHookEventTid; + MockqueryNativeHookEventTid.mockResolvedValue([{ + eventId: 0, + eventType: "AllocEvent", + heap_size: 2, + addr: "addr", + startTs: 0, + endTs: 500, + tid: 2, + threadName: "threadName" + }]) + tab.data = { + leftNs: 0, + rightNs: 500, + nativeMemory: "All Heap & Anonymous VM" + } + + tab.startWorker = jest.fn(()=>true) + expect(tab.data).toBeUndefined(); + }); + + it('TabPaneNMCallInfoTest12', function () { + expect(tabPaneNMCallInfo.initHtml()).toMatchInlineSnapshot(` +" + +
+ + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+ + + + + +
+
+ " +`); + }); + it('TabPaneNMCallInfoTest04', function () { + TabPaneNMCallInfo.getParentTree = jest.fn(()=>true) + let hook = { + id:"1", + dur:1, + children:[], + } + let id = "1"; + expect(tabPaneNMCallInfo.getParentTree([hook],{id},[])).not.toBeUndefined(); + }); + it('TabPaneNMCallInfoTest05', function () { + TabPaneNMCallInfo.getChildTree = jest.fn(()=>true) + let hook = { + eventId:"1", + dur:1, + children:[], + } + expect(tabPaneNMCallInfo.getChildTree([hook],"1",[])).not.toBeUndefined(); + }); + it('TabPaneNMCallInfoTest13', function () { + expect(tabPaneNMCallInfo.showButtomMenu()).toBeUndefined(); + }); + it('TabPaneNMCallInfoTest14', function () { + let isShow = 1; + expect(tabPaneNMCallInfo.showButtomMenu(isShow)).toBeUndefined(); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/native-memory/TabPaneNMSampleList.test.ts b/host/ide/test/trace/component/trace/sheet/native-memory/TabPaneNMSampleList.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..65bced0f55c0b79858389e605937dac7de26ff07 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/native-memory/TabPaneNMSampleList.test.ts @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneNMSampleList} from "../../../../../../dist/trace/component/trace/sheet/native-memory/TabPaneNMSampleList.js" +// @ts-ignore +import {LitTable} from "../../../../../../dist/base-ui/table/lit-table"; +// @ts-ignore +import {NativeHookSampleQueryInfo, NativeHookSamplerInfo} from "../../../../../../dist/trace/bean/NativeHook.js"; +// @ts-ignore +import {NativeMemory} from "../../../../../../dist/trace/bean/NativeHook.js"; +// @ts-ignore +import {queryAllHookData} from "../../../../../../dist/trace/database/SqlLite.js"; +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), +})); +describe('TabPaneNMSampleList Test', () => { + document.body.innerHTML = '' + let tabPaneNMSampleList = document.querySelector('#ddt') + + TabPaneNMSampleList.source = [{ + current: "", + currentSize: 0, + startTs: 0, + heapSize: 0, + snapshot: "", + growth: "", + total: 0, + totalGrowth: "", + existing: 0, + children: [], + tempList: [], + timestamp: "", + eventId: -1, + }] + TabPaneNMSampleList.filterSelect = '0' + + tabPaneNMSampleList.currentSelection = jest.fn(()=>true) + let dat = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds: [], + nativeMemory: [], + leftNs: 0, + rightNs: 0, + hasFps: false, + statisticsSelectData: undefined + } + + let NativeHookSnapshotTypes = [{ + eventId: -1, + current: 0, + eventType: "", + subType: "", + growth: 0, + existing: 0, + addr: "", + startTs: 0, + endTs: 0, + total: 0, + children: [], + }] + + + let MockNativeHookSnapshotTypes = sqlit.queryNativeHookSnapshotTypes + + MockNativeHookSnapshotTypes.mockResolvedValue([new NativeHookSampleQueryInfo()]) + + tabPaneNMSampleList.data = dat + it('TabPaneNMSampleListTest01', function () { + expect(TabPaneNMSampleList.serSelection(dat)).toBeUndefined() + }); + + it('TabPaneNMSampleListTest02', function () { + let sampleData = new NativeMemory(); + + let MockqueryAllHookData = sqlit.queryAllHookData + MockqueryAllHookData.mockResolvedValue([new NativeHookSampleQueryInfo()]) + + expect(TabPaneNMSampleList.addSampleData(sampleData)).toBeUndefined() + }); + + it('TabPaneNMSampleListTest04', function () { + let snapshot = { + current: "", + currentSize: 0, + startTs: 0, + heapSize: 0, + snapshot: "", + growth: "", + total: 0, + totalGrowth: "", + existing: 0, + children: [], + tempList: [], + timestamp: "", + eventId: -1, + } + + let snapshotLeft = { + current: "", + currentSize: 0, + startTs: 0, + heapSize: 0, + snapshot: "", + growth: "", + total: 0, + totalGrowth: "", + existing: 0, + children: [snapshot], + tempList: [], + timestamp: "", + eventId: -1, + } + + let snapshotRight = { + current: "", + currentSize: 0, + startTs: 0, + heapSize: 0, + snapshot: "", + growth: "", + total: 0, + totalGrowth: "", + existing: 0, + children: [snapshot], + tempList: [], + timestamp: "", + eventId: -1, + } + expect(TabPaneNMSampleList.prepChild(snapshotLeft, snapshotRight)).toBeUndefined() + }); + + it('TabPaneNMSampleListTest10', function () { + expect(TabPaneNMSampleList.data).toBeUndefined() + }); + + it('TabPaneNMSampleListTest11', function () { + expect(TabPaneNMSampleList.initTypes()).toBeUndefined() + }); + + it('TabPaneNMSampleListTest05', function () { + expect(tabPaneNMSampleList.initHtml()).toMatchInlineSnapshot(` +" + + +
+ + + + + + + + + + + + + +
+ + + + + + + + +
+ " +`); + }); + + it('TabPaneNMSampleListTest09', function () { + let rootSample = new NativeHookSamplerInfo() + + let merageSample ={ + growth:1, + endTs:2, + startTs:2, + addr:"1", + eventId:0, + } + expect(TabPaneNMSampleList.merageSampleData(1,1,rootSample,merageSample)).toBeUndefined() + }); + + it('TabPaneNMSampleListTest12', function () { + let rootSample = new NativeHookSamplerInfo() + + let MockqueryAllHookData = sqlit.queryAllHookData + + MockqueryAllHookData.mockResolvedValue([{eventId:1,eventType:"aa",subType:1, addr:"aaaa",growth:2,startTs:11111, endTs:211111}]) + expect(TabPaneNMSampleList.queryAllHookInfo(dat,rootSample)).toBeUndefined(); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.test.ts b/host/ide/test/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..5246abd9bfe68fc4f5296155616761807c5e12d0 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.test.ts @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneNMStatstics} from "../../../../../../dist/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.js" +// @ts-ignore +import {NativeHookMalloc, NativeHookStatistics, NativeHookStatisticsTableData} from "../../../../../../dist/trace/bean/NativeHook"; + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe('TabPaneNMStatstics Test', () => { + let tabPaneNMStatstics = new TabPaneNMStatstics(); + document.body.innerHTML = '
' + + it('TabPaneNMStatsticsTest01', function () { + expect(tabPaneNMStatstics.setMallocTableData([1],[1])).toBeUndefined(); + }); + it('TabPaneNMStatsticsTest09', function () { + expect(tabPaneNMStatstics.setSubTypeTableData([1],[1])).toBeUndefined(); + }); + + it('TabPaneNMStatsticsTest02', function () { + let nativeHookMalloc: Array = [{ + eventType: "", + subType: "", + heapSize: 0, + allocByte: 0, + allocCount: 0, + freeByte: 0, + freeCount: 0, + }] + let nativeHookStatisticsTableData: Array = [{ + memoryTap: "", + existing: 0, + existingString: "", + allocCount: 0, + freeCount: 0, + totalBytes: 0, + totalBytesString: "", + maxStr: "", + max: 0, + totalCount: 0, + existingValue: [], + }] + + expect(tabPaneNMStatstics.setSubTypeTableData(nativeHookMalloc,nativeHookStatisticsTableData)).toBeUndefined(); + }); + + it('TabPaneNMStatsticsTest03', function () { + expect(tabPaneNMStatstics.initHtml()).toMatchInlineSnapshot(` +" + + + + + + + + + + + + + + + " +`); + }); + + it('TabPaneNMStatsticsTest04', function () { + let valData = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds: [], + nativeMemory: ["All Heap & Anonymous VM", "All Heap", "All Anonymous VM"], + cpuAbilityIds: [], + memoryAbilityIds: [], + diskAbilityIds: [], + networkAbilityIds: [], + leftNs: 0, + rightNs: 0, + hasFps: false, + statisticsSelectData: undefined, + perfSampleIds: [], + perfCpus: [], + perfProcess: [], + perfThread: [], + perfAll: false, + } + let nativeHookStatistics: Array = [{ + eventId: 0, + eventType: "AllocEvent", + subType: "", + heapSize: 0, + addr: "", + startTs: 0, + endTs: 0, + sumHeapSize: 0, + max: 100000, + count: 0, + tid: 0, + isSelected: false, + }] + + let nativeHookStatisticsTableData: Array = [{ + memoryTap: "", + existing: 0, + existingString: "", + allocCount: 0, + freeCount: 0, + totalBytes: 0, + totalBytesString: "", + maxStr: "", + max: 0, + totalCount: 0, + existingValue: [], + }] + + expect(tabPaneNMStatstics.setMemoryTypeData(valData,nativeHookStatistics, nativeHookStatisticsTableData)).toBeUndefined(); + }); + + it('TabPaneNMStatsticsTest05', function () { + let valData = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds: [], + nativeMemory: ["All Heap"], + cpuAbilityIds: [], + memoryAbilityIds: [], + diskAbilityIds: [], + networkAbilityIds: [], + leftNs: 0, + rightNs: 0, + hasFps: false, + statisticsSelectData: undefined, + perfSampleIds: [], + perfCpus: [], + perfProcess: [], + perfThread: [], + perfAll: false, + } + let nativeHookStatistics: Array = [{ + eventId: 0, + eventType: "FreeEvent", + subType: "", + heapSize: 0, + addr: "", + startTs: 0, + endTs: 0, + sumHeapSize: 0, + max: 100000, + count: 0, + tid: 0, + isSelected: false, + }] + + let nativeHookStatisticsTableData: Array = [{ + memoryTap: "", + existing: 0, + existingString: "", + allocCount: 0, + freeCount: 0, + totalBytes: 0, + totalBytesString: "", + maxStr: "", + max: 0, + totalCount: 0, + existingValue: [], + }] + + expect(tabPaneNMStatstics.setMemoryTypeData(valData,nativeHookStatistics, nativeHookStatisticsTableData)).toBeUndefined(); + }); + + it('TabPaneNMStatsticsTest06', function () { + let valData = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds: [], + nativeMemory: ["All Anonymous VM"], + cpuAbilityIds: [], + memoryAbilityIds: [], + diskAbilityIds: [], + networkAbilityIds: [], + leftNs: 0, + rightNs: 0, + hasFps: false, + statisticsSelectData: undefined, + perfSampleIds: [], + perfCpus: [], + perfProcess: [], + perfThread: [], + perfAll: false, + } + let nativeHookStatistics: Array = [{ + eventId: 0, + eventType: "MmapEvent", + subType: "", + heapSize: 0, + addr: "", + startTs: 0, + endTs: 0, + sumHeapSize: 0, + max: 100000, + count: 0, + tid: 0, + isSelected: false, + }] + + let nativeHookStatisticsTableData: Array = [{ + memoryTap: "", + existing: 0, + existingString: "", + allocCount: 0, + freeCount: 0, + totalBytes: 0, + totalBytesString: "", + maxStr: "", + max: 0, + totalCount: 0, + existingValue: [], + }] + + expect(tabPaneNMStatstics.setMemoryTypeData(valData,nativeHookStatistics, nativeHookStatisticsTableData)).toBeUndefined(); + }); + + it('TabPaneNMStatsticsTest07', function () { + let valData = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds: [], + nativeMemory: ["All Anonymous VM"], + cpuAbilityIds: [], + memoryAbilityIds: [], + diskAbilityIds: [], + networkAbilityIds: [], + leftNs: 0, + rightNs: 0, + hasFps: false, + statisticsSelectData: undefined, + perfSampleIds: [], + perfCpus: [], + perfProcess: [], + perfThread: [], + perfAll: false, + } + let nativeHookStatistics: Array = [{ + eventId: 0, + eventType: "MunmapEvent", + subType: "", + heapSize: 0, + addr: "", + startTs: 0, + endTs: 0, + sumHeapSize: 0, + max: 100000, + count: 0, + tid: 0, + isSelected: false, + }] + + let nativeHookStatisticsTableData: Array = [{ + memoryTap: "", + existing: 0, + existingString: "", + allocCount: 0, + freeCount: 0, + totalBytes: 0, + totalBytesString: "", + maxStr: "", + max: 0, + totalCount: 0, + existingValue: [], + }] + + expect(tabPaneNMStatstics.setMemoryTypeData(valData,nativeHookStatistics, nativeHookStatisticsTableData)).toBeUndefined(); + }); + + it('TabPaneNMStatsticsTest08', function () { + let valData = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds: [], + nativeMemory: ["All Heap & Anonymous VM", "All Heap", "All Anonymous VM"], + cpuAbilityIds: [], + memoryAbilityIds: [], + diskAbilityIds: [], + networkAbilityIds: [], + leftNs: 0, + rightNs: 0, + hasFps: false, + statisticsSelectData: undefined, + perfSampleIds: [], + perfCpus: [], + perfProcess: [], + perfThread: [], + perfAll: false, + } + let nativeHookStatistics: Array = [{ + eventId: 0, + eventType: "FreeEvent", + subType: "", + heapSize: 0, + addr: "", + startTs: 0, + endTs: 0, + sumHeapSize: 0, + max: 100000, + count: 0, + tid: 0, + isSelected: false, + }] + + let nativeHookStatisticsTableData: Array = [{ + memoryTap: "", + existing: 0, + existingString: "", + allocCount: 0, + freeCount: 0, + totalBytes: 0, + totalBytesString: "", + maxStr: "", + max: 100, + totalCount: 0, + existingValue: [], + }] + + expect(tabPaneNMStatstics.setMemoryTypeData(valData,nativeHookStatistics, nativeHookStatisticsTableData)).toBeUndefined(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/native-memory/TabPaneNMemory.test.ts b/host/ide/test/trace/component/trace/sheet/native-memory/TabPaneNMemory.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..d831ef837d01db175fd95c248b94e23d842575c2 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/native-memory/TabPaneNMemory.test.ts @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//@ts-ignore +import {TabPaneNMemory} from "../../../../../../dist/trace/component/trace/sheet/native-memory/TabPaneNMemory.js" +// @ts-ignore +import {TabPaneNMSampleList} from "../../../../../../dist/trace/component/trace/sheet/native-memory/TabPaneNMSampleList.js"; + +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), +})); + +describe('TabPaneNMemory Test', () => { + let tabPaneNMemory = new TabPaneNMemory(); + let val = { + statisticsSelectData: { + memoryTap: 1 + } + } + let hook = {eventId: 1} + + + it('TabPaneNMemoryTest01', function () { + expect(tabPaneNMemory.initFilterTypes()).toBeUndefined(); + }); + + it('TabPaneNMemoryTest02', function () { + let MockqueryNativeHookEventTid = sqlit.queryNativeHookEventTid; + MockqueryNativeHookEventTid.mockResolvedValue([{ + eventId: 0, + eventType: "MmapEvent", + heap_size: 2, + addr: "addr", + startTs: 0, + endTs: 500, + tid: 2, + threadName: "threadName" + }]) + + let MockNativeHookSnapshotTypes = sqlit.queryNativeHookSnapshotTypes; + MockNativeHookSnapshotTypes.mockResolvedValue([{ + eventType: "MmapEvent", + subType: "" + }]) + + let tab = new TabPaneNMSampleList() + tabPaneNMemory.startWorker = jest.fn(() => true) + tabPaneNMemory.data = { + leftNs: 0, + rightNs: 500, + nativeMemory: "All Anonymous VM" + } + expect(tabPaneNMemory.initFilterTypes()).toBeUndefined(); + }); + + it('TabPaneNMemoryTest08', function () { + expect(tabPaneNMemory.initHtml()).toMatchInlineSnapshot(` +" + +
+
+ +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+ + +
+
+ " +`); + }); + + it('TabPaneNMemoryTest09', function () { + tabPaneNMemory.tblData = jest.fn(() => undefined) + tabPaneNMemory.tblData.recycleDataSource = jest.fn(() => true) + tabPaneNMemory.startWorker = jest.fn(() => true) + expect(tabPaneNMemory.setRightTableData(hook)).toBeUndefined(); + }); + it('TabPaneNMemoryTest010', function () { + let column = "index"; + let sort = 0; + expect(tabPaneNMemory.sortByColumn(column, sort)).toBeUndefined(); + }); + it('TabPaneNMemoryTest011', function () { + let column = "index"; + let sort = 1; + expect(tabPaneNMemory.sortByColumn(column, sort)).toBeUndefined(); + }); + it('TabPaneNMemoryTest012', function () { + let column = "addr" + let sort = 1; + expect(tabPaneNMemory.sortByColumn(column, sort)).toBeUndefined(); + }); + it('TabPaneNMemoryTest013', function () { + let column = "timestamp" + let sort = 1; + expect(tabPaneNMemory.sortByColumn(column, sort)).toBeUndefined(); + }); + it('TabPaneNMemoryTest014', function () { + let column = "heapSizeUnit" + let sort = 1; + expect(tabPaneNMemory.sortByColumn(column, sort)).toBeUndefined(); + }); + it('TabPaneNMemoryTest015', function () { + let column = "library" + let sort = 1; + expect(tabPaneNMemory.sortByColumn(column, sort)).toBeUndefined(); + }); + it('TabPaneNMemoryTest016', function () { + let column = "symbol" + let sort = 1; + expect(tabPaneNMemory.sortByColumn(column, sort)).toBeUndefined(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneCounter.test.ts b/host/ide/test/trace/component/trace/sheet/process/TabPaneCounter.test.ts similarity index 43% rename from host/ide/test/trace/component/trace/sheet/TabPaneCounter.test.ts rename to host/ide/test/trace/component/trace/sheet/process/TabPaneCounter.test.ts index d7206491353087ba6a80996160e1f10a0c48096c..a546135cc78403f53e164df605a499a1373419b3 100644 --- a/host/ide/test/trace/component/trace/sheet/TabPaneCounter.test.ts +++ b/host/ide/test/trace/component/trace/sheet/process/TabPaneCounter.test.ts @@ -14,10 +14,17 @@ */ // @ts-ignore -import {TabPaneCounter} from "../../../../../dist/trace/component/trace/sheet/TabPaneCounter.js" +import {TabPaneCounter} from "../../../../../../dist/trace/component/trace/sheet/process/TabPaneCounter.js" -const sqlit = require("../../../../../dist/trace/database/SqlLite.js") -jest.mock("../../../../../dist/trace/database/SqlLite.js"); +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); describe('TabPaneCounter Test', () => { let tabPaneCounter = new TabPaneCounter(); it('TabPaneCounterTest01', function () { @@ -45,9 +52,16 @@ describe('TabPaneCounter Test', () => { key: 'name', sort: () => { } - })) + })).toBeUndefined(); }); + it('TabPaneCounterTest06', function () { + expect(tabPaneCounter.sortByColumn({ + key: 'number', + sort: () => { + } + })).toBeUndefined(); + }); it('TabPaneCounterTest04', function () { let mockgetTabCounters = sqlit.getTabCounters @@ -65,7 +79,6 @@ describe('TabPaneCounter Test', () => { expect(tabPaneCounter.data = a).toBeTruthy(); }); - it('TabPaneCounterTest05', function () { let mockgetTabCounters = sqlit.getTabCounters mockgetTabCounters.mockResolvedValue([] @@ -73,4 +86,39 @@ describe('TabPaneCounter Test', () => { let a = {rightNs: 1, trackIds: [11, 12, 13]} expect(tabPaneCounter.data = a).toBeTruthy(); }); + + it('TabPaneCounterTest06', function () { + expect(tabPaneCounter.initHtml()).toMatchInlineSnapshot(` +" + + + + + + + + + + + + + + + + + + + + + + + " +`); + }); }) diff --git a/host/ide/test/trace/component/trace/sheet/process/TabPaneSlices.test.ts b/host/ide/test/trace/component/trace/sheet/process/TabPaneSlices.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..f30fa7ad09ee54bbb5bbd333a6eaa0cefb9a1c19 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/process/TabPaneSlices.test.ts @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneSlices} from "../../../../../../dist/trace/component/trace/sheet/process/TabPaneSlices.js" + +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe('TabPaneSlices Test', () => { + let tabPaneSlices = new TabPaneSlices(); + + it('TabPaneSlicesTest01', function () { + expect(tabPaneSlices.sortByColumn({ + key: 'name', + sort: () => { + } + })).toBeUndefined(); + }); + + it('TabPaneSlicesTest05', function () { + expect(tabPaneSlices.sortByColumn({ + key: !'name', + sort: () => { + } + })).toBeUndefined(); + }); + + it('TabPaneSlicesTest04', function () { + expect(tabPaneSlices.initHtml()).toMatchInlineSnapshot(` +" + + + + + + + + + + + + + " +`); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneThreadStates.test.ts b/host/ide/test/trace/component/trace/sheet/process/TabPaneThreadStates.test.ts similarity index 39% rename from host/ide/test/trace/component/trace/sheet/TabPaneThreadStates.test.ts rename to host/ide/test/trace/component/trace/sheet/process/TabPaneThreadStates.test.ts index e2dcc099a1cc0b51909d5da77044a3f024601246..affe2b32d0872aa6e0cc31d702db1a3057c45758 100644 --- a/host/ide/test/trace/component/trace/sheet/TabPaneThreadStates.test.ts +++ b/host/ide/test/trace/component/trace/sheet/process/TabPaneThreadStates.test.ts @@ -14,21 +14,34 @@ */ // @ts-ignore -import {TabPaneThreadStates} from "../../../../../dist/trace/component/trace/sheet/TabPaneThreadStates.js" +import {TabPaneThreadStates} from "../../../../../../dist/trace/component/trace/sheet/process/TabPaneThreadStates.js" -const sqlit = require("../../../../../dist/trace/database/SqlLite.js") -jest.mock("../../../../../dist/trace/database/SqlLite.js"); +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); describe('TabPaneThreadStates Test', () => { let tabPaneThreadStates = new TabPaneThreadStates(); - tabPaneThreadStates.sortByColumn = jest.fn(() => true) - it('TabPaneThreadStatesTest01', function () { expect(tabPaneThreadStates.sortByColumn({ - key: 'name', + key: 'name' || "thread" || "state", sort: () => { } - })).toBeTruthy(); + })).toBeUndefined(); + }); + + it('TabPaneThreadStatesTest05', function () { + expect(tabPaneThreadStates.sortByColumn({ + key: !'name' || ! "thread" || !"state", + sort: () => { + } + })).toBeUndefined(); }); @@ -61,4 +74,40 @@ describe('TabPaneThreadStates Test', () => { let a = {rightNs: 1, leftNs: 0, threadIds: [11, 12, 13]} expect(tabPaneThreadStates.data = a).toBeTruthy(); }); + + it('TabPaneThreadStatesTest04', function () { + expect(tabPaneThreadStates.initHtml()).toMatchInlineSnapshot(` +" + +
+ + +
+ + + + + + + + + + + + + + + + + + + " +`); + }); }) diff --git a/host/ide/test/trace/component/trace/sheet/sdk/TabPaneSdkCounter.test.ts b/host/ide/test/trace/component/trace/sheet/sdk/TabPaneSdkCounter.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..0dc72a878c63cac864f15b5b317537c9d30aa8bb --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/sdk/TabPaneSdkCounter.test.ts @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneSdkCounter} from '../../../../../../dist/trace/component/trace/sheet/sdk/TabPaneSdkCounter.js' +// @ts-ignore +import '../../../../../../dist/trace/component/trace/sheet/sdk/TabPaneSdkCounter.js' +// @ts-ignore +import {SpSystemTrace} from "../../../../../../dist/trace/component/SpSystemTrace.js"; + +// @ts-ignore +import {LitTable} from "../../../../../../dist/base-ui/table/lit-table.js"; + +window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), +})) + +const sqlite = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +describe('TabPaneSdkCounter Test', () => { + document.body.innerHTML= `` + let litTable = document.querySelector("#tb-counter") as LitTable + it('TabPaneSdkCounterTest00', () => { + let tabPaneSdkCounter = new TabPaneSdkCounter() + tabPaneSdkCounter.tbl = jest.fn(() => litTable) + let a = new Map(); + let config = `{"tableConfig":{"showType":[{"tableName":"gpu_counter","inner":{"tableName":"gpu_counter_object", + "columns":[{"column":"counter_name","type":"STRING","displayName":"","showType":[0]},{"column":"counter_id", + "type":"INTEGER","displayName":"","showType":[0]}]},"columns":[{"column":"ts","type":"INTEGER","displayName": + "TimeStamp","showType":[1,3]},{"column":"counter_id","type":"INTEGER","displayName":"MonitorValue","showType": + [1,3]},{"column":"value","type":"INTEGER","displayName":"Value","showType":[1,3]}]},{"tableName":"slice_table", + "inner":{"tableName":"slice_object_table","columns":[{"column":"slice_name","type":"STRING","displayName":"", + "showType":[0]},{"column":"slice_id","type":"INTEGER","displayName":"","showType":[0]}]},"columns":[{"column": + "start_ts","type":"INTEGER","displayName":"startts","showType":[2,3]},{"column":"end_ts","type":"INTEGER", + "displayName":"endts","showType":[2,3]},{"column":"slice_id","type":"INTEGER","displayName":"slice_id", + "showType":[2,3]},{"column":"value","type":"INTEGER","displayName":"Value","showType":[2,3]}]}]}, + "settingConfig":{"name":"mailG77","configuration":{"version":{"type":"number","default":"1","description": + "gatord version"},"counters":{"type":"string","enum":["ARM_Mali-TTRx_JS1_ACTIVE","ARM_Mali-TTRx_JS0_ACTIVE", + "ARM_Mali-TTRx_GPU_ACTIVE","ARM_Mali-TTRx_FRAG_ACTIVE"]},"stop_gator":{"type":"boolean","default":"true", + "description":"stop_gator"}}}}` + a.set("1", config) + SpSystemTrace.SDK_CONFIG_MAP = a + let startTime = sqlite.queryStartTime; + let dataTime: Array = [{ + start_ts: 1000 + }] + startTime.mockResolvedValue(dataTime) + + let tabSdkCounterLeftData = sqlite.getTabSdkCounterLeftData; + let data = [ + { + max_value: 1000 + }, { + max_value: 2000 + }, { + max_value: 3000 + } + ] + tabSdkCounterLeftData.mockResolvedValue(data) + + let tabSdkCounterData = sqlite.getTabSdkCounterData; + let counter = [{ + ts: 1000, + counter_id: 0, + value: 100 + }, { + ts: 2000, + counter_id: 0, + value: 100 + }, { + ts: 3000, + counter_id: 0, + value: 100 + }, { + ts: 4000, + counter_id: 0, + value: 100 + }, { + ts: 5000, + counter_id: 0, + value: 100 + }] + tabSdkCounterData.mockResolvedValue(counter) + + let d = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds: [], + nativeMemory: [], + cpuAbilityIds: [], + memoryAbilityIds: [], + diskAbilityIds: [], + networkAbilityIds: [], + leftNs: 0, + rightNs: 0, + hasFps: false, + statisticsSelectData: [], + perfSampleIds: [], + perfCpus: [], + perfProcess: [], + perfThread: [], + perfAll: false, + sdkCounterIds: ["a-b","b-c","d-e"] + } + tabPaneSdkCounter.tbl.recycleDataSource = jest.fn(() => d) + tabPaneSdkCounter.tbl.appendChild = jest.fn(() => true) + tabPaneSdkCounter.data = d + expect(tabPaneSdkCounter.data).toBeUndefined(); + }); + + it('TabPaneSdkCounterTest01', () => { + let tabPaneSdkCounter = new TabPaneSdkCounter() + expect(tabPaneSdkCounter.parseJson([])).toBe(""); + }); + + it('TabPaneSdkCounterTest02', () => { + let tabPaneSdkCounter = new TabPaneSdkCounter() + let type = { + columns: [{showType: 'counter'}] + } + expect(tabPaneSdkCounter.getTableType(type)).toBe(""); + }); + + it('TabPaneSdkCounterTest03', () => { + let tabPaneSdkCounter = new TabPaneSdkCounter() + expect(tabPaneSdkCounter.initDataElement()).toBeUndefined(); + }); + + it('TabPaneSdkCounterTest05', () => { + let tabPaneSdkCounter = new TabPaneSdkCounter() + expect(tabPaneSdkCounter.initHtml()).toMatchInlineSnapshot(` +" + +
+ + +
+ + + " +`); + }); + + it('TabPaneSdkCounterTest04', function () { + let tabPaneSdkCounter = new TabPaneSdkCounter() + tabPaneSdkCounter.tbl = jest.fn(() => true) + tabPaneSdkCounter.tbl!.recycleDataSource = jest.fn(() => true) + expect(tabPaneSdkCounter.sortByColumn({ + key: '', + sort: '' + })).toBeUndefined(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/sdk/TabPaneSdkSlice.test.ts b/host/ide/test/trace/component/trace/sheet/sdk/TabPaneSdkSlice.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..fe0622716ea01368c05001c15e48b27b4710bf12 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/sdk/TabPaneSdkSlice.test.ts @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneSdkSlice} from "../../../../../../dist/trace/component/trace/sheet/sdk/TabPaneSdkSlice.js"; +// @ts-ignore +import {LitTable} from "../../../../../../dist/base-ui/table/lit-table.js"; +// @ts-ignore +import {SpSystemTrace} from "../../../../../../dist/trace/component/SpSystemTrace.js"; + +window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), +})) + +const sqlite = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +describe('TabPaneSdkSlice Test', () => { + let tabPaneSdkSlice = new TabPaneSdkSlice(); + document.body.innerHTML = `` + let litTable = document.querySelector("#tb-counter") as LitTable + it('TabPaneSdkSliceTest00', () => { + let mockStartTime = sqlite.queryStartTime; + let startTime: Array = [{ + start_ts: 1000 + }] + mockStartTime.mockResolvedValue(startTime) + + let mockSdkSliceData = sqlite.getTabSdkSliceData; + let sliceData = [{ + start_ts: 1000, + end_ts: 1500, + type: 0, + value: 100 + }, { + start_ts: 2000, + end_ts: 2500, + type: 0, + value: 100 + }, { + start_ts: 3000, + end_ts: 3500, + type: 0, + value: 100 + }, { + start_ts: 4000, + end_ts: 4500, + type: 0, + value: 100 + }, { + start_ts: 5000, + end_ts: 5500, + type: 0, + value: 100 + }] + mockSdkSliceData.mockResolvedValue(sliceData) + + let slice = new TabPaneSdkSlice(); + slice.tbl = jest.fn(() => litTable) + slice.tbl.appendChild = jest.fn(() => true) + let a = new Map(); + let config = `{"tableConfig":{"showType":[{"tableName":"gpu_counter","inner":{"tableName":"gpu_counter_object", + "columns":[{"column":"counter_name","type":"STRING","displayName":"","showType":[0]},{"column":"counter_id", + "type":"INTEGER","displayName":"","showType":[0]}]},"columns":[{"column":"ts","type":"INTEGER","displayName": + "TimeStamp","showType":[1,3]},{"column":"counter_id","type":"INTEGER","displayName":"MonitorValue","showType": + [1,3]},{"column":"value","type":"INTEGER","displayName":"Value","showType":[1,3]}]},{"tableName":"slice_table", + "inner":{"tableName":"slice_object_table","columns":[{"column":"slice_name","type":"STRING","displayName":"", + "showType":[0]},{"column":"slice_id","type":"INTEGER","displayName":"","showType":[0]}]},"columns":[{"column": + "start_ts","type":"INTEGER","displayName":"startts","showType":[2,3]},{"column":"end_ts","type":"INTEGER", + "displayName":"endts","showType":[2,3]},{"column":"slice_id","type":"INTEGER","displayName":"slice_id", + "showType":[2,3]},{"column":"value","type":"INTEGER","displayName":"Value","showType":[2,3]}]}]}, + "settingConfig":{"name":"mailG77","configuration":{"version":{"type":"number","default":"1","description": + "gatord version"},"counters":{"type":"string","enum":["ARM_Mali-TTRx_JS1_ACTIVE","ARM_Mali-TTRx_JS0_ACTIVE", + "ARM_Mali-TTRx_GPU_ACTIVE","ARM_Mali-TTRx_FRAG_ACTIVE"]},"stop_gator":{"type":"boolean","default":"true", + "description":"stop_gator"}}}}` + a.set("1", config) + SpSystemTrace.SDK_CONFIG_MAP = a + + let data = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds: [], + nativeMemory: [], + cpuAbilityIds: [], + memoryAbilityIds: [], + diskAbilityIds: [], + networkAbilityIds: [], + leftNs: 0, + rightNs: 0, + hasFps: false, + statisticsSelectData: [], + perfSampleIds: [], + perfCpus: [], + perfProcess: [], + perfThread: [], + perfAll: false, + sdkSliceIds: ["a-b", "b-c", "d-e"] + } + slice.tbl.recycleDataSource = jest.fn(() => data) + slice.data = data + expect(slice.data).toBeUndefined(); + }); + + it('TabPaneSdkSliceTest01', () => { + expect(tabPaneSdkSlice.parseJson([])).toBe(""); + }); + + it('TabPaneSdkSliceTest02', () => { + let type = { + columns: [{showType: 'slice'}] + } + expect(tabPaneSdkSlice.getTableType(type)).toBe(""); + }); + + it('TabPaneSdkSliceTest03', () => { + expect(tabPaneSdkSlice.initDataElement()).toBeUndefined(); + }); + + it('TabPaneSdkSliceTest04', function () { + tabPaneSdkSlice.tbl = jest.fn(() => true) + tabPaneSdkSlice.tbl!.recycleDataSource = jest.fn(() => true) + expect(tabPaneSdkSlice.sortByColumn({ + key: '', + sort: '' + })).toBeUndefined(); + }); + + it('TabPaneSdkSliceTest05', () => { + expect(tabPaneSdkSlice.initHtml()).toMatchInlineSnapshot(` +" + +
+ + +
+ + + " +`); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/smaps/TabPaneSmapsRecord.test.ts b/host/ide/test/trace/component/trace/sheet/smaps/TabPaneSmapsRecord.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..b3250443aac9267aca74962c951b29b906e534e9 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/smaps/TabPaneSmapsRecord.test.ts @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneSmapsRecord} from "../../../../../../dist/trace/component/trace/sheet/smaps/TabPaneSmapsRecord.js" + +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), +})) +describe('TabPaneSmapsRecord Test', () => { + let MockgetTabSmapsData = sqlit.getTabSmapsData; + MockgetTabSmapsData.mockResolvedValue([{ + tsNS: 0, + start_addr: "start_addr", + end_addr: "end_addr", + dirty: 0, + swapper: 0, + rss: 0, + pss: 0, + size: 1, + reside: 1, + permission: "rw-", + path: "path" + }]) + + let tabPaneSmapsRecord = new TabPaneSmapsRecord(); + tabPaneSmapsRecord.data = { + leftNs: 0, + rightNs: 500, + smapsType: [0, 1, 2] + } + + it('tabPaneSmapsRecord01', function () { + tabPaneSmapsRecord.tbl = jest.fn(() => true) + tabPaneSmapsRecord.tbl!.recycleDataSource = jest.fn(() => true) + expect(tabPaneSmapsRecord.sortByColumn({ + key: '', + sort: '' + })).toBeUndefined(); + }); + + it('tabPaneSmapsRecord02', () => { + expect(tabPaneSmapsRecord.initElements()).toBeUndefined(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/smaps/TabPaneSmapsStatistics.test.ts b/host/ide/test/trace/component/trace/sheet/smaps/TabPaneSmapsStatistics.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..91f61de49141884231c3e943fc473ac1a1ec1322 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/smaps/TabPaneSmapsStatistics.test.ts @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneSmapsStatistics} from "../../../../../../dist/trace/component/trace/sheet/smaps/TabPaneSmapsStatistics.js" +// @ts-ignore +import {Smaps, SmapsTreeObj} from "../../../../../../dist/trace/bean/SmapsStruct.js"; + +const sqlit = require("../../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../../dist/trace/database/SqlLite.js"); + +window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), +})) + +describe('TabPaneSmapsStatistics Test', () => { + let MockgetTabSmapsMaxRss = sqlit.getTabSmapsMaxRss; + MockgetTabSmapsMaxRss.mockResolvedValue([{ + startNS: 0, max_value: 100 + }]) + let smaps = new Smaps() + smaps.tsNS = -1; + smaps.start_addr = "aaaaa"; + smaps.end_addr = "bbbbb"; + smaps.permission = "dddd"; + smaps.path = "/asdasdas"; + smaps.size = 0; + smaps.rss = 0; + smaps.pss = 0; + smaps.reside = 0; + smaps.dirty = 0; + smaps.swapper = 0; + smaps.address = "aaaaa-bbbbb"; + smaps.type = "Dta"; + smaps.dirtyStr = "1212"; + smaps.swapperStr = "222"; + smaps.rssStr = "333"; + smaps.pssStr = "444"; + smaps.sizeStr = "555"; + smaps.resideStr = "666"; + smaps.pss = 2 + let MockgetTabSmapsData = sqlit.getTabSmapsData; + MockgetTabSmapsData.mockResolvedValue([smaps]) + + let tabPaneSmapsStatistics = new TabPaneSmapsStatistics(); + let dataTree: SmapsTreeObj = new SmapsTreeObj("DATA", "", "DATA"); + + + it('TabPaneSmapsStatisticsTest01', () => { + tabPaneSmapsStatistics.handleSmapsTreeObj(dataTree, 2); + expect(dataTree.rsspro).toBe(0); + }); + + it('TabPaneSmapsStatisticsTest02', () => { + tabPaneSmapsStatistics.handleAllDataTree(new Smaps(), 0, "All", dataTree, 3); + expect(dataTree.children.length).toBe(1); + }); + + it('TabPaneSmapsStatisticsTest03', () => { + tabPaneSmapsStatistics.handleTree(smaps, 0, "TEXT", dataTree, 4); + expect(dataTree.pss).toBe(2); + }); + + it('TabPaneSmapsStatisticsTest04', () => { + let select = { + leftNs: 0, + rightNs: 500, + smapsType: [0, 1, 2] + } + tabPaneSmapsStatistics.data = select + expect(tabPaneSmapsStatistics.data = select).toBeTruthy() + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/timer-shaft/Flag.test.ts b/host/ide/test/trace/component/trace/timer-shaft/Flag.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..965a7d64ce7905eee8366a86bd0a8f47a9958803 --- /dev/null +++ b/host/ide/test/trace/component/trace/timer-shaft/Flag.test.ts @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {Flag} from "../../../../../dist/trace/component/trace/timer-shaft/Flag.js"; + +describe('Flag Test',()=>{ + + it('FlagTest01 ', function () { + let flag = new Flag(); + expect(flag).not.toBeUndefined(); + }); +}) diff --git a/host/ide/test/trace/component/trace/timer-shaft/Graph.test.ts b/host/ide/test/trace/component/trace/timer-shaft/Graph.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..0e6422c8e9d6c36fef42f1955eb284b6ce14ee93 --- /dev/null +++ b/host/ide/test/trace/component/trace/timer-shaft/Graph.test.ts @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {Graph} from "../../../../../dist/trace/component/trace/timer-shaft/Graph.js"; + +describe('Flag Test',()=>{ + + it('FlagTest01 ', function () { + let graph = new Graph(); + expect(graph).not.toBeUndefined(); + }); +}) diff --git a/host/ide/test/trace/component/trace/timer-shaft/RangeRuler.test.ts b/host/ide/test/trace/component/trace/timer-shaft/RangeRuler.test.ts index 99775c99538cd8e4f44aab9dc3baca4773796fcb..b8842b6a8a0504e06bc4d1e43830bfd0f2986aa1 100644 --- a/host/ide/test/trace/component/trace/timer-shaft/RangeRuler.test.ts +++ b/host/ide/test/trace/component/trace/timer-shaft/RangeRuler.test.ts @@ -17,14 +17,19 @@ import {RangeRuler} from "../../../../../dist/trace/component/trace/timer-shaft/RangeRuler.js" // @ts-ignore import {Mark} from "../../../../../dist/trace/component/trace/timer-shaft/RangeRuler.js"; +import {TimerShaftElement} from "../../../../../src/trace/component/trace/TimerShaftElement"; -describe('RangeRuler Test', ()=>{ +describe('RangeRuler Test', () => { const canvas = document.createElement('canvas'); canvas.width = 1; canvas.height = 1; const ctx = canvas.getContext('2d'); - let rangeRuler = new RangeRuler(canvas , ctx, { + document.body.innerHTML = '' + + let timerShaftElement = document.querySelector('#timerShaftEL') as TimerShaftElement; + + let rangeRuler = new RangeRuler(timerShaftElement, { x: 20, y: 20, width: 100, @@ -32,8 +37,9 @@ describe('RangeRuler Test', ()=>{ }, { startX: 10, endX: 30 + }, () => { }); - let mark = new Mark(canvas , ctx, '', { + let mark = new Mark(canvas, ctx, '', { x: 20, y: 20, width: 100, @@ -56,7 +62,33 @@ describe('RangeRuler Test', ()=>{ expect(rangeRuler.fillX()).toBeUndefined(); }); + it('RangeRulerTest21', function () { + rangeRuler.range.startNS =-1 + expect(rangeRuler.fillX()).toBe(undefined); + }); + + it('RangeRulerTest22', function () { + rangeRuler.range.endNS =-1 + expect(rangeRuler.fillX()).toBe(undefined); + }); + + it('RangeRulerTest23', function () { + rangeRuler.range.endNS =-1; + rangeRuler.range.totalNS =-2 + expect(rangeRuler.fillX()).toBe(undefined); + }); + + it('RangeRulerTest24', function () { + rangeRuler.range.startNS =-1; + rangeRuler.range.totalNS =-2 + expect(rangeRuler.fillX()).toBe(undefined); + }); + it('RangeRulerTest03', function () { + // window.requestAnimationFrame = window.requestAnimationFrame || + // jest.fn().mockImplementation(() => ({ + // + // })); expect(rangeRuler.keyPress({ key: 'w' })).toBeUndefined(); @@ -117,20 +149,20 @@ describe('RangeRuler Test', ()=>{ }); it('RangeRulerTest13', function () { - rangeRuler.markA = jest.fn(()=>true) - rangeRuler.rangeRect = jest.fn(()=>true) - rangeRuler.rangeRect.containsWithPadding = jest.fn(()=>true) + rangeRuler.markA = jest.fn(() => true) + rangeRuler.rangeRect = jest.fn(() => true) + rangeRuler.rangeRect.containsWithPadding = jest.fn(() => true) - rangeRuler.markA = jest.fn(()=> { + rangeRuler.markA = jest.fn(() => { return { frame: { x: 20 } } }) - rangeRuler.markA.isHover = jest.fn(()=> true) - rangeRuler.markA.frame = jest.fn(()=> []) - rangeRuler.markA.frame.x = jest.fn(()=>true) + rangeRuler.markA.isHover = jest.fn(() => true) + rangeRuler.markA.frame = jest.fn(() => []) + rangeRuler.markA.frame.x = jest.fn(() => true) expect(rangeRuler.mouseDown({ key: '' @@ -138,62 +170,80 @@ describe('RangeRuler Test', ()=>{ }); it('RangeRulerTest14', function () { - rangeRuler.markA = jest.fn(()=>true) - rangeRuler.rangeRect = jest.fn(()=>true) - rangeRuler.rangeRect.containsWithPadding = jest.fn(()=>false) - rangeRuler.frame = jest.fn(()=>false) - rangeRuler.frame.containsWithMargin = jest.fn(()=> true) - rangeRuler.rangeRect.containsWithMargin = jest.fn(()=> false) - rangeRuler.markB.isHover = jest.fn(()=> true) - rangeRuler.markB.frame = jest.fn(()=> true) - rangeRuler.markB.frame.x = jest.fn(()=>true) + rangeRuler.markA = jest.fn(() => true) + rangeRuler.rangeRect = jest.fn(() => true) + rangeRuler.rangeRect.containsWithPadding = jest.fn(() => false) + rangeRuler.frame = jest.fn(() => false) + rangeRuler.frame.containsWithMargin = jest.fn(() => true) + rangeRuler.rangeRect.containsWithMargin = jest.fn(() => false) + rangeRuler.markB.isHover = jest.fn(() => true) + rangeRuler.markB.frame = jest.fn(() => true) + rangeRuler.markB.frame.x = jest.fn(() => true) expect(rangeRuler.mouseDown({ key: '' })).toBeUndefined(); }); it('RangeRulerTest15', function () { - rangeRuler.markA = jest.fn(()=>true) - rangeRuler.markA.inspectionFrame = jest.fn(()=>true) - rangeRuler.markA.inspectionFrame.contains = jest.fn(()=>true) - rangeRuler.markA.frame = jest.fn(()=> true) - rangeRuler.markA.frame.x = jest.fn(()=>true) - rangeRuler.markA.draw = jest.fn(()=>true) + rangeRuler.markA = jest.fn(() => true) + rangeRuler.markA.inspectionFrame = jest.fn(() => true) + rangeRuler.markA.inspectionFrame.contains = jest.fn(() => true) + rangeRuler.markA.frame = jest.fn(() => true) + rangeRuler.markA.frame.x = jest.fn(() => true) + rangeRuler.markA.draw = jest.fn(() => true) + rangeRuler.centerXPercentage = jest.fn(() => -1) expect(rangeRuler.mouseMove({ key: '' })).toBeUndefined(); }); - it('RangeRulerTest16', ()=> { - rangeRuler.markA = jest.fn(()=>false) - rangeRuler.markA.draw = jest.fn(()=>true) - rangeRuler.markA.frame = jest.fn(()=> true) - rangeRuler.markA.frame.x = jest.fn(()=>true) - rangeRuler.markA.inspectionFrame = jest.fn(()=>false) - rangeRuler.markA.inspectionFrame.contains = jest.fn(()=>false) - rangeRuler.movingMark = jest.fn(()=>false) - rangeRuler.movingMark.frame = jest.fn(()=> false) - rangeRuler.movingMark.frame.x = jest.fn(()=>false) - rangeRuler.rangeRect = jest.fn(()=>true) - rangeRuler.rangeRect.containsWithPadding = jest.fn(()=>true) - rangeRuler.movingMark.inspectionFrame = jest.fn(()=>false) - rangeRuler.movingMark.inspectionFrame.x = jest.fn(()=>false) + it('RangeRulerTest16', () => { + rangeRuler.markA = jest.fn(() => false) + rangeRuler.markA.draw = jest.fn(() => true) + rangeRuler.markA.frame = jest.fn(() => true) + rangeRuler.markA.frame.x = jest.fn(() => true) + rangeRuler.markA.inspectionFrame = jest.fn(() => false) + rangeRuler.markA.inspectionFrame.contains = jest.fn(() => false) + rangeRuler.movingMark = jest.fn(() => false) + rangeRuler.movingMark.frame = jest.fn(() => false) + rangeRuler.movingMark.frame.x = jest.fn(() => false) + rangeRuler.rangeRect = jest.fn(() => true) + rangeRuler.rangeRect.containsWithPadding = jest.fn(() => true) + rangeRuler.movingMark.inspectionFrame = jest.fn(() => false) + rangeRuler.movingMark.inspectionFrame.x = jest.fn(() => false) expect(rangeRuler.mouseMove({ key: '' })).toBeUndefined(); }); - it('RangeRulerTest17', ()=> { - rangeRuler.notifyHandler = jest.fn(()=>true) - rangeRuler.movingMark.inspectionFrame.x = jest.fn(()=>false) - rangeRuler.c = jest.fn(()=>true) - rangeRuler.frame = jest.fn(()=>true) - rangeRuler.frame.x = jest.fn(()=>true) - rangeRuler.frame.y = jest.fn(()=>true) - rangeRuler.c.clearRect = jest.fn(()=>true) + + it('RangeRulerTest17', () => { + rangeRuler.notifyHandler = jest.fn(() => true) + rangeRuler.movingMark.inspectionFrame.x = jest.fn(() => false) + // rangeRuler.c = jest.fn(()=>true) + // rangeRuler.c.clearRect = jest.fn(()=>true) + rangeRuler.frame = jest.fn(() => true) + rangeRuler.frame.x = jest.fn(() => true) + rangeRuler.frame.y = jest.fn(() => true) expect(rangeRuler.draw()).toBeUndefined(); }); it('RangeRulerTest18', function () { expect(mark.isHover).toBeTruthy(); }); + it('RangeRulerTest19', function () { + rangeRuler.clearRect = jest.fn(() => true) + expect(rangeRuler.draw()).toBeUndefined(); + + }); + + it('RangeRulerTest20', function () { + rangeRuler.setRangeNS(0, 2000) + expect(rangeRuler.getRange().startX).toBe(0) + + }); + + it('RangeRulerTest25', function () { + expect(rangeRuler.delayDraw()).toBeUndefined(); + }); + }) diff --git a/host/ide/test/trace/component/trace/timer-shaft/SportRuler.test.ts b/host/ide/test/trace/component/trace/timer-shaft/SportRuler.test.ts index 41d3e8338cfab12b07b2b86f45ff640415871dcd..e62e3d0f89c440dbf29749c72287f2af94824518 100644 --- a/host/ide/test/trace/component/trace/timer-shaft/SportRuler.test.ts +++ b/host/ide/test/trace/component/trace/timer-shaft/SportRuler.test.ts @@ -15,18 +15,30 @@ // @ts-ignore import {SportRuler} from "../../../../../dist/trace/component/trace/timer-shaft/SportRuler.js" +// @ts-ignore +import {TimerShaftElement} from "../../../../../dist/trace/component/trace/TimerShaftElement.js"; +// @ts-ignore +import {Flag} from "../../../../../dist/trace/component/trace/timer-shaft/Flag.js"; +// @ts-ignore +import {TraceRow, RangeSelectStruct} from "../../../../../dist/trace/component/trace/base/TraceRow.js"; -describe('SportRuler Test', ()=>{ +describe('SportRuler Test', () => { const canvas = document.createElement('canvas'); canvas.width = 1; canvas.height = 1; const ctx = canvas.getContext('2d'); - let sportRuler = new SportRuler(canvas, ctx, { + document.body.innerHTML = '' + + let timerShaftElement = document.querySelector('#timerShaftEL') as TimerShaftElement; + + let sportRuler = new SportRuler(timerShaftElement, { x: 20, y: 20, width: 100, height: 100, + }, () => { + }, () => { }); sportRuler.range = { @@ -39,29 +51,6 @@ describe('SportRuler Test', ()=>{ xsTxt: [], } - it('SportRulerTest01', function () { - expect(sportRuler.drawTheFlag(2, '#999999', false, 'text')).toBeUndefined(); - }); - - it('SportRulerTest02', function () { - let randomRgbColor = sportRuler.randomRgbColor(); - let isColor = randomRgbColor.length > 4; - expect(isColor).toBeTruthy() - }); - - it('SportRulerTest03', function () { - expect(sportRuler.onFlagRangeEvent({ - x: 0, - y: 0, - width: 0, - height: 0, - time: 0, - color: "", - selected: false, - text: "", - }, 2)).toBeUndefined(); - }); - it('SportRulerTest04', function () { expect(sportRuler.mouseMove({ offsetY: 20, @@ -74,31 +63,228 @@ describe('SportRuler Test', ()=>{ expect(ranges.endNS).toBe(20); }) - it('SportRulerTest06', function () { - sportRuler.flagListIdx = jest.fn(()=>"flagListIdx") - sportRuler.flagList = jest.fn(()=>true) - expect(sportRuler.modifyFlagList('amend', {})).toBeUndefined(); - }) + // it('SportRulerTest06', function () { + // sportRuler.flagListIdx = jest.fn(() => "flagListIdx") + // sportRuler.flagList = jest.fn(() => true) + // expect(sportRuler.modifyFlagList('amend', {})).toBeUndefined(); + // }) it('SportRulerTest07', function () { - sportRuler.flagList.splice = jest.fn(()=>true) - expect(sportRuler.modifyFlagList('remove', {})).toBeUndefined(); + sportRuler.flagList.splice = jest.fn(() => true) + expect(sportRuler.modifyFlagList('remove')).toBeUndefined(); }) it('SportRulerTest08', function () { + let numbers = Array(); + numbers.push(12) + numbers.push(56) + sportRuler.flagList = [{ + totalNS: 10000, + startX: 0, + endX: 1000, + startNS: 0, + endNS: 10000, + xs: numbers, + xsTxt: ['s', 'f'] + }] + sportRuler.flagList.xs = jest.fn(()=> numbers) + let flags = new Array() + flags.push({ + x: 0, + y: 0, + width: 0, + height: 0, + time: 20, + color: "", + selected: false, + text: "", + hidden: false, + type: "", + }) + sportRuler.flagList = flags; + + let rangeSelectStruct = new RangeSelectStruct(); + rangeSelectStruct.startNS = 20 + rangeSelectStruct.endX = 1000 + rangeSelectStruct.startNS = 20 + rangeSelectStruct.endNS = 200 + // TraceRow.rangeSelectObject = rangeSelectStruct expect(sportRuler.draw()).toBeUndefined(); }) it('SportRulerTest09', function () { - expect(sportRuler.mouseUp()).toBeUndefined(); + let flags = new Array() + flags.push({ + x: 0, + y: 0, + width: 0, + height: 0, + time: 20, + color: "", + selected: false, + text: "", + hidden: false, + type: "", + }) + sportRuler.flagList = flags; + sportRuler.edgeDetection = jest.fn(()=> true) + + expect(sportRuler.mouseUp({offsetX: 20})).toBeUndefined(); }) it('SportRulerTest10', function () { - sportRuler.draw = jest.fn(()=>true) + sportRuler.draw = jest.fn(() => true) expect(sportRuler.mouseMove({ offsetX: 10000, offsetY: 10000 })).toBeUndefined(); }); + it('SportRulerTest11', function () { + let range = sportRuler.range; + expect(sportRuler.range.endNS).toBe(20) + }) + + it('SportRulerTest12', function () { + let flags = new Array() + flags.push({ + x: 0, + y: 0, + width: 0, + height: 0, + time: 0, + color: "", + selected: false, + text: "", + hidden: false, + type: "", + }) + sportRuler.flagList = flags; + sportRuler.drawTriangle(1000, 'triangle'); + // expect(sportRuler.range()).toBeUndefined(); + }) + + it('SportRulerTest13', function () { + let flags = new Array() + flags.push({ + x: 0, + y: 0, + width: 0, + height: 0, + time: 1000, + color: "", + selected: false, + text: "", + hidden: false, + type: "triangle", + }) + sportRuler.flagList = flags; + sportRuler.drawTriangle(1000, 'triangle'); + // expect(sportRuler.range()).toBeUndefined(); + }) + + it('SportRulerTest14', function () { + let flags = new Array() + flags.push({ + x: 0, + y: 0, + width: 0, + height: 0, + time: 0, + color: "", + selected: false, + text: "", + hidden: false, + type: "triangle", + }) + sportRuler.flagList = flags; + sportRuler.drawTriangle(1000, 'square'); + // expect(sportRuler.range()).toBeUndefined(); + }) + + it('SportRulerTest22', function () { + let flags = new Array() + flags.push({ + x: 0, + y: 0, + width: 0, + height: 0, + time: 0, + color: "", + selected: false, + text: "", + hidden: false, + type: "triangle", + }) + sportRuler.flagList = flags; + sportRuler.drawTriangle(1000, 'inverted'); + + }) + + // it('SportRulerTest15', function () { + // sportRuler.flagList.findIndex = jest.fn(() => 0) + // sportRuler.drawTriangle(1000, 'square') + // expect(sportRuler.range()).toBeUndefined(); + // }) + + // it('SportRulerTest16', function () { + // sportRuler.flagList.findIndex = jest.fn(() => -1) + // sportRuler.drawTriangle(1000, 'inverted') + // expect(sportRuler.range()).toBeUndefined(); + // }) + + it('SportRulerTest17', function () { + sportRuler.removeTriangle('inverted') + // expect(sportRuler.range()).toBeUndefined(); + }) + + it('SportRulerTest18', function () { + sportRuler.flagList.findIndex = jest.fn(() => 0) + sportRuler.removeTriangle('square') + // expect(sportRuler.range()).toBeUndefined(); + }) + + it('SportRulerTest19', function () { + sportRuler.drawInvertedTriangle(100, '#000000') + // expect(sportRuler.range()).toBeUndefined(); + }) + + it('SportRulerTest20', function () { + sportRuler.drawFlag(100, '#000000', false, 'text', '') + // expect(sportRuler.range()).toBeUndefined(); + }) + + it('SportRulerTest23', function () { + sportRuler.drawFlag(100, '#000000', false, 'text', 'triangle') + }) + + it('SportRulerTest21', function () { + let flags = new Array() + flags.push({ + x: 0, + y: 0, + width: 0, + height: 0, + time: 20, + color: "", + selected: false, + text: "", + hidden: false, + type: "", + }) + sportRuler.flagList = flags; + sportRuler.flagList.find = jest.fn(()=> false) + expect(sportRuler.mouseUp({offsetX: 20})).toBeUndefined(); + }) + + it('SportRulerTest24', function () { + sportRuler.drawSlicesMark(null,null) + + }) + + it('SportRulerTest25', function () { + sportRuler.setSlicesMark(null,null) + + }) + }) diff --git a/host/ide/test/trace/component/trace/timer-shaft/TabPaneFlag.test.ts b/host/ide/test/trace/component/trace/timer-shaft/TabPaneFlag.test.ts index 88198fa1f5bb856f9a54d18c55be597b1af29b7f..31483b8595039e62530c365c25d44e6a7a82ffe5 100644 --- a/host/ide/test/trace/component/trace/timer-shaft/TabPaneFlag.test.ts +++ b/host/ide/test/trace/component/trace/timer-shaft/TabPaneFlag.test.ts @@ -21,23 +21,22 @@ describe('TabPaneFlag Test', ()=>{ canvas.width = 1; canvas.height = 1; const ctx = canvas.getContext('2d'); - - let tabPaneFlag = new TabPaneFlag(canvas , ctx, { - x: 20, - y: 20, - width: 100, - height: 100 - }, 10000000000); + let tabPaneFlag = new TabPaneFlag() it('TabPaneFlagTest01', function () { + document.body.innerHTML = ' ' + tabPaneFlag = document.querySelector('#remove-flag') as TabPaneFlag; + let htmlButtonElement = document.createElement('button') as HTMLButtonElement; + document.body.appendChild(htmlButtonElement) + htmlButtonElement.dispatchEvent(new Event('click')) expect(tabPaneFlag.initElements()).toBeUndefined(); }); - it('TabPaneFlagTest01', function () { + it('TabPaneFlagTest02', function () { expect(tabPaneFlag.initHtml()).not.toBe('') }); - it('TabPaneFlagTest01', function () { + it('TabPaneFlagTest03', function () { expect(tabPaneFlag.setFlagObj({ x: 0, y: 0, @@ -47,6 +46,57 @@ describe('TabPaneFlag Test', ()=>{ color: "", selected: false, text: "", - }, 5)).toBeUndefined(); + })).toBeUndefined(); + }); + + it('TabPaneFlagTest04', function () { + expect(tabPaneFlag.initHtml()).toMatchInlineSnapshot(` +" + +
+
Annotation at
+ + Change color: + +
+ " +`); }); }) diff --git a/host/ide/test/trace/component/trace/timer-shaft/TimeRuler.test.ts b/host/ide/test/trace/component/trace/timer-shaft/TimeRuler.test.ts index cb3ae26ea93cedbc8bbf821b0757d47c2bf1d080..f9105019985fea08064b60a0dbf150f48adfa961 100644 --- a/host/ide/test/trace/component/trace/timer-shaft/TimeRuler.test.ts +++ b/host/ide/test/trace/component/trace/timer-shaft/TimeRuler.test.ts @@ -15,14 +15,19 @@ // @ts-ignore import {TimeRuler} from "../../../../../dist/trace/component/trace/timer-shaft/TimeRuler.js" +// @ts-ignore +import {TimerShaftElement} from "../../../../../dist/trace/component/trace/TimerShaftElement.js"; describe('TimeRuler Test', ()=>{ const canvas = document.createElement('canvas'); canvas.width = 1; canvas.height = 1; const ctx = canvas.getContext('2d'); + document.body.innerHTML = '' + + let timerShaftElement = document.querySelector('#timerShaftEL') as TimerShaftElement; - let timeRuler = new TimeRuler(canvas , ctx, { + let timeRuler = new TimeRuler(timerShaftElement ,{ x: 20, y: 20, width: 100, diff --git a/host/ide/test/trace/database/Procedure.test.ts b/host/ide/test/trace/database/Procedure.test.ts index c3cb4c95993cfc4840c0068f96a92307c1897c4c..d2d46e1169b6d351c61c14f49403b6a00c30585f 100644 --- a/host/ide/test/trace/database/Procedure.test.ts +++ b/host/ide/test/trace/database/Procedure.test.ts @@ -13,12 +13,16 @@ * limitations under the License. */ // @ts-ignore -import {procedurePool} from "../../../dist/trace/database/Procedure.js" +import {procedurePool,ProcedureThread} from "../../../dist/trace/database/Procedure.js" describe('procedure Test', () => { - // let procedure = new procedurePool(); + + it('ProfilerClientTest02', function () { + expect(procedurePool.isIdle()).not.toBeUndefined(); + }); + it('ProfilerClientTest01', function () { - expect(procedurePool.uuid).toBeUndefined(); + expect(procedurePool.submitWithName()).toBeUndefined(); }); - }) +}) diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneCpu.test.ts b/host/ide/test/trace/database/SqlLite.test.ts similarity index 64% rename from host/ide/test/trace/component/trace/sheet/TabPaneCpu.test.ts rename to host/ide/test/trace/database/SqlLite.test.ts index fed58e89359ecf027e3cd11f8481d1f21840ac8d..ad207dc9445b9aa5345b102e64e7266ad01ad198 100644 --- a/host/ide/test/trace/component/trace/sheet/TabPaneCpu.test.ts +++ b/host/ide/test/trace/database/SqlLite.test.ts @@ -12,18 +12,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - // @ts-ignore -import {TabPaneCpu} from "../../../../../dist/trace/component/trace/sheet/TabPaneCpu.js" - -describe('TabPaneCpu Test', ()=>{ +import {threadPool, DbThread,DbPool } from "../../../dist/trace/database/SqlLite.js"; +// import {DbPool} from "../../../src/trace/database/SqlLite"; - let tabPaneCpu = new TabPaneCpu(); - - it('TabPaneCpuTest01', function () { - expect(tabPaneCpu.initHtml()).not.toBe('') +describe('SqlLite Test', () => { + it('SqlLiteTest01', function () { + expect(DbThread).not.toBeTruthy(); }); - it('TabPaneCpuTest02', function () { - expect(tabPaneCpu.initElements()).toBeUndefined() + it('SqlLiteTest02', function () { + expect(DbPool).not.toBeUndefined(); + }); }) \ No newline at end of file diff --git a/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerCommon.test.ts b/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerCommon.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..80ab8c66825e47fcf44998afc2c225ff1a29d53c --- /dev/null +++ b/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerCommon.test.ts @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//@ts-ignore +import { ChartStruct, + Msg, + MerageBean, + merageBeanDataSplit, + getByteWithUnit, + getTimeString, + timeMsFormat2p, + getProbablyTime, + convertJSON} + //@ts-ignore + from "../../../../dist/trace/database/logic-worker/ProcedureLogicWorkerCommon.js" +describe('ProcedureLogicWorkerCommon Test', ()=> { + + it('ChartStructTest', function () { + let chartStruct = new ChartStruct(); + expect(chartStruct).not.toBeUndefined(); + }); + + it('MsgTest', function () { + let msg = new Msg(); + expect(msg).not.toBeUndefined(); + }); + + it('MerageBeanTest01', function () { + let merageBean = new MerageBean(); + expect(merageBean).not.toBeUndefined(); + }); + + it('MerageBeanTest02', function () { + let merageBean = new MerageBean(); + merageBean.parentNode = true; + expect(merageBean.parentNode).toBeTruthy(); + }); + + it('MerageBeanTest03', function () { + let merageBean = new MerageBean(); + merageBean.parentNode = false; + expect(merageBean.parentNode).toBeFalsy(); + }); + + it('MerageBeanTest04', function () { + let merageBean = new MerageBean(); + merageBean.total = true; + expect(merageBean.total).toBeTruthy(); + }); + + it('MerageBeanTest05', function () { + let merageBean = new MerageBean(); + merageBean.total = false; + expect(merageBean.total).toBeFalsy(); + }); + + it('MerageBeanTest06', function () { + merageBeanDataSplit.recursionChargeInitTree = jest.fn(()=>true) + merageBeanDataSplit.resetAllNode = jest.fn(()=>true) + expect(merageBeanDataSplit.splitTree('',[{children:[]}],"",true,[''],"")).toBeUndefined(); + }); + it('MerageBeanTest30', function () { + merageBeanDataSplit.recursionPruneInitTree = jest.fn(()=>true) + merageBeanDataSplit.resetAllNode = jest.fn(()=>true) + expect(merageBeanDataSplit.splitTree('',[{children:[]}],"",false,[''],"")).toBeUndefined(); + }); + + it('MerageBeanTest07', function () { + merageBeanDataSplit.recursionChargeInitTree = jest.fn(()=>true) + let node ={ + symbolName: '', + libName: '', + } + expect(merageBeanDataSplit.recursionChargeInitTree('',node,"",true)).toBeTruthy(); + }); + + it('MerageBeanTest47', function () { + merageBeanDataSplit.recursionChargeInitTree = jest.fn(()=>undefined); + merageBeanDataSplit.resetAllNode = jest.fn(()=>true) + let node = { + symbolName: '', + libName: '', + initChildren: { + length: 1, + } + } + expect(merageBeanDataSplit.recursionChargeInitTree('',node,[],true)).toBeUndefined(); + }); + + it('MerageBeanTest30', function () { + expect(getByteWithUnit(-1_000_000_001)).toBe("-953.67 Mb"); + }); + + it('MerageBeanTest08', function () { + expect(getByteWithUnit(1_000_000_001)).toBe("953.67 Mb"); + }); + + it('MerageBeanTest09', function () { + expect(getByteWithUnit(1_000_001)).toBe("976.56 Kb"); + }); + + it('MerageBeanTest10', function () { + expect(getByteWithUnit(1_001)).toBe("1001 byte"); + }); + + it('MerageBeanTest11', function () { + expect(getByteWithUnit(1_000_000_000_1)).toBe("9.31 Gb"); + }); + + it('MerageBeanTest12', function () { + expect(getTimeString(3600_000_000_002)).toBe("1h 2ns "); + }); + + it('MerageBeanTest13', function () { + expect(getTimeString(60_000_000_002)).toBe("1m 2ns "); + }); + + it('MerageBeanTest14', function () { + expect(getTimeString(1_000_000_003)).toBe("1s 3ns "); + }); + + it('MerageBeanTest15', function () { + expect(getTimeString(1_000_004)).toBe("1ms 4ns "); + }); + + it('MerageBeanTest16', function () { + expect(getTimeString(1_003)).toBe("1μs 3ns "); + }); + + it('MerageBeanTest31', function () { + expect(convertJSON('')).toBe(""); + }); + + it('MerageBeanTest33', function () { + expect(getProbablyTime('')).toBe(""); + }); + + it('MerageBeanTest34', function () { + expect(getProbablyTime(3600_000_000_000)).toBe("1.00h "); + }); + + it('MerageBeanTest35', function () { + expect(getProbablyTime(60_000_000_002)).toBe("1.00m "); + }); + + it('MerageBeanTest36', function () { + expect(getProbablyTime(1_000_000_000)).toBe("1.00s "); + }); + + it('MerageBeanTest37', function () { + expect(getProbablyTime(1_000_000)).toBe("1.00ms "); + }); + + it('MerageBeanTest38', function () { + expect(getProbablyTime(1_000)).toBe("1.00μs "); + }); + + it('MerageBeanTest44', function () { + expect(getProbablyTime(100)).toBe("100ns "); + }); + + it('MerageBeanTest39', function () { + expect(timeMsFormat2p('')).toBe("0s"); + }); + + it('MerageBeanTest40', function () { + expect(timeMsFormat2p(3600_000)).toBe("1.00h"); + }); + + it('MerageBeanTest41', function () { + expect(timeMsFormat2p(60_000)).toBe("1.00min"); + }); + + it('MerageBeanTest42', function () { + expect(timeMsFormat2p(1_000)).toBe("1.00s"); + }); + + it('MerageBeanTest43', function () { + expect(timeMsFormat2p(100)).toBe("100.00ms"); + }); + + it('MerageBeanTest17', function () { + merageBeanDataSplit.recursionChargeTree = jest.fn(()=>true); + let node = [{ + initChildren:{ + length:1 + } + }] + expect(merageBeanDataSplit.recursionChargeTree(node,"",true)).toBeTruthy(); + }); + + it('MerageBeanTest18', function () { + merageBeanDataSplit.recursionPruneInitTree = jest.fn(()=>true); + let node = [{ + initChildren:{ + length:1 + } + }] + expect(merageBeanDataSplit.recursionPruneInitTree('',node,"",true)).toBeTruthy(); + }); + + it('MerageBeanTest19', function () { + merageBeanDataSplit.recursionPruneTree = jest.fn(()=>true); + let node = [{ + initChildren:{ + length:1 + } + }] + expect(merageBeanDataSplit.recursionPruneTree(node,"",true)).toBeTruthy(); + }); + + it('MerageBeanTest20', function () { + merageBeanDataSplit.recursionChargeByRule = jest.fn(()=>true); + let node = [{ + initChildren:{ + length:1 + } + }] + expect(merageBeanDataSplit.recursionChargeByRule('',node,"",true)).toBeTruthy(); + }); + + it('MerageBeanTest21', function () { + merageBeanDataSplit.pruneChildren = jest.fn(()=>true); + let node = [{ + initChildren:{ + length:1 + } + }] + expect(merageBeanDataSplit.pruneChildren('',node,"")).toBeTruthy(); + }); + + it('MerageBeanTest22', function () { + merageBeanDataSplit.hideSystemLibrary = jest.fn(()=>true); + expect(merageBeanDataSplit.hideSystemLibrary('','')).toBeTruthy(); + }); + + it('MerageBeanTest23', function () { + merageBeanDataSplit.hideNumMaxAndMin = jest.fn(()=>true); + expect(merageBeanDataSplit.hideNumMaxAndMin('','',1,1)).toBeTruthy(); + }); + + it('MerageBeanTest24', function () { + merageBeanDataSplit.resotreAllNode = jest.fn(()=>true); + expect(merageBeanDataSplit.resotreAllNode('',true)).toBeTruthy(); + }); + + it('MerageBeanTest25', function () { + merageBeanDataSplit.resetAllNode = jest.fn(()=>true); + expect(merageBeanDataSplit.resetAllNode('',[],'')).toBeTruthy(); + }); + + it('MerageBeanTest26', function () { + merageBeanDataSplit.resetNewAllNode = jest.fn(()=>true); + expect(merageBeanDataSplit.resetNewAllNode('',[])).toBeTruthy(); + }); + + it('MerageBeanTest27', function () { + merageBeanDataSplit.clearSearchNode = jest.fn(()=>true); + expect(merageBeanDataSplit.clearSearchNode('')).toBeTruthy(); + }); + + it('MerageBeanTest28', function () { + merageBeanDataSplit.splitAllProcess = jest.fn(()=>true); + expect(merageBeanDataSplit.splitAllProcess('','',[])).toBeTruthy(); + }); + + it('MerageBeanTest29', function () { + merageBeanDataSplit.splitAllProcess = jest.fn(()=>true); + expect(merageBeanDataSplit.splitAllProcess('','',[])).toBeTruthy(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerCpuState.test.ts b/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerCpuState.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..bc5a1bf369089225cbd414c48714caac98b407bd --- /dev/null +++ b/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerCpuState.test.ts @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//@ts-ignore +import {ProcedureLogicWorkerCpuState, CpuState} from "../../../../dist/trace/database/logic-worker/ProcedureLogicWorkerCpuState.js" +describe('ProcedureLogicWorkerCpuState Test', ()=> { + + it('ProcedureLogicWorkerCpuStateTest01', function () { + let procedureLogicWorkerCpuState = new ProcedureLogicWorkerCpuState(); + expect(procedureLogicWorkerCpuState).not.toBeUndefined(); + + }); + + it('ProcedureLogicWorkerCpuStateTest02', function () { + let procedureLogicWorkerCpuState = new ProcedureLogicWorkerCpuState(); + let arr = [{ + startTs: 1, + endTs: 1, + length:1, + }] + expect(procedureLogicWorkerCpuState.supplementCpuState(arr)).toEqual([{"dur": 1, "endTs": 1, "startTs": 0, "value": 3}, {"endTs": 1, "length": 1, "startTs": 1}]) + }); + + it('ProcedureLogicWorkerCpuStateTest03', function () { + let procedureLogicWorkerCpuState = new ProcedureLogicWorkerCpuState(); + let data = { + type:"CpuState-getCpuState", + params:{ + list:true, + } + } + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerCpuState.handle(data)).toBeUndefined(); + + }); + + it('ProcedureLogicWorkerCpuStateTest04', function () { + let cpuState = new CpuState(); + cpuState = { + startTs: 0, + endTs: 0, + dur: 0, + value: 0, + } + expect(cpuState).not.toBeUndefined(); + }); + it('ProcedureLogicWorkerCpuStateTest05', function () { + let procedureLogicWorkerCpuState = new ProcedureLogicWorkerCpuState(); + let data = { + type:"CpuState-getCpuState", + params:{ + list:false, + } + } + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerCpuState.handle(data)).toBeUndefined(); + + }); + it('ProcedureLogicWorkerCpuStateTest06', function () { + let procedureLogicWorkerCpuState = new ProcedureLogicWorkerCpuState(); + + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerCpuState.queryData()).toBeUndefined(); + + }); + it('ProcedureLogicWorkerCpuStateTest07', function () { + let procedureLogicWorkerCpuState = new ProcedureLogicWorkerCpuState(); + + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerCpuState.getCpuState()).toBeUndefined(); + + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerFileSystem.test.ts b/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerFileSystem.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..c844d55ac1dcd683f8c60862223b5b39d3274c14 --- /dev/null +++ b/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerFileSystem.test.ts @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//@ts-ignore +import { + ProcedureLogicWorkerFileSystem, + FileCallChain, + FileSample, + Stack, + FileSysEvent, + FileMerageBean, + IoCompletionTimes, VirtualMemoryEvent + //@ts-ignore +} from "../../../../dist/trace/database/logic-worker/ProcedureLogicWorkerFileSystem.js" + +describe('ProcedureLogicWorkerFileSystem Test', ()=> { + + it('procedureLogicWorkerFileSystemTest', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + expect(procedureLogicWorkerFileSystem).not.toBeUndefined(); + }); + + it('procedureLogicWorkerFileSystemTest01', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + window.postMessage = jest.fn(()=>true) + let data ={ + type: "fileSystem-init" + } + expect(procedureLogicWorkerFileSystem.handle(data)).toBeUndefined() + }); + it('procedureLogicWorkerFileSystemTest35', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + window.postMessage = jest.fn(()=>true) + let data ={ + type: "fileSystem-queryCallchains", + params: { + list:[] + } + } + expect(procedureLogicWorkerFileSystem.handle(data)).toBeUndefined() + }); + it('procedureLogicWorkerFileSystemTest36', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + window.postMessage = jest.fn(()=>true) + let data ={ + type: "fileSystem-queryFileSamples", + params: { + list:[] + } + } + expect(procedureLogicWorkerFileSystem.handle(data)).toBeUndefined() + }); + it('procedureLogicWorkerFileSystemTest37', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + window.postMessage = jest.fn(()=>true) + let data ={ + type: "fileSystem-action", + length:0, + params: { + list:[], + filter:() => {return []} + } + } + expect(procedureLogicWorkerFileSystem.handle(data)).toBeUndefined() + }); + it('procedureLogicWorkerFileSystemTest38', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + window.postMessage = jest.fn(()=>true) + let data ={ + type: "fileSystem-queryStack", + params: { + list:[] + } + } + expect(procedureLogicWorkerFileSystem.handle(data)).toBeUndefined() + }); + it('procedureLogicWorkerFileSystemTest39', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + window.postMessage = jest.fn(()=>true) + let data ={ + type: "fileSystem-queryFileSysEvents", + params: { + list:[] + } + } + expect(procedureLogicWorkerFileSystem.handle(data)).toBeUndefined() + }); + + it('procedureLogicWorkerFileSystemTest07', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + expect(procedureLogicWorkerFileSystem.clearSplitMapData()).toBeUndefined() + }); + + it('procedureLogicWorkerFileSystemTest08', function () { + let fileCallChain = { + callChainId: 0, + depth: 0, + symbolsId: 0, + pathId: 0, + ip: "", + } + expect(fileCallChain).not.toBeUndefined() + }); + + it('procedureLogicWorkerFileSystemTest09', function () { + let stack = new Stack (); + stack = { + type: 0, + symbol: "", + path: "", + } + expect(stack).not.toBeUndefined() + }); + + it('procedureLogicWorkerFileSystemTest10', function () { + let fileSysEvent = new FileSysEvent (); + fileSysEvent = { + id: 0, + callchainId: 0, + startTs: 0, + startTsStr: "", + durStr: "", + dur: 0, + process: 0, + type: 0, + typeStr: "", + fd: "", + size: 0, + depth: 0, + firstArg: "", + secondArg: "", + thirdArg: "", + fourthArg: "", + returnValue: "", + error: "", + path: "", + symbol: "", + backtrace: [], + } + expect(fileSysEvent).not.toBeUndefined() + }); + + it('procedureLogicWorkerFileSystemTest11', function () { + let fileMerageBean = new FileMerageBean(); + expect(fileMerageBean).not.toBeUndefined(); + + }); + + it('procedureLogicWorkerFileSystemTest13', function () { + let fileSample = { + callChainId: 0, + dur: 0, + pid: 0, + processName: "", + } + expect(fileSample).not.toBeUndefined() + }); + + it('procedureLogicWorkerFileSystemTest14', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + expect(procedureLogicWorkerFileSystem.clearAll()).toBeUndefined(); + + }); + + it('procedureLogicWorkerFileSystemTest15', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + let currentNode = { + symbol: '', + path: '', + libName: '', + symbolName: '', + } + expect(procedureLogicWorkerFileSystem.setMerageName(currentNode)).toBeUndefined(); + + }); + + it('procedureLogicWorkerFileSystemTest33', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + let currentNode = { + pathId: -1, + symbol: '', + path: '', + libName: '', + symbolName: '', + } + expect(procedureLogicWorkerFileSystem.setMerageName(currentNode)).toBeUndefined(); + + }); + + it('procedureLogicWorkerFileSystemTest17', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + expect(procedureLogicWorkerFileSystem.freshCurrentCallchains([],1)).toBeUndefined(); + + }); + + it('procedureLogicWorkerFileSystemTest18', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + expect(procedureLogicWorkerFileSystem.initCallChainTopDown([])).toBeUndefined(); + + }); + + it('procedureLogicWorkerFileSystemTest19', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + expect(procedureLogicWorkerFileSystem.supplementFileSysEvents([],'events')); + + }); + + it('procedureLogicWorkerFileSystemTest21', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + expect(procedureLogicWorkerFileSystem.supplementFileSysEvents([],'')); + + }); + it('procedureLogicWorkerFileSystemTest22', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + expect(procedureLogicWorkerFileSystem.supplementFileSysEvents([])); + + }); + + it('procedureLogicWorkerFileSystemTest20', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + expect(procedureLogicWorkerFileSystem.getStacksByCallchainId([])); + + }); + + it('procedureLogicWorkerFileSystemTest23', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + let params = { + funcName: 'getCallChainsBySampleIds', + } + expect(procedureLogicWorkerFileSystem.resolvingAction(params)); + + }); + + it('procedureLogicWorkerFileSystemTest24', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + let params = { + funcName: 'getCurrentDataFromDb', + } + expect(procedureLogicWorkerFileSystem.resolvingAction(params)); + + }); + + it('procedureLogicWorkerFileSystemTest25', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + let params = { + funcName: 'hideSystemLibrary', + } + expect(procedureLogicWorkerFileSystem.resolvingAction(params)); + + }); + + it('procedureLogicWorkerFileSystemTest26', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + let params = { + funcName: 'hideNumMaxAndMin', + } + expect(procedureLogicWorkerFileSystem.resolvingAction(params)); + + }); + + it('procedureLogicWorkerFileSystemTest27', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + let params = { + funcName: 'splitAllProcess', + } + expect(procedureLogicWorkerFileSystem.resolvingAction(params)); + + }); + + it('procedureLogicWorkerFileSystemTest28', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + let params = { + funcName: 'resetAllNode', + } + expect(procedureLogicWorkerFileSystem.resolvingAction(params)); + + }); + + it('procedureLogicWorkerFileSystemTest29', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + let params = { + funcName: 'resotreAllNode', + } + expect(procedureLogicWorkerFileSystem.resolvingAction(params)); + + }); + + it('procedureLogicWorkerFileSystemTest30', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + let params = { + funcName: 'clearSplitMapData', + } + expect(procedureLogicWorkerFileSystem.resolvingAction(params)); + + }); + + it('procedureLogicWorkerFileSystemTest31', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + let params = { + funcName: 'splitTree', + } + expect(procedureLogicWorkerFileSystem.resolvingAction(params)); + + }); + + it('procedureLogicWorkerFileSystemTest32', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + let params = { + funcName: 'setSearchValue', + } + expect(procedureLogicWorkerFileSystem.resolvingAction(params)); + + }); + it('procedureLogicWorkerFileSystemTest34', function () { + let currentNode = { + processName: "", + ip:"", + pid:1, + pathId:"", + symbolsId:"", + selfDur:1, + self:1, + count:1, + } + let callChain = { + ip:"", + pid:1, + pathId:"", + symbolsId:"", + + } + let sample = { + processName:"", + dur:1, + } + let isEnd = true; + expect(FileMerageBean .merageCallChainSample(currentNode, callChain, sample, isEnd)); + + }); + it('procedureLogicWorkerFileSystemTest40', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + let selectionParam = { + fileSystemType:{ + length:1, + join:jest.fn(()=>true) + } + } + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerFileSystem.queryFileSamples(selectionParam)).toBeUndefined(); + + }); + it('procedureLogicWorkerFileSystemTest41', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + let sample = { + callChainId:1, + type:{ + toString + } + } + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerFileSystem.createThreadAndType(sample)).toBeTruthy() + + }); + it('procedureLogicWorkerFileSystemTest42', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + let currentNode = { + initChildren:{ + filter:jest.fn(()=>-1) + } + } + let callChainDataList = { + length:1, + } + let index = 0; + let sample = { + + } + let isTopDown = { + + } + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerFileSystem.merageChildrenByIndex(currentNode, callChainDataList, index, sample, isTopDown)).toBeUndefined() + + }); + it('procedureLogicWorkerFileSystemTest43', function () { + let procedureLogicWorkerFileSystem = new ProcedureLogicWorkerFileSystem(); + let params = { + length:1, + forEach:jest.fn(()=>true) + + + } + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerFileSystem.resolvingAction(params)).toStrictEqual([]) + + }); + + it('procedureLogicWorkerFileSystemTest45', function () { + let ioCompletionTimes = new IoCompletionTimes(); + expect(ioCompletionTimes).toBeDefined(); + + }); + + it('procedureLogicWorkerFileSystemTest46', function () { + let virtualMemoryEvent = new VirtualMemoryEvent(); + expect(virtualMemoryEvent).toBeDefined(); + + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerNativeNemory.test.ts b/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerNativeNemory.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..fb3666a4443c9209c87f7ed11d0c73078c200014 --- /dev/null +++ b/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerNativeNemory.test.ts @@ -0,0 +1,411 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//@ts-ignore +import {HeapTreeDataBean, NativeHookStatistics, NativeHookCallInfo, ProcedureLogicWorkerNativeMemory, NativeMemory, HeapStruct, NativeEvent, StatisticsSelection} from "../../../../dist/trace/database/logic-worker/ProcedureLogicWorkerNativeNemory.js" + +describe('ProcedureLogicWorkerNativeNemory Test', ()=> { + + it('ProcedureLogicWorkerNativeNemoryTest01', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + expect(procedureLogicWorkerNativeMemory).not.toBeUndefined(); + + }); + + it('ProcedureLogicWorkerNativeNemoryTest02', function () { + let nativeHookStatistics = new NativeHookStatistics(); + nativeHookStatistics = { + eventId: 0, + eventType: "", + subType: "", + subTypeId: 0, + heapSize: 0, + addr: "", + startTs: 0, + endTs: 0, + sumHeapSize: 0, + max: 0, + count: 0, + tid: 0, + threadName: "", + sSelected: false, + } + expect(nativeHookStatistics).not.toBeUndefined(); + + }); + + it('ProcedureLogicWorkerNativeNemoryTest03', function () { + let nativeHookCallInfo = new NativeHookCallInfo(); + expect(nativeHookCallInfo).not.toBeUndefined(); + + }); + + it('ProcedureLogicWorkerNativeNemoryTest04', function () { + let heapTreeDataBean = new HeapTreeDataBean(); + heapTreeDataBean = { + symbolId: 0, + fileId: 0, + startTs: 0, + endTs: 0, + depth: 0, + heapSize: 0, + eventId: "", + } + expect(heapTreeDataBean).not.toBeUndefined(); + }); + + it('ProcedureLogicWorkerNativeNemoryTest05', function () { + let nativeMemory = new NativeMemory(); + nativeMemory = { + index: 0, + eventId: 0, + eventType: "", + subType: "", + addr: "", + startTs: 0, + endTs: 0, + timestamp: "", + heapSize: 0, + heapSizeUnit: "", + symbol: "", + library: "", + isSelected: false, + state: "", + threadId: 0, + threadName: "", + } + expect(nativeMemory).not.toBeUndefined(); + }); + + it('ProcedureLogicWorkerNativeNemoryTest06', function () { + let heapStruct = new HeapStruct(); + expect(heapStruct).not.toBeUndefined(); + + }); + + it('ProcedureLogicWorkerNativeNemoryTest07', function () { + let nativeEvent = new NativeEvent(); + expect(nativeEvent).not.toBeUndefined(); + + }); + + it('ProcedureLogicWorkerNativeNemoryTest08', function () { + let statisticsSelection = new StatisticsSelection(); + expect(statisticsSelection).not.toBeUndefined(); + + }); + + it('ProcedureLogicWorkerNativeNemoryTest09', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + expect(procedureLogicWorkerNativeMemory.clearAll()).toBeUndefined(); + + }); + + it('ProcedureLogicWorkerNativeNemoryTest10', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let target = { + pid: 0, + depth: 1, + } + let src = { + depth: 0, + children:{ + push:jest.fn(()=>true), + } + } + expect(procedureLogicWorkerNativeMemory.listToTree(target,src)).toBeUndefined(); + + }); + + it('ProcedureLogicWorkerNativeNemoryTest11', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + expect(procedureLogicWorkerNativeMemory.getTypeFromIndex(-1,'','')).toBeFalsy(); + + }); + + it('ProcedureLogicWorkerNativeNemoryTest12', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + expect(procedureLogicWorkerNativeMemory.getTypeFromIndex(0,'','')).toBeTruthy(); + + }); + + it('ProcedureLogicWorkerNativeNemoryTest13', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let item = { + eventType: 'AllocEvent', + } + expect(procedureLogicWorkerNativeMemory.getTypeFromIndex(1,item,'')).toBeTruthy(); + + }); + + it('ProcedureLogicWorkerNativeNemoryTest14', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let item = { + eventType: 'MmapEvent', + } + expect(procedureLogicWorkerNativeMemory.getTypeFromIndex(2,item,'')).toBeTruthy(); + + }); + + it('ProcedureLogicWorkerNativeNemoryTest15', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let stack = { + children: [], + count: 1, + countValue: '', + countPercent: '', + size: 0, + threadId: 0, + threadName: '', + heapSizeStr: '', + heapPercent: '', + } + expect(procedureLogicWorkerNativeMemory.traverseTree(stack,1)).toBeUndefined(); + + }); + + it('ProcedureLogicWorkerNativeNemoryTest16', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let stack = { + children: [], + count: 1, + countValue: '', + countPercent: '', + size: 0, + threadId: 0, + threadName: '', + heapSizeStr: '', + heapPercent: '', + } + expect(procedureLogicWorkerNativeMemory.traverseSampleTree(stack,1)).toBeUndefined(); + + }); + + it('ProcedureLogicWorkerNativeNemoryTest17', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let target = { + depth: 1, + children: [], + count: 1, + countValue: '', + countPercent: '', + size: 0, + threadId: 0, + threadName: '', + heapSizeStr: '', + heapPercent: '', + } + let src = { + depth: 1, + children: [], + count: 1, + countValue: '', + countPercent: '', + size: 0, + threadId: 0, + threadName: '', + heapSizeStr: '', + heapPercent: '', + } + expect(procedureLogicWorkerNativeMemory.mergeTree(target,src)).toBeUndefined(); + + }); + + it('procedureLogicWorkerFileSystemTest18', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let data = { + id:1, + params:[{ + list:'', + }], + action:'', + type: 'native-memory-init' + } + procedureLogicWorkerNativeMemory.initDataDict = jest.fn(()=>true) + procedureLogicWorkerNativeMemory.clearAll = jest.fn(()=>true) + expect(procedureLogicWorkerNativeMemory.handle(data)).toBeUndefined(); + }); + + it('procedureLogicWorkerFileSystemTest19', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let data = { + id:1, + params:[{ + list:'', + }], + action:'', + type: 'native-memory-queryDataDICT' + } + procedureLogicWorkerNativeMemory.initNMChartData = jest.fn(()=>true) + expect(procedureLogicWorkerNativeMemory.handle(data)).toBeUndefined(); + }); + + it('procedureLogicWorkerFileSystemTest20', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let data = { + id:1, + params:[{ + list:'', + }], + action:'', + type: 'native-memory-queryNMChartData' + } + procedureLogicWorkerNativeMemory.initNMFrameData = jest.fn(()=>true) + expect(procedureLogicWorkerNativeMemory.handle(data)).toBeUndefined(); + }); + + it('procedureLogicWorkerFileSystemTest21', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let data = { + id:1, + params:[{ + list:'', + }], + action:'', + type: 'native-memory-queryNMFrameData' + } + window.postMessage = jest.fn(()=>true) + procedureLogicWorkerNativeMemory.initNMStack = jest.fn(()=>true) + expect(procedureLogicWorkerNativeMemory.handle(data)).toBeUndefined(); + }); + + it('procedureLogicWorkerFileSystemTest22', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let data = { + id:1, + params:[{ + list:'', + }], + action:'', + type: 'native-memory-action' + } + window.postMessage = jest.fn(()=>true) + procedureLogicWorkerNativeMemory.resolvingAction = jest.fn(()=>true) + expect(procedureLogicWorkerNativeMemory.handle(data)).toBeUndefined(); + }); + it('procedureLogicWorkerFileSystemTest23', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerNativeMemory.queryData()).toBeUndefined(); + }); + it('procedureLogicWorkerFileSystemTest24', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerNativeMemory.initDataDict()).toBeUndefined(); + }); + it('procedureLogicWorkerFileSystemTest25', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerNativeMemory.initNMChartData()).toBeUndefined(); + }); + it('procedureLogicWorkerFileSystemTest26', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerNativeMemory.initNMFrameData()).toBeUndefined(); + }); + it('procedureLogicWorkerFileSystemTest27', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + window.postMessage = jest.fn(()=>true) + let frameArr = { + map:jest.fn(()=>true) + } + expect(procedureLogicWorkerNativeMemory.initNMStack(frameArr)).toBeUndefined(); + }); + it('procedureLogicWorkerFileSystemTest28', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let paramMap = { + get:jest.fn(()=>"call-info") + } + procedureLogicWorkerNativeMemory.resolvingActionCallInfo = jest.fn(()=>true) + procedureLogicWorkerNativeMemory.resolvingActionCallInfo.dataSource = jest.fn(()=>true) + procedureLogicWorkerNativeMemory.resolvingActionCallInfo.dataSource.map = jest.fn(()=>true) + expect(procedureLogicWorkerNativeMemory.resolvingAction(paramMap)).toBeTruthy() + }); + it('procedureLogicWorkerFileSystemTest29', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let paramMap = new Map(); + paramMap.set("actionType","info") + procedureLogicWorkerNativeMemory.resolvingActionCallInfo = jest.fn(()=>true) + procedureLogicWorkerNativeMemory.resolvingActionCallInfo.dataSource = jest.fn(()=>true) + procedureLogicWorkerNativeMemory.resolvingActionCallInfo.dataSource.map = jest.fn(()=>true) + expect(procedureLogicWorkerNativeMemory.resolvingAction(paramMap)).toBeTruthy() + }); + it('procedureLogicWorkerFileSystemTest30', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let paramMap = { + get:jest.fn(()=>"memory-stack") + } + procedureLogicWorkerNativeMemory.resolvingActionCallInfo = jest.fn(()=>true) + procedureLogicWorkerNativeMemory.resolvingActionCallInfo.dataSource = jest.fn(()=>true) + procedureLogicWorkerNativeMemory.resolvingActionCallInfo.dataSource.map = jest.fn(()=>true) + expect(procedureLogicWorkerNativeMemory.resolvingAction(paramMap)).toBeTruthy() + }); + it('procedureLogicWorkerFileSystemTest31', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let paramMap = { + get:jest.fn(()=>"memory-chart") + } + procedureLogicWorkerNativeMemory.resolvingActionCallInfo = jest.fn(()=>true) + procedureLogicWorkerNativeMemory.resolvingActionCallInfo.dataSource = jest.fn(()=>true) + procedureLogicWorkerNativeMemory.resolvingActionCallInfo.dataSource.map = jest.fn(()=>true) + expect(procedureLogicWorkerNativeMemory.resolvingAction(paramMap)).toBeTruthy() + }); + it('procedureLogicWorkerFileSystemTest32', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let paramMap = { + get:jest.fn(()=>true) + } + procedureLogicWorkerNativeMemory.resolvingActionCallInfo = jest.fn(()=>true) + procedureLogicWorkerNativeMemory.resolvingActionCallInfo.dataSource = jest.fn(()=>true) + procedureLogicWorkerNativeMemory.resolvingActionCallInfo.dataSource.map = jest.fn(()=>true) + expect(procedureLogicWorkerNativeMemory.resolvingAction(paramMap)).toBeTruthy() + }); + it('procedureLogicWorkerFileSystemTest33', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let paramMap = { + get:jest.fn(()=>0) + } + procedureLogicWorkerNativeMemory.resolvingActionCallInfo = jest.fn(()=>true) + procedureLogicWorkerNativeMemory.resolvingActionCallInfo.dataSource = jest.fn(()=>true) + procedureLogicWorkerNativeMemory.resolvingActionCallInfo.dataSource.map = jest.fn(()=>true) + expect(procedureLogicWorkerNativeMemory.resolvingActionNativeMemoryChartData(paramMap)).toBeTruthy() + }); + it('procedureLogicWorkerFileSystemTest34', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let paramMap = { + get:jest.fn(()=>1) + } + procedureLogicWorkerNativeMemory.resolvingActionCallInfo = jest.fn(()=>true) + procedureLogicWorkerNativeMemory.resolvingActionCallInfo.dataSource = jest.fn(()=>true) + procedureLogicWorkerNativeMemory.resolvingActionCallInfo.dataSource.map = jest.fn(()=>true) + expect(procedureLogicWorkerNativeMemory.resolvingActionNativeMemoryChartData(paramMap)).toBeTruthy() + }); + it('ProcedureLogicWorkerNativeNemoryTest35', function () { + let procedureLogicWorkerNativeMemory = new ProcedureLogicWorkerNativeMemory(); + let target = { + pid: 0, + depth: 1, + } + let src = { + depth: 0, + children:{ + push:jest.fn(()=>true), + length:1, + } + } + expect(procedureLogicWorkerNativeMemory.listToTree(target,src)).toBeUndefined(); + + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerPerf.test.ts b/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerPerf.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..8358b8bd30abddf2c3b203bdb633fd94f763963b --- /dev/null +++ b/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerPerf.test.ts @@ -0,0 +1,517 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//@ts-ignore +import {ProcedureLogicWorkerPerf, PerfCountSample,PerfCallChainMerageData, PerfStack, PerfCmdLine, PerfCall,timeMsFormat2p,PerfFile,PerfThread,PerfCallChain} from "../../../../dist/trace/database/logic-worker/ProcedureLogicWorkerPerf.js" + +describe('ProcedureLogicWorkerPerf Test', ()=> { + + it('ProcedureLogicWorkerPerfTest', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + expect(procedureLogicWorkerPerf).not.toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest01', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let data = { + id:1, + params:[{ + list:'', + }], + action:'', + type: 'perf-init' + } + procedureLogicWorkerPerf.initPerfFiles = jest.fn(()=>true) + expect(procedureLogicWorkerPerf.handle(data)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest02', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let data = { + id:1, + params:[{ + list:'', + }], + action:'', + type: 'perf-queryPerfFiles' + } + procedureLogicWorkerPerf.initPerfThreads = jest.fn(()=>true) + expect(procedureLogicWorkerPerf.handle(data)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest03', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let data = { + id:1, + params:[{ + list:'', + }], + action:'', + type: 'perf-queryPerfThread' + } + procedureLogicWorkerPerf.initPerfCalls = jest.fn(()=>true) + expect(procedureLogicWorkerPerf.handle(data)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest04', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let data = { + id:1, + params:[{ + list:'', + }], + action:'', + type: 'perf-queryPerfCalls' + } + procedureLogicWorkerPerf.initPerfCallchains = jest.fn(()=>true) + expect(procedureLogicWorkerPerf.handle(data)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest05', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let data = { + id:1, + params:[{ + list:'', + }], + action:'', + type: 'perf-queryPerfCallchains' + } + window.postMessage = jest.fn(()=>true) + procedureLogicWorkerPerf.initCallChainTopDown = jest.fn(()=>true) + expect(procedureLogicWorkerPerf.handle(data)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest06', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let data = { + id:1, + params:[{ + list:'', + }], + action:'', + type: 'perf-queryCallchainsGroupSample' + } + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerPerf.handle(data)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest07', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let data = { + id:1, + params:[{ + list:'', + }], + action:'', + type: 'perf-action' + } + procedureLogicWorkerPerf.resolvingAction = jest.fn(()=>true) + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerPerf.handle(data)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest08', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + expect(procedureLogicWorkerPerf.clearAll()).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest09', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let callChain = [{ + sampleId: '', + depth: 0, + canCharge: false, + name: '', + tid: '', + fileName: '', + threadName: '', + }] + expect(procedureLogicWorkerPerf.initCallChainBottomUp(callChain)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest10', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let callChain = [{ + sampleId: '', + depth: 0, + canCharge: false, + name: '', + tid: '', + fileName: '', + threadName: '', + }] + expect(procedureLogicWorkerPerf.initCallChainTopDown([callChain])).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest11', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let callChain = { + sampleId: -1, + depth: 0, + canCharge: true, + name: '', + tid: '', + fileName: '', + threadName: '', + symbolId:-1 + } + expect(procedureLogicWorkerPerf.setCallChainName(callChain)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest12', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let callChain = { + sampleId: 0, + } + expect(procedureLogicWorkerPerf.setCallChainName(callChain)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest14', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let callChain = { + sampleId: '', + depth: 0, + canCharge: false, + name: '', + tid: '', + fileName: '', + threadName: '', + } + expect(procedureLogicWorkerPerf.addPerfCallData(callChain)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest15', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let callChain = { + sampleId: '', + } + expect(procedureLogicWorkerPerf.addGroupData(callChain)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest16', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + expect(procedureLogicWorkerPerf.getCallChainsBySampleIds([],[])).toBeTruthy(); + }); + + it('ProcedureLogicWorkerPerfTest17', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + expect(procedureLogicWorkerPerf.freshCurrentCallchains([],1)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest19', function () { + let perfCountSample = new PerfCountSample(); + perfCountSample = { + sampleId: 0, + count: 0, + pid: 0, + tid: 0, + threadState: '', + } + expect(perfCountSample).not.toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest20', function () { + let perfStack = new PerfStack(); + perfStack = { + sample: '', + path: '', + fileId: 0, + type: 0, + vaddrInFile: 0, + } + expect(perfStack).not.toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest21', function () { + let perfCmdLine = new PerfCmdLine(); + perfCmdLine = { + report_value: '', + } + expect(perfCmdLine).not.toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest21', function () { + let perfCmdLine = new PerfCmdLine(); + perfCmdLine = { + report_value: '', + } + expect(perfCmdLine).not.toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest21', function () { + let perfCall = new PerfCall(); + perfCall = { + sampleId: 0, + name: '', + depth: 0, + } + expect(perfCall).not.toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest22', function () { + expect(timeMsFormat2p('')).toBe("0s"); + }); + + it('ProcedureLogicWorkerPerfTest23', function () { + expect(timeMsFormat2p(3600_000)).toBe("1.00h"); + }); + + it('ProcedureLogicWorkerPerfTest24', function () { + expect(timeMsFormat2p(60_000)).toBe("1.00min"); + }); + + it('ProcedureLogicWorkerPerfTest25', function () { + expect(timeMsFormat2p(1_000)).toBe("1.00s"); + }); + + it('ProcedureLogicWorkerPerfTest26', function () { + expect(timeMsFormat2p(100)).toBe("100.00ms"); + }); + + it('ProcedureLogicWorkerPerfTest31', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + procedureLogicWorkerPerf.recursionChargeInitTree = jest.fn(()=>undefined); + let node = [{ + symbolName: '', + libName: '', + length: 1, + initChildren: { + length: 1, + } + }] + expect(procedureLogicWorkerPerf.recursionChargeInitTree(node,'',true)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest32', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + expect(procedureLogicWorkerPerf.splitTree([],'','',true)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest33', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + procedureLogicWorkerPerf.recursionPruneInitTree = jest.fn(()=>undefined); + let node = { + symbolName: '', + libName: '', + length: 1, + initChildren: { + length: 1, + } + } + expect(procedureLogicWorkerPerf.recursionPruneInitTree(node,'',true)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest34', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + procedureLogicWorkerPerf.recursionChargeByRule = jest.fn(()=>undefined); + let node = { + initChildren: [{ + length: 1, + }] + } + let rule = { + child: { + isStore: 1, + } + } + expect(procedureLogicWorkerPerf.recursionChargeByRule(node,'',rule)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest35', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerPerf.queryData("","","")).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest36', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + procedureLogicWorkerPerf.queryData = jest.fn(()=>true) + expect(procedureLogicWorkerPerf.initPerfFiles()).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest37', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + procedureLogicWorkerPerf.queryData = jest.fn(()=>true) + expect(procedureLogicWorkerPerf.initPerfThreads()).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest38', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + procedureLogicWorkerPerf.queryData = jest.fn(()=>true) + expect(procedureLogicWorkerPerf.initPerfCalls()).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest39', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + procedureLogicWorkerPerf.queryData = jest.fn(()=>true) + expect(procedureLogicWorkerPerf.initPerfCallchains()).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest40', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + procedureLogicWorkerPerf.queryData = jest.fn(()=>true) + let selectionParam = { + perfAll:'', + perfCpus:[1], + perfProcess:[2], + perfThread:[1], + leftNs:0, + rightNs:0 + } + expect(procedureLogicWorkerPerf.getCurrentDataFromDb(selectionParam)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerPerfTest41', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let currentNode = { + children:[], + initChildren:[], + } + let list = [{ + length:1, + name:"" + }] + expect(procedureLogicWorkerPerf.merageChildren(currentNode,list,true)).toBeUndefined(); + }); + it('ProcedureLogicWorkerPerfTest42', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let sampleIds = { + length:1, + } + let isTopDown = { + + } + expect(procedureLogicWorkerPerf.groupNewTreeNoId(sampleIds, isTopDown)).toStrictEqual([]); + }); + it('ProcedureLogicWorkerPerfTest43', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let node = { + initChildren:{ + length:1, + forEach:jest.fn(()=>true) + }, + libName:1 + } + let symbolName = 1; + + let isSymbol = true; + expect(procedureLogicWorkerPerf.recursionChargeInitTree(node, symbolName, isSymbol)).toBeUndefined(); + }); + it('ProcedureLogicWorkerPerfTest44', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let node = { + children:{ + length:1, + forEach:jest.fn(()=>true) + }, + libName:1 + } + let symbolName = 1; + + let isSymbol = true; + expect(procedureLogicWorkerPerf.recursionChargeTree(node, symbolName, isSymbol)).toBeUndefined(); + }); + it('ProcedureLogicWorkerPerfTest45', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let node = { + initChildren:{ + length:1, + forEach:jest.fn(()=>true) + }, + libName:1 + } + let symbolName = 1; + + let isSymbol = true; + expect(procedureLogicWorkerPerf.recursionPruneInitTree(node, symbolName, isSymbol)).toBeUndefined(); + }); + it('ProcedureLogicWorkerPerfTest46', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let node = { + children:{ + length:1, + forEach:jest.fn(()=>true) + }, + libName:1 + } + let symbolName = 1; + + let isSymbol = true; + expect(procedureLogicWorkerPerf.recursionPruneTree(node, symbolName, isSymbol)).toBeUndefined(); + }); + it('ProcedureLogicWorkerPerfTest47', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let node = { + initChildren:{ + length:1, + forEach:jest.fn(()=>true) + }, + } + let ruleName = 1; + + let rule = true; + expect(procedureLogicWorkerPerf.recursionChargeByRule(node, ruleName, rule)).toBeUndefined(); + }); + it('ProcedureLogicWorkerPerfTest48', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + let node = { + initChildren:{ + length:1, + forEach:jest.fn(()=>true) + }, + } + let symbolName = 1; + expect(procedureLogicWorkerPerf.pruneChildren(node, symbolName)).toBeUndefined(); + }); + it('ProcedureLogicWorkerPerfTest49', function () { + let procedureLogicWorkerPerf = new ProcedureLogicWorkerPerf(); + expect(procedureLogicWorkerPerf.clearSplitMapData()).toBeUndefined(); + }); + it('PerfFileTest01', function () { + let perfFile = new PerfFile(); + expect(perfFile.constructor()).toBeUndefined(); + }); + it('PerfFileTest02', function () { + let perfFile = new PerfFile(); + let path=true + expect(perfFile.setFileName(path)).toBeUndefined(); + }); + it('PerfThreadTest01', function () { + let perfThread = new PerfThread(); + expect(perfThread.constructor()).toBeUndefined(); + }); + it('PerfCallChainTest01', function () { + let perfCallChain = new PerfCallChain(); + expect(perfCallChain.constructor()).toBeUndefined(); + }); + it('PerfCallChainMerageDataTest01', function () { + let perfCallChainMerageData = new PerfCallChainMerageData(); + expect(perfCallChainMerageData.constructor()).toEqual({"canCharge": true, "children": [], "count": 0, "currentTreeParentNode": undefined, + "depth": 0, "dur": 0, "id": "", "initChildren": [], "isSelected": false, "isStore": 0, "libName": "", + "parentId": "", "path": "", "pid": 0, "searchShow": true, "self": "0s", "selfDur": 0, "size": 0, "symbol": "", + "symbolName": "", "tid": 0, "type": 0, "vaddrInFile": 0, "weight": "", "weightPercent": ""}); + }); + it('PerfCallChainMerageDataTest03', function () { + let perfCallChainMerageData = new PerfCallChainMerageData(); + perfCallChainMerageData.parentNode = true + expect(perfCallChainMerageData.parentNode).toBeTruthy() + }); + it('PerfCallChainMerageDataTest04', function () { + let perfCallChainMerageData = new PerfCallChainMerageData(); + perfCallChainMerageData.total = true + expect(perfCallChainMerageData.total).toBeTruthy() + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerSPT.test.ts b/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerSPT.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..8151ec745a8e4dad0b518742c0c1828911c9272a --- /dev/null +++ b/host/ide/test/trace/database/logic-worker/ProcedureLogicWorkerSPT.test.ts @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//@ts-ignore +import {ProcedureLogicWorkerSPT, ThreadState, ThreadProcess, SPT} from "../../../../dist/trace/database/logic-worker/ProcedureLogicWorkerSPT.js" + +describe('ProcedureLogicWorkerSPT Test', ()=> { + + it('ProcedureLogicWorkerSPTTest01', function () { + let procedureLogicWorkerSPT = new ProcedureLogicWorkerSPT(); + expect(procedureLogicWorkerSPT).not.toBeUndefined(); + }); + + it('ProcedureLogicWorkerSPTTest03', function () { + let threadState = new ThreadState(); + expect(threadState).not.toBeUndefined(); + }); + + it('ProcedureLogicWorkerSPTTest04', function () { + let threadProcess = new ThreadProcess(); + expect(threadProcess).not.toBeUndefined(); + }); + + it('ProcedureLogicWorkerSPTTest05', function () { + let sPT = new SPT(); + expect(sPT).not.toBeUndefined(); + }); + + it('ProcedureLogicWorkerSPTTest06', function () { + let procedureLogicWorkerSPT = new ProcedureLogicWorkerSPT(); + let data = { + id:1, + params:[{ + list:'', + }], + type: 'spt-init' + } + procedureLogicWorkerSPT.getThreadState = jest.fn(()=>true) + expect(procedureLogicWorkerSPT.handle(data)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerSPTTest07', function () { + let procedureLogicWorkerSPT = new ProcedureLogicWorkerSPT(); + let data = { + id:1, + params:[{ + list:'', + }], + type: 'spt-getThreadStateData' + } + procedureLogicWorkerSPT.getThreadProcessData = jest.fn(()=>true) + expect(procedureLogicWorkerSPT.handle(data)).toBeUndefined(); + }); + + it('ProcedureLogicWorkerSPTTest08', function () { + let procedureLogicWorkerSPT = new ProcedureLogicWorkerSPT(); + let data = { + id:1, + params:[{ + list:'', + }], + type: 'spt-getThreadProcessData' + } + procedureLogicWorkerSPT.initProcessThreadStateData = jest.fn(()=>true) + expect(procedureLogicWorkerSPT.handle(data)).toBeUndefined(); + }); + it('ProcedureLogicWorkerSPTTest09', function () { + let procedureLogicWorkerSPT = new ProcedureLogicWorkerSPT(); + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerSPT.queryData()).toBeUndefined(); + }); + it('ProcedureLogicWorkerSPTTest10', function () { + let procedureLogicWorkerSPT = new ProcedureLogicWorkerSPT(); + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerSPT.getThreadState()).toBeUndefined(); + }); + it('ProcedureLogicWorkerSPTTest11', function () { + let procedureLogicWorkerSPT = new ProcedureLogicWorkerSPT(); + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerSPT.getThreadProcessData()).toBeUndefined(); + }); + it('ProcedureLogicWorkerSPTTest12', function () { + let procedureLogicWorkerSPT = new ProcedureLogicWorkerSPT(); + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerSPT.getSPT()).toBeUndefined(); + }); + it('ProcedureLogicWorkerSPTTest13', function () { + let procedureLogicWorkerSPT = new ProcedureLogicWorkerSPT(); + window.postMessage = jest.fn(()=>true) + expect(procedureLogicWorkerSPT.initProcessThreadStateData()).toBeUndefined(); + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorker.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorker.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..aa116ac15a7c0e154cdb257bbff2713566ad553e --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorker.test.ts @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {ProcedureWorker,drawSelection} from "../../../dist/trace/database/ProcedureWorker.js"; + +describe('ProcedureWorker Test', ()=>{ + + it('ProcedureWorkerTest01', function () { + const context = { + globalAlpha:0.5, + fillStyle:"#666666", + fillRect:'', + } + const params ={ + isRangeSelect:{}, + rangeSelectObject:{ + startX:"", + endX:"", + startNS:"", + endNS:"", + + }, + startNS:"", + endNS:"", + totalNS:1, + frame:{ + x:"", + y:"", + height:1, + width:1, + } + + } + let drawSelection = jest.fn(() => true) + // @ts-ignore + expect(drawSelection(context,params)).toBeTruthy(); + + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerCPU.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerCPU.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..bd0df6034de5c37f40c6ae20e30befbe4d239a76 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerCPU.test.ts @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {cpu, CpuStruct,CpuRender,rtCpu,EmptyRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerCPU.js"; +// @ts-ignore +import {Rect} from "../../../../dist/trace/component/trace/timer-shaft/Rect.js"; + +describe(' Test', () => { + const dataSource = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + processId : '' + } + + it('CPUTest03', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + expect(CpuStruct.draw(ctx, data)).toBeUndefined() + }) + + it('CPUTest04', () => { + expect(CpuStruct.equals(new CpuStruct(),new CpuStruct())).toBeTruthy(); + }) + + it('CPUTest06', () => { + expect(CpuStruct.equals([],dataSource)).toBeFalsy() + }) + + + it('CPUTest05', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + expect(CpuStruct.draw(ctx, data)).toBeUndefined() + }) + + + it('CPUTest07', function () { + let cpuRender = new CpuRender() + let node = [{ + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + length:1, + height:2 + }] + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + let list = [{ + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + length:2, + height:2 + }] + expect(cpuRender.cpu(list ,node,1,1,1,frame,true)).toBeUndefined() + }); + + it('CPUTest07', function () { + let cpuRender = new CpuRender() + let node = [{ + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + length:1, + height:0 + }] + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + let list = [{ + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + length:2, + height:2 + }] + expect(cpuRender.cpu(list ,node,1,1,1,frame,false)).toBeUndefined() + }); + + it('CPUTest08', () => { + let node = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + length:1, + height:0, + startTime:0, + dur:1 + } + expect(CpuStruct.setCpuFrame(node,1,1,1,{width:10})).toBeUndefined() + }) + + it('CPUTest09', () => { + let node = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + length:1, + height:0, + startTime:2, + dur:1 + } + expect(CpuStruct.setCpuFrame(node,1,1,1,{width:10})).toBeUndefined() + }) + + it('CPUTest10', function () { + let emptyRender = new EmptyRender() + let req = { + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + canvas:'', + context:{}, + lineColor:'', + isHover:'', + hoverX:1, + params:'', + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100 + } + window.postMessage = jest.fn(()=>true) + expect(emptyRender.render(req,[],[])).toBeUndefined() + }); + + it('CPUTest11', function () { + let cpuRender = new CpuRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + }, + lineColor:'', + isHover:'', + hoverX:1, + params:'', + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100 + } + window.postMessage = jest.fn(()=>true) + expect(cpuRender.render(req,[],[])).toBeUndefined() + }); +}); \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerCommon.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerCommon.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..a6aaa1dedf1ac0f25f38183993626cbda17b878a --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerCommon.test.ts @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import { + ChartStruct, + drawFlagLine, + drawLines, + getFrameChartColor, + getHeatColor, + Point, + Rect, + ns2s, + ns2x, + drawSelection, + drawWakeUp + // @ts-ignore +} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerCommon.js" +// @ts-ignore +import {Flag} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerTimeline.js"; +// @ts-ignore +import {ColorUtils} from "../../../../dist/trace/component/trace/base/ColorUtils.js"; + +describe('ProcedureWorkerCommon Test', () => { + let rect = new Rect(); + + + it('ProcedureWorkerCommon01', function () { + expect(rect.contains(1, 2)).not.toBeUndefined(); + }); + + it('ProcedureWorkerCommon02', function () { + expect(rect.containsWithPadding()).not.toBeUndefined(); + }); + + it('ProcedureWorkerCommon03', function () { + let point = new Point(); + expect(point).not.toBeUndefined(); + }) + + + it('ProcedureWorkerCommon04', function () { + let rect = new Rect(); + expect(Rect.contains(rect, 1, 2)).toBe(false); + }) + + + it('ProcedureWorkerCommon05', function () { + let rect = new Rect(); + expect(Rect.containsWithPadding(rect, 1, 2, 1, 2)).toBe(false); + }) + + it('ProcedureWorkerCommon06', function () { + let rect = new Rect(); + expect(Rect.containsWithMargin(rect, 1, 2, 1, 2, 1, 1)).toBe(false); + }) + + + it('ProcedureWorkerCommon07', function () { + let rect = new Rect(); + let rect2 = new Rect(); + expect(Rect.intersect(rect, rect2)).toBe(false); + }) + + it('ProcedureWorkerCommon08', function () { + let rect = new Rect(); + expect(rect.containsWithMargin(1, 2, 3, 5, 4, 5)).toBe(false); + }) + + it('ProcedureWorkerCommon09', function () { + let rect = new Rect(); + expect(rect.containsWithPadding(1, 2, 3, 5)).toBe(false); + }) + + it('ProcedureWorkerCommon10', function () { + let rect = new Rect(); + let rect2 = new Rect(); + expect(rect.intersect(rect2)).toBe(false); + }) + + + it('ProcedureWorkerCommon011', function () { + expect(ColorUtils.formatNumberComma("11232")).toBe("11,232"); + }) + + it('ProcedureWorkerCommon012', function () { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + let aaa = [1, 2, 3] + drawLines(ctx, aaa, 1, "#ffff") + expect(ColorUtils.formatNumberComma("11232")).toBe("11,232"); + }) + + it('ProcedureWorkerCommon013', function () { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + let aaa = [1, 2, 3] + let flag = new Flag(1, 2, 3, 4, 5, "#FFF", false); + let rect2 = new Rect(); + drawFlagLine(ctx, aaa, flag, 1, 2, 2, rect2) + expect(ColorUtils.formatNumberComma("11232")).toBe("11,232"); + }) + + + it('ProcedureWorkerCommon20', function () { + expect(ns2s(2_000_000_000)).toBe("2.0 s"); + }); + + it('ProcedureWorkerCommon21', function () { + expect(ns2s(2_000_000)).toBe("2.0 ms"); + }); + + it('ProcedureWorkerCommon22', function () { + expect(ns2s(2_000)).toBe("2.0 μs"); + }); + + it('ProcedureWorkerCommon23', function () { + expect(ns2s(1)).toBe("1.0 ns"); + }); + + it('ProcedureWorkerCommon24', function () { + expect(ns2s(-1)).toBe("-1.0 s"); + }); + + it('ProcedureWorkerCommon25', function () { + expect(ColorUtils.hashFunc("",10,10)).toBe(3); + }); + + it('ProcedureWorkerCommon26', function () { + expect(ns2x(10,1,0,1,{width:2})).toBe(2); + }); + + it('ProcedureWorkerCommon27', function () { + expect(ns2x(-10,1,0,1,{width:2})).toBe(0); + }); + + it('ProcedureWorkerCommon28', function () { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + let flag = { + color:"", + x:1 + } + let select ={ + color:"", + x:1, + time:"", + } + let frame ={ + height:1 + } + let slicesTime ={ + startTime:1, + endTime:1, + color:"#dadada" + } + expect(drawFlagLine(ctx,flag,select,1,2,1,frame,slicesTime)).toBeUndefined(); + }); + + it('ProcedureWorkerCommon29', function () { + let context = { + globalAlpha:0.5, + fillStyle:"#666666", + } + let params = { + isRangeSelect:'', + rangeSelectObject: { + startX:1, + endX:10, + startNS:1, + endNS:10, + }, + startNS:1, + endNS:10, + totalNS:9, + frame:{ + y:0, + }, + + } + expect(drawSelection(context,params)).toBeUndefined(); + }); + + it('ProcedureWorkerCommon30', function () { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const context = canvas.getContext('2d'); + let wake = { + wakeupTime:2, + cpu:1 + } + let frame = new Rect(0, 10, 10, 10); + expect(drawWakeUp(context,wake,1,2,1,frame,undefined,undefined)).toBeUndefined(); + }); +}) + diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerCpuAbility.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerCpuAbility.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..ca93bc3b73f819f6a527314c975350dc023f33c1 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerCpuAbility.test.ts @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {CpuAbilityMonitorStruct,cpuAbility,CpuAbilityRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerCpuAbility.js"; +//@ts-ignore +import {Rect} from "../../../dist/trace/database/ProcedureWorkerCommon"; + +describe('CpuAbilityMonitorStruct Test', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + + const Sourcedata = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + maxCpuUtilization: 200, + value: 50 + } + it('CpuAbilityMonitorStructTest01', function () { + expect(CpuAbilityMonitorStruct.draw(ctx, data)).toBeUndefined() + }); + it('CpuAbilityMonitorStructTest03', function () { + expect(CpuAbilityMonitorStruct.draw(ctx, Sourcedata)).toBeUndefined() + }); + it('CpuAbilityMonitorStructTest02', function () { + let dataList = new Array(); + dataList.push({startNs: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNs: 1, dur: 111}) + cpuAbility(dataList, [{length:0}], 1, 100254, 100254, frame,true) + }); + + it('CpuAbilityMonitorStructTest05', function () { + let dataList = new Array(); + dataList.push({startNs: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNs: 1, dur: 111}) + cpuAbility(dataList, [{length:0}], 1, 100254, 100254, frame,false) + }); + + it('CpuAbilityMonitorStructTest06', function () { + let cpuAbilityRender = new CpuAbilityRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + }, + lineColor:'', + isHover:'', + hoverX:1, + params:'', + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100 + } + window.postMessage = jest.fn(()=>true) + expect(cpuAbilityRender.render(req,[],[])).toBeUndefined() + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerCpuState.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerCpuState.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..689ff6149e3e5f400668d691a80d173d78a9e383 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerCpuState.test.ts @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {CpuStateRender,CpuStateStruct,cpuState} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerCpuState.js" + +describe('ProcedureWorkerCpuState Test', () => { + + it('ProcedureWorkerCpuStateTest01', function () { + let node = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50, + startTs:1, + dur:10, + height:2 + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(CpuStateStruct.setFrame(node ,2,2,6,4,frame)).toBeUndefined() + }); + + it('ProcedureWorkerCpuStateTest01', function () { + let node = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50, + startTs:3, + dur:1, + height:2 + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(CpuStateStruct.setFrame(node ,2,2,6,4,frame)).toBeUndefined() + }); + + it('ProcedureWorkerCpuStateTest02', function () { + let cpuStateRender = new CpuStateRender() + let node = [{ + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + length:0, + height:2 + }] + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(cpuStateRender.cpuState(node ,[{length:1}],"",[],4,1,1,frame,true)).toBeUndefined() + }); + + it('ProcedureWorkerCpuStateTest03', function () { + let cpuStateRender = new CpuStateRender() + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10,length:1, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 2,length:1}) + let res = [{ + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 1, + length:1, + height:2, + dur:1 + }] + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(cpuStateRender.cpuState([],dataList,"",res,1,6,5,frame,true)).toBeUndefined() + }); + + it('ProcedureWorkerCpuStateTest04', function () { + let cpuStateRender = new CpuStateRender() + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10,length:1, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 2,length:1}) + let res = [{ + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 10, + length:1, + height:2, + dur:1 + }] + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(cpuStateRender.cpuState([],dataList,"",res,1,6,5,frame,true)).toBeUndefined() + }); + + +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerDiskIoAbility.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerDiskIoAbility.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..581b8983ab569dd008de2a5fedb9eb48fd239853 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerDiskIoAbility.test.ts @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {DiskAbilityMonitorStruct,diskIoAbility,DiskIoAbilityRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerDiskIoAbility.js"; +//@ts-ignore +import {Rect} from "../../../dist/trace/database/ProcedureWorkerCommon"; + +describe('ProcedureWorkerDiskIoAbility Test', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + const Sourcedata = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + maxDiskRate: 200, + value: 50 + } + let res = [{ + startNS: 0, + dur: 10, + frame: { + x:0, + y:9, + width:10, + height:10 + } + }] + + it('ProcedureWorkerDiskIoAbilityTest01', function () { + expect(DiskAbilityMonitorStruct.draw(ctx, data)).toBeUndefined() + }); + + it('ProcedureWorkerDiskIoAbilityTest03', function () { + expect(DiskAbilityMonitorStruct.draw(ctx, Sourcedata)).toBeUndefined() + }); + it('CpuAbilityMonitorStructTest02', function () { + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 111}) + diskIoAbility(dataList, [{length: 1}], 1, 100254, 100254, "",true) + }); + + it('CpuAbilityMonitorStructTest03', function () { + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 111}) + diskIoAbility(dataList, [{length: 0}], 1, 100254, 100254, "",false) + }); + + it('CpuAbilityMonitorStructTest04', function () { + let diskIoAbilityRender = new DiskIoAbilityRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + }, + lineColor:'', + isHover:'', + hoverX:1, + params:'', + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100 + } + window.postMessage = jest.fn(()=>true) + expect(diskIoAbilityRender.render(req,[],[])).toBeUndefined() + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerEnergyAnomaly.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerEnergyAnomaly.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..c8e1a3976093463b79a8b359524ab95ed727fb0d --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerEnergyAnomaly.test.ts @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {anomaly,EnergyAnomalyStruct,EnergyAnomalyRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerEnergyAnomaly.js" + +describe('ProcedureWorkerEnergyAnomaly Test', () => { + + it('ProcedureWorkerEnergyAnomalyTest01', function () { + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10,length:1, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 2,length:1}) + anomaly(dataList, [{length:1}], 1, 3, 2, frame, "",true) + }); + + it('ProcedureWorkerEnergyAnomalyTest02', function () { + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10,length:1, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 2,length:1}) + anomaly(dataList, [{length:0}], 1, 3, 2, frame, "",false) + }); + + it('ProcedureWorkerEnergyAnomalyTest03', function () { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + } + } + let path = new Path2D() + expect(EnergyAnomalyStruct.draw(ctx, path, data)).toBeUndefined() + }); + + it('ProcedureWorkerEnergyAnomalyTest04', function () { + let node = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 1, + value: 50, + startTs:3, + dur:3, + height:2 + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(EnergyAnomalyStruct.setAnomalyFrame(node, 1,2,5, frame)).toBeUndefined() + }); + + it('ProcedureWorkerEnergyAnomalyTest05', function () { + let node = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 6, + value: 50, + startTs:3, + dur:3, + height:2 + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(EnergyAnomalyStruct.setAnomalyFrame(node, 1,2,5, frame)).toBeUndefined() + }); + + it('ProcedureWorkerEnergyAnomalyTest06', function () { + let energyAnomalyRender = new EnergyAnomalyRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + }, + lineColor:'', + isHover:'', + hoverX:1, + params:'', + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100 + } + window.postMessage = jest.fn(()=>true) + expect(energyAnomalyRender.render(req,[],[])).toBeUndefined() + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerEnergyPower.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerEnergyPower.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..6a3b25037a3d10a132dcbbf2c770ae7ba3f95352 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerEnergyPower.test.ts @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {EnergyPowerStruct,EnergyPowerRender,power} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerEnergyPower.js" + +describe('ProcedureWorkerEnergyPower Test', () => { + + it('ProcedureWorkerEnergyPowerTest01', function () { + let req = { + context:{ + globalAlpha:1.0, + lineWidth:1, + fillStyle:"#333", + } + } + let data = { + cpu:1, + location:2, + gpu:1, + display:1, + camera:1, + bluetooth:3, + flashlight:10, + audio:16, + wifiscan:1, + ts:10, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + } + } + EnergyPowerStruct.drawHistogram = jest.fn(()=>true) + EnergyPowerStruct.drawPolyline = jest.fn(()=>true) + expect(EnergyPowerStruct.draw(req, 3, data)).toBeUndefined() + }); + + it('ProcedureWorkerEnergyPowerTest02', function () { + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + let node = { + ts:10, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + } + } + expect(EnergyPowerStruct.setPowerFrame(node, 1, 2,5,3,frame)).toBeUndefined() + }); + + it('ProcedureWorkerEnergyPowerTest03', function () { + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + let node = { + ts:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + } + } + expect(EnergyPowerStruct.setPowerFrame(node, 1, 2,2000000002,2000000000,frame)).toBeUndefined() + }); + + it('ProcedureWorkerEnergyPowerTest04', function () { + expect(EnergyPowerStruct.getHistogramColor('CPU')).toBe("#92D6CC") + }); + + it('ProcedureWorkerEnergyPowerTest05', function () { + expect(EnergyPowerStruct.getHistogramColor('LOCATION')).toBe("#61CFBE") + }); + + it('ProcedureWorkerEnergyPowerTest06', function () { + expect(EnergyPowerStruct.getHistogramColor('GPU')).toBe("#86C5E3") + }); + + it('ProcedureWorkerEnergyPowerTest07', function () { + expect(EnergyPowerStruct.getHistogramColor('DISPLAY')).toBe("#46B1E3") + }); + + it('ProcedureWorkerEnergyPowerTest08', function () { + expect(EnergyPowerStruct.getHistogramColor('CAMERA')).toBe("#C386F0") + }); + + it('ProcedureWorkerEnergyPowerTest09', function () { + expect(EnergyPowerStruct.getHistogramColor('BLUETOOTH')).toBe("#8981F7") + }); + + it('ProcedureWorkerEnergyPowerTest10', function () { + expect(EnergyPowerStruct.getHistogramColor('AUDIO')).toBe("#AC49F5") + }); + + it('ProcedureWorkerEnergyPowerTest11', function () { + expect(EnergyPowerStruct.getHistogramColor('WIFISCAN')).toBe("#92C4BD") + }); + + it('ProcedureWorkerEnergyPowerTest12', function () { + expect(EnergyPowerStruct.getHistogramColor('WIFISCANxcda')).toBe("#564AF7") + }); + + it('ProcedureWorkerEnergyPowerTest13', function () { + expect(EnergyPowerStruct).not.toBeUndefined() + }); + + it('ProcedureWorkerEnergyPowerTest14', function () { + let energyPowerRender = new EnergyPowerRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + }, + lineColor:'', + isHover:'', + hoverX:1, + params:'', + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100 + } + window.postMessage = jest.fn(()=>true) + expect(energyPowerRender.render(req,[],[])).toBeUndefined() + }); + + it('ProcedureWorkerEnergyPowerTest15', function () { + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10,length:1, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 2,length:1}) + power(dataList, [{length:1}],1,3,2, frame,true,"") + }); + + it('ProcedureWorkerEnergyPowerTest16', function () { + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10,length:1, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 2,length:1}) + power(dataList, [{length:0}],1,3,2, frame,false,"") + }); +}) diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerEnergyState.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerEnergyState.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..0599ed7f2353a9f825ee8634bd51d5f2aab03c43 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerEnergyState.test.ts @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {state,EnergyStateStruct,EnergyStateRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerEnergyState.js" + +describe('ProcedureWorkerEnergyState Test', () => { + + it('ProcedureWorkerEnergyStateTest01', function () { + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10,length:1, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 2,length:1}) + state(dataList, [{length:1}],1,3,2, frame,true) + }); + + it('ProcedureWorkerEnergyStateTest02', function () { + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10,length:1, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 2,length:1}) + state(dataList, [{length:0}],1,3,2, frame,false) + }); + + it('ProcedureWorkerEnergyStateTest03', function () { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + type :"", + value: 0, + startNs: 1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + } + } + expect(EnergyStateStruct.draw(ctx , data)).toBeUndefined() + }); + + it('ProcedureWorkerEnergyStateTest04', function () { + expect(EnergyStateStruct.setDrawColor('BRIGHTNESS_NIT')).toBe("#92D6CC") + }); + + it('ProcedureWorkerEnergyStateTest05', function () { + expect(EnergyStateStruct.setDrawColor('SIGNAL_LEVEL')).toBe("#61CFBE") + }); + + it('ProcedureWorkerEnergyStateTest06', function () { + expect(EnergyStateStruct.setDrawColor('WIFI_EVENT_RECEIVED')).toBe("#46B1E3") + }); + + it('ProcedureWorkerEnergyStateTest07', function () { + expect(EnergyStateStruct.setDrawColor('AUDIO_STREAM_CHANGE')).toBe("#ED6F21") + }); + + it('ProcedureWorkerEnergyStateTest08', function () { + expect(EnergyStateStruct.setDrawColor('WIFI_STATE')).toBe("#61CFBE") + }); + + it('ProcedureWorkerEnergyStateTest09', function () { + expect(EnergyStateStruct.setDrawColor('LOCATION_SWITCH_STATE')).toBe("#61CFBE") + }); + + it('ProcedureWorkerEnergyStateTest10', function () { + expect(EnergyStateStruct.setDrawColor('SENSOR_STATE')).toBe("#61CFBE") + }); + + it('ProcedureWorkerEnergyStateTest11', function () { + expect(EnergyStateStruct.setDrawColor('aaaa')).toBe("#61CFBE") + }); + + it('ProcedureWorkerEnergyStateTest12', function () { + let energyStateRender = new EnergyStateRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + height:150, + width:100 + }, + lineColor:'', + isHover:'', + hoverX:1, + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100, + params:{ + isLive:false, + maxHeight:2, + dpr:1, + hoverFuncStruct:'', + selectFuncStruct:undefined, + }, + } + window.postMessage = jest.fn(()=>true) + expect(energyStateRender.render(req,[{}],[])).toBeUndefined() + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerEnergySystem.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerEnergySystem.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..6b0a96b2989141eda0c4aa4379882dadd6d86720 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerEnergySystem.test.ts @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {system,EnergySystemStruct,EnergySystemRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerEnergySystem.js" + +describe('ProcedureWorkerEnergySystem Test', () => { + + it('ProcedureWorkerEnergySystemTest01', function () { + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + let dataList = new Array(); + dataList.push({startNs: 0, dur: 10, length: 1, frame: {x: 0, y: 9, width: 10, height: 10}}) + dataList.push({startNs: 1, dur: 2, length: 1}) + system(dataList, [{length: 1}], 1, 3, 2, frame, true) + }); + + it('ProcedureWorkerEnergySystemTest02', function () { + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + + let aa: any = [] + let dataList = new Array(); + dataList.push({startNs: 0, dur: 10, frame: {x: 0, y: 9, width: 10, height: 10}}); + dataList.push({startNs: 1, dur: 2}) + aa[0] = dataList + aa[1] = dataList + aa[2] = dataList + system(aa , [], 1, 3, 2, frame, false) + }); + + it('ProcedureWorkerEnergyStateTest04', function () { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + type :0, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + } + } + expect(EnergySystemStruct.draw(ctx , data)).toBeUndefined() + }); + + it('ProcedureWorkerEnergyStateTest05', function () { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + type :1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + } + } + expect(EnergySystemStruct.draw(ctx , data)).toBeUndefined() + }); + + it('ProcedureWorkerEnergyStateTest06', function () { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + type :2, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + } + } + expect(EnergySystemStruct.draw(ctx , data)).toBeUndefined() + }); + + it('ProcedureWorkerEnergyStateTest07', function () { + let node = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 1, + value: 50, + startTs:3, + dur:3, + height:2, + type:0, + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(EnergySystemStruct.setSystemFrame(node , 1,1,3,2,frame)).toBeUndefined() + }); + + it('ProcedureWorkerEnergyStateTest08', function () { + let node = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 3, + value: 50, + startTs:3, + dur:3, + height:2, + type:1, + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(EnergySystemStruct.setSystemFrame(node , 1,2,3,1,frame)).toBeUndefined() + }); + + it('ProcedureWorkerEnergyStateTest09', function () { + let node = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 1, + value: 50, + startTs:3, + dur:3, + height:2, + type:2, + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(EnergySystemStruct.setSystemFrame(node , 1,1,3,2,frame)).toBeUndefined() + }); + + it('ProcedureWorkerEnergyStateTest10', function () { + let energySystemRender = new EnergySystemRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + height:150, + width:100 + }, + lineColor:'', + isHover:'', + hoverX:1, + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100, + params:{ + isLive:false, + maxHeight:2, + dpr:1, + hoverFuncStruct:'', + selectFuncStruct:undefined, + }, + } + window.postMessage = jest.fn(()=>true) + expect(energySystemRender.render(req,[{}],[])).toBeUndefined() + }); +}) diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerFPS.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerFPS.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..ff93a7400f6466d4b84cde028064a2fffee6d640 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerFPS.test.ts @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {fps, FpsStruct,FpsRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerFPS.js"; +// @ts-ignore +import {Rect} from "../../../../dist/trace/component/trace/timer-shaft/Rect.js"; + +describe(' FPSTest', () => { + + it('FpsTest01', () => { + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111}) + let rect = new Rect(0, 10, 10, 10); + fps(dataList, [{length: 1}], 1, 100254, 100254, rect,true) + }) + + it('FpsTest02', () => { + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111, frame: {x:0, y:9, width:10, height:10}}) + let rect = new Rect(0, 10, 10, 10); + fps(dataList, [{length: 0}], 1, 100254, 100254, rect,false) + }) + + it('FpsTest03', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + + expect(FpsStruct.draw(ctx, data)).toBeUndefined() + }) + + + it('FpsTest04', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + new FpsStruct(1); + FpsStruct.hoverFpsStruct = jest.fn(() => {startNS:200}) + FpsStruct.a = jest.fn(() => data); + expect(FpsStruct.draw(ctx, data)).toBeUndefined() + }) + it('FpsTest05 ', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + const Sourcedate = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + maxFps: 200, + value: 50 + } + expect(FpsStruct.draw(ctx,Sourcedate)).toBeUndefined() + }); + + it('FpsTest06', function () { + let fpsRender = new FpsRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + height:150, + width:100 + }, + lineColor:'', + isHover:'', + hoverX:1, + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100, + params:{ + isLive:false, + maxHeight:2, + dpr:1, + hoverFuncStruct:'', + selectFuncStruct:undefined, + } + } + window.postMessage = jest.fn(()=>true) + expect(fpsRender.render(req,[],[])).toBeUndefined() + }); +}); \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerFileSystem.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerFileSystem.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..6fbb12a7f8b1aa380cda3721936c59c3fbc8cae7 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerFileSystem.test.ts @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {fileSysChart,FileSysChartStruct} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerFileSystem.js" + +describe('ProcedureWorkerFileSystem Test', () => { + + it('ProcedureWorkerFileSystemTest01', function () { + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(fileSysChart([], [{length: 1}], "", [{length: 1}], 1, 2, 1, frame, true, true,true)).toBeUndefined() + }); + + it('ProcedureWorkerFileSystemTest02', function () { + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(fileSysChart([], [{length: 1}], "", [{length: 0}], 1, 2, 1, frame, false, false,false)).toBeUndefined() + }); + + it('ProcedureWorkerFileSystemTest03', function () { + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:1}}) + dataList.push({startTime: 1, dur: 111}) + fileSysChart(dataList, dataList, "", [{length: 0}], 1, 2, 1, frame, true, false,false) + }); + + it('ProcedureWorkerFileSystemTest03', function () { + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:0}}) + dataList.push({startTime: 1, dur: 111}) + fileSysChart(dataList, dataList, "", [{length: 0}], 1, 2, 1, frame, true, false,false) + }); + + it('ProcedureWorkerFileSystemTest04', function () { + let node = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 0, + value: 50, + startTs:3, + dur:1, + height:2 + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(FileSysChartStruct.setFrame(node,2, 1,2,frame)).toBeUndefined() + }); + + it('ProcedureWorkerFileSystemTest05', function () { + let node = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 2, + value: 50, + startTs:3, + dur:3, + height:2 + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(FileSysChartStruct.setFrame(node,2, 1,2,frame)).toBeUndefined() + }); + + it('ProcedureWorkerFileSystemTest06', function () { + expect(FileSysChartStruct.computeHeightNoGroup([{length:1}],10)).toEqual([{ + "dur": 10, "group10Ms": false, "height": 18, "size": 1, "startNS": 0}, + {"dur": 0, "group10Ms": false, "height": 0, "size": 0, "startNS": 10} + ]); + }); + + it('ProcedureWorkerFileSystemTest07', function () { + expect(FileSysChartStruct.groupBy10MSWithMaxLatency([{id:1,NS:3},{copy:"1"}])).toEqual([{"dur": 10000000, "height": NaN, "startNS": NaN,"group10Ms": true,"size": undefined,}]) + }); + + it('ProcedureWorkerFileSystemTest08', function () { + expect(FileSysChartStruct.groupBy10MSWithCount([{id:1,NS:3},{copy:"1"}])).toEqual([{"dur": 10000000, "height": 36, "startNS": NaN,"group10Ms": true,"size": 2,}]) + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerFreq.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerFreq.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..ba6e0a5ffc2ce257e3a2a763fcbbc7c4afd4e6e7 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerFreq.test.ts @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {CpuFreqStruct,FreqRender, freq} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerFreq.js"; +// @ts-ignore +import {Rect} from "../../../../dist/trace/component/trace/timer-shaft/Rect.js"; + +describe('freqTest', () => { + + it('freqTest01', () => { + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111}) + let rect = new Rect(0, 10, 10, 10); + freq(dataList, new Set(), 1, 100254, 100254, rect) + }) + + it('freqTest02', () => { + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111, frame: {x:0, y:9, width:10, height:10}}) + let rect = new Rect(0, 10, 10, 10); + freq(dataList, new Set(), 1, 100254, 100254, rect) + }) + + it('freqTest03', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + + expect(CpuFreqStruct.draw(ctx, data)).toBeUndefined() + + }) + it('freqTest04', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + const Sourcedata = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + maxFreq: 200, + value: 50 + } + expect(CpuFreqStruct.draw(ctx,Sourcedata)).toBeUndefined()}) + + it('freqTest05', function () { + let freqRender = new FreqRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + height:150, + width:100 + }, + lineColor:'', + isHover:'', + hoverX:1, + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100, + params:{ + isLive:false, + maxHeight:2, + dpr:1, + hoverFuncStruct:'', + selectFuncStruct:undefined, + } + } + window.postMessage = jest.fn(()=>true) + expect(freqRender.render(req,[],[])).toBeUndefined() + }); + +}); \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerFunc.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerFunc.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..0d7f3c45532db526929c925a5d37a9dad74f6a73 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerFunc.test.ts @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {func, FuncStruct,FuncRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerFunc.js"; +// @ts-ignore +import {Rect} from "../../../../dist/trace/component/trace/timer-shaft/Rect.js"; +import {markAsUntransferable} from "worker_threads"; + +describe(' FPSTest', () => { + + it('FuncTest01', () => { + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111}) + let rect = new Rect(0, 10, 10, 10); + let res = [{ + startTs: 0, + dur: 10, + length:1, + frame: "" + }] + func(dataList, res, 1, 100254, 100254, rect,true) + }) + + it('FuncTest02', () => { + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111, frame: {x:0, y:9, width:10, height:10}}) + let rect = new Rect(0, 10, 10, 10); + let res = [{ + startTs: 0, + dur: 10, + length:0, + frame: "" + }] + func(dataList, res, 1, 100254, 100254, rect,false) + }) + + it('FuncTest03', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50, + dur:undefined || null || 0 + } + expect(FuncStruct.draw(ctx, data)).toBeUndefined() + }) + + it('FuncTest07', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50, + dur:10 + } + expect(FuncStruct.draw(ctx, data)).toBeUndefined() + }) + + it('FuncTest04', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + FuncStruct.drawString(ctx, "1", 1,new Rect(0,0,100,100)); + }) + + it('FuncTest05', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + FuncStruct.drawString(ctx, "1", 2,new Rect(1,1,150,150)); + }); + + it('FuncTest06 ', function () { + let str = "" + expect(FuncStruct.getInt(str)).toBe(0); + }); + + it('FuncTest07 ', function () { + let data = { + startTs:2, + depth:1 + } + expect(FuncStruct.isSelected(data)).toBe(false); + }); + + it('FuncTest08', function () { + let funcRender = new FuncRender() + let req = { + lazyRefresh:undefined, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + height:150, + width:100 + }, + lineColor:'', + isHover:'', + hoverX:1, + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100, + params:{ + isLive:false, + maxHeight:2, + dpr:1, + hoverFuncStruct:'', + selectFuncStruct:undefined, + } + } + window.postMessage = jest.fn(()=>true) + expect(funcRender.render(req,[],[])).toBeUndefined() + }); + +}); \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerHeap.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerHeap.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..9698a1c841c37505b32fa1b4ae4c42fdc772553b --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerHeap.test.ts @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {heap, HeapStruct,NativeMemoryRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerHeap.js"; +// @ts-ignore +import {Rect} from "../../../../dist/trace/component/trace/timer-shaft/Rect.js"; + +describe(' Test', () => { + + it('HeapTest01', () => { + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111}) + let rect = new Rect(0, 10, 10, 10); + let res = [{ + startTs: 0, + dur: 10, + length:1, + frame: "" + }] + heap(dataList, res, 1, 100254, 100254, rect,true) + }) + + it('HeapTest02', () => { + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111, frame: {x:0, y:9, width:10, height:10}}) + let rect = new Rect(0, 10, 10, 10); + let res = [{ + startTs: 0, + dur: 10, + length:0, + frame: "" + }] + heap(dataList, res, 1, 100254, 100254, rect,false) + }) + + it('HeapTest03', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + expect(HeapStruct.draw(ctx, data)).toBeUndefined() + }) + it('HeapTest04', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + maxHeapSize: 200, + value: 50 + } + expect(HeapStruct.draw(ctx, data)).toBeUndefined() + }) + + it('HeapTest05', function () { + let nativeMemoryRender = new NativeMemoryRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + }, + lineColor:'', + isHover:'', + hoverX:1, + params:'', + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100, + } + window.postMessage = jest.fn(()=>true) + expect(nativeMemoryRender.render(req,[],[])).toBeUndefined() + }); +}); \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerHiPerfCPU.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerHiPerfCPU.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..b7da90d8e305e611d769c9fcf07702705d03abd1 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerHiPerfCPU.test.ts @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//@ts-ignore +import {hiPerfCpu,HiPerfCpuStruct} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerHiPerfCPU.js"; + +describe('ProcedureWorkerHiPerfCPU Test', ()=>{ + + + let frame={ + x:0, + y:9, + width:10, + height:10 + } + it('ProcedureWorkerHiPerfCPUTest01',()=>{ + const data = { + frame:undefined, + cpu:1, + startNs:1, + value:1, + } + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + expect(HiPerfCpuStruct.draw(ctx,'',data,true)).toBeUndefined(); + }); + + it('ProcedureWorkerHiPerfCPUTest02', function () { + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10,length:1, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 2,length:1}) + let res = [{ + length:1, + }] + hiPerfCpu(dataList, [{length:1}], "1", res, 3, 6,3,frame,true,1,2,true) + }); + + it('ProcedureWorkerHiPerfCPUTest03', function () { + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10,length:1, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 2,length:1}) + let res = [{ + length:0, + }] + hiPerfCpu(dataList,[{length:1}], "1", res, 3, 6,3,frame,false,1,2,false) + }); + + it('ProcedureWorkerHiPerfCPUTest04',()=>{ + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + expect(HiPerfCpuStruct.drawRoundRectPath(ctx,1,1,1,1,1)).toBeUndefined(); + }); + + it('ProcedureWorkerHiPerfCPUTest05', function () { + expect(HiPerfCpuStruct.groupBy10MS([{id:1,NS:3},{copy:"1"}],10,"")).toEqual([{"dur": 10000000, "height": 0, "startNS": NaN,}]) + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerHiPerfEvent.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerHiPerfEvent.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..84d1e7171521b01f1b474a9b8573ea04baa7e1d9 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerHiPerfEvent.test.ts @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {HiPerfEvent,HiPerfEventStruct,HiperfEventRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerHiPerfEvent.js" +// @ts-ignore +import {Rect} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerCommon"; + +describe('ProcedureWorkerHiPerfEvent Test', ()=> { + + it('ProcedureWorkerHiPerfEventTest01', () => { + let frame = { + x:0, + y:9, + width:10, + height:10 + } + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111}) + let dataList2 = new Array(); + dataList2.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:1}}) + dataList2.push({startTime: 1, dur: 111}) + let rect = new Rect(0, 10, 10, 10); + HiPerfEvent(dataList, dataList2, "", [{length: 1}], 1, 1024, 1024, frame, true, 1, true) + }); + + it('ProcedureWorkerHiPerfEventTest02', () => { + let frame = { + x:0, + y:9, + width:10, + height:10 + } + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111}) + let dataList2 = new Array(); + dataList2.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:1}}) + dataList2.push({startTime: 1, dur: 111}) + let rect = new Rect(0, 10, 10, 10); + HiPerfEvent(dataList, dataList2, "", [{length: 0}], 1, 1024, 1024, frame, true, 1, false) + }); + + it('ProcedureWorkerHiPerfEventTest03',()=>{ + const data = { + frame : { + x:0, + y:9, + width:10, + height:10 + }, + cpu:1, + startNs:1, + value:1, + } + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + expect(HiPerfEventStruct.drawRoundRectPath(ctx,1,0,10,10,12)).toBeUndefined(); + }); + + it('ProcedureWorkerHiPerfEventTest04', function () { + let node = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 0, + value: 50, + startTs:3, + dur:1, + height:2 + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(HiPerfEventStruct.setFrame(node,2, 1,2,frame)).toBeUndefined() + }); + + it('ProcedureWorkerHiPerfEventTest05', function () { + let node = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 2, + value: 50, + startTs:3, + dur:3, + height:2 + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(HiPerfEventStruct.setFrame(node,2, 1,2,frame)).toBeUndefined() + }); + + it('ProcedureWorkerHiPerfEventTest06', function () { + expect(HiPerfEventStruct.groupBy10MS([{ps:1},{coX:"1"}],10,"")).toEqual([{"dur": 10000000, "height": NaN, "max": 0, "startNS": NaN, "sum": NaN,}]) + }); + + // it('ProcedureWorkerHiPerfEventTest07', function () { + // let hiperfEventRender = new HiperfEventRender() + // let req = { + // lazyRefresh:true, + // type:"test", + // startNS:1, + // endNS:1, + // totalNS:1, + // frame: { + // x: 20, + // y: 20, + // width: 100, + // height: 100 + // }, + // useCache:false, + // range:{ + // refresh:"", + // }, + // canvas:'', + // context:{ + // font:"11px sans-serif", + // fillStyle:"#ec407a", + // globalAlpha:0.6, + // }, + // lineColor:'', + // isHover:'', + // hoverX:1, + // params:'', + // wakeupBean:undefined, + // flagMoveInfo:'', + // flagSelectedInfo:'', + // slicesTime:3, + // id:1, + // x: 20, + // y: 20, + // width: 100, + // height: 100, + // scale:100_000_001 + // } + // window.postMessage = jest.fn(()=>true) + // expect(hiperfEventRender.render(req,[],[])).toBeUndefined() + // }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerHiPerfProcess.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerHiPerfProcess.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..0133b89ad1b5434ef22f1addead7d31c07f0bac6 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerHiPerfProcess.test.ts @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//@ts-ignore +import {hiPerfProcess,HiPerfProcessStruct,HiperfProcessRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerHiPerfProcess.js"; + +describe('ProcedureWorkerHiPerfCPU Test', ()=>{ + + it('ProcedureWorkerHiPerfCPUTest01',()=>{ + const data = { + frame:undefined, + cpu:1, + startNs:1, + value:1, + } + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + expect(HiPerfProcessStruct.draw(ctx,'',data,true)).toBeUndefined(); + }); + + it('ProcedureWorkerHiPerfCPUTest02', function () { + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10,length:1, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 2,length:1}) + hiPerfProcess(dataList, [{length:0}], 1, 8, 3, "",true,1,true) + }); + + it('ProcedureWorkerHiPerfCPUTest03', function () { + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10,length:1, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 2,length:1}) + hiPerfProcess(dataList, [{length:0}], 1, 8, 3, "",false,1,false) + }); + + it('ProcedureWorkerHiPerfCPUTest04', function () { + expect(HiPerfProcessStruct.groupBy10MS([{a:'1',b:2,c:3}],10,)).toEqual([{"dur": 10000000, "height": 40, "startNS": NaN,}]) + }); + + it('ProcedureWorkerHiPerfCPUTest05', function () { + let hiperfProcessRender = new HiperfProcessRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + }, + lineColor:'', + isHover:'', + hoverX:1, + params:'', + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100, + scale:100_000_001 + } + window.postMessage = jest.fn(()=>true) + expect(hiperfProcessRender.render(req,[],[])).toBeUndefined() + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerHiPerfReport.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerHiPerfReport.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..10dbee023fc33a29a241a39c6ef7a20b2159e15d --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerHiPerfReport.test.ts @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {HiPerfReport,HiPerfReportStruct} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerHiPerfReport.js" +// @ts-ignore +import {Rect} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerCommon"; + +describe('ProcedureWorkerHiPerfReport Test', ()=> { + + it('ProcedureWorkerHiPerfReportTest01', () => { + let frame = { + x:0, + y:9, + width:10, + height:10 + } + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111}) + let dataList2 = new Array(); + dataList2.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:1}}) + dataList2.push({startTime: 1, dur: 111}) + let rect = new Rect(0, 10, 10, 10); + HiPerfReport(dataList, dataList2, "", [{length: 1}], 1, 1024, 1024, frame, true, 1, true) + }); + + it('ProcedureWorkerHiPerfReportTest02', () => { + let frame = { + x:0, + y:9, + width:10, + height:10 + } + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111, frame: {x:0, y:9, width:10, height:10}}) + let rect = new Rect(0, 10, 10, 10); + let dataList2 = new Array(); + dataList2.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:1}}) + dataList2.push({startTime: 1, dur: 111}) + HiPerfReport(dataList, dataList2, "", [{length: 0}], 1, 1024, 1024, frame, true, 1, false) + }); + + it('ProcedureWorkerHiPerfReportTest07', () => { + let frame = { + x:0, + y:9, + width:10, + height:10 + } + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111, frame: {x:0, y:9, width:10, height:10}}) + let rect = new Rect(0, 10, 10, 10); + let dataList2 = new Array(); + dataList2.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:1}}) + dataList2.push({startTime: 1, dur: 111}) + HiPerfReport(dataList, dataList2, "", [{length: 0}], 1, 1024, 1024, frame, false, 1, false) + }); + + it('ProcedureWorkerHiPerfReportTest03',()=>{ + const data = { + frame : { + x:0, + y:9, + width:10, + height:10 + }, + cpu:1, + startNs:1, + value:1, + } + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + expect(HiPerfReportStruct.drawRoundRectPath(ctx,1,0,10,10,12)).toBeUndefined(); + }); + + it('ProcedureWorkerHiPerfReportTest04', function () { + let node = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 0, + value: 50, + startTs:3, + dur:1, + height:2 + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(HiPerfReportStruct.setFrame(node,2, 1,2,frame)).toBeUndefined() + }); + + it('ProcedureWorkerHiPerfReportTest05', function () { + let node = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 2, + value: 50, + startTs:3, + dur:3, + height:2 + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(HiPerfReportStruct.setFrame(node,2, 1,2,frame)).toBeUndefined() + }); + + it('ProcedureWorkerHiPerfReportTest06', function () { + expect(HiPerfReportStruct.groupBy10MS([{ps:1},{coX:"1"}],10,"")).toEqual([{"dur": 10000000, "height": NaN, "startNS": NaN, "sum": NaN,}]) + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerHiPerfThread.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerHiPerfThread.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..df3f948aae2f88221c01702da4ac0cd45b5675c4 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerHiPerfThread.test.ts @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//@ts-ignore +import {hiPerfThread,HiPerfThreadStruct,HiperfThreadRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerHiPerfThread.js"; + +describe('ProcedureWorkerHiPerfCPU Test', ()=>{ + + let res = [{ + startNS: 0, + dur: 10, + frame: { + x:0, + y:9, + width:10, + height:10 + } + }] + it('ProcedureWorkerHiPerfCPUTest01',()=>{ + const data = { + frame:undefined, + cpu:1, + startNs:1, + value:1, + } + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + expect(HiPerfThreadStruct.draw(ctx,'',data,true)).toBeUndefined(); + }); + + it('ProcedureWorkerHiPerfCPUTest02', function () { + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10,length:1, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 2,length:1}) + let frame = { + x:0, + y:9, + width:10, + height:10 + } + hiPerfThread(dataList, [{length:0}], 1, 8, 3, frame,false,1,false) + }); + + it('ProcedureWorkerHiPerfCPUTest03', function () { + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10,length:1, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 2,length:1}) + let frame = { + x:0, + y:9, + width:10, + height:10 + } + hiPerfThread(dataList, [{length:1}], 1, 8, 3, frame,true,1,true) + }); + + it('ProcedureWorkerHiPerfCPUTest04', function () { + expect(HiPerfThreadStruct.groupBy10MS([{ps:1},{coX:"1"}],10,"")).toEqual([{"dur": 10000000,"height": 80, "startNS": NaN}]) + }); + + it('ProcedureWorkerHiPerfCPUTest05', function () { + let hiperfThreadRender = new HiperfThreadRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + }, + lineColor:'', + isHover:'', + hoverX:1, + params:'', + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100, + scale:100_000_001 + } + window.postMessage = jest.fn(()=>true) + expect(hiperfThreadRender.render(req,[],[])).toBeUndefined() + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerMem.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerMem.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..0da478da2dfe2c0bfceebe57dfa8268df9cd07af --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerMem.test.ts @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {mem, ProcessMemStruct,MemRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerMem.js"; +// @ts-ignore +import {Rect} from "../../../../dist/trace/component/trace/timer-shaft/Rect.js"; + +describe(' Test', () => { + + let frame={ + x:0, + y:9, + width:10, + height:10 + } + it('MemTest01', () => { + let dataList = new Array(); + dataList.push({startTime: 0, duration: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, duration: 111, frame: {x:0, y:9, width:10, height:10}}) + let rect = new Rect(0, 10, 10, 10); + mem(dataList, [{length:0}], 2, 100254, 100254, frame,false) + }) + + it('MemTest02', () => { + let dataList = new Array(); + dataList.push({startTime: 0, duration: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, duration: 111, frame: {x:0, y:9, width:10, height:10}}) + let rect = new Rect(0, 10, 10, 10); + mem(dataList, [{length:0}], 2, 100254, 100254, frame,true) + }) + + it('MemTest03', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + expect(ProcessMemStruct.draw(ctx, data)).toBeUndefined() + }) + + it('MemTest04', function () { + let memRender = new MemRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + }, + lineColor:'', + isHover:'', + hoverX:1, + params:'', + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100 + } + window.postMessage = jest.fn(()=>true) + expect(memRender.render(req,[],[])).toBeUndefined() + }); +}); \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerMemoryAbility.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerMemoryAbility.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..00da2e440e2ef70706685655563e48b964ee9ad6 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerMemoryAbility.test.ts @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//@ts-ignore +import {memoryAbility,MemoryAbilityMonitorStruct,MemoryAbilityRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerMemoryAbility.js"; + +describe('ProcedureWorkerMemoryAbility Test', ()=>{ + + let frame={ + x:0, + y:9, + width:10, + height:10 + } + it('ProcedureWorkerMemoryAbilityTest01',()=>{ + const data = { + frame:{ + width:10, + height:10, + x:1, + y:1, + }, + cpu:1, + startNs:1, + value:1, + } + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + expect(MemoryAbilityMonitorStruct.draw(ctx,data)).toBeUndefined(); + }); + + it('ProcedureWorkerMemoryAbilityTest02', function () { + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 2}) + memoryAbility(dataList, [{length:0}], 1, 8, 3, frame,true) + }); + + it('ProcedureWorkerMemoryAbilityTest02', function () { + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 2}) + memoryAbility(dataList, [{length:0}], 1, 8, 3, frame,false) + }); + + it('ProcedureWorkerMemoryAbilityTest03', function () { + let memoryAbilityRender = new MemoryAbilityRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + }, + lineColor:'', + isHover:'', + hoverX:1, + params:'', + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100 + } + window.postMessage = jest.fn(()=>true) + expect(memoryAbilityRender.render(req,[],[])).toBeUndefined() + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerNetworkAbility.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerNetworkAbility.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..5bc8030dece00fb8db559fecd6fefa8181b479f9 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerNetworkAbility.test.ts @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//@ts-ignore +import {NetworkAbilityMonitorStruct,networkAbility,NetworkAbilityRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerNetworkAbility.js"; + +describe('ProcedureWorkerNetworkAbility Test', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 2, + y: 2, + width: 10, + height: 10 + }, + startNS: 21, + value: 5 + } + let res = [{ + startNS: 0, + dur: 10, + frame: { + x:0, + y:9, + width:10, + height:10 + } + }] + + it('ProcedureWorkerNetworkAbilityTest01', function () { + expect(NetworkAbilityMonitorStruct.draw(ctx, data)).toBeUndefined() + }); + + it('ProcedureWorkerNetworkAbilityTest02', function () { + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 1}) + networkAbility(dataList, [{length:1}], 1, 9, 8, "",true) + }); + + it('ProcedureWorkerNetworkAbilityTest03', function () { + let dataList = new Array(); + dataList.push({startNS: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startNS: 1, dur: 1}) + networkAbility(dataList, [{length:0}], 1, 9, 8, "",false) + }); + + it('ProcedureWorkerNetworkAbilityTest04', function () { + let networkAbilityRender = new NetworkAbilityRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + }, + lineColor:'', + isHover:'', + hoverX:1, + params:'', + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100 + } + window.postMessage = jest.fn(()=>true) + expect(networkAbilityRender.render(req,[],[])).toBeUndefined() + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneCpuByThread.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerPerfCallchains.test.ts similarity index 61% rename from host/ide/test/trace/component/trace/sheet/TabPaneCpuByThread.test.ts rename to host/ide/test/trace/database/ui-worker/ProcedureWorkerPerfCallchains.test.ts index d01b6ecce862afb4924bb6de15024a4edd9d46a8..fafa5c1ab83c44bcc8f8354c4fe76ace8341c711 100644 --- a/host/ide/test/trace/component/trace/sheet/TabPaneCpuByThread.test.ts +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerPerfCallchains.test.ts @@ -14,16 +14,12 @@ */ // @ts-ignore -import {TabPaneCpuByThread} from "../../../../../dist/trace/component/trace/sheet/TabPaneCpuByThread.js" +import {PerfCallChainThread,PerfCallChainPool} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerPerfCallchains.js" -describe('TabPaneCpuByThread Test', () => { - let tabPaneCpuByThread = new TabPaneCpuByThread(); +describe('ProcedureWorkerPerfCallchains Test', ()=>{ - it('TabPaneCpuByThreadTest01', function () { - expect(tabPaneCpuByThread.sortByColumn({ - key: 'name', - sort: () => { - } - })).toBeUndefined(); + it('ProcedureWorkerPerfCallchainsTest01',()=>{ + expect(PerfCallChainPool).not.toBeUndefined() }); + }) diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerProcess.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerProcess.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..049c15bf7eb92618f71d49a81306ed3884bf9277 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerProcess.test.ts @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {proc, ProcessStruct,ProcessRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerProcess.js"; +// @ts-ignore +import {Rect} from "../../../../dist/trace/component/trace/timer-shaft/Rect.js"; + +describe(' ProcessTest', () => { + + let res = [{ + startNS: 0, + dur: 10, + frame: { + x:0, + y:9, + width:10, + height:10 + } + }] + it('ProcessTest01', () => { + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111}) + let rect = new Rect(0, 10, 10, 10); + proc(dataList, res, 1, 100254, 100254, rect) + }) + + it('ProcessTest02', () => { + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111, frame: {x:0, y:9, width:10, height:10}}) + let rect = new Rect(0, 10, 10, 10); + proc(dataList, res, 1, 100254, 100254, rect) + }) + + it('ProcessTest04', () => { + const node = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50, + startTime:0, + dur:0 + } + const frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(ProcessStruct.setFrame(node, 1,1,1,frame)).toBeUndefined() + }) + + it('ProcessTest05', () => { + const node = { + frame: { + x: 20, + y: 20, + width: 0, + height: 100 + }, + startNS: 200, + value: 50, + startTime:2, + dur:2 + } + const frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(ProcessStruct.setFrame(node, 1,1,1,frame)).toBeUndefined() + }) + + it('ProcessTest06', function () { + let processRender = new ProcessRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + }, + lineColor:'', + isHover:'', + hoverX:1, + params:'', + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100 + } + window.postMessage = jest.fn(()=>true) + expect(processRender.render(req,[],[])).toBeUndefined() + }); +}); \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerSmaps.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerSmaps.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..5736a1aa6976d75e1b39976c186419297a98e7ff --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerSmaps.test.ts @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {smaps, SmapsRender, SmapsStruct} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerSmaps.js" + +describe('ProcedureWorkerSmaps Test', () => { + + it('ProcedureWorkerSmapsTest01', function () { + let List = [{ + length: 1, + ts: 1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + }] + let arr = [{ + frame: null, + length: 1, + }] + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(smaps(List, arr, 1, 1, 1, frame, true)).toBeUndefined() + }); + + it('ProcedureWorkerSmapsTest02', function () { + let List = [{ + length: 1, + ts: 1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + }] + let arr = [{ + frame: null, + length: 0, + }] + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(smaps(List, arr, 1, 1, 1, frame, false)).toBeUndefined() + }); + + it('ProcedureWorkerSmapsTest03', () => { + const data = { + startNs: 1, + value: 1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startTime: 1, + ts: 1 + } + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + expect(SmapsStruct.draw(ctx, data, 1)).toBeUndefined(); + }); + + it('ProcedureWorkerSmapsTest04', () => { + let node = { + startNs: 1, + value: 1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + ts: 1, + dur: 1 + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(SmapsStruct.setSmapsFrame(node, 2, 1, 2, 2, frame)).toBeUndefined(); + }); + + it('ProcedureWorkerSmapsTest05', () => { + let node = { + startNs: 1, + value: 1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + ts: 0, + dur: 3 + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(SmapsStruct.setSmapsFrame(node, 2, 1, 2, 2, frame)).toBeUndefined(); + }); + + it('ProcedureWorkerSmapsTest06', function () { + let sMapsRender = new SmapsRender() + let req = { + lazyRefresh: true, + type: "", + startNS: 1, + endNS: 1, + totalNS: 1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache: false, + range: { + refresh: "", + }, + canvas: '', + context: { + font: "11px sans-serif", + fillStyle: "#ffffff", + globalAlpha: 0.6 + }, + lineColor: '', + isHover: true, + hoverX: 1, + wakeupBean: undefined, + flagMoveInfo: '', + flagSelectedInfo: '', + slicesTime: 3, + id: 1, + x: 20, + y: 20, + width: 100, + height: 100, + params: { + maxValue: 10, + maxValueName: "maxValueName", + rowName: "rowName" + } + } + window.postMessage = jest.fn(() => true) + expect(sMapsRender.render(req, [], [])).toBeUndefined() + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerThread.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerThread.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..84f648278c3a2dac934adfa5e738dc0b0a158508 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerThread.test.ts @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {thread, ThreadStruct,ThreadRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerThread.js"; +// @ts-ignore +import {Rect} from "../../../../dist/trace/component/trace/timer-shaft/Rect.js"; + +describe(' ThreadTest', () => { + + let frame={ + x:0, + y:9, + width:10, + height:10 + } + it('ThreadTest01', () => { + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111}) + let rect = new Rect(0, 10, 10, 10); + thread(dataList, [{length: 0}], 1, 100254, 100254, frame,true) + }) + + it('ThreadTest02', () => { + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111, frame: {x:0, y:9, width:10, height:10}}) + let rect = new Rect(0, 10, 10, 10); + thread(dataList, [{length: 0}], 1, 100254, 100254, frame,false) + }) + + it('ThreadTest03', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + expect(ThreadStruct.draw(ctx, data)).toBeUndefined() + }) + + it('ThreadTest04', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50, + state:"S" + } + expect(ThreadStruct.draw(ctx, data)).toBeUndefined() + }) + + it('ThreadTest05', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50, + state:"R" + } + expect(ThreadStruct.draw(ctx, data)).toBeUndefined() + }) + + it('ThreadTest06', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50, + state:"D" + } + expect(ThreadStruct.draw(ctx, data)).toBeUndefined() + }) + + it('ThreadTest07', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50, + state:"Running" + } + expect(ThreadStruct.draw(ctx, data)).toBeUndefined() + }) + + it('ThreadTest08', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50, + state:"T" + } + expect(ThreadStruct.draw(ctx, data)).toBeUndefined() + }) + + it('ThreadTest09', () => { + const d1 = { + cpu:1, + tid:1, + state:"", + startTime:1, + dur:1 + } + const d2 = { + cpu:1, + tid:1, + state:"", + startTime:1, + dur:1 + } + expect(ThreadStruct.equals(d1, d2)).toBeTruthy() + }) + + it('ThreadTest10', function () { + let threadRender = new ThreadRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + }, + lineColor:'', + isHover:'', + hoverX:1, + params:'', + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100 + } + window.postMessage = jest.fn(()=>true) + expect(threadRender.render(req,[],[])).toBeUndefined() + }); +}); \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerTimeline.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerTimeline.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..b19d0a0f3c7479a0f38a660077d5487fc3078f14 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerTimeline.test.ts @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {RangeRuler, SportRuler, timeline,TimelineRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerTimeline.js"; +// @ts-ignore +import {Rect} from "../../../../dist/trace/component/trace/timer-shaft/Rect.js"; + +describe(' ProcedureWorkerTimelineTest', () => { + + it('timelineTest', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111}) + let rect = new Rect(0, 10, 10, 10); + timeline(canvas, ctx, 1, 100254, 100254, rect, null, null, null, null,null,null,0,0,(e:any) => { + }) + }) + + + it('SportRulerTest01', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + let rect = new Rect(0, 10, 10, 10); + let sportRuler = new SportRuler(canvas,ctx,rect); + sportRuler.modifyFlagList("amend") + sportRuler.modifyFlagList("remove") + sportRuler.drawTheFlag(0,"#999999",false,!""); + sportRuler.randomRgbColor(); + sportRuler.mouseMove(new MouseEvent("")); + sportRuler.mouseUp(new MouseEvent("")); + sportRuler.onFlagRangeEvent('1',2); + }) + + it('SportRulerTest02', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + let rect = new Rect(0, 10, 10, 10); + let rangeRuler = new RangeRuler(canvas,ctx,rect,{ + startX: 0, + endX: rect.width, + startNS: 0, + endNS: 111, + totalNS: 111, + xs: [], + xsTxt: [] + },(a:any) =>{}); + rangeRuler.draw(); + rangeRuler.drawCpuUsage(); + rangeRuler.mouseDown({offsetX:1,offsetY:1}) + rangeRuler.mouseUp(new MouseEvent("")) + rangeRuler.mouseMove(new MouseEvent("")) + rangeRuler.mouseOut(new MouseEvent("")) + rangeRuler.range.startNS=-2 + rangeRuler.range.endNS=-2 + rangeRuler.range.totalNS=-7 + rangeRuler.fillX(); + rangeRuler.keyPress(new KeyboardEvent("")); + rangeRuler.pressFrameId = !-1 + rangeRuler.keyUp(new KeyboardEvent("")); + rangeRuler.keyUp({key:'w'}); + rangeRuler.keyUp({key:'s'}); + rangeRuler.keyUp({key:'a'}); + rangeRuler.keyUp({key:'d'}); + + }) + + it('SportRulerTest03', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + let rect = new Rect(0, 10, 10, 10); + let rangeRuler = new RangeRuler(canvas,ctx,rect,{ + startX: 0, + endX: rect.width, + startNS: 0, + endNS: 111, + totalNS: 111, + xs: [], + xsTxt: [] + },(a:any) =>{}); + rangeRuler.cpuUsage = true; + expect(rangeRuler.cpuUsage).toBeUndefined(); + }) + +}); \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProcedureWorkerVirtualMemory.test.ts b/host/ide/test/trace/database/ui-worker/ProcedureWorkerVirtualMemory.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..d121a44956e651a60236f412c5378314624798eb --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProcedureWorkerVirtualMemory.test.ts @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {setMemFrame,mem,VirtualMemoryStruct,VirtualMemoryRender} from "../../../../dist/trace/database/ui-worker/ProcedureWorkerVirtualMemory.js" + +describe('ProcedureWorkerVirtualMemory Test', () => { + + it('ProcedureWorkerVirtualMemoryTest01', function () { + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111}) + mem(dataList, [{length: 1}], 1, 1, 1, frame, true) + }); + + it('ProcedureWorkerVirtualMemoryTest02', function () { + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + let dataList = new Array(); + dataList.push({startTime: 0, dur: 10, frame: {x:0, y:9, width:10, height:10}}) + dataList.push({startTime: 1, dur: 111}) + mem(dataList, [{length: 0}], 1, 1, 1, frame, false) + }); + + it('ProcedureWorkerVirtualMemoryTest03',()=>{ + const data = { + cpu:1, + startNs:1, + value:1, + frame:{ + x: 20, + y: 20, + width: 100, + height: 100 + }, + maxValue:undefined, + startTime:1, + filterID:2, + + } + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + expect(VirtualMemoryStruct.draw(ctx,data)).toBeUndefined(); + }); + + it('ProcedureWorkerVirtualMemoryTest04', function () { + let virtualMemoryRender = new VirtualMemoryRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + }, + lineColor:'', + isHover:'', + hoverX:1, + params:'', + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100 + } + window.postMessage = jest.fn(()=>true) + expect(virtualMemoryRender.render(req,[],[])).toBeUndefined() + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProduceWorkerSdkCounter.test.ts b/host/ide/test/trace/database/ui-worker/ProduceWorkerSdkCounter.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..2c45aee489032b17e4bb6531755ac835aa9c7ea2 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProduceWorkerSdkCounter.test.ts @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SdkCounterRender,CounterStruct} from "../../../../dist/trace/database/ui-worker/ProduceWorkerSdkCounter.js" + +describe('ProduceWorkerSdkCounter Test', () => { + + it('ProduceWorkerSdkCounterTest01', function () { + let sdkCounterRender = new SdkCounterRender() + let List = [{ + length:1, + ts:1, + frame:{ + x: 20, + y: 20, + width: 100, + height: 100 + }, + }] + let arr = [{ + frame:null, + length:1, + }] + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(sdkCounterRender.counter(List, arr, 1, 1, 1, frame, true)).toBeUndefined() + }); + + it('ProduceWorkerSdkCounterTest02', function () { + let sdkCounterRender = new SdkCounterRender() + let List = [{ + length:1, + ts:1, + frame:{ + x: 20, + y: 20, + width: 100, + height: 100 + }, + }] + let arr = [{ + frame:null, + length:0, + }] + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(sdkCounterRender.counter(List, arr, 1, 1, 1, frame, false)).toBeUndefined() + }); + + it('ProduceWorkerSdkCounterTest03',()=>{ + const data = { + startNs:1, + value:1, + frame:{ + x: 20, + y: 20, + width: 100, + height: 100 + }, + startTime:1, + ts:1 + } + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + expect(CounterStruct.draw(ctx,data,1)).toBeUndefined(); + }); + + it('ProduceWorkerSdkCounterTest04',()=>{ + let node = { + startNs:1, + value:1, + frame:{ + x: 20, + y: 20, + width: 100, + height: 100 + }, + ts:1, + dur:1 + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(CounterStruct.setCounterFrame(node,2,1,2,2,frame)).toBeUndefined(); + }); + + it('ProduceWorkerSdkCounterTest05',()=>{ + let node = { + startNs:1, + value:1, + frame:{ + x: 20, + y: 20, + width: 100, + height: 100 + }, + ts:0, + dur:3 + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(CounterStruct.setCounterFrame(node,2,1,2,2,frame)).toBeUndefined(); + }); + + it('ProduceWorkerSdkCounterTest06', function () { + let sdkCounterRender = new SdkCounterRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + }, + lineColor:'', + isHover:'', + hoverX:1, + params:'', + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100 + } + window.postMessage = jest.fn(()=>true) + expect(sdkCounterRender.render(req,[],[])).toBeUndefined() + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/database/ui-worker/ProduceWorkerSdkSlice.test.ts b/host/ide/test/trace/database/ui-worker/ProduceWorkerSdkSlice.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..aac4494da5c0078f0d417ba077bac8f5cdaac9b8 --- /dev/null +++ b/host/ide/test/trace/database/ui-worker/ProduceWorkerSdkSlice.test.ts @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SdkSliceRender,SdkSliceStruct} from "../../../../dist/trace/database/ui-worker/ProduceWorkerSdkSlice.js" + +describe('ProduceWorkerSdkSlice Test', () => { + + it('ProduceWorkerSdkSliceTest01', function () { + let sdkSliceRender = new SdkSliceRender() + let list = [{ + length:1, + frame :{ + x:1, + Y:10, + width:100, + height:20, + } + }] + let res = [{ + length:1, + frame:null, + }] + expect(sdkSliceRender.sdkSlice(list,res,1,5,4,true)).toBeUndefined() + }); + + it('ProduceWorkerSdkSliceTest02', function () { + let sdkSliceRender = new SdkSliceRender() + let list = [{ + length:1, + frame :{ + x:1, + Y:10, + width:100, + height:20, + } + }] + let res = [{ + length:0, + frame:null, + }] + expect(sdkSliceRender.sdkSlice(list,res,1,5,4,false)).toBeUndefined() + }); + + it('ProduceWorkerSdkSliceTest03',()=>{ + const data = { + startNs:1, + value:1, + frame:{ + x: 20, + y: 20, + width: 100, + height: 100 + }, + start_ts:1 + } + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + expect(SdkSliceStruct.draw(ctx,data)).toBeUndefined(); + }); + + it('ProduceWorkerSdkSliceTest04',()=>{ + let node = { + startNs:1, + value:1, + frame:{ + x: 20, + y: 20, + width: 100, + height: 100 + }, + start_ts:1, + end_ts:2 + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(SdkSliceStruct.setSdkSliceFrame(node,2,2,3,1,frame)).toBeUndefined(); + }); + + it('ProduceWorkerSdkSliceTest05',()=>{ + let node = { + startNs:1, + value:1, + frame:{ + x: 20, + y: 20, + width: 100, + height: 100 + }, + start_ts:3, + end_ts:5 + } + let frame = { + x: 20, + y: 20, + width: 100, + height: 100 + } + expect(SdkSliceStruct.setSdkSliceFrame(node,2,2,3,1,frame)).toBeUndefined(); + }); + + it('ProduceWorkerSdkSliceTest06', function () { + let sdkSliceRender = new SdkSliceRender() + let req = { + lazyRefresh:true, + type:"", + startNS:1, + endNS:1, + totalNS:1, + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + useCache:false, + range:{ + refresh:"", + }, + canvas:'', + context:{ + font:"11px sans-serif", + fillStyle:"#ec407a", + globalAlpha:0.6, + }, + lineColor:'', + isHover:'', + hoverX:1, + params:'', + wakeupBean:undefined, + flagMoveInfo:'', + flagSelectedInfo:'', + slicesTime:3, + id:1, + x: 20, + y: 20, + width: 100, + height: 100 + } + window.postMessage = jest.fn(()=>true) + expect(sdkSliceRender.render(req,[],[])).toBeUndefined() + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/grpc/HiProfilerClient.test.ts b/host/ide/test/trace/grpc/HiProfilerClient.test.ts index cfe9dcee069dd66c11c03f7bdb44d0631124da53..08c2a9ee3c54a0330346d753cce9374e839fc3d5 100644 --- a/host/ide/test/trace/grpc/HiProfilerClient.test.ts +++ b/host/ide/test/trace/grpc/HiProfilerClient.test.ts @@ -37,7 +37,7 @@ describe('HiProfilerClient Test', ()=>{ }); it('HiProfilerClientTest05', function () { - expect(hiProfilerClient.getProfilerClient()).toBeUndefined(); + expect(hiProfilerClient.getProfilerClient()).toBeTruthy(); }); }) \ No newline at end of file diff --git a/host/ide/test/trace/grpc/ProfilerClient.test.ts b/host/ide/test/trace/grpc/ProfilerClient.test.ts index a4e00e769e34b03384a98e71ce12369508ca8cfb..0021ee1b6326007df5281a2305f2c4be489b3b50 100644 --- a/host/ide/test/trace/grpc/ProfilerClient.test.ts +++ b/host/ide/test/trace/grpc/ProfilerClient.test.ts @@ -17,14 +17,39 @@ import {ProfilerClient} from "../../../dist/trace/grpc/ProfilerClient.js" describe('HiProfilerClient Test', ()=>{ + it('HiProfilerClientTest01 ', function () { + expect(ProfilerClient.client).toBeUndefined() - - it('ProfilerClientTest01', function () { - expect(ProfilerClient.client).toBeUndefined(); }); - it('ProfilerClientTest01', function () { + it('HiProfilerClientTest02', function () { ProfilerClient.client = true; - expect(ProfilerClient.client).toBeTruthy(); + expect(ProfilerClient.client).toBeTruthy() + + }); + it('HiProfilerClientTest03 ', function () { + expect(ProfilerClient.filePaths).toBeUndefined() + + }); + it('HiProfilerClientTest04', function () { + ProfilerClient.filePaths = true; + expect(ProfilerClient.filePaths).toBeTruthy() + + }); + it('HiProfilerClientTest05', function () { + expect(ProfilerClient.profiler_proto).toBeUndefined() + }); + it('HiProfilerClientTest06', function () { + ProfilerClient.profiler_proto = true; + expect(ProfilerClient.profiler_proto).toBeTruthy() + }); + + it('HiProfilerClientTest07 ', function () { + expect(ProfilerClient.shutdown).toBeUndefined() + + }); + it('HiProfilerClientTest08', function () { + ProfilerClient.getChannel = jest.fn(()=>true) + expect(ProfilerClient.getChannel()).toBeTruthy(); }); }) \ No newline at end of file diff --git a/host/ide/test/trace/grpc/ProfilerController.test.ts b/host/ide/test/trace/grpc/ProfilerController.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..955e879fda759f96fd9264a382c1ddb3d9ee700d --- /dev/null +++ b/host/ide/test/trace/grpc/ProfilerController.test.ts @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {ClientContainer, SettingRegistry} from "../../../dist/trace/grpc/ProfilerController.js" + +describe('HiProfilerClient Test', ()=>{ + + let profilerController= new ClientContainer(); + + it('ProfilerClientTest01', function () { + expect(profilerController.port).toBeUndefined(); + }); + + it('ProfilerClientTest02', function () { + profilerController.port = true; + expect(profilerController.port).toBeTruthy(); + }); + + it('ProfilerClientTest03', function () { + expect(profilerController.host).toBeUndefined(); + }); + + it('ProfilerClientTest04', function () { + profilerController.host = true; + expect(profilerController.host).toBeTruthy(); + }); + + // it('ProfilerClientTest05', function () { + // expect(profilerController.host).toBe(true); + // }); + + it('ProfilerClientTest06', function () { + profilerController.loadSettings = jest.fn(()=>true) + expect(profilerController.start()).toBeUndefined(); + }); + + it('ProfilerClientTest07', function () { + profilerController.loadSettings = jest.fn(()=>true) + expect(profilerController.loadSettings()).toBeTruthy(); + }); + it('ProfilerClientTest08', function () { + expect(profilerController. registryClient()).toBeUndefined() + }); + it('ProfilerClientTest09', function () { + expect(SettingRegistry. registry()).toBeUndefined() + }); +}) \ No newline at end of file