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 data 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 */ 15import { element } from '../../../../../base-ui/BaseElement'; 16import { type LitSelect } from '../../../../../base-ui/select/LitSelect'; 17import { LitSelectOption } from '../../../../../base-ui/select/LitSelectOption'; 18import { type LitTable } from '../../../../../base-ui/table/lit-table'; 19import { type SelectionParam } from '../../../../bean/BoxSelection'; 20import { resizeObserverFromMemory } from '../SheetUtils'; 21import { type TabPaneJsMemoryFilter } from '../TabPaneJsMemoryFilter'; 22import { TabPaneSmapsStatistics } from './TabPaneSmapsStatistics'; 23import { type SmapsType } from '../../../../bean/SmapsStruct'; 24import {getTabSmapsStatisticData} from "../../../../database/sql/Smaps.sql"; 25 26@element('tabpane-smaps-comparison') 27export class TabPaneSmapsComparison extends TabPaneSmapsStatistics { 28 private smapsCompariosnTable: LitTable | null | undefined; 29 private filterEl: TabPaneJsMemoryFilter | undefined | null; 30 private selectEl: LitSelect | undefined | null; 31 private selectionParam: SelectionParam | undefined; 32 33 public initElements(): void { 34 this.smapsCompariosnTable = this.shadowRoot?.querySelector<LitTable>('#tb-smaps-comparison'); 35 this.filterEl = this.shadowRoot!.querySelector<TabPaneJsMemoryFilter>('#filter'); 36 this.selectEl = this.filterEl?.shadowRoot?.querySelector<LitSelect>('lit-select'); 37 this.tabTitle = this.smapsCompariosnTable!.shadowRoot?.querySelector('.thead') as HTMLDivElement; 38 this.smapsCompariosnTable!.addEventListener('column-click', (evt) => { 39 // @ts-ignore 40 this.sortByColumn(evt.detail.key, evt.detail.sort, this.smapsCompariosnTable); 41 }); 42 } 43 public setData(data: SelectionParam | any, dataList: any): void { 44 if (data == this.selectionParam) { 45 return; 46 } 47 this.selectionParam = data; 48 //@ts-ignore 49 this.smapsCompariosnTable?.shadowRoot?.querySelector('.table')?.style?.height = `${ 50 this.parentElement!.clientHeight - 45 51 }px`; 52 this.smapsCompariosnTable!.loading = true; 53 this.init(this.tabTitle!); 54 let fileArr: any[] = []; 55 for (let file of dataList) { 56 if (file.startNs !== data.leftNs) { 57 fileArr.push(file); 58 } 59 } 60 fileArr = fileArr.sort(); 61 this.initSelect(data.leftNs, fileArr); 62 this.querySmapsData(data.leftNs, fileArr[0].startNs); 63 } 64 private initSelect(fileStartNs: number, smapsComFileArr: Array<any>): void { 65 let that = this; 66 let input = this.selectEl!.shadowRoot?.querySelector('input') as HTMLInputElement; 67 this.selectEl!.innerHTML = ''; 68 let option = new LitSelectOption(); 69 option.innerHTML = 'File Name'; 70 option.setAttribute('disabled', 'disabled'); 71 this.selectEl?.appendChild(option); 72 if (smapsComFileArr[0].name) { 73 option.setAttribute('value', smapsComFileArr[0].name); 74 } 75 this.selectEl!.defaultValue = smapsComFileArr[0].name; 76 this.selectEl!.placeholder = smapsComFileArr[0].name; 77 this.selectEl!.dataSource = smapsComFileArr; 78 this.selectEl!.querySelectorAll('lit-select-option').forEach((a) => { 79 a.addEventListener('onSelected', (e: any) => { 80 for (let f of smapsComFileArr) { 81 if (input.value === f.name) { 82 that.querySmapsData(fileStartNs, f.startNs); 83 } 84 } 85 e.stopPropagation(); 86 }); 87 }); 88 } 89 90 private async querySmapsData(baseTime: number, targetTime: number): Promise<void> { 91 const baseArr: SmapsCompareStruct[] = []; 92 const targetArr: SmapsCompareStruct[] = []; 93 // 点击的 94 await getTabSmapsStatisticData(baseTime).then(async (smapsComResults) => { 95 this.smapsCompariosnTable!.loading = false; 96 for (let i = 0; i < smapsComResults.length; i++) { 97 baseArr.push( 98 new SmapsCompareStruct( 99 smapsComResults[i].type, 100 smapsComResults[i].path, 101 smapsComResults[i].size, 102 smapsComResults[i].count, 103 smapsComResults[i].rss, 104 smapsComResults[i].pss, 105 smapsComResults[i].sharedClean, 106 smapsComResults[i].sharedDirty, 107 smapsComResults[i].privateClean, 108 smapsComResults[i].privateDirty, 109 smapsComResults[i].swap, 110 smapsComResults[i].swapPss 111 ) 112 ); 113 } 114 // 被比较的 115 await getTabSmapsStatisticData(targetTime).then((results) => { 116 for (let i = 0; i < results.length; i++) { 117 targetArr.push( 118 new SmapsCompareStruct( 119 results[i].type, 120 results[i].path, 121 results[i].size, 122 results[i].count, 123 results[i].rss, 124 results[i].pss, 125 results[i].sharedClean, 126 results[i].sharedDirty, 127 results[i].privateClean, 128 results[i].privateDirty, 129 results[i].swap, 130 results[i].swapPss 131 ) 132 ); 133 } 134 let compareData = this.compare(baseArr, targetArr); 135 this.filteredData(compareData, this.smapsCompariosnTable!); 136 }); 137 }); 138 } 139 140 private compare(base: Array<SmapsCompareStruct>, target: Array<SmapsCompareStruct>): Array<SmapsCompareStruct> { 141 const diffMap = new Map<string, SmapsCompareStruct>(); 142 143 for (const item of base) { 144 diffMap.set(item.type + ' ' + item.path, item.clone(true)); 145 } 146 147 for (const item of target) { 148 if (diffMap.has(item.type + ' ' + item.path)) { 149 const diffItem = diffMap.get(item.type + ' ' + item.path); 150 diffItem!.size = diffItem!.size - item.size; 151 diffItem!.count = diffItem!.count - item.count; 152 diffItem!.rss = diffItem!.rss - item.rss; 153 diffItem!.pss = diffItem!.pss - item.pss; 154 diffItem!.sharedClean = diffItem!.sharedClean - item.sharedClean; 155 diffItem!.sharedDirty = diffItem!.sharedDirty - item.sharedDirty; 156 diffItem!.privateClean = diffItem!.privateClean - item.privateClean; 157 diffItem!.privateDirty = diffItem!.privateDirty - item.privateDirty; 158 diffItem!.swap = diffItem!.swap - item.swap; 159 diffItem!.swapPss = diffItem!.swapPss - item.swapPss; 160 } else { 161 diffMap.set(item.type + ' ' + item.path, item.clone()); 162 } 163 } 164 return Array.from(diffMap.values()); 165 } 166 167 public connectedCallback(): void { 168 super.connectedCallback(); 169 resizeObserverFromMemory(this.parentElement!, this.smapsCompariosnTable!, this.filterEl!); 170 } 171 public initHtml(): string { 172 return ` 173 <style> 174 :host{ 175 display: flex; 176 flex-direction: column; 177 padding: 10px 10px; 178 } 179 </style> 180 <div style="overflow: auto;" class="d-box"> 181 <lit-table id="tb-smaps-comparison" class="smaps-comparison-table" style="height: auto;" tree> 182 <lit-table-column width="250px" title="Type" data-index="typeName" key="typeName" align="flex-start" order retract> 183 </lit-table-column> 184 <lit-table-column width="150px" title="Path" data-index="path" key="path" align="flex-start" > 185 </lit-table-column> 186 <lit-table-column width="150px" title="SizeDelta" data-index="sizeStr" key="sizeStr" align="flex-start" order> 187 </lit-table-column> 188 <lit-table-column width="150px" title="Count" data-index="count" key="count" align="flex-start" order> 189 </lit-table-column> 190 <lit-table-column width="150px" title="RssDelta" data-index="rssStr" key="rssStr" align="flex-start" order> 191 </lit-table-column> 192 <lit-table-column width="150px" title="PssDelta" data-index="pssStr" key="pssStr" align="flex-start" order> 193 </lit-table-column> 194 <lit-table-column width="150px" title="SharedCleanDelta" data-index="sharedCleanStr" key="sharedCleanStr" align="flex-start" order> 195 </lit-table-column> 196 <lit-table-column width="150px" title="SharedDirtyDelta" data-index="sharedDirtyStr" key="sharedDirtyStr" align="flex-start" order> 197 </lit-table-column> 198 <lit-table-column width="150px" title="PrivateCleanDelta" data-index="privateCleanStr" key="privateCleanStr" align="flex-start" order> 199 </lit-table-column> 200 <lit-table-column width="150px" title="PrivateDirtyDelta" data-index="privateDirtyStr" key="privateDirtyStr" align="flex-start" order> 201 </lit-table-column> 202 <lit-table-column width="150px" title="SwapDelta" data-index="swapStr" key="swapStr" align="flex-start" order> 203 </lit-table-column> 204 <lit-table-column width="150px" title="SwapPssDelta" data-index="swapPssStr" key="swapPssStr" align="flex-start" order> 205 </lit-table-column> 206 </lit-table> 207 <tab-pane-js-memory-filter id="filter" first hideFilter></tab-pane-js-memory-filter> 208 </div>`; 209 } 210} 211 212class SmapsCompareStruct { 213 type: SmapsType; 214 path: string; 215 size: number; 216 count: number; 217 rss: number; 218 pss: number; 219 sharedClean: number; 220 sharedDirty: number; 221 privateClean: number; 222 privateDirty: number; 223 swap: number; 224 swapPss: number; 225 226 constructor( 227 type: SmapsType, 228 path: string, 229 size: number, 230 count: number, 231 rss: number, 232 pss: number, 233 sharedClean: number, 234 sharedDirty: number, 235 privateClean: number, 236 privateDirty: number, 237 swap: number, 238 swapPss: number 239 ) { 240 this.type = type; 241 this.path = path; 242 this.size = size; 243 this.count = count; 244 this.rss = rss; 245 this.pss = pss; 246 this.sharedClean = sharedClean; 247 this.sharedDirty = sharedDirty; 248 this.privateClean = privateClean; 249 this.privateDirty = privateDirty; 250 this.swap = swap; 251 this.swapPss = swapPss; 252 } 253 254 clone(isBase?: boolean): SmapsCompareStruct { 255 if (isBase) { 256 return new SmapsCompareStruct( 257 this.type, 258 this.path, 259 this.size, 260 this.count, 261 this.rss, 262 this.pss, 263 this.sharedClean, 264 this.sharedDirty, 265 this.privateClean, 266 this.privateDirty, 267 this.swap, 268 this.swapPss 269 ); 270 } else { 271 return new SmapsCompareStruct( 272 this.type, 273 this.path, 274 -this.size, 275 -this.count, 276 -this.rss, 277 -this.pss, 278 -this.sharedClean, 279 -this.sharedDirty, 280 -this.privateClean, 281 -this.privateDirty, 282 -this.swap, 283 -this.swapPss 284 ); 285 } 286 } 287} 288