1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import {SpSystemTrace} from "../SpSystemTrace.js"; 17import {TraceRow} from "../trace/base/TraceRow.js"; 18import {procedurePool} from "../../database/Procedure.js"; 19import { 20 getDiskIOLatencyChartDataByProcess, 21 getDiskIOProcess, 22 getFileSysChartDataByType, getFileSysVirtualMemoryChartData, 23 hasFileSysData 24} from "../../database/SqlLite.js"; 25import {FileSysChartStruct} from "../../database/ui-worker/ProcedureWorkerFileSystem.js"; 26import { ColorUtils } from "../trace/base/ColorUtils.js"; 27 28export class SpFileSystemChart { 29 private trace: SpSystemTrace; 30 static hoverFileSysStruct: FileSysChartStruct | undefined; 31 32 constructor(trace: SpSystemTrace) { 33 this.trace = trace; 34 } 35 36 async init() { 37 let sys = await hasFileSysData(); 38 if(sys.length > 0){ 39 let fsCount = sys[0]['fsCount'] ?? 0; 40 let vmCount = sys[0]['vmCount'] ?? 0; 41 let ioCount = sys[0]['ioCount'] ?? 0; 42 if(sys && sys.length > 0 && (fsCount > 0 || vmCount > 0 || ioCount > 0)){ 43 let folder = await this.initFolder(); 44 await this.initFileCallchain() 45 if(fsCount > 0){ 46 await this.initLogicalRead(folder); 47 await this.initLogicalWrite(folder); 48 } 49 if(vmCount > 0){ 50 await this.initVirtualMemoryTrace(folder); 51 } 52 } 53 } 54 } 55 56 async initFileCallchain(){ 57 return new Promise<any>((resolve, reject) => { 58 procedurePool.submitWithName("logic0","fileSystem-init",SpSystemTrace.DATA_DICT,undefined,(res:any)=>{ 59 resolve(res) 60 }) 61 }) 62 } 63 64 async initFolder():Promise<TraceRow<any>>{ 65 let folder = new TraceRow(); 66 folder.rowId = `FileSystem`; 67 folder.index = 0; 68 folder.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM_GROUP 69 folder.rowParentId = ''; 70 folder.folder = true; 71 folder.name = `EBPF` ;/* & I/O Latency */ 72 folder.supplier = () => new Promise<Array<any>>((resolve) => resolve([])); 73 folder.favoriteChangeHandler = this.trace.favoriteChangeHandler; 74 folder.selectChangeHandler = this.trace.selectChangeHandler; 75 folder.onThreadHandler = (useCache) => { 76 procedurePool.submitWithName(`process${folder.index}`, `${TraceRow.ROW_TYPE_FILE_SYSTEM_GROUP}`, folder.buildArgs({ 77 flagMoveInfo: this.trace.hoverFlag, 78 flagSelectedInfo: this.trace.selectFlag, 79 useCache: useCache, 80 scale: TraceRow.range?.scale || 50, 81 }), !folder.isTransferCanvas ? folder.offscreen[0] : undefined, (res: any) => { 82 folder.must = false; 83 }) 84 folder.isTransferCanvas = true; 85 } 86 this.trace.rowsEL?.appendChild(folder) 87 return folder; 88 } 89 90 async initLogicalRead(folder:TraceRow<any>){ 91 let row = new TraceRow(); 92 row.rowId = `FileSystemLogicalRead`; 93 row.index = 1; 94 row.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM 95 row.rowParentId = folder.rowId; 96 row.rowHidden = !folder.expansion 97 row.rangeSelect = true; 98 row.isHover = true; 99 row.style.height = '40px' 100 row.style.width = `100%`; 101 row.setAttribute('children', ''); 102 row.name = `FileSystem Logical Read`; 103 row.supplier = () => getFileSysChartDataByType(2); 104 row.favoriteChangeHandler = this.trace.favoriteChangeHandler; 105 row.selectChangeHandler = this.trace.selectChangeHandler; 106 row.onThreadHandler = (useCache) => { 107 procedurePool.submitWithName(`process${(row.index) % procedurePool.processLen.length}`, `${TraceRow.ROW_TYPE_FILE_SYSTEM}-logical-read`, row.buildArgs({ 108 flagMoveInfo: this.trace.hoverFlag, 109 flagSelectedInfo: this.trace.selectFlag, 110 useCache: useCache, 111 chartColor:ColorUtils.MD_PALETTE[0], 112 lineColor: row.getLineColor(), 113 scale: TraceRow.range?.scale || 50, 114 }), row.getTransferArray(), (res: any,hover: any) => { 115 row.must = false; 116 if (row.isHover) { 117 SpFileSystemChart.hoverFileSysStruct = hover; 118 } 119 }) 120 row.isTransferCanvas = true; 121 } 122 this.trace.rowsEL?.appendChild(row) 123 } 124 125 async initLogicalWrite(folder:TraceRow<any>){ 126 let row = new TraceRow(); 127 row.rowId = `FileSystemLogicalWrite`; 128 row.index = 2; 129 row.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM 130 row.rowParentId = folder.rowId; 131 row.rowHidden = !folder.expansion; 132 row.rangeSelect = true; 133 row.isHover = true; 134 row.style.height = '40px' 135 row.style.width = `100%`; 136 row.setAttribute('children', ''); 137 row.name = `FileSystem Logical Write`; 138 row.supplier = () => getFileSysChartDataByType(3); 139 row.favoriteChangeHandler = this.trace.favoriteChangeHandler; 140 row.selectChangeHandler = this.trace.selectChangeHandler; 141 row.onThreadHandler = (useCache) => { 142 procedurePool.submitWithName(`process${(row.index) % procedurePool.processLen.length}`, `${TraceRow.ROW_TYPE_FILE_SYSTEM}-logical-write`, row.buildArgs({ 143 flagMoveInfo: this.trace.hoverFlag, 144 flagSelectedInfo: this.trace.selectFlag, 145 useCache: useCache, 146 lineColor: row.getLineColor(), 147 chartColor:ColorUtils.MD_PALETTE[8], 148 scale: TraceRow.range?.scale || 50, 149 }), row.getTransferArray(), (res: any,hover: any) => { 150 row.must = false; 151 if (row.isHover) { 152 SpFileSystemChart.hoverFileSysStruct = hover; 153 } 154 }) 155 row.isTransferCanvas = true; 156 } 157 this.trace.rowsEL?.appendChild(row) 158 } 159 160 async initDiskIOLatency(folder:TraceRow<any>){ 161 let row = new TraceRow(); 162 row.rowId = `FileSystemDiskIOLatency`; 163 row.index = 4; 164 row.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM 165 row.rowParentId = folder.rowId; 166 row.rowHidden = !folder.expansion 167 row.style.height = '40px' 168 row.style.width = `100%`; 169 row.setAttribute('children', ''); 170 row.name = `Disk I/O Latency`; 171 row.supplier = () => getDiskIOLatencyChartDataByProcess(true,0,[2,3]); 172 row.favoriteChangeHandler = this.trace.favoriteChangeHandler; 173 row.selectChangeHandler = this.trace.selectChangeHandler; 174 row.onThreadHandler = (useCache) => { 175 procedurePool.submitWithName(`process${(row.index) % procedurePool.processLen.length}`, `${TraceRow.ROW_TYPE_FILE_SYSTEM}-disk-io`, row.buildArgs({ 176 flagMoveInfo: this.trace.hoverFlag, 177 flagSelectedInfo: this.trace.selectFlag, 178 chartColor:ColorUtils.MD_PALETTE[0], 179 useCache: useCache, 180 scale: TraceRow.range?.scale || 50, 181 }), row.getTransferArray(), (res: any,hover: any) => { 182 row.must = false; 183 if (row.isHover) { 184 SpFileSystemChart.hoverFileSysStruct = hover; 185 } 186 }) 187 row.isTransferCanvas = true; 188 } 189 this.trace.rowsEL?.appendChild(row) 190 } 191 192 async initProcessDiskIOLatency(folder:TraceRow<any>){ 193 let processes = await getDiskIOProcess() || []; 194 for (let i = 0,len = processes.length; i < len; i++) { 195 let process = processes[i]; 196 let rowRead = new TraceRow(); 197 rowRead.index = 5 + 2 * i; 198 rowRead.rowId = `FileSystemDiskIOLatency-read-${process['ipid']}`; 199 rowRead.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM 200 rowRead.rowParentId = folder.rowId; 201 rowRead.rowHidden = !folder.expansion 202 rowRead.style.height = '40px' 203 rowRead.style.width = `100%`; 204 rowRead.setAttribute('children', ''); 205 rowRead.name = `${process['name'] ?? 'Process'}(${process['pid']}) Max Read Latency`; 206 rowRead.supplier = () => getDiskIOLatencyChartDataByProcess(false,process['ipid'],[2]); 207 rowRead.favoriteChangeHandler = this.trace.favoriteChangeHandler; 208 rowRead.selectChangeHandler = this.trace.selectChangeHandler; 209 rowRead.onThreadHandler = (useCache) => { 210 procedurePool.submitWithName(`process${(rowRead.index) % procedurePool.processLen.length}`, 211 `${TraceRow.ROW_TYPE_FILE_SYSTEM}-disk-io-process-read-${process['pid']}`, rowRead.buildArgs({ 212 flagMoveInfo: this.trace.hoverFlag, 213 flagSelectedInfo: this.trace.selectFlag, 214 chartColor:ColorUtils.MD_PALETTE[0], 215 useCache: useCache, 216 scale: TraceRow.range?.scale || 50, 217 }), rowRead.getTransferArray(), (res: any,hover: any) => { 218 rowRead.must = false; 219 if (rowRead.isHover) { 220 SpFileSystemChart.hoverFileSysStruct = hover; 221 } 222 }) 223 rowRead.isTransferCanvas = true; 224 } 225 this.trace.rowsEL?.appendChild(rowRead) 226 let rowWrite = new TraceRow(); 227 rowWrite.index = 5 + 2 * i + 1; 228 rowWrite.rowId = `FileSystemDiskIOLatency-write-${process['ipid']}`; 229 rowWrite.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM 230 rowWrite.rowParentId = folder.rowId; 231 rowWrite.rowHidden = !folder.expansion 232 rowWrite.style.height = '40px' 233 rowWrite.style.width = `100%`; 234 rowWrite.setAttribute('children', ''); 235 rowWrite.name = `${process['name'] ?? 'Process'}(${process['pid']}) Max Write Latency`; 236 rowWrite.supplier = () => getDiskIOLatencyChartDataByProcess(false,process['ipid'],[3]); 237 rowWrite.favoriteChangeHandler = this.trace.favoriteChangeHandler; 238 rowWrite.selectChangeHandler = this.trace.selectChangeHandler; 239 rowWrite.onThreadHandler = (useCache) => { 240 procedurePool.submitWithName(`process${(rowWrite.index) % procedurePool.processLen.length}`, 241 `${TraceRow.ROW_TYPE_FILE_SYSTEM}-disk-io-process-write-${process['pid']}`, rowWrite.buildArgs({ 242 flagMoveInfo: this.trace.hoverFlag, 243 flagSelectedInfo: this.trace.selectFlag, 244 chartColor:ColorUtils.MD_PALETTE[8], 245 useCache: useCache, 246 scale: TraceRow.range?.scale || 50, 247 }), rowWrite.getTransferArray(), (res: any,hover: any) => { 248 rowWrite.must = false; 249 if (rowWrite.isHover) { 250 SpFileSystemChart.hoverFileSysStruct = hover; 251 } 252 }) 253 rowWrite.isTransferCanvas = true; 254 } 255 this.trace.rowsEL?.appendChild(rowWrite) 256 } 257 } 258 259 async initVirtualMemoryTrace(folder:TraceRow<any>){ 260 let row = new TraceRow(); 261 row.rowId = `FileSystemVirtualMemory`; 262 row.index = 3; 263 row.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM 264 row.rowParentId = folder.rowId; 265 row.rowHidden = !folder.expansion 266 row.rangeSelect = true; 267 row.style.height = '40px' 268 row.style.width = `100%`; 269 row.setAttribute('children', ''); 270 row.name = `Virtual Memory Trace`; 271 row.supplier = () => getFileSysVirtualMemoryChartData(); 272 row.favoriteChangeHandler = this.trace.favoriteChangeHandler; 273 row.selectChangeHandler = this.trace.selectChangeHandler; 274 row.onThreadHandler = (useCache) => { 275 procedurePool.submitWithName(`process${(row.index) % procedurePool.processLen.length}`, `${TraceRow.ROW_TYPE_FILE_SYSTEM}-virtual-memory`, row.buildArgs({ 276 flagMoveInfo: this.trace.hoverFlag, 277 flagSelectedInfo: this.trace.selectFlag, 278 chartColor:ColorUtils.MD_PALETTE[0], 279 useCache: useCache, 280 scale: TraceRow.range?.scale || 50, 281 }), row.getTransferArray(), (res: any,hover: any) => { 282 row.must = false; 283 if (row.isHover) { 284 SpFileSystemChart.hoverFileSysStruct = hover; 285 } 286 }) 287 row.isTransferCanvas = true; 288 } 289 this.trace.rowsEL?.appendChild(row) 290 } 291}