更新池利用率

This commit is contained in:
YHH
2025-06-17 07:35:23 +08:00
parent 1b5363611d
commit 797619aece
6 changed files with 681 additions and 43 deletions

View File

@@ -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'),

View File

@@ -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;
}
}

View File

@@ -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>

View File

@@ -149,4 +149,38 @@ export class ComponentPoolManager {
}
return stats;
}
/**
* 获取池利用率信息(用于调试)
*/
getPoolUtilization(): Map<string, { used: number; total: number; utilization: number }> {
const utilization = new Map();
for (const [name, pool] of this.pools) {
const available = pool.getAvailableCount();
const maxSize = pool.getMaxSize();
const used = maxSize - available;
const utilRate = maxSize > 0 ? (used / maxSize * 100) : 0;
utilization.set(name, {
used: used,
total: maxSize,
utilization: utilRate
});
}
return utilization;
}
/**
* 获取指定组件的池利用率
*/
getComponentUtilization(componentName: string): number {
const pool = this.pools.get(componentName);
if (!pool) return 0;
const available = pool.getAvailableCount();
const maxSize = pool.getMaxSize();
const used = maxSize - available;
return maxSize > 0 ? (used / maxSize * 100) : 0;
}
}

View File

@@ -386,6 +386,12 @@ export interface IPerformanceDebugData {
samples: number;
percentage?: number; // 系统占ECS总时间的百分比
}>;
/** 系统占比分析数据 */
systemBreakdown?: Array<{
systemName: string;
executionTime: number;
percentage: number;
}>;
/** 内存分配详情 */
memoryDetails?: {
entities: number;

View File

@@ -41,6 +41,14 @@ export class DebugReporter {
this.config = config;
this.sceneStartTime = Date.now();
// 确保性能监控器在调试模式下被启用
if (this.config.enabled && this.config.channels.performance) {
if (!this.core._performanceMonitor.isEnabled) {
this.core._performanceMonitor.enable();
console.log('[ECS Debug] Performance monitor enabled for debugging');
}
}
if (this.config.enabled) {
this.start();
}
@@ -80,6 +88,14 @@ export class DebugReporter {
this.config = newConfig;
// 根据配置启用或禁用性能监控器
if (newConfig.enabled && newConfig.channels.performance) {
if (!this.core._performanceMonitor.isEnabled) {
this.core._performanceMonitor.enable();
console.log('[ECS Debug] Performance monitor enabled for debugging');
}
}
if (!newConfig.enabled && wasEnabled) {
this.stop();
} else if (newConfig.enabled && (!wasEnabled || urlChanged)) {
@@ -429,6 +445,7 @@ export class DebugReporter {
maxFrameTime: maxECSTime, // ECS最长执行时间
frameTimeHistory: [...this.frameTimeHistory],
systemPerformance: this.getSystemPerformance(),
systemBreakdown: ecsPerformanceData.systemBreakdown,
memoryDetails: this.getMemoryDetails()
};
}
@@ -439,6 +456,14 @@ export class DebugReporter {
private getECSPerformanceData(): { totalExecutionTime: number; systemBreakdown: Array<any> } {
const monitor = this.core._performanceMonitor;
if (!monitor) {
console.warn('[ECS Debug] Performance monitor not found');
return { totalExecutionTime: 0, systemBreakdown: [] };
}
if (!monitor.isEnabled) {
console.warn('[ECS Debug] Performance monitor is disabled. Enable it to see ECS performance data.');
// 尝试启用性能监控器
monitor.enable();
return { totalExecutionTime: 0, systemBreakdown: [] };
}
@@ -448,6 +473,11 @@ export class DebugReporter {
const stats = monitor.getAllSystemStats();
if (stats.size === 0) {
console.log('[ECS Debug] No system performance data available yet. This is normal on first frames.');
return { totalExecutionTime: 0, systemBreakdown: [] };
}
// 计算各系统的执行时间
for (const [systemName, stat] of stats.entries()) {
const systemTime = stat.averageTime || 0;
@@ -468,11 +498,14 @@ export class DebugReporter {
// 按执行时间排序
systemBreakdown.sort((a, b) => b.executionTime - a.executionTime);
console.log(`[ECS Debug] Performance data: ${stats.size} systems, total time: ${totalTime.toFixed(2)}ms`);
return {
totalExecutionTime: totalTime,
systemBreakdown: systemBreakdown
};
} catch (error) {
console.error('[ECS Debug] Error getting ECS performance data:', error);
return { totalExecutionTime: 0, systemBreakdown: [] };
}
}
@@ -544,29 +577,56 @@ export class DebugReporter {
});
}
});
} else {
// 如果entityManager不存在尝试从场景直接获取
const entityList = (scene as any).entities;
if (entityList?.buffer) {
entityList.buffer.forEach((entity: any) => {
entityMemory += this.estimateObjectSize(entity);
if (entity.components) {
entity.components.forEach((component: any) => {
componentMemory += this.estimateObjectSize(component);
});
}
});
}
}
// 计算系统内存(估算)
// 计算系统内存
const entitySystems = (scene as any).entitySystems;
if (entitySystems?.systems) {
entitySystems.systems.forEach((system: any) => {
systemMemory += this.estimateObjectSize(system);
});
} else {
// 尝试从entityProcessors获取
const entityProcessors = (scene as any).entityProcessors;
if (entityProcessors?.processors) {
entityProcessors.processors.forEach((system: any) => {
systemMemory += this.estimateObjectSize(system);
});
}
}
// 计算对象池内存(估算)
// 计算对象池内存
try {
const poolManager = this.core._poolManager;
if (poolManager) {
// 简单估算对象池内存
pooledMemory = 1024 * 1024; // 1MB估算值
const { ComponentPoolManager } = require('../ECS/Core/ComponentPool');
const poolManager = ComponentPoolManager.getInstance();
const poolStats = poolManager.getPoolStats();
for (const [typeName, stats] of poolStats.entries()) {
// 估算每个组件实例的大小
const estimatedComponentSize = this.calculateComponentMemorySize(typeName);
pooledMemory += stats.available * estimatedComponentSize;
}
} catch (error) {
// 忽略对象池内存计算错误
// 如果无法访问ComponentPoolManager使用估算值
pooledMemory = 512 * 1024; // 512KB估算值
}
// 获取浏览器内存信息
let totalMemory = 512 * 1024 * 1024; // 默认512MB
let totalMemory = 512 * 1024 * 1024;
let usedMemory = entityMemory + componentMemory + systemMemory + pooledMemory;
let gcCollections = 0;
@@ -637,37 +697,48 @@ export class DebugReporter {
}
});
// 获取池利用率信息
let poolUtilizations = new Map<string, number>();
let poolSizes = new Map<string, number>();
try {
const { ComponentPoolManager } = require('../ECS/Core/ComponentPool');
const poolManager = ComponentPoolManager.getInstance();
const poolStats = poolManager.getPoolStats();
const utilizations = poolManager.getPoolUtilization();
for (const [typeName, stats] of poolStats.entries()) {
poolSizes.set(typeName, stats.maxSize);
}
for (const [typeName, util] of utilizations.entries()) {
poolUtilizations.set(typeName, util.utilization);
}
} catch (error) {
// 如果无法获取池信息,使用默认值
}
return {
componentTypes: componentStats.size,
componentInstances: totalInstances,
componentStats: Array.from(componentStats.entries()).map(([typeName, stats]) => {
const poolSize = this.getComponentPoolSize(typeName);
const poolSize = poolSizes.get(typeName) || 0;
const poolUtilization = poolUtilizations.get(typeName) || 0;
const memoryPerInstance = this.calculateComponentMemorySize(typeName);
return {
typeName,
instanceCount: stats.count,
memoryPerInstance: memoryPerInstance,
totalMemory: stats.count * memoryPerInstance,
poolSize: poolSize,
poolUtilization: poolSize > 0 ? (stats.count / poolSize * 100) : 0,
poolUtilization: poolUtilization,
averagePerEntity: stats.count / entityList.buffer.length
};
})
};
}
/**
* 获取组件池大小
*/
private getComponentPoolSize(typeName: string): number {
try {
const poolManager = this.core._poolManager;
return (poolManager as any).getPoolSize?.(typeName) || 0;
} catch (error) {
return 0;
}
}
/**
* 计算组件实际内存大小
*/