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