更新池利用率
This commit is contained in:
@@ -38,6 +38,8 @@ interface DetailedDebugInfo {
|
||||
minFrameTime: number;
|
||||
maxFrameTime: number;
|
||||
frameTimeHistory: number[];
|
||||
engineFrameTime: number;
|
||||
ecsPercentage: number;
|
||||
};
|
||||
|
||||
// 内存信息
|
||||
@@ -100,6 +102,7 @@ interface DetailedDebugInfo {
|
||||
memoryUsage: number;
|
||||
updateOrder: number;
|
||||
enabled: boolean;
|
||||
percentage: number;
|
||||
}>;
|
||||
};
|
||||
|
||||
@@ -254,6 +257,16 @@ class ECSDebugServer {
|
||||
private transformToDetailedDebugInfo(instance: GameInstance, rawData: any): DetailedDebugInfo {
|
||||
const uptime = (Date.now() - instance.connectTime) / 1000;
|
||||
|
||||
// 计算系统性能数据,包括ECS占比
|
||||
const systemBreakdown = rawData.performance?.systemBreakdown || [];
|
||||
const systemPerformance = rawData.performance?.systemPerformance || [];
|
||||
|
||||
// 创建系统名称到占比的映射
|
||||
const systemPercentageMap = new Map<string, number>();
|
||||
systemBreakdown.forEach((sys: any) => {
|
||||
systemPercentageMap.set(sys.systemName, sys.percentage || 0);
|
||||
});
|
||||
|
||||
return {
|
||||
instanceId: instance.id,
|
||||
instanceName: instance.name,
|
||||
@@ -268,7 +281,9 @@ class ECSDebugServer {
|
||||
averageFrameTime: rawData.performance?.averageFrameTime || rawData.performance?.frameTime || 0,
|
||||
minFrameTime: rawData.performance?.minFrameTime || rawData.performance?.frameTime || 0,
|
||||
maxFrameTime: rawData.performance?.maxFrameTime || rawData.performance?.frameTime || 0,
|
||||
frameTimeHistory: rawData.performance?.frameTimeHistory || []
|
||||
frameTimeHistory: rawData.performance?.frameTimeHistory || [],
|
||||
engineFrameTime: rawData.performance?.engineFrameTime || 0,
|
||||
ecsPercentage: rawData.performance?.ecsPercentage || 0
|
||||
},
|
||||
|
||||
memory: {
|
||||
@@ -307,18 +322,24 @@ class ECSDebugServer {
|
||||
|
||||
systems: {
|
||||
total: rawData.systems?.totalSystems || 0,
|
||||
systemStats: (rawData.systems?.systemsInfo || []).map((sys: any) => ({
|
||||
name: sys.name,
|
||||
type: sys.type || 'Unknown',
|
||||
entityCount: sys.entityCount || 0,
|
||||
averageExecutionTime: sys.executionTime || 0,
|
||||
minExecutionTime: sys.minExecutionTime || sys.executionTime || 0,
|
||||
maxExecutionTime: sys.maxExecutionTime || sys.executionTime || 0,
|
||||
executionTimeHistory: sys.executionTimeHistory || [],
|
||||
memoryUsage: sys.memoryUsage || 0,
|
||||
updateOrder: sys.updateOrder || 0,
|
||||
enabled: sys.enabled !== false
|
||||
}))
|
||||
systemStats: (rawData.systems?.systemsInfo || []).map((sys: any) => {
|
||||
const systemName = sys.name;
|
||||
const percentage = systemPercentageMap.get(systemName) || 0;
|
||||
|
||||
return {
|
||||
name: systemName,
|
||||
type: sys.type || 'Unknown',
|
||||
entityCount: sys.entityCount || 0,
|
||||
averageExecutionTime: sys.executionTime || 0,
|
||||
minExecutionTime: sys.minExecutionTime || sys.executionTime || 0,
|
||||
maxExecutionTime: sys.maxExecutionTime || sys.executionTime || 0,
|
||||
executionTimeHistory: sys.executionTimeHistory || [],
|
||||
memoryUsage: sys.memoryUsage || 0,
|
||||
updateOrder: sys.updateOrder || 0,
|
||||
enabled: sys.enabled !== false,
|
||||
percentage: percentage
|
||||
};
|
||||
})
|
||||
},
|
||||
|
||||
scenes: {
|
||||
@@ -348,7 +369,9 @@ const defaultDebugInfo: DetailedDebugInfo = {
|
||||
averageFrameTime: 0,
|
||||
minFrameTime: 0,
|
||||
maxFrameTime: 0,
|
||||
frameTimeHistory: []
|
||||
frameTimeHistory: [],
|
||||
engineFrameTime: 0,
|
||||
ecsPercentage: 0
|
||||
},
|
||||
memory: {
|
||||
totalMemory: 0,
|
||||
@@ -425,6 +448,7 @@ module.exports = Editor.Panel.define({
|
||||
const isAutoRefresh = ref(true);
|
||||
const refreshInterval = ref(100);
|
||||
const lastUpdateTime = ref('');
|
||||
const showComponentPoolHelp = ref(false);
|
||||
|
||||
let intervalId: NodeJS.Timeout | null = null;
|
||||
let debugServer: ECSDebugServer | null = null;
|
||||
@@ -556,6 +580,84 @@ module.exports = Editor.Panel.define({
|
||||
return 'critical';
|
||||
};
|
||||
|
||||
// 打开文档链接
|
||||
const openDocumentation = (section: string): void => {
|
||||
const urls: Record<string, string> = {
|
||||
'component-pool': 'https://github.com/esengine/ecs-framework/tree/master/docs/component-design-guide.md#1-对象池优化',
|
||||
'performance-optimization': 'https://github.com/esengine/ecs-framework/tree/master/docs/performance-optimization.md'
|
||||
};
|
||||
|
||||
const url = urls[section];
|
||||
if (!url) return;
|
||||
|
||||
try {
|
||||
// 在Cocos Creator扩展环境中,直接使用Electron的shell模块
|
||||
const { shell } = require('electron');
|
||||
shell.openExternal(url);
|
||||
} catch (error) {
|
||||
console.error('无法打开链接:', error);
|
||||
// 如果失败,复制到剪贴板
|
||||
copyUrlToClipboard(url);
|
||||
}
|
||||
};
|
||||
|
||||
// 复制链接到剪贴板的辅助函数
|
||||
const copyUrlToClipboard = (url: string): void => {
|
||||
try {
|
||||
// 尝试使用现代的剪贴板API
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
navigator.clipboard.writeText(url).then(() => {
|
||||
console.log(`文档链接已复制到剪贴板: ${url}`);
|
||||
// 如果可能的话,显示用户友好的提示
|
||||
if (typeof alert !== 'undefined') {
|
||||
alert(`文档链接已复制到剪贴板,请在浏览器中粘贴访问:\n${url}`);
|
||||
}
|
||||
}).catch(() => {
|
||||
fallbackCopyText(url);
|
||||
});
|
||||
} else {
|
||||
fallbackCopyText(url);
|
||||
}
|
||||
} catch (error) {
|
||||
fallbackCopyText(url);
|
||||
}
|
||||
};
|
||||
|
||||
// 备用的复制文本方法
|
||||
const fallbackCopyText = (text: string): void => {
|
||||
try {
|
||||
// 创建临时的文本区域
|
||||
const textArea = document.createElement('textarea');
|
||||
textArea.value = text;
|
||||
textArea.style.position = 'fixed';
|
||||
textArea.style.left = '-999999px';
|
||||
textArea.style.top = '-999999px';
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
|
||||
const successful = document.execCommand('copy');
|
||||
document.body.removeChild(textArea);
|
||||
|
||||
if (successful) {
|
||||
console.log(`文档链接已复制到剪贴板: ${text}`);
|
||||
if (typeof alert !== 'undefined') {
|
||||
alert(`文档链接已复制到剪贴板,请在浏览器中粘贴访问:\n${text}`);
|
||||
}
|
||||
} else {
|
||||
console.log(`请手动复制文档链接: ${text}`);
|
||||
if (typeof alert !== 'undefined') {
|
||||
alert(`请手动复制文档链接:\n${text}`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`请手动访问文档: ${text}`);
|
||||
if (typeof alert !== 'undefined') {
|
||||
alert(`请手动访问文档:\n${text}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 组件挂载时初始化
|
||||
onMounted(async () => {
|
||||
await initializeServer();
|
||||
@@ -575,6 +677,7 @@ module.exports = Editor.Panel.define({
|
||||
isAutoRefresh,
|
||||
refreshInterval,
|
||||
lastUpdateTime,
|
||||
showComponentPoolHelp,
|
||||
manualRefresh,
|
||||
toggleAutoRefresh,
|
||||
changeRefreshInterval,
|
||||
@@ -584,7 +687,8 @@ module.exports = Editor.Panel.define({
|
||||
getFpsColor,
|
||||
getMemoryColor,
|
||||
getECSTimeColor,
|
||||
getExecutionTimeColor
|
||||
getExecutionTimeColor,
|
||||
openDocumentation
|
||||
};
|
||||
},
|
||||
template: readFileSync(join(__dirname, '../../../static/template/debug/index.html'), 'utf-8'),
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
background: var(--color-normal-fill);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100vh;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
.debug-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
height: 100%;
|
||||
background: var(--color-normal-fill);
|
||||
}
|
||||
|
||||
@@ -660,10 +660,12 @@ ui-button ui-icon {
|
||||
/* ECS调试面板样式 */
|
||||
.debug-panel {
|
||||
padding: 16px;
|
||||
padding-bottom: 32px;
|
||||
background: var(--color-normal-fill);
|
||||
color: var(--color-normal-contrast);
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
}
|
||||
|
||||
@@ -1242,7 +1244,7 @@ ui-button ui-icon {
|
||||
}
|
||||
|
||||
.debug-panel::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--color-normal-contrast-weaken);
|
||||
background-color: var(--color-focus-border-emphasis);
|
||||
}
|
||||
|
||||
/* 百分比条样式 */
|
||||
@@ -1261,7 +1263,340 @@ ui-button ui-icon {
|
||||
}
|
||||
|
||||
.percentage-fill {
|
||||
background: linear-gradient(90deg, var(--color-primary), var(--color-primary-emphasis));
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #4CAF50 0%, #FF9800 50%, #F44336 100%);
|
||||
border-radius: inherit;
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
/* 调试面板滚动条样式 */
|
||||
.debug-panel::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.debug-panel::-webkit-scrollbar-track {
|
||||
background: var(--color-normal-fill-weaker);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.debug-panel::-webkit-scrollbar-thumb {
|
||||
background: var(--color-normal-border);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.debug-panel::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--color-focus-border);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
帮助面板和文档链接样式
|
||||
============================================ */
|
||||
|
||||
.section-help {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.help-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 6px 12px;
|
||||
background: var(--color-normal-fill);
|
||||
border: 1px solid var(--color-normal-border);
|
||||
border-radius: 4px;
|
||||
color: var(--color-default-contrast);
|
||||
font-size: 11px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.help-btn:hover {
|
||||
background: var(--color-normal-fill-emphasis);
|
||||
border-color: var(--color-focus-border);
|
||||
color: var(--color-focus-contrast);
|
||||
}
|
||||
|
||||
.help-btn ui-icon {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.help-panel {
|
||||
margin: 16px 0;
|
||||
padding: 20px;
|
||||
background: var(--color-normal-fill);
|
||||
border: 1px solid var(--color-normal-border);
|
||||
border-radius: 8px;
|
||||
animation: fadeInDown 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes fadeInDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.help-content h4 {
|
||||
margin: 0 0 12px 0;
|
||||
color: var(--color-focus-contrast);
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.help-content p {
|
||||
margin: 0 0 16px 0;
|
||||
color: var(--color-default-contrast);
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.help-steps {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.help-step {
|
||||
margin-bottom: 20px;
|
||||
padding: 16px;
|
||||
background: var(--color-normal-fill-emphasis);
|
||||
border-radius: 6px;
|
||||
border-left: 3px solid var(--color-focus-border);
|
||||
}
|
||||
|
||||
.help-step:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.help-step h5 {
|
||||
margin: 0 0 12px 0;
|
||||
color: var(--color-focus-contrast);
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.help-step p {
|
||||
margin: 0;
|
||||
color: var(--color-default-contrast);
|
||||
font-size: 11px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.code-example {
|
||||
background: var(--color-normal-fill);
|
||||
border: 1px solid var(--color-normal-border);
|
||||
border-radius: 4px;
|
||||
padding: 12px;
|
||||
margin: 8px 0 0 0;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 10px;
|
||||
line-height: 1.4;
|
||||
color: var(--color-focus-border);
|
||||
overflow-x: auto;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.help-links {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin-top: 16px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid var(--color-normal-border);
|
||||
}
|
||||
|
||||
.doc-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 8px 12px;
|
||||
background: var(--color-focus-fill);
|
||||
border: 1px solid var(--color-focus-border);
|
||||
border-radius: 4px;
|
||||
color: var(--color-focus-contrast);
|
||||
text-decoration: none;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.doc-link:hover {
|
||||
background: var(--color-focus-fill-emphasis);
|
||||
border-color: var(--color-focus-border-emphasis);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.doc-link ui-icon {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.doc-access-note {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
margin-top: 12px;
|
||||
padding: 12px;
|
||||
background: var(--color-info-fill);
|
||||
border: 1px solid var(--color-info-border);
|
||||
border-radius: 4px;
|
||||
font-size: 10px;
|
||||
color: var(--color-info-contrast);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.doc-access-note ui-icon {
|
||||
font-size: 14px;
|
||||
color: var(--color-info-border);
|
||||
margin-top: 1px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
组件池相关样式
|
||||
============================================ */
|
||||
|
||||
.help-tooltip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-left: 4px;
|
||||
cursor: help;
|
||||
color: var(--color-normal-contrast-weaker);
|
||||
}
|
||||
|
||||
.help-tooltip:hover {
|
||||
color: var(--color-focus-border);
|
||||
}
|
||||
|
||||
.help-tooltip ui-icon {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.not-configured {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-left: 4px;
|
||||
color: var(--color-warn-border);
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
.not-configured ui-icon {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.no-pool-hint {
|
||||
font-size: 10px;
|
||||
color: var(--color-normal-contrast-weaker);
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.pool-suggestion {
|
||||
margin-top: 16px;
|
||||
padding: 16px;
|
||||
background: linear-gradient(135deg, var(--color-warn-fill) 0%, var(--color-focus-fill) 100%);
|
||||
border: 1px solid var(--color-warn-border);
|
||||
border-radius: 8px;
|
||||
animation: fadeInUp 0.4s ease;
|
||||
}
|
||||
|
||||
.suggestion-content {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.suggestion-icon {
|
||||
color: var(--color-warn-border);
|
||||
font-size: 20px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.suggestion-text {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.suggestion-text h4 {
|
||||
margin: 0 0 8px 0;
|
||||
color: var(--color-focus-contrast);
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.suggestion-text p {
|
||||
margin: 0 0 12px 0;
|
||||
color: var(--color-default-contrast);
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.suggestion-action {
|
||||
padding: 6px 12px;
|
||||
background: var(--color-focus-border);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
color: white;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.suggestion-action:hover {
|
||||
background: var(--color-focus-border-emphasis);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
响应式设计增强
|
||||
============================================ */
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.help-links {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.doc-link {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.suggestion-content {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.suggestion-icon {
|
||||
align-self: center;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.help-panel {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.help-step {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.code-example {
|
||||
font-size: 9px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.help-btn {
|
||||
padding: 4px 8px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.section-help {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
@@ -188,7 +188,68 @@
|
||||
<div class="debug-section" v-if="debugInfo.instanceId">
|
||||
<div class="section-header">
|
||||
<h2>🧩 组件分析</h2>
|
||||
<div class="section-help">
|
||||
<button class="help-btn" @click="showComponentPoolHelp = !showComponentPoolHelp" title="组件对象池使用说明">
|
||||
<ui-icon value="help"></ui-icon>
|
||||
对象池使用说明
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 对象池使用说明 -->
|
||||
<div v-if="showComponentPoolHelp" class="help-panel">
|
||||
<div class="help-content">
|
||||
<h4>📖 组件对象池使用指南</h4>
|
||||
<p>组件对象池用于复用组件实例,减少频繁创建/销毁组件带来的内存分配开销。当前利用率为0表示还未配置对象池。</p>
|
||||
|
||||
<div class="help-steps">
|
||||
<div class="help-step">
|
||||
<h5>1. 注册组件对象池</h5>
|
||||
<pre class="code-example">import { ComponentPoolManager } from '@esengine/ecs-framework';
|
||||
|
||||
// 为Transform组件注册对象池
|
||||
ComponentPoolManager.getInstance().registerPool(
|
||||
'Transform',
|
||||
() => new Transform(),
|
||||
(comp) => comp.reset(), // 可选的重置函数
|
||||
100 // 池大小
|
||||
);</pre>
|
||||
</div>
|
||||
|
||||
<div class="help-step">
|
||||
<h5>2. 使用对象池获取组件</h5>
|
||||
<pre class="code-example">// 从对象池获取组件实例
|
||||
const poolManager = ComponentPoolManager.getInstance();
|
||||
const transform = poolManager.acquireComponent('Transform');
|
||||
|
||||
// 使用完毕后释放回池中
|
||||
poolManager.releaseComponent('Transform', transform);</pre>
|
||||
</div>
|
||||
|
||||
<div class="help-step">
|
||||
<h5>3. 查看性能改进</h5>
|
||||
<p>正确配置后,利用率栏将显示池的使用情况。利用率越高说明对象池被有效使用,可以减少GC压力。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="help-links">
|
||||
<a href="#" @click="openDocumentation('component-pool')" class="doc-link">
|
||||
<ui-icon value="book"></ui-icon>
|
||||
查看详细文档
|
||||
</a>
|
||||
<a href="#" @click="openDocumentation('performance-optimization')" class="doc-link">
|
||||
<ui-icon value="speed"></ui-icon>
|
||||
性能优化指南
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="doc-access-note">
|
||||
<ui-icon value="info"></ui-icon>
|
||||
<span>如果无法直接打开文档链接,链接将自动复制到剪贴板,请在浏览器中粘贴访问</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="component-overview">
|
||||
<div class="overview-item">
|
||||
<span class="label">组件类型:</span>
|
||||
@@ -206,18 +267,45 @@
|
||||
<div class="col-count">实例数</div>
|
||||
<div class="col-memory">内存占用</div>
|
||||
<div class="col-pool">对象池</div>
|
||||
<div class="col-efficiency">利用率</div>
|
||||
<div class="col-efficiency">
|
||||
利用率
|
||||
<span class="help-tooltip" title="对象池利用率:使用中的实例 / 池总大小。利用率为0表示未配置对象池">
|
||||
<ui-icon value="help"></ui-icon>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-for="comp in debugInfo.components.componentStats" :key="comp.typeName" class="table-row">
|
||||
<div class="col-name">{{ comp.typeName }}</div>
|
||||
<div class="col-count">{{ comp.instanceCount }}</div>
|
||||
<div class="col-memory">{{ formatMemory(comp.totalMemory) }}</div>
|
||||
<div class="col-pool">{{ comp.poolSize }}</div>
|
||||
<div class="col-pool">
|
||||
{{ comp.poolSize || '未配置' }}
|
||||
<span v-if="comp.poolSize === 0" class="not-configured" title="点击上方说明了解如何配置对象池">
|
||||
<ui-icon value="warning"></ui-icon>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-efficiency">
|
||||
<div class="efficiency-bar">
|
||||
<div class="efficiency-fill" :style="{ width: comp.poolUtilization + '%' }"></div>
|
||||
</div>
|
||||
{{ comp.poolUtilization.toFixed(1) }}%
|
||||
<span v-if="comp.poolUtilization === 0 && comp.poolSize === 0" class="no-pool-hint">
|
||||
(无对象池)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 无对象池组件提示 -->
|
||||
<div v-if="debugInfo.components.componentStats.length > 0 && debugInfo.components.componentStats.every(c => c.poolSize === 0)" class="pool-suggestion">
|
||||
<div class="suggestion-content">
|
||||
<ui-icon value="lightbulb" class="suggestion-icon"></ui-icon>
|
||||
<div class="suggestion-text">
|
||||
<h4>💡 性能优化建议</h4>
|
||||
<p>检测到所有组件都未配置对象池。为频繁创建/销毁的组件配置对象池可以显著提升性能,减少垃圾回收压力。</p>
|
||||
<button @click="showComponentPoolHelp = true" class="suggestion-action">
|
||||
了解如何配置对象池
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user