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