diff --git a/0001-feat-golang-ad.patch b/0001-feat-golang-ad.patch
new file mode 100644
index 0000000000000000000000000000000000000000..61eb0698d55b26749ef91dc2733becfa0b080581
--- /dev/null
+++ b/0001-feat-golang-ad.patch
@@ -0,0 +1,165 @@
+From e11eae509f944c2f0387d2dbf862dcd5763b84da Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=E9=9B=86=E5=B7=9D?=
+Date: Fri, 6 Sep 2024 16:35:20 +0800
+Subject: [PATCH] =?UTF-8?q?feat:=20golang=E6=9C=8D=E5=8A=A1=E6=8F=90?=
+ =?UTF-8?q?=E4=BE=9Bad=E6=8E=A5=E5=8F=A3?=
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: 集川
+---
+ ide/server/main.go | 75 ++++++++++++++++++++++++++++++++---
+ ide/server/server-config.json | 4 ++
+ ide/server/server-config.txt | 1 -
+ ide/webpack.config.js | 4 +-
+ 4 files changed, 75 insertions(+), 9 deletions(-)
+ create mode 100644 ide/server/server-config.json
+ delete mode 100644 ide/server/server-config.txt
+
+diff --git a/ide/server/main.go b/ide/server/main.go
+index 80a242fb..5de296ef 100644
+--- a/ide/server/main.go
++++ b/ide/server/main.go
+@@ -45,6 +45,7 @@ import (
+ "runtime"
+ "strconv"
+ "strings"
++ "sync"
+ "time"
+ )
+
+@@ -52,6 +53,7 @@ const HttpPort = 9000
+
+ var exPath string
+ var serveInfo string
++var msgPublishData MsgPublishData
+ var hdcPublicKey string
+ var hdcPrivateKey *rsa.PrivateKey
+
+@@ -178,6 +180,7 @@ func main() {
+ mux.HandleFunc("/application/hdcPublicKey", getHdcPublicKey)
+ mux.HandleFunc("/application/encryptHdcMsg", encryptHdcMsg)
+ mux.HandleFunc("/application/signatureHdcMsg", signatureHdcMsg)
++ mux.HandleFunc("/application/messagePublish", getMsgPublish)
+ fs := http.FileServer(http.Dir(exPath + "/"))
+ mux.Handle("/application/", http.StripPrefix("/application/", cors(fs, version)))
+ go func() {
+@@ -299,14 +302,74 @@ func signatureHdcMsg(w http.ResponseWriter, r *http.Request) {
+ }
+ }
+
+-func readReqServerConfig() string {
+- readServerConfig, serverConfigErr := os.ReadFile(exPath + "/server-config.txt")
+- if serverConfigErr != nil {
+- serveInfo = ""
++func parseMsgPublishFile() {
++ msgPublishData.Mux.RLock()
++ defer msgPublishData.Mux.RUnlock()
++ exist, err := PathExists(msgPublishData.FilePath)
++ if err != nil || !exist {
++ return
++ }
++ buf, err := os.ReadFile(msgPublishData.FilePath)
++ if err != nil {
++ fmt.Println("read fail", err)
++ return
++ }
++ msgPublishData.Msg = string(buf)
++}
++
++func getMsgPublish(w http.ResponseWriter, r *http.Request) {
++ w.Header().Set("Access-Control-Allow-Origin", "*")
++ w.Header().Set("Content-Type", "text/json")
++ msgPublishData.Mux.Lock()
++ data := msgPublishData.Msg
++ msgPublishData.Mux.Unlock()
++ if len(data) == 0 {
++ resp(&w)(false, -1, "msg failed", nil)
+ } else {
+- serveInfo = string(readServerConfig)
++ resp(&w)(true, 0, "success", map[string]interface{}{
++ "data": data,
++ })
++ }
++}
++
++type ServerConfig struct {
++ ServeInfo string `json:"ServeInfo"`
++ MsgPublishFile string `json:"MsgPublishFile"`
++}
++
++type MsgPublishData struct {
++ FilePath string
++ Msg string
++ Mux sync.RWMutex
++}
++
++func loopUpdateMsgPublishData() {
++ loopTime := 30 * time.Second
++ timer := time.NewTimer(loopTime)
++ for {
++ select {
++ case <-timer.C:
++ parseMsgPublishFile()
++ }
++ timer.Reset(loopTime)
++ }
++}
++
++func readReqServerConfig() {
++ serverConfigBuffer, err := os.ReadFile(exPath + "/server-config.json")
++ if err != nil {
++ return
++ }
++ var sc ServerConfig
++ err = json.Unmarshal(serverConfigBuffer, &sc)
++ if err != nil {
++ return
+ }
+- return serveInfo
++ serveInfo = sc.ServeInfo
++ msgPublishData.Mux.RLock()
++ msgPublishData.FilePath = sc.MsgPublishFile
++ msgPublishData.Mux.RUnlock()
++ go loopUpdateMsgPublishData()
+ }
+
+ func mapToJson(m map[string]interface{}) (string, error) {
+diff --git a/ide/server/server-config.json b/ide/server/server-config.json
+new file mode 100644
+index 00000000..637b4034
+--- /dev/null
++++ b/ide/server/server-config.json
+@@ -0,0 +1,4 @@
++{
++ "ServeInfo": "127.0.0.1:9100/statistics",
++ "MsgPublishFile": ""
++}
+\ No newline at end of file
+diff --git a/ide/server/server-config.txt b/ide/server/server-config.txt
+deleted file mode 100644
+index fde29681..00000000
+--- a/ide/server/server-config.txt
++++ /dev/null
+@@ -1 +0,0 @@
+-127.0.0.1:9100/statistics
+\ No newline at end of file
+diff --git a/ide/webpack.config.js b/ide/webpack.config.js
+index f7702c1c..55397917 100644
+--- a/ide/webpack.config.js
++++ b/ide/webpack.config.js
+@@ -168,8 +168,8 @@ const config = {
+ to: 'wasm.json',
+ },
+ {
+- from: './server/server-config.txt',
+- to: 'server-config.txt',
++ from: './server/server-config.json',
++ to: 'server-config.json',
+ },
+ ],
+ }),
+--
+2.34.1
+
diff --git a/ide/server/main.go b/ide/server/main.go
index 80a242fb8889f8f3dd94a01c3f16edf8bdd1b4a7..530ff115573a70338e10786ec5502b39091784da 100644
--- a/ide/server/main.go
+++ b/ide/server/main.go
@@ -45,6 +45,7 @@ import (
"runtime"
"strconv"
"strings"
+ "sync"
"time"
)
@@ -52,6 +53,7 @@ const HttpPort = 9000
var exPath string
var serveInfo string
+var msgPublishData MsgPublishData
var hdcPublicKey string
var hdcPrivateKey *rsa.PrivateKey
@@ -178,6 +180,7 @@ func main() {
mux.HandleFunc("/application/hdcPublicKey", getHdcPublicKey)
mux.HandleFunc("/application/encryptHdcMsg", encryptHdcMsg)
mux.HandleFunc("/application/signatureHdcMsg", signatureHdcMsg)
+ mux.HandleFunc("/application/messagePublish", getMsgPublish)
fs := http.FileServer(http.Dir(exPath + "/"))
mux.Handle("/application/", http.StripPrefix("/application/", cors(fs, version)))
go func() {
@@ -299,14 +302,79 @@ func signatureHdcMsg(w http.ResponseWriter, r *http.Request) {
}
}
-func readReqServerConfig() string {
- readServerConfig, serverConfigErr := os.ReadFile(exPath + "/server-config.txt")
- if serverConfigErr != nil {
- serveInfo = ""
+func parseMsgPublishFile() {
+ defer func() {
+ if r := recover(); r != nil {
+ fmt.Printf("parseMsgPublishFile happen panic, content is %+v\n", r)
+ }
+ }()
+ msgPublishData.Mux.Lock()
+ defer msgPublishData.Mux.Unlock()
+ exist, err := PathExists(msgPublishData.FilePath)
+ if err != nil || !exist {
+ return
+ }
+ buf, err := os.ReadFile(msgPublishData.FilePath)
+ if err != nil {
+ fmt.Println("read fail", err)
+ return
+ }
+ msgPublishData.Msg = string(buf)
+}
+
+func getMsgPublish(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Access-Control-Allow-Origin", "*")
+ w.Header().Set("Content-Type", "text/json")
+ msgPublishData.Mux.RLock()
+ data := msgPublishData.Msg
+ msgPublishData.Mux.RUnlock()
+ if len(data) == 0 {
+ resp(&w)(false, -1, "msg failed", nil)
} else {
- serveInfo = string(readServerConfig)
+ resp(&w)(true, 0, "success", map[string]interface{}{
+ "data": data,
+ })
+ }
+}
+
+type ServerConfig struct {
+ ServeInfo string `json:"ServeInfo"`
+ MsgPublishFile string `json:"MsgPublishFile"`
+}
+
+type MsgPublishData struct {
+ FilePath string
+ Msg string
+ Mux sync.RWMutex
+}
+
+func loopUpdateMsgPublishData() {
+ loopTime := 5 * time.Minute
+ timer := time.NewTimer(5 * time.Second)
+ for {
+ select {
+ case <-timer.C:
+ parseMsgPublishFile()
+ }
+ timer.Reset(loopTime)
+ }
+}
+
+func readReqServerConfig() {
+ serverConfigBuffer, err := os.ReadFile(exPath + "/server-config.json")
+ if err != nil {
+ return
+ }
+ var sc ServerConfig
+ err = json.Unmarshal(serverConfigBuffer, &sc)
+ if err != nil {
+ return
}
- return serveInfo
+ serveInfo = sc.ServeInfo
+ msgPublishData.Mux.Lock()
+ msgPublishData.FilePath = sc.MsgPublishFile
+ msgPublishData.Mux.Unlock()
+ go loopUpdateMsgPublishData()
}
func mapToJson(m map[string]interface{}) (string, error) {
diff --git a/ide/server/server-config.json b/ide/server/server-config.json
new file mode 100644
index 0000000000000000000000000000000000000000..637b403495932e12805e858f50883d962caca8d4
--- /dev/null
+++ b/ide/server/server-config.json
@@ -0,0 +1,4 @@
+{
+ "ServeInfo": "127.0.0.1:9100/statistics",
+ "MsgPublishFile": ""
+}
\ No newline at end of file
diff --git a/ide/server/server-config.txt b/ide/server/server-config.txt
deleted file mode 100644
index fde296819b41b01eef3ffaef5c795bd5ab2c9569..0000000000000000000000000000000000000000
--- a/ide/server/server-config.txt
+++ /dev/null
@@ -1 +0,0 @@
-127.0.0.1:9100/statistics
\ No newline at end of file
diff --git a/ide/src/base-ui/chart/pie/LitChartPie.ts b/ide/src/base-ui/chart/pie/LitChartPie.ts
index 560893146b932e392852f614dc61fb57d4416385..252a537038a97fbd0be9493eb92d511124cf5b18 100644
--- a/ide/src/base-ui/chart/pie/LitChartPie.ts
+++ b/ide/src/base-ui/chart/pie/LitChartPie.ts
@@ -179,11 +179,13 @@ export class LitChartPie extends BaseElement {
}
this.updateHoverItemStatus(it);
if (it.hover) {
- this.showTip(
- this.centerX || 0,
- this.centerY || 0,
- this.litChartPieConfig!.tip ? this.litChartPieConfig!.tip(it) : `${it.key}: ${it.value}`
- );
+ if (this.centerX && this.centerX > 0 && this.centerY && this.centerY > 0) {
+ this.showTip(
+ this.centerX - 40 || 0,
+ this.centerY || 0,
+ this.litChartPieConfig!.tip ? this.litChartPieConfig!.tip(it) : `${it.key}: ${it.value}`
+ );
+ }
}
});
if (!hasHover) {
@@ -270,8 +272,8 @@ export class LitChartPie extends BaseElement {
if (it.hover && this.litChartPieConfig) {
this.litChartPieConfig.hoverHandler?.(it.obj);
this.showTip(
- ev.pageX - rect.left + 10,
- ev.pageY - this.offsetTop - 10,
+ ev.pageX - rect.left > this.centerX! ? ev.pageX - rect.left - 165 : ev.pageX - rect.left + 10,
+ ev.pageY - this.offsetTop > this.centerY! ? ev.pageY - this.offsetTop - 50 : ev.pageY + (this.offsetTop - rect.top) - this.offsetTop + 20,
this.litChartPieConfig.tip ? this.litChartPieConfig!.tip(it) : `${it.key}: ${it.value}`
);
}
diff --git a/ide/src/base-ui/loading/LitLoading.ts b/ide/src/base-ui/loading/LitLoading.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f0b3fd56ec075f103e51a63644305bff678f4cf3
--- /dev/null
+++ b/ide/src/base-ui/loading/LitLoading.ts
@@ -0,0 +1,177 @@
+import { BaseElement, element } from '../BaseElement'
+
+@element('lit-loading')
+export class LitLoading extends BaseElement {
+
+ initHtml(): string {
+ return `
+
+
+ `;
+ }
+
+ initElements(): void {
+ }
+}
\ No newline at end of file
diff --git a/ide/src/base-ui/menu/LitMainMenu.ts b/ide/src/base-ui/menu/LitMainMenu.ts
index 89fa33020c8b5897c95d378e14488d07336d14fb..e5465cc75cf409c6e2bdbfcb113caeaeaeeab76c 100644
--- a/ide/src/base-ui/menu/LitMainMenu.ts
+++ b/ide/src/base-ui/menu/LitMainMenu.ts
@@ -95,6 +95,7 @@ const initHtmlStyle: string = `
cursor: pointer;
height: 47px;
width: 48px;
+ color: #1E4EEA;
}
`;
diff --git a/ide/src/base-ui/select/LitSelect.ts b/ide/src/base-ui/select/LitSelect.ts
index aad124e5c4d87417f569bb5ed2acf24fbeb63129..da9d3e108939c3e05f5f15476b50fb2f00c5b4bd 100644
--- a/ide/src/base-ui/select/LitSelect.ts
+++ b/ide/src/base-ui/select/LitSelect.ts
@@ -16,6 +16,7 @@
import { BaseElement, element } from '../BaseElement';
import { selectHtmlStr } from './LitSelectHtml';
import { LitSelectOption } from './LitSelectOption';
+import { SpSystemTrace } from '../../trace/component/SpSystemTrace';
@element('lit-select')
export class LitSelect extends BaseElement {
@@ -45,6 +46,7 @@ export class LitSelect extends BaseElement {
'border',
'mode',
'showSearchInput',
+ 'tabSelect'
];
}
@@ -471,7 +473,12 @@ export class LitSelect extends BaseElement {
setOnkeydown(): void {
// @ts-ignore
- this.selectInputEl.onkeydown = (ev: unknown): void => {
+ this.selectInputEl.onkeydown = (ev: KeyboardEvent): void => {
+ ev.stopPropagation();
+ if (this.hasAttribute('tabselect')) {
+ // @ts-ignore
+ this.selectInputEl.readOnly = true;
+ } else {
// @ts-ignore
if (ev.key === 'Backspace') {
if (this.isMultiple()) {
@@ -513,11 +520,12 @@ export class LitSelect extends BaseElement {
})
);
}
- } // @ts-ignore
+ }// @ts-ignore
} else if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') {
// @ts-ignore
ev.preventDefault();
}
+ }
};
}
diff --git a/ide/src/base-ui/tabs/lit-tabs.ts b/ide/src/base-ui/tabs/lit-tabs.ts
index 75935c8f16a7ac1aea3e34401dbeae8a3be5657b..e2014306dca5b203152552f46d74d7e00b08fedd 100644
--- a/ide/src/base-ui/tabs/lit-tabs.ts
+++ b/ide/src/base-ui/tabs/lit-tabs.ts
@@ -17,6 +17,7 @@ import { element } from '../BaseElement';
import { LitTabpane } from './lit-tabpane';
import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil';
import { LitTabsHtml } from './lit-tabs.html';
+import { shadowRootInput } from '../../trace/component/trace/base/shadowRootInput';
@element('lit-tabs')
export class LitTabs extends HTMLElement {
@@ -281,7 +282,6 @@ export class LitTabs extends HTMLElement {
a.removeAttribute('data-selected');
}
});
- let tbp = this.querySelector(`lit-tabpane[key='${key}']`);
let panes = this.querySelectorAll('lit-tabpane');
panes.forEach((a) => {
if (a.key === key) {
@@ -292,8 +292,14 @@ export class LitTabs extends HTMLElement {
a.style.display = 'none';
}
});
+ let tbp = this.querySelector(`lit-tabpane[key='${key}']`);
+ if (tbp) {
+ setTimeout(() => {
+ shadowRootInput.preventBubbling(tbp);
+ }, 500);
+ }
}
-
+
byKeyIsValid(isValid: boolean, a: Element): void {
if (isValid) {
let span = a.querySelector('span') as HTMLSpanElement;
diff --git a/ide/src/doc/quickstart_parsing_ability.html b/ide/src/doc/quickstart_parsing_ability.html
index b495caf5a293832896040d6f78c036d57f5181ca..45ee591a2622877f6a0bed6af3bb7688fec8876d 100644
--- a/ide/src/doc/quickstart_parsing_ability.html
+++ b/ide/src/doc/quickstart_parsing_ability.html
@@ -877,6 +877,196 @@ Single file max size: trace文件分割的大小。
+
+
+
+ 挂起(hang)是离散用户交互中的明显延迟,并且它几乎总是主线程上长时间运行工作的结果。
+ 仅当主线程在大约 50 毫秒到 100 毫秒或更长时间内无响应时,离散交互延迟才会开始变得明显。
+
+
+
+
+ 进入Probes config页面,打开Record mode开关,勾选notification可以抓取Hangs数据(此选项为默认勾选)。
+
+
+
+
+ 解析时需要打开Flags页面的Hangs Detection开关(Disabled切换为Enabled)。
+
+
+
+
+
+ 将抓取的trace文件导入到smartperf工具中,查看挂起的情况。
+
+
+
+
+
+
+ 点击Hangs Detection开关下的选项可以选择展示的不同类型。
+
+
+ 根据duration大小将hang划分为4个type,即Instant、Circumstantial、Micro、Severe。4个type分别对应时长为
+ 33ms<d<100ms、100ms≤d<250ms、250ms≤d<500ms、500ms≤d。
+
+
+ 颜色按type由浅及深:Instant蓝色、Circumstantial黄色、Micro橙色、Severe红色。
+
+
+ 选择不同类型展示出的泳道会不一样: 选择Instant会显示Instant、Circumstantial、Micro、Severe,如图一;
+ 选择Circumstantial则显示Circumstantial、Micro、Severe,如图二,以此类推。
+
+
+
+ 图一
+
+
+
+ 图二
+
+
+
+ 可以对hangs的各个slice进行点选,点选后在最下方的弹出层中会展示点选数据的统计的tab页。点击Hang type右侧蓝色箭头,会跳转到该hang对应的trace点。
+
+
+
+
+
+ Trace点的name依次对应tab页的Sender tid、Send time、Expect handle time、Task name/ID、Prio、Sender。
+
+
+ -
+
+StartTime(Relative):开始时间(相对时间)。
+
+
+ -
+
+StartTime(Absolute):开始时间(绝对时间)。
+
+
+ -
+
+Duration:持续时间。
+
+
+ -
+
+Hang Type:挂起类型。
+
+
+ -
+
+Sender tid:发送event的线程ID。
+
+
+ -
+
+Send time:事件发送时间。
+
+
+ -
+
+Expect handle time:期望事件开始时间。
+
+
+ -
+
+Task name/Id:事件名/事件ID。
+
+
+ -
+
+Prio:优先级。
+
+
+ -
+
+Sender:发送者。
+
+
+
+
+
+ 框选Hangs的泳道图,展示Hangs的tab页,右侧第一个下拉框可以选择类型,也能根据process ,sender去搜索。
+
+
+
+ -
+
+StartTime:开始时间。
+
+
+ -
+
+Duration:持续时间。
+
+
+ -
+
+Hang Type:挂起类型。
+
+
+ -
+
+Process:进程名。
+
+
+ -
+
+Sender tid:发送event的线程ID。
+
+
+ -
+
+Send time:事件发送时间。
+
+
+ -
+
+Expect handle time:期望事件开始时间。
+
+
+ -
+
+Task name/Id:事件名/事件ID。
+
+
+ -
+
+Prio:优先级。
+
+
+ -
+
+Sender:发送者。
+
+
+
+
+ 框选Hangs的泳道图,展示Summary的tab页。
+
+
+
+
+
+ 为了方便查看hangs数据,对不同进程下的hangs泳道进行了归一化处理
+
+