meminsight-test-demo 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +36 -0
- package/docs/Build.md +68 -0
- package/docs/Interface.md +35 -0
- package/docs/UserGuide.md +332 -0
- package/docs/resources/analyzer.png +0 -0
- package/docs/resources/cfg_filter_filetype_json.png +0 -0
- package/docs/resources/filetype_txt.png +0 -0
- package/docs/resources/framework.png +0 -0
- package/docs/resources/output.png +0 -0
- package/docs/resources/process.png +0 -0
- package/package.json +54 -0
- package/packages/cfg/ArkStatCfg.json +33 -0
- package/packages/core/jest.config.js +8 -0
- package/packages/core/package.json +61 -0
- package/packages/core/src/Index.ts +53 -0
- package/packages/core/src/analyzer/AnalysisInfo.ts +298 -0
- package/packages/core/src/analyzer/ArkAnalyzer.ts +42 -0
- package/packages/core/src/analyzer/ArkCmpCfg.ts +22 -0
- package/packages/core/src/analyzer/ArkCompareAnalyzer.ts +173 -0
- package/packages/core/src/analyzer/ArkLeakAnalyzer.ts +196 -0
- package/packages/core/src/analyzer/ArkSerializer.ts +163 -0
- package/packages/core/src/analyzer/ArkStatAnalyzer.ts +191 -0
- package/packages/core/src/analyzer/ArkStatCfg.ts +77 -0
- package/packages/core/src/analyzer/ArkTracePath.ts +269 -0
- package/packages/core/src/analyzer/ArkTracer.ts +42 -0
- package/packages/core/src/analyzer/ArkXAnalyzer.ts +631 -0
- package/packages/core/src/analyzer/IAnalyzer.ts +27 -0
- package/packages/core/src/file/FileReader.ts +82 -0
- package/packages/core/src/file/FileService.ts +50 -0
- package/packages/core/src/file/FileWriter.ts +148 -0
- package/packages/core/src/report/Reporter.ts +81 -0
- package/packages/core/src/report/templates/template.ejs +101 -0
- package/packages/core/src/report/templates/template.ts +103 -0
- package/packages/core/src/shell/DeviceShell.ts +179 -0
- package/packages/core/src/shell/Shell.ts +99 -0
- package/packages/core/src/types/Constants.ts +16 -0
- package/packages/core/src/types/LeakTypes.ts +21 -0
- package/packages/core/src/types/OhosTypes.ts +115 -0
- package/packages/core/src/utils/Common.ts +37 -0
- package/packages/core/src/utils/Finder.ts +390 -0
- package/packages/core/src/utils/Loader.ts +53 -0
- package/packages/core/src/utils/Log.ts +252 -0
- package/packages/core/src/utils/Output.ts +271 -0
- package/packages/core/tsconfig.json +10 -0
- package/packages/exampletools/package.json +52 -0
- package/packages/exampletools/src/MemTest.ts +64 -0
- package/packages/exampletools/tsconfig.json +15 -0
- package/packages/meminsight/jest.config.js +8 -0
- package/packages/meminsight/package.json +52 -0
- package/packages/meminsight/src/Index.ts +4 -0
- package/packages/meminsight/src/Version.ts +7 -0
- package/packages/meminsight/src/process/ArkCompareProc.ts +160 -0
- package/packages/meminsight/src/process/ArkGCProc.ts +61 -0
- package/packages/meminsight/src/process/ArkLeakProc.ts +47 -0
- package/packages/meminsight/src/process/ArkStatProc.ts +320 -0
- package/packages/meminsight/src/process/ArkXProc.ts +73 -0
- package/packages/meminsight/src/process/HMemXProc.ts +50 -0
- package/packages/meminsight/src/process/IProcess.ts +12 -0
- package/packages/meminsight/tsconfig.json +15 -0
- package/packages/stack/README.md +31 -0
- package/packages/stack/libs/hstack_lib-1.0.0.tgz +0 -0
- package/packages/stack/libs/hstack_lib-1.0.1.tgz +0 -0
- package/packages/stack/libs/hstack_lib-1.0.4.tgz +0 -0
- package/packages/stack/libs/lib_list.json +34 -0
- package/packages/stack/package.json +27 -0
- package/packages/stack/src/Index.js +29 -0
- package/packages/stack/src/StackTracer.js +53 -0
- package/packages/templates/ArkLeaks.template +9 -0
- package/packages/templates/ArkNodes.template +9 -0
- package/packages/templates/ArkPaths.template +9 -0
- package/test/scripts/merge.py +145 -0
- package/test/scripts/stat.py +175 -0
- package/test/test_ark_stat_proc.sh +14 -0
- package/tsconfig.base.json +38 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { Shell, ShellArgs } from "./Shell";
|
|
2
|
+
import { AppInfo, DeviceInfo } from "../types/OhosTypes";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* DeviceShell
|
|
6
|
+
*/
|
|
7
|
+
export class DeviceShell {
|
|
8
|
+
private static defaultInstance: DeviceShell = new DeviceShell();
|
|
9
|
+
private static deviceMap: Map<string, DeviceShell> = new Map();
|
|
10
|
+
private deviceInfo?: DeviceInfo;
|
|
11
|
+
|
|
12
|
+
constructor(deviceId?: string) {
|
|
13
|
+
this.deviceInfo = new DeviceInfo(deviceId);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 获取DeviceShell实例
|
|
18
|
+
* @param deviceId device id
|
|
19
|
+
* @returns DeviceShell
|
|
20
|
+
*/
|
|
21
|
+
public static getDeviceShell(deviceId?: string) : DeviceShell {
|
|
22
|
+
let shellInst: DeviceShell | undefined = DeviceShell.deviceMap.get(deviceId || '');
|
|
23
|
+
if (!shellInst) {
|
|
24
|
+
shellInst = new DeviceShell(deviceId);
|
|
25
|
+
DeviceShell.deviceMap.set(deviceId || '', shellInst);
|
|
26
|
+
}
|
|
27
|
+
return shellInst;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* clear device shell instances
|
|
32
|
+
*/
|
|
33
|
+
public static clearDeviceShell() : void {
|
|
34
|
+
DeviceShell.deviceMap.clear();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private getDeviceCmd(): string {
|
|
38
|
+
let deviceId = this.getDeviceId();
|
|
39
|
+
return `${deviceId === '' ? '' : `-t ${deviceId}`}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 默认 DeviceShell 单例
|
|
44
|
+
* @returns device instance
|
|
45
|
+
*/
|
|
46
|
+
public static default(): DeviceShell {
|
|
47
|
+
return this.defaultInstance;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 获取设备信息
|
|
52
|
+
* @returns device info
|
|
53
|
+
*/
|
|
54
|
+
public getDeviceInfo(): DeviceInfo | undefined {
|
|
55
|
+
return this.deviceInfo;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 获取设备ID
|
|
60
|
+
* @returns device id
|
|
61
|
+
*/
|
|
62
|
+
public getDeviceId() : string {
|
|
63
|
+
return this.deviceInfo?.deviceId || '';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 执行设备命令
|
|
68
|
+
* @param cmd command
|
|
69
|
+
* @param excludeEmptyLine 输出不包含空行
|
|
70
|
+
* @param trimLine 输出行去空格
|
|
71
|
+
* @returns 输出信息
|
|
72
|
+
*/
|
|
73
|
+
public execSync(cmd: string, excludeEmptyLine: boolean = true, trimLine: boolean = true): string[] {
|
|
74
|
+
let args: ShellArgs = {
|
|
75
|
+
excludeEmptyLine: excludeEmptyLine,
|
|
76
|
+
trimLine: trimLine }
|
|
77
|
+
return Shell.execSync(`hdc ${this.getDeviceCmd()} shell "${cmd}"`, args);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 接收文件到本地
|
|
82
|
+
* @param remoteFile 远程文件路径
|
|
83
|
+
* @param localFile 本地文件路径
|
|
84
|
+
*/
|
|
85
|
+
public recvFile(remoteFile: string, localFile: string): void {
|
|
86
|
+
Shell.execSync(`hdc ${this.getDeviceCmd()} file recv "${remoteFile}" "${localFile}"`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* 发送文件到设备
|
|
91
|
+
* @param localFile 本地文件路径
|
|
92
|
+
* @param remoteFile 远程文件路径
|
|
93
|
+
*/
|
|
94
|
+
public sendFile(localFile: string, remoteFile: string): void {
|
|
95
|
+
Shell.execSync(`hdc ${this.getDeviceCmd()} file send "${localFile}" "${remoteFile}"`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 通过应用名称获取app信息
|
|
100
|
+
* @param bundleName 应用名称
|
|
101
|
+
* @returns AppInfo
|
|
102
|
+
*/
|
|
103
|
+
public getAppInfoByName(bundleName: string) : AppInfo {
|
|
104
|
+
const appInfo = new AppInfo();
|
|
105
|
+
appInfo.name = bundleName;
|
|
106
|
+
appInfo.pid = this.getAppPid(bundleName);
|
|
107
|
+
return appInfo;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* 通过pid获取app信息
|
|
112
|
+
* @param pid pid
|
|
113
|
+
* @returns AppInfo
|
|
114
|
+
*/
|
|
115
|
+
public getAppInfoByPid(pid: number) : AppInfo {
|
|
116
|
+
const appInfo = new AppInfo();
|
|
117
|
+
appInfo.pid = pid;
|
|
118
|
+
appInfo.name = this.getAppName(pid);
|
|
119
|
+
return appInfo;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* 应用进程PID
|
|
124
|
+
* @param bundleName 应用名称
|
|
125
|
+
* @returns pid | undefined
|
|
126
|
+
*/
|
|
127
|
+
public getAppPid(bundleName: string) : number | undefined {
|
|
128
|
+
let strs = this.execSync(`pidof ${bundleName}`);
|
|
129
|
+
if (strs.length === 1) {
|
|
130
|
+
return parseInt(strs[0].trim().split(' ')[0]);
|
|
131
|
+
} else {
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 获取应用名称
|
|
138
|
+
* @param pid 进程id
|
|
139
|
+
* @returns 进程名称
|
|
140
|
+
*/
|
|
141
|
+
public getAppName(pid: number) : string {
|
|
142
|
+
// 20008 2940 674 0 12:35:30 ? 00:00:16 com.xxx.yyy.zzz
|
|
143
|
+
let strs = this.execSync(`ps -ef | grep ${pid} | grep -v grep`);
|
|
144
|
+
let appName: string | undefined;
|
|
145
|
+
if (strs.length === 1) {
|
|
146
|
+
appName = strs[0].split(/\s+/).pop();
|
|
147
|
+
}
|
|
148
|
+
return appName || '';
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* 是否是Root镜像设备
|
|
153
|
+
* @returns true/false
|
|
154
|
+
*/
|
|
155
|
+
public isRootDevice() : boolean {
|
|
156
|
+
let strs = this.execSync('ls /system');
|
|
157
|
+
return strs.findIndex(str => str.indexOf('ls: /system: Permission denied') >= 0) == -1;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* 指定pid GC
|
|
162
|
+
* @param pid 进程id
|
|
163
|
+
*/
|
|
164
|
+
public async forceGC(pid: number) : Promise<void> {
|
|
165
|
+
let cmd = `hidumper --mem-jsheap ${pid} --gc`;
|
|
166
|
+
this.execSync(cmd);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* 指定包名 GC
|
|
171
|
+
* @param name 进程名
|
|
172
|
+
*/
|
|
173
|
+
public async forceGCByName(app: string) : Promise<void> {
|
|
174
|
+
let pid = this.getAppPid(app);
|
|
175
|
+
if (pid) {
|
|
176
|
+
await this.forceGC(pid);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { execSync, execFileSync, ExecFileSyncOptions } from 'child_process';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* execute args
|
|
5
|
+
*/
|
|
6
|
+
export class ShellArgs {
|
|
7
|
+
/**
|
|
8
|
+
* exclude empty line
|
|
9
|
+
*/
|
|
10
|
+
excludeEmptyLine: boolean = true;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* trim line start and end
|
|
14
|
+
*/
|
|
15
|
+
trimLine: boolean = true;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* shell interface
|
|
20
|
+
*/
|
|
21
|
+
export interface IShell {
|
|
22
|
+
/**
|
|
23
|
+
* execute command
|
|
24
|
+
* @param command command
|
|
25
|
+
* @param ExecuteArgs execute args
|
|
26
|
+
*/
|
|
27
|
+
execSync(command: string, args?: ShellArgs): string[];
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* execute target
|
|
31
|
+
* @param target target path
|
|
32
|
+
* @param ExecuteArgs execute args
|
|
33
|
+
* @param options options
|
|
34
|
+
*/
|
|
35
|
+
execSyncTarget(target: string, args?: ShellArgs, options?: ExecFileSyncOptions): string[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* shell implementation
|
|
40
|
+
*/
|
|
41
|
+
class ShellImpl implements IShell {
|
|
42
|
+
/**
|
|
43
|
+
* 执行同步命令
|
|
44
|
+
* @param command 命令
|
|
45
|
+
* @param args 执行参数
|
|
46
|
+
* @returns 输出字符串数组
|
|
47
|
+
*/
|
|
48
|
+
execSync(command: string, args?: ShellArgs): string[] {
|
|
49
|
+
let lines = execSync(command).toString("utf-8").split(/\r?\n/);
|
|
50
|
+
if (args) {
|
|
51
|
+
if (args.excludeEmptyLine) {
|
|
52
|
+
lines = lines.filter(line => !!line);
|
|
53
|
+
}
|
|
54
|
+
if (args.trimLine) {
|
|
55
|
+
lines = lines.map(lines => lines.trim())
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return lines;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
execSyncTarget(target: string, args?: ShellArgs, options?: ExecFileSyncOptions): string[] {
|
|
62
|
+
let lines = execFileSync(target, options).toString('utf-8').split(/\r?\n/);
|
|
63
|
+
if (args) {
|
|
64
|
+
if (args.excludeEmptyLine) {
|
|
65
|
+
lines = lines.filter(line => !!line);
|
|
66
|
+
}
|
|
67
|
+
if (args.trimLine) {
|
|
68
|
+
lines = lines.map(lines => lines.trim())
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return lines;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* shell wrapper
|
|
77
|
+
*/
|
|
78
|
+
export class Shell {
|
|
79
|
+
private static _impl: IShell = new ShellImpl();
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* execute command
|
|
83
|
+
* @param command commanda
|
|
84
|
+
* @param formatArgs output format args
|
|
85
|
+
*/
|
|
86
|
+
public static execSync(command: string, args?: ShellArgs): string[] {
|
|
87
|
+
return this._impl.execSync(command, args);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* execute target
|
|
92
|
+
* @param target target path
|
|
93
|
+
* @param args args
|
|
94
|
+
* @param options options
|
|
95
|
+
*/
|
|
96
|
+
public static execSyncTarget(target: string, args?: ShellArgs, options?: ExecFileSyncOptions): string[] {
|
|
97
|
+
return this._impl.execSyncTarget(target, args, options);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* strings enum
|
|
3
|
+
*/
|
|
4
|
+
export enum STRINGS {
|
|
5
|
+
IS_DELETING = 'isDeleting_',
|
|
6
|
+
BOOLEAN_TRUE = 'Boolean:true',
|
|
7
|
+
|
|
8
|
+
OBJECT = '(object)',
|
|
9
|
+
CLOSURE = '(closure)',
|
|
10
|
+
FUNCTION = '(function)',
|
|
11
|
+
ARRAY = '(array)',
|
|
12
|
+
STRING = '(string)',
|
|
13
|
+
|
|
14
|
+
CONSTRUCTOR = 'constructor',
|
|
15
|
+
PROTO = '__proto__',
|
|
16
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { LeakTracePathItem } from '@memlab/core'
|
|
2
|
+
|
|
3
|
+
export interface ILeakBase {
|
|
4
|
+
nodeId: number;
|
|
5
|
+
startTime: number;
|
|
6
|
+
endTime: number;
|
|
7
|
+
duration?: number; // leaked duration
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface ILeakTrace extends ILeakBase {
|
|
11
|
+
trace: LeakTracePathItem,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface ILeakUnit extends ILeakBase {
|
|
15
|
+
trace: string[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ILeakResult {
|
|
19
|
+
related: Map<any, any>;
|
|
20
|
+
leaks: ILeakUnit[];
|
|
21
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* interface for data info
|
|
3
|
+
*/
|
|
4
|
+
export interface IDataInfo {
|
|
5
|
+
type: string;
|
|
6
|
+
toString(): string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* os info
|
|
11
|
+
*/
|
|
12
|
+
export class OsInfo implements IDataInfo {
|
|
13
|
+
public type: string = "os";
|
|
14
|
+
public name: string;
|
|
15
|
+
public version?: string;
|
|
16
|
+
|
|
17
|
+
constructor(name?: string, version?: string) {
|
|
18
|
+
this.name = name || "ohos";
|
|
19
|
+
this.version = version;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public toString(): string {
|
|
23
|
+
return `${this.type} ${this.name} ${this.version}`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* device info
|
|
29
|
+
*/
|
|
30
|
+
export class DeviceInfo implements IDataInfo {
|
|
31
|
+
public type: string = 'ohos-device';
|
|
32
|
+
public deviceId: string;
|
|
33
|
+
public deviceName?: string;
|
|
34
|
+
public version?: string;
|
|
35
|
+
|
|
36
|
+
constructor(deviceId?: string) {
|
|
37
|
+
this.deviceId = deviceId || '';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public toString(): string {
|
|
41
|
+
return `${this.deviceId}`;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* app info
|
|
47
|
+
*/
|
|
48
|
+
export class AppInfo implements IDataInfo {
|
|
49
|
+
public type: string = 'app';
|
|
50
|
+
public name: string;
|
|
51
|
+
public pid?: number;
|
|
52
|
+
public version?: string;
|
|
53
|
+
|
|
54
|
+
constructor(name?: string, pid?: number, version?: string) {
|
|
55
|
+
this.name = name || '';
|
|
56
|
+
this.pid = pid;
|
|
57
|
+
this.version = version;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public toString(): string {
|
|
61
|
+
return `${this.name}`;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* url info
|
|
67
|
+
*/
|
|
68
|
+
export class UrlInfo implements IDataInfo {
|
|
69
|
+
public type: string = 'url';
|
|
70
|
+
public url: string;
|
|
71
|
+
public mappingUrl?: string;
|
|
72
|
+
|
|
73
|
+
public toString(): string {
|
|
74
|
+
return `${this.url}`;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* heap file info
|
|
80
|
+
*/
|
|
81
|
+
export class HeapFileInfo implements IDataInfo {
|
|
82
|
+
public type: string = 'heap';
|
|
83
|
+
public name: string;
|
|
84
|
+
public path: string;
|
|
85
|
+
public size?: number;
|
|
86
|
+
public region?: string;
|
|
87
|
+
public scene?: string;
|
|
88
|
+
public url?: UrlInfo;
|
|
89
|
+
public createTime?: number = 0; // create time
|
|
90
|
+
|
|
91
|
+
constructor(path: string) {
|
|
92
|
+
this.path = path;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
public toString(): string {
|
|
96
|
+
return `${this.name}:${this.path}`;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* heap infos
|
|
102
|
+
*/
|
|
103
|
+
export class HeapInfos {
|
|
104
|
+
public osInfo?: OsInfo;
|
|
105
|
+
public deviceInfo?: DeviceInfo;
|
|
106
|
+
public appInfo?: AppInfo;
|
|
107
|
+
public heapFileInfo?: HeapFileInfo;
|
|
108
|
+
|
|
109
|
+
constructor(os?: OsInfo, device?: DeviceInfo, app?: AppInfo, heapFile?: HeapFileInfo) {
|
|
110
|
+
this.osInfo = os;
|
|
111
|
+
this.deviceInfo = device;
|
|
112
|
+
this.appInfo = app;
|
|
113
|
+
this.heapFileInfo = heapFile;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* T != null
|
|
3
|
+
* @param value T instance
|
|
4
|
+
* @returns true if T instance is not null or undefined
|
|
5
|
+
*/
|
|
6
|
+
export function isDefined<T>(value: T | null | undefined): value is T {
|
|
7
|
+
return value != null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 格式化 Date 为指定字符串
|
|
12
|
+
* @param date 要格式化的日期(默认当前时间)
|
|
13
|
+
* @param format 格式模板:YYYY=年, MM=月, DD=日, HH=时, mm=分, ss=秒, SSS=毫秒
|
|
14
|
+
* @returns 格式化后的字符串
|
|
15
|
+
*/
|
|
16
|
+
export function formatDate(date: Date, format: string = 'YYYYMMDDHHmmss'): string {
|
|
17
|
+
// 补零函数:确保数字为两位数(如 9 → 09)
|
|
18
|
+
const padZero = (num: number, length = 2): string => num.toString().padStart(length, '0');
|
|
19
|
+
|
|
20
|
+
const year = date.getFullYear();
|
|
21
|
+
const month = padZero(date.getMonth() + 1); // 月份从 0 开始,需 +1
|
|
22
|
+
const day = padZero(date.getDate());
|
|
23
|
+
const hour = padZero(date.getHours());
|
|
24
|
+
const minute = padZero(date.getMinutes());
|
|
25
|
+
const second = padZero(date.getSeconds());
|
|
26
|
+
const millisecond = padZero(date.getMilliseconds(), 3); // 三位数毫秒
|
|
27
|
+
|
|
28
|
+
// 替换格式模板
|
|
29
|
+
return format
|
|
30
|
+
.replace('YYYY', year.toString())
|
|
31
|
+
.replace('MM', month)
|
|
32
|
+
.replace('DD', day)
|
|
33
|
+
.replace('HH', hour)
|
|
34
|
+
.replace('mm', minute)
|
|
35
|
+
.replace('ss', second)
|
|
36
|
+
.replace('SSS', millisecond);
|
|
37
|
+
}
|