1172 lines
51 KiB
Python
1172 lines
51 KiB
Python
"""
|
||
VR性能监控子系统
|
||
负责VR应用的性能监控、GPU计时、管线统计和性能诊断
|
||
"""
|
||
|
||
import sys
|
||
import gc
|
||
import time
|
||
|
||
# 可选依赖
|
||
try:
|
||
import psutil
|
||
PSUTIL_AVAILABLE = True
|
||
except ImportError:
|
||
PSUTIL_AVAILABLE = False
|
||
|
||
try:
|
||
import GPUtil
|
||
GPUTIL_AVAILABLE = True
|
||
except ImportError:
|
||
GPUTIL_AVAILABLE = False
|
||
|
||
try:
|
||
import pynvml
|
||
PYNVML_AVAILABLE = True
|
||
except ImportError:
|
||
PYNVML_AVAILABLE = False
|
||
|
||
|
||
class VRPerformanceMonitor:
|
||
"""VR性能监控系统
|
||
|
||
功能:
|
||
- 实时性能监控(CPU、内存、GPU)
|
||
- GPU渲染时间统计
|
||
- 渲染管线分析
|
||
- 性能诊断和优化建议
|
||
"""
|
||
|
||
def __init__(self, vr_manager):
|
||
"""初始化性能监控系统
|
||
|
||
Args:
|
||
vr_manager: VRManager实例的引用
|
||
"""
|
||
self.vr_manager = vr_manager
|
||
|
||
# ===== 性能计数器 =====
|
||
self.frame_count = 0
|
||
self.last_fps_check = 0
|
||
self.last_fps_time = 0
|
||
self.vr_fps = 0
|
||
self.submit_failures = 0
|
||
self.pose_failures = 0
|
||
|
||
# ===== 性能监控配置 =====
|
||
self.performance_monitoring = False # 是否启用性能监控
|
||
self.debug_output_enabled = False # 是否启用调试输出
|
||
self.debug_mode = 'detailed' # 'brief' 或 'detailed'
|
||
self.cpu_usage = 0.0
|
||
self.memory_usage = 0.0
|
||
self.gpu_usage = 0.0
|
||
self.gpu_memory_usage = 0.0
|
||
self.frame_times = [] # 存储最近帧时间
|
||
self.max_frame_time_history = 60 # 保存60帧的历史
|
||
self.last_performance_check = 0
|
||
self.performance_check_interval = 0.5 # 每0.5秒更新一次性能数据
|
||
|
||
# ===== 渲染管线监控 =====
|
||
self.enable_pipeline_monitoring = True # 是否启用管线监控
|
||
self.performance_mode_enabled = False # 性能优化模式(禁用监控以减少对象创建)
|
||
self.performance_mode_trigger_frame = 600 # 第600帧后启用性能模式
|
||
self.wait_poses_time = 0.0 # waitGetPoses耗时
|
||
self.left_render_time = 0.0 # 左眼渲染耗时
|
||
self.right_render_time = 0.0 # 右眼渲染耗时
|
||
self.submit_time = 0.0 # 纹理提交耗时
|
||
self.left_render_count = 0 # 左眼渲染次数计数
|
||
self.right_render_count = 0 # 右眼渲染次数计数
|
||
self.total_frame_time = 0.0 # 总帧时间
|
||
self.vr_sync_wait_time = 0.0 # VR同步等待时间
|
||
|
||
# ===== 时间监控历史 =====
|
||
self.wait_poses_times = []
|
||
self.render_times = []
|
||
self.submit_times = []
|
||
self.sync_wait_times = []
|
||
self.pipeline_history_size = 30
|
||
|
||
# ===== GPU渲染时间监控 =====
|
||
self.enable_gpu_timing = False # 是否启用GPU时间监控(默认关闭)
|
||
self.gpu_scene_render_ms = 0.0 # GPU场景渲染时间
|
||
self.gpu_pre_submit_ms = 0.0 # 提交前GPU时间
|
||
self.gpu_post_submit_ms = 0.0 # 提交后GPU时间
|
||
self.gpu_total_render_ms = 0.0 # GPU总渲染时间
|
||
self.gpu_compositor_render_ms = 0.0 # GPU合成器渲染时间
|
||
self.gpu_client_frame_interval_ms = 0.0 # 客户端帧间隔
|
||
self.gpu_timing_history = [] # GPU时间历史记录
|
||
self.gpu_timing_history_size = 30 # GPU时间历史记录大小
|
||
self.gpu_timing_failure_count = 0 # GPU时间获取失败次数
|
||
|
||
# ===== VR系统信息 =====
|
||
self.current_eye_resolution = (0, 0)
|
||
self.recommended_eye_resolution = (0, 0)
|
||
self.vr_display_frequency = 0.0
|
||
self.vr_vsync_enabled = True
|
||
self.vsync_to_photons_ms = 0.0 # VSync到光子的延迟
|
||
self.target_frame_time_ms = 0.0 # 目标帧时间
|
||
self.vsync_window_ms = 0.0 # VSync时间窗口
|
||
self.async_reprojection_enabled = False # 异步重投影状态
|
||
self.motion_smoothing_enabled = False # 运动平滑状态
|
||
|
||
# ===== 性能报告间隔 =====
|
||
self.performance_report_interval = 1800 # 默认1800帧(30秒@60fps)
|
||
|
||
# ===== 内部状态 =====
|
||
self._last_frame_time = None # 用于帧时间计算
|
||
|
||
# 初始化性能监控库
|
||
self._init_performance_monitoring()
|
||
|
||
# ========== 性能报告方法 ==========
|
||
|
||
def _print_performance_report(self):
|
||
"""输出VR性能报告"""
|
||
if not self.performance_monitoring or not self.debug_output_enabled:
|
||
return
|
||
|
||
stats = self.get_performance_stats()
|
||
|
||
# 简短模式输出
|
||
if self.debug_mode == 'brief':
|
||
self._print_brief_performance_report(stats)
|
||
return
|
||
|
||
print("📊 ======= VR性能监控报告 =======")
|
||
|
||
# 帧率和帧时间信息
|
||
print(f"🎯 渲染性能:")
|
||
print(f" VR帧率: {stats['vr_fps']:.1f} FPS")
|
||
print(f" 平均帧时间: {stats['frame_time_avg']:.2f} ms")
|
||
print(f" 最小帧时间: {stats['frame_time_min']:.2f} ms")
|
||
print(f" 最大帧时间: {stats['frame_time_max']:.2f} ms")
|
||
print(f" 95%帧时间: {stats['frame_time_95th']:.2f} ms")
|
||
|
||
# 系统性能
|
||
print(f"💻 系统性能:")
|
||
print(f" CPU使用率: {stats['cpu_usage']:.1f}%")
|
||
print(f" 内存使用率: {stats['memory_usage']:.1f}%")
|
||
|
||
# GPU性能
|
||
print(f"🎮 GPU性能:")
|
||
if self.gputil_available or self.nvidia_ml_available:
|
||
print(f" GPU使用率: {stats['gpu_usage']:.1f}%")
|
||
print(f" 显存使用率: {stats['gpu_memory_usage']:.1f}%")
|
||
else:
|
||
print(f" GPU监控: 不可用 (需要安装 GPUtil 或 pynvml)")
|
||
print(f" 安装命令: pip install GPUtil nvidia-ml-py")
|
||
|
||
# GPU渲染时间(OpenVR Frame Timing)
|
||
if self.enable_gpu_timing:
|
||
print(f"⚡ GPU渲染时间:")
|
||
pipeline_stats = self._get_pipeline_stats()
|
||
gpu_stats = pipeline_stats.get('gpu_timing', {})
|
||
gpu_current = pipeline_stats.get('current', {})
|
||
|
||
# 检查是否有可用的GPU时间数据
|
||
has_gpu_data = any(
|
||
gpu_current.get(field, 0) > 0
|
||
for field in ['gpu_scene_render', 'gpu_total_render', 'gpu_pre_submit', 'gpu_post_submit', 'gpu_compositor_render']
|
||
)
|
||
|
||
if has_gpu_data:
|
||
# 显示GPU时间统计(最近30帧平均)
|
||
scene_render = gpu_stats.get('scene_render', {'avg': 0})
|
||
total_render = gpu_stats.get('total_render', {'avg': 0})
|
||
pre_submit = gpu_stats.get('pre_submit', {'avg': 0})
|
||
post_submit = gpu_stats.get('post_submit', {'avg': 0})
|
||
compositor = gpu_stats.get('compositor_render', {'avg': 0})
|
||
|
||
if scene_render['avg'] > 0:
|
||
print(f" GPU场景渲染: {scene_render['avg']:.2f}ms (min:{scene_render['min']:.1f}, max:{scene_render['max']:.1f})")
|
||
if total_render['avg'] > 0:
|
||
print(f" GPU总渲染时间: {total_render['avg']:.2f}ms (min:{total_render['min']:.1f}, max:{total_render['max']:.1f})")
|
||
if pre_submit['avg'] > 0:
|
||
print(f" GPU提交前时间: {pre_submit['avg']:.2f}ms (min:{pre_submit['min']:.1f}, max:{pre_submit['max']:.1f})")
|
||
if post_submit['avg'] > 0:
|
||
print(f" GPU提交后时间: {post_submit['avg']:.2f}ms (min:{post_submit['min']:.1f}, max:{post_submit['max']:.1f})")
|
||
if compositor['avg'] > 0:
|
||
print(f" GPU合成器时间: {compositor['avg']:.2f}ms (min:{compositor['min']:.1f}, max:{compositor['max']:.1f})")
|
||
|
||
# 显示当前帧GPU时间
|
||
print(f"🔍 当前帧GPU时间:")
|
||
if gpu_current.get('gpu_scene_render', 0) > 0:
|
||
print(f" 场景渲染: {gpu_current['gpu_scene_render']:.2f}ms")
|
||
if gpu_current.get('gpu_total_render', 0) > 0:
|
||
print(f" 总渲染: {gpu_current['gpu_total_render']:.2f}ms")
|
||
if gpu_current.get('gpu_compositor_render', 0) > 0:
|
||
print(f" 合成器: {gpu_current['gpu_compositor_render']:.2f}ms")
|
||
|
||
# GPU时间瓶颈分析
|
||
current_total = gpu_current.get('gpu_total_render', 0)
|
||
current_scene = gpu_current.get('gpu_scene_render', 0)
|
||
if current_total > 12.0: # 假设72fps目标,留出一些余量
|
||
print(f" ⚠️ GPU总渲染时间过长: {current_total:.1f}ms")
|
||
elif current_scene > 8.0:
|
||
print(f" ⚠️ GPU场景渲染时间偏高: {current_scene:.1f}ms")
|
||
|
||
else:
|
||
print(f" GPU渲染时间: 暂无数据")
|
||
if self.gpu_timing_failure_count > 0:
|
||
print(f" 获取失败次数: {self.gpu_timing_failure_count}")
|
||
else:
|
||
print(f" 等待OpenVR Frame Timing数据...")
|
||
else:
|
||
print(f"⚡ GPU渲染时间: 已禁用")
|
||
|
||
# VR特定指标
|
||
print(f"🥽 VR指标:")
|
||
print(f" 总帧数: {stats['frame_count']}")
|
||
print(f" 提交失败: {stats['submit_failures']}")
|
||
print(f" 姿态失败: {stats['pose_failures']}")
|
||
|
||
# 计算失败率
|
||
if stats['frame_count'] > 0:
|
||
submit_fail_rate = (stats['submit_failures'] / stats['frame_count']) * 100
|
||
pose_fail_rate = (stats['pose_failures'] / stats['frame_count']) * 100
|
||
print(f" 提交失败率: {submit_fail_rate:.2f}%")
|
||
print(f" 姿态失败率: {pose_fail_rate:.2f}%")
|
||
|
||
# 渲染管线监控
|
||
target_frame_time = 13.9 # 默认目标帧时间(72Hz)
|
||
if self.enable_pipeline_monitoring:
|
||
pipeline_stats = self._get_pipeline_stats()
|
||
print(f"⚙️ 渲染管线分析:")
|
||
print(f" 当前分辨率: {pipeline_stats['vr_info']['eye_resolution'][0]}x{pipeline_stats['vr_info']['eye_resolution'][1]}")
|
||
print(f" 推荐分辨率: {pipeline_stats['vr_info']['recommended_resolution'][0]}x{pipeline_stats['vr_info']['recommended_resolution'][1]}")
|
||
print(f" 显示频率: {pipeline_stats['vr_info']['display_frequency']:.1f} Hz")
|
||
|
||
# VSync和时序信息
|
||
if pipeline_stats['vr_info']['target_frame_time_ms'] > 0:
|
||
print(f"🎯 VSync时序:")
|
||
print(f" 目标帧时间: {pipeline_stats['vr_info']['target_frame_time_ms']:.2f}ms")
|
||
print(f" VSync到光子: {pipeline_stats['vr_info']['vsync_to_photons_ms']:.2f}ms")
|
||
print(f" VSync窗口: ±{pipeline_stats['vr_info']['vsync_window_ms']:.2f}ms")
|
||
print(f" 异步重投影: {'启用' if pipeline_stats['vr_info']['async_reprojection'] else '禁用'}")
|
||
print(f" 运动平滑: {'启用' if pipeline_stats['vr_info']['motion_smoothing'] else '禁用'}")
|
||
|
||
# 分析帧时间是否在目标范围内
|
||
current_frame_time = stats['frame_time_avg']
|
||
target_frame_time = pipeline_stats['vr_info']['target_frame_time_ms']
|
||
if current_frame_time > 0 and target_frame_time > 0:
|
||
frame_time_ratio = current_frame_time / target_frame_time
|
||
if frame_time_ratio > 1.1:
|
||
print(f" ⚠️ 帧时间超标: {current_frame_time:.1f}ms (目标:{target_frame_time:.1f}ms)")
|
||
elif frame_time_ratio < 0.9:
|
||
print(f" ✅ 帧时间充裕: {current_frame_time:.1f}ms (目标:{target_frame_time:.1f}ms)")
|
||
else:
|
||
print(f" ✓ 帧时间正常: {current_frame_time:.1f}ms (目标:{target_frame_time:.1f}ms)")
|
||
|
||
# 🔧 性能优化诊断
|
||
print(f"🔧 优化诊断:")
|
||
current = pipeline_stats.get('current', {}) if self.enable_pipeline_monitoring else {}
|
||
|
||
# 🔍 渲染回调诊断 - 新增
|
||
self._print_render_callback_diagnostics()
|
||
|
||
# waitGetPoses时序分析
|
||
wait_poses_time = current.get('wait_poses', 0)
|
||
if wait_poses_time > 10:
|
||
print(f" ⚠️ waitGetPoses时间过长: {wait_poses_time:.1f}ms")
|
||
print(f" 可能原因: 错过VSync窗口,建议调整预测时间")
|
||
elif wait_poses_time > 5:
|
||
print(f" ⚠️ waitGetPoses时间偏高: {wait_poses_time:.1f}ms")
|
||
else:
|
||
print(f" ✓ waitGetPoses时间正常: {wait_poses_time:.1f}ms")
|
||
|
||
# CPU-GPU并行度分析 - 增强诊断
|
||
gpu_total = current.get('gpu_total_render', 0)
|
||
cpu_render_left = self.left_render_time
|
||
cpu_render_right = self.right_render_time
|
||
cpu_render_total = cpu_render_left + cpu_render_right
|
||
|
||
print(f" 真实渲染时间对比:")
|
||
print(f" CPU左眼: {cpu_render_left:.2f}ms")
|
||
print(f" CPU右眼: {cpu_render_right:.2f}ms")
|
||
print(f" CPU总计: {cpu_render_total:.2f}ms")
|
||
print(f" GPU总计: {gpu_total:.2f}ms")
|
||
|
||
if cpu_render_total < 1.0:
|
||
print(f" ⚠️ CPU渲染时间异常短: {cpu_render_total:.2f}ms")
|
||
print(f" 可能原因: 渲染回调未正确执行或渲染被跳过")
|
||
elif gpu_total > 0 and cpu_render_total > 0:
|
||
ratio = gpu_total / cpu_render_total
|
||
if ratio > 10:
|
||
print(f" ⚠️ GPU严重等待CPU: 比例{ratio:.1f}:1")
|
||
print(f" 建议: 检查OpenGL命令提交时机和渲染状态")
|
||
elif ratio > 3:
|
||
print(f" ⚠️ GPU等待CPU: 比例{ratio:.1f}:1")
|
||
print(f" 建议: 检查OpenGL命令提交是否及时")
|
||
else:
|
||
print(f" ✓ CPU-GPU时间匹配: 比例{ratio:.1f}:1")
|
||
|
||
# 预测时间诊断
|
||
current_prediction = self.vr_manager.use_prediction_time * 1000
|
||
print(f" 预测时间设置: {current_prediction:.1f}ms")
|
||
if current_prediction > 15:
|
||
print(f" 建议: 预测时间较高,可能增加waitGetPoses延迟")
|
||
elif current_prediction < 8:
|
||
print(f" 注意: 预测时间较低,可能影响姿态准确性")
|
||
else:
|
||
print(f" ✓ 预测时间在合理范围内")
|
||
|
||
# 优化状态总结
|
||
optimization_score = 0
|
||
if wait_poses_time < 8:
|
||
optimization_score += 1
|
||
if stats['vr_fps'] > 60:
|
||
optimization_score += 1
|
||
if stats.get('frame_time_avg', 0) < target_frame_time * 1.1:
|
||
optimization_score += 1
|
||
|
||
if optimization_score >= 2:
|
||
print(f" ✅ 优化效果良好 ({optimization_score}/3)")
|
||
else:
|
||
print(f" ⚠️ 仍有优化空间 ({optimization_score}/3)")
|
||
|
||
# 显示详细统计信息(仅当管线监控启用时)
|
||
if self.enable_pipeline_monitoring:
|
||
print(f"🕐 各阶段耗时 (最近{self.pipeline_history_size}帧平均):")
|
||
print(f" waitGetPoses: {pipeline_stats['wait_poses']['avg']:.2f}ms (min:{pipeline_stats['wait_poses']['min']:.1f}, max:{pipeline_stats['wait_poses']['max']:.1f})")
|
||
print(f" 渲染总计: {pipeline_stats['render']['avg']:.2f}ms (min:{pipeline_stats['render']['min']:.1f}, max:{pipeline_stats['render']['max']:.1f})")
|
||
print(f" 纹理提交: {pipeline_stats['submit']['avg']:.2f}ms (min:{pipeline_stats['submit']['min']:.1f}, max:{pipeline_stats['submit']['max']:.1f})")
|
||
if pipeline_stats['sync_wait']['avg'] > 0:
|
||
print(f" 同步等待: {pipeline_stats['sync_wait']['avg']:.2f}ms (min:{pipeline_stats['sync_wait']['min']:.1f}, max:{pipeline_stats['sync_wait']['max']:.1f})")
|
||
|
||
print(f"🔍 当前帧详情:")
|
||
print(f" 左眼渲染: {pipeline_stats['current']['left_render']:.2f}ms")
|
||
print(f" 右眼渲染: {pipeline_stats['current']['right_render']:.2f}ms")
|
||
print(f" 姿态获取: {pipeline_stats['current']['wait_poses']:.2f}ms")
|
||
|
||
# 显示Running Start模式信息
|
||
print(f"🎯 Running Start模式:")
|
||
print(f" 模式: Valve Running Start - 帧开始时获取姿态")
|
||
print(f" 优势: VSync前3ms获取姿态,提供充足渲染时间")
|
||
print(f" 预测时间: {self.vr_manager.use_prediction_time * 1000:.1f}ms")
|
||
|
||
# 分析最大瓶颈
|
||
current = pipeline_stats['current']
|
||
bottleneck_analysis = []
|
||
if current['wait_poses'] > 5.0:
|
||
bottleneck_analysis.append(f"姿态获取耗时过长({current['wait_poses']:.1f}ms)")
|
||
if current['total_render'] > 8.0:
|
||
bottleneck_analysis.append(f"渲染耗时过长({current['total_render']:.1f}ms)")
|
||
if current['submit'] > 2.0:
|
||
bottleneck_analysis.append(f"纹理提交耗时过长({current['submit']:.1f}ms)")
|
||
|
||
if bottleneck_analysis:
|
||
print(f"🚨 瓶颈分析:")
|
||
for analysis in bottleneck_analysis:
|
||
print(f" ⚠️ {analysis}")
|
||
|
||
# 性能建议
|
||
self._print_performance_recommendations(stats)
|
||
|
||
print("===============================")
|
||
|
||
def _print_performance_recommendations(self, stats):
|
||
"""根据性能数据输出优化建议"""
|
||
print(f"💡 性能建议:")
|
||
|
||
recommendations = []
|
||
|
||
# FPS相关建议
|
||
if stats['vr_fps'] < 60:
|
||
recommendations.append(" ⚠️ VR帧率过低,可能影响体验")
|
||
|
||
# 帧时间相关建议
|
||
if stats['frame_time_avg'] > 16.7: # 60fps = 16.7ms
|
||
recommendations.append(" ⚠️ 平均帧时间过高,建议降低渲染质量")
|
||
|
||
if stats['frame_time_max'] > 50:
|
||
recommendations.append(" ⚠️ 检测到严重卡顿,检查CPU/GPU负载")
|
||
|
||
# CPU建议
|
||
if stats['cpu_usage'] > 80:
|
||
recommendations.append(" 🔴 CPU使用率过高,可能存在CPU瓶颈")
|
||
elif stats['cpu_usage'] > 60:
|
||
recommendations.append(" 🟡 CPU使用率偏高,注意监控")
|
||
|
||
# 内存建议
|
||
if stats['memory_usage'] > 85:
|
||
recommendations.append(" 🔴 内存使用率过高,可能影响性能")
|
||
|
||
# GPU建议
|
||
if self.gputil_available or self.nvidia_ml_available:
|
||
if stats['gpu_usage'] > 95:
|
||
recommendations.append(" 🔴 GPU使用率接近满载,存在GPU瓶颈")
|
||
if stats['gpu_memory_usage'] > 90:
|
||
recommendations.append(" 🔴 显存使用率过高,可能需要降低纹理质量")
|
||
|
||
# GPU渲染时间建议
|
||
if self.enable_gpu_timing:
|
||
if self.gpu_total_render_ms > 12.0:
|
||
recommendations.append(" ⚠️ GPU总渲染时间过长,建议优化场景复杂度")
|
||
if self.gpu_scene_render_ms > 8.0:
|
||
recommendations.append(" ⚠️ GPU场景渲染时间偏高,考虑降低渲染质量")
|
||
if self.gpu_compositor_render_ms > 3.0:
|
||
recommendations.append(" ⚠️ GPU合成器时间过长,检查VR设置或叠加层")
|
||
if self.gpu_timing_failure_count > 100:
|
||
recommendations.append(" ⚠️ GPU时间统计频繁失败,可能需要更新OpenVR")
|
||
|
||
# 失败率建议
|
||
submit_fail_rate = (stats['submit_failures'] / max(stats['frame_count'], 1)) * 100
|
||
if submit_fail_rate > 1:
|
||
recommendations.append(" ⚠️ VR帧提交失败率较高,检查VR系统状态")
|
||
|
||
if not recommendations:
|
||
recommendations.append(" ✅ 性能表现良好,无明显问题")
|
||
|
||
for rec in recommendations:
|
||
print(rec)
|
||
|
||
def _print_brief_performance_report(self, stats):
|
||
"""输出简短的VR性能报告"""
|
||
# 创建一行简短摘要
|
||
summary = f"🥽 VR性能: {stats['vr_fps']:.1f}fps"
|
||
|
||
if stats['frame_time_avg'] > 0:
|
||
summary += f" | 帧时间: {stats['frame_time_avg']:.1f}ms"
|
||
|
||
if self.psutil_available:
|
||
summary += f" | CPU: {stats['cpu_usage']:.0f}%"
|
||
summary += f" | 内存: {stats['memory_usage']:.0f}%"
|
||
|
||
# 显示GPU信息,如果库不可用则显示提示
|
||
if self.gputil_available or self.nvidia_ml_available:
|
||
summary += f" | GPU: {stats['gpu_usage']:.0f}%"
|
||
else:
|
||
summary += " | GPU: N/A"
|
||
|
||
# 添加失败率指示
|
||
if stats['frame_count'] > 0:
|
||
submit_fail_rate = (stats['submit_failures'] / stats['frame_count']) * 100
|
||
if submit_fail_rate > 0.1:
|
||
summary += f" | 提交失败: {submit_fail_rate:.1f}%"
|
||
|
||
# 添加管线关键信息
|
||
if self.enable_pipeline_monitoring:
|
||
pipeline_stats = self._get_pipeline_stats()
|
||
current = pipeline_stats['current']
|
||
|
||
# 显示关键瓶颈
|
||
if current['wait_poses'] > 5.0:
|
||
summary += f" | 姿态: {current['wait_poses']:.1f}ms⚠️"
|
||
elif current['wait_poses'] > 0:
|
||
summary += f" | 姿态: {current['wait_poses']:.1f}ms"
|
||
|
||
if current['total_render'] > 8.0:
|
||
summary += f" | 渲染: {current['total_render']:.1f}ms⚠️"
|
||
elif current['total_render'] > 0:
|
||
summary += f" | 渲染: {current['total_render']:.1f}ms"
|
||
|
||
# 添加GPU渲染时间信息
|
||
if self.enable_gpu_timing:
|
||
gpu_total = current.get('gpu_total_render', 0)
|
||
gpu_scene = current.get('gpu_scene_render', 0)
|
||
if gpu_total > 12.0:
|
||
summary += f" | GPU: {gpu_total:.1f}ms⚠️"
|
||
elif gpu_total > 0:
|
||
summary += f" | GPU: {gpu_total:.1f}ms"
|
||
elif gpu_scene > 0:
|
||
summary += f" | GPU场景: {gpu_scene:.1f}ms"
|
||
|
||
# 显示目标帧时间对比
|
||
vr_info = pipeline_stats['vr_info']
|
||
if vr_info['target_frame_time_ms'] > 0:
|
||
target = vr_info['target_frame_time_ms']
|
||
current_avg = stats['frame_time_avg']
|
||
if current_avg > target * 1.1:
|
||
summary += f" | 目标:{target:.0f}ms⚠️"
|
||
else:
|
||
summary += f" | 目标:{target:.0f}ms"
|
||
|
||
# 性能状态指示
|
||
if stats['vr_fps'] < 72:
|
||
summary += " ⚠️"
|
||
elif stats['vr_fps'] > 85:
|
||
summary += " ✅"
|
||
|
||
print(summary)
|
||
|
||
# ========== 性能监控核心方法 ==========
|
||
|
||
def _init_performance_monitoring(self):
|
||
"""初始化性能监控库"""
|
||
self.psutil_available = False
|
||
self.gputil_available = False
|
||
self.nvidia_ml_available = False
|
||
|
||
try:
|
||
import psutil
|
||
self.psutil = psutil
|
||
self.psutil_available = True
|
||
print("✓ psutil性能监控库已加载")
|
||
except ImportError:
|
||
print("⚠️ psutil库未安装,CPU和内存监控将不可用")
|
||
|
||
try:
|
||
import GPUtil
|
||
self.gputil = GPUtil
|
||
self.gputil_available = True
|
||
print("✓ GPUtil GPU监控库已加载")
|
||
except ImportError:
|
||
print("⚠️ GPUtil库未安装,GPU监控将不可用")
|
||
|
||
try:
|
||
import pynvml
|
||
self.pynvml = pynvml
|
||
pynvml.nvmlInit()
|
||
self.nvidia_ml_available = True
|
||
print("✓ NVIDIA-ML GPU监控库已加载")
|
||
except ImportError:
|
||
print("⚠️ pynvml库未安装,NVIDIA GPU详细监控将不可用")
|
||
except Exception as e:
|
||
print(f"⚠️ NVIDIA-ML初始化失败: {e}")
|
||
|
||
def _update_performance_metrics(self):
|
||
"""更新系统性能指标"""
|
||
if not self.performance_monitoring:
|
||
return
|
||
|
||
current_time = time.time()
|
||
|
||
# 限制更新频率
|
||
if current_time - self.last_performance_check < self.performance_check_interval:
|
||
return
|
||
|
||
self.last_performance_check = current_time
|
||
|
||
try:
|
||
# 更新CPU和内存使用率
|
||
if self.psutil_available:
|
||
self.cpu_usage = self.psutil.cpu_percent(interval=None)
|
||
memory = self.psutil.virtual_memory()
|
||
self.memory_usage = memory.percent
|
||
|
||
# 更新GPU使用率
|
||
self._update_gpu_metrics()
|
||
|
||
except Exception as e:
|
||
if self.frame_count % 600 == 0: # 每10秒输出一次错误
|
||
print(f"⚠️ 性能监控更新失败: {e}")
|
||
|
||
def _update_gpu_metrics(self):
|
||
"""更新GPU相关指标"""
|
||
try:
|
||
# 方法1: 使用GPUtil
|
||
if self.gputil_available:
|
||
gpus = self.gputil.getGPUs()
|
||
if gpus:
|
||
gpu = gpus[0] # 使用第一个GPU
|
||
self.gpu_usage = gpu.load * 100
|
||
self.gpu_memory_usage = gpu.memoryUtil * 100
|
||
|
||
# 方法2: 使用NVIDIA-ML (更精确)
|
||
elif self.nvidia_ml_available:
|
||
try:
|
||
handle = self.pynvml.nvmlDeviceGetHandleByIndex(0)
|
||
|
||
# GPU使用率
|
||
utilization = self.pynvml.nvmlDeviceGetUtilizationRates(handle)
|
||
self.gpu_usage = utilization.gpu
|
||
|
||
# GPU内存使用率
|
||
memory_info = self.pynvml.nvmlDeviceGetMemoryInfo(handle)
|
||
self.gpu_memory_usage = (memory_info.used / memory_info.total) * 100
|
||
|
||
except Exception as e:
|
||
# NVIDIA-ML可能无法在某些系统上工作
|
||
pass
|
||
|
||
except Exception as e:
|
||
# GPU监控失败,但不影响VR功能
|
||
pass
|
||
|
||
def _track_frame_time(self):
|
||
"""记录帧时间 - 性能优化版本"""
|
||
current_time = time.time()
|
||
|
||
if self._last_frame_time is not None:
|
||
frame_time = (current_time - self._last_frame_time) * 1000 # 转换为毫秒
|
||
|
||
# 🚀 性能优化:性能模式下跳过列表操作以减少内存分配
|
||
if not self.performance_mode_enabled:
|
||
# 添加到帧时间历史
|
||
self.frame_times.append(frame_time)
|
||
|
||
# 限制历史长度
|
||
if len(self.frame_times) > self.max_frame_time_history:
|
||
self.frame_times.pop(0)
|
||
|
||
self._last_frame_time = current_time
|
||
|
||
# ========== GPU计时方法 ==========
|
||
|
||
def _get_gpu_frame_timing(self, frames_ago=0):
|
||
"""获取GPU渲染时间统计
|
||
|
||
Args:
|
||
frames_ago: 获取多少帧之前的数据,0表示当前帧
|
||
|
||
Returns:
|
||
dict: GPU时间数据,如果获取失败返回None
|
||
"""
|
||
if not self.enable_gpu_timing or not self.vr_manager.vr_compositor:
|
||
return None
|
||
|
||
try:
|
||
# 调用OpenVR的getFrameTiming API
|
||
result, timing = self.vr_manager.vr_compositor.getFrameTiming(framesAgo=frames_ago)
|
||
|
||
if not result:
|
||
self.gpu_timing_failure_count += 1
|
||
if self.gpu_timing_failure_count % 300 == 1: # 每5秒输出一次错误
|
||
print("⚠️ OpenVR getFrameTiming调用失败")
|
||
return None
|
||
|
||
# 提取GPU时间数据(单位:毫秒)
|
||
gpu_data = {}
|
||
|
||
# 检查timing对象是否有GPU时间相关的属性
|
||
if hasattr(timing, 'm_flSceneRenderGpuMs'):
|
||
gpu_data['scene_render'] = timing.m_flSceneRenderGpuMs
|
||
self.gpu_scene_render_ms = timing.m_flSceneRenderGpuMs
|
||
|
||
if hasattr(timing, 'm_flPreSubmitGpuMs'):
|
||
gpu_data['pre_submit'] = timing.m_flPreSubmitGpuMs
|
||
self.gpu_pre_submit_ms = timing.m_flPreSubmitGpuMs
|
||
|
||
if hasattr(timing, 'm_flPostSubmitGpuMs'):
|
||
gpu_data['post_submit'] = timing.m_flPostSubmitGpuMs
|
||
self.gpu_post_submit_ms = timing.m_flPostSubmitGpuMs
|
||
|
||
if hasattr(timing, 'm_flTotalRenderGpuMs'):
|
||
gpu_data['total_render'] = timing.m_flTotalRenderGpuMs
|
||
self.gpu_total_render_ms = timing.m_flTotalRenderGpuMs
|
||
|
||
if hasattr(timing, 'm_flCompositorRenderGpuMs'):
|
||
gpu_data['compositor_render'] = timing.m_flCompositorRenderGpuMs
|
||
self.gpu_compositor_render_ms = timing.m_flCompositorRenderGpuMs
|
||
|
||
if hasattr(timing, 'm_flClientFrameIntervalMs'):
|
||
gpu_data['frame_interval'] = timing.m_flClientFrameIntervalMs
|
||
self.gpu_client_frame_interval_ms = timing.m_flClientFrameIntervalMs
|
||
|
||
# 将GPU时间数据添加到历史记录
|
||
if gpu_data:
|
||
self.gpu_timing_history.append(gpu_data)
|
||
if len(self.gpu_timing_history) > self.gpu_timing_history_size:
|
||
self.gpu_timing_history.pop(0)
|
||
|
||
# 调试信息 - 仅在第一次成功时输出
|
||
if not hasattr(self, '_gpu_timing_success_logged'):
|
||
available_fields = list(gpu_data.keys())
|
||
print(f"✅ GPU时间统计已启用 - 可用字段: {available_fields}")
|
||
self._gpu_timing_success_logged = True
|
||
|
||
return gpu_data
|
||
|
||
except AttributeError as e:
|
||
# OpenVR Python绑定可能不包含某些字段
|
||
if self.gpu_timing_failure_count == 0:
|
||
print(f"⚠️ GPU时间统计部分功能不可用: {e}")
|
||
print(" 这可能是由于OpenVR Python绑定版本问题")
|
||
self.gpu_timing_failure_count += 1
|
||
return None
|
||
|
||
except Exception as e:
|
||
self.gpu_timing_failure_count += 1
|
||
if self.gpu_timing_failure_count % 300 == 1: # 每5秒输出一次错误
|
||
print(f"⚠️ 获取GPU时间统计失败: {e}")
|
||
return None
|
||
|
||
def enable_gpu_timing_monitoring(self):
|
||
"""启用GPU时间监控"""
|
||
self.enable_gpu_timing = True
|
||
print("✓ VR GPU时间监控已启用")
|
||
|
||
def disable_gpu_timing_monitoring(self):
|
||
"""禁用GPU时间监控"""
|
||
self.enable_gpu_timing = False
|
||
print("✓ VR GPU时间监控已禁用")
|
||
|
||
# ========== 管线统计方法 ==========
|
||
|
||
def _start_timing(self, operation_name):
|
||
"""开始计时操作 - 性能优化版本"""
|
||
if not self.enable_pipeline_monitoring or self.performance_mode_enabled:
|
||
return None
|
||
|
||
# 🚀 性能优化:减少字典创建,只在必要时创建
|
||
return {
|
||
'operation': operation_name,
|
||
'start_time': time.perf_counter()
|
||
}
|
||
|
||
def _end_timing(self, timing_data):
|
||
"""结束计时并记录结果 - 性能优化版本"""
|
||
if not self.enable_pipeline_monitoring or self.performance_mode_enabled or not timing_data:
|
||
return 0.0
|
||
|
||
elapsed = (time.perf_counter() - timing_data['start_time']) * 1000 # 转换为毫秒
|
||
|
||
# 保存到相应的历史记录
|
||
operation = timing_data['operation']
|
||
if operation == 'wait_poses':
|
||
self.wait_poses_time = elapsed
|
||
self.wait_poses_times.append(elapsed)
|
||
if len(self.wait_poses_times) > self.pipeline_history_size:
|
||
self.wait_poses_times.pop(0)
|
||
elif operation == 'left_render':
|
||
self.left_render_time = elapsed
|
||
elif operation == 'right_render':
|
||
self.right_render_time = elapsed
|
||
elif operation == 'submit':
|
||
self.submit_time = elapsed
|
||
self.submit_times.append(elapsed)
|
||
if len(self.submit_times) > self.pipeline_history_size:
|
||
self.submit_times.pop(0)
|
||
elif operation == 'sync_wait':
|
||
self.vr_sync_wait_time = elapsed
|
||
self.sync_wait_times.append(elapsed)
|
||
if len(self.sync_wait_times) > self.pipeline_history_size:
|
||
self.sync_wait_times.pop(0)
|
||
|
||
# 计算总渲染时间
|
||
total_render = self.left_render_time + self.right_render_time
|
||
self.render_times.append(total_render)
|
||
if len(self.render_times) > self.pipeline_history_size:
|
||
self.render_times.pop(0)
|
||
|
||
return elapsed
|
||
|
||
def _get_pipeline_stats(self):
|
||
"""获取渲染管线统计信息"""
|
||
def get_stats(times_list):
|
||
if not times_list:
|
||
return {'avg': 0.0, 'min': 0.0, 'max': 0.0}
|
||
return {
|
||
'avg': sum(times_list) / len(times_list),
|
||
'min': min(times_list),
|
||
'max': max(times_list)
|
||
}
|
||
|
||
# 计算GPU时间统计
|
||
def get_gpu_field_stats(field_name):
|
||
"""从GPU时间历史记录中提取特定字段的统计信息"""
|
||
values = []
|
||
for gpu_data in self.gpu_timing_history:
|
||
if field_name in gpu_data:
|
||
values.append(gpu_data[field_name])
|
||
return get_stats(values)
|
||
|
||
return {
|
||
'wait_poses': get_stats(self.wait_poses_times),
|
||
'render': get_stats(self.render_times),
|
||
'submit': get_stats(self.submit_times),
|
||
'sync_wait': get_stats(self.sync_wait_times),
|
||
'gpu_timing': {
|
||
'scene_render': get_gpu_field_stats('scene_render'),
|
||
'pre_submit': get_gpu_field_stats('pre_submit'),
|
||
'post_submit': get_gpu_field_stats('post_submit'),
|
||
'total_render': get_gpu_field_stats('total_render'),
|
||
'compositor_render': get_gpu_field_stats('compositor_render'),
|
||
'frame_interval': get_gpu_field_stats('frame_interval')
|
||
},
|
||
'current': {
|
||
'wait_poses': self.wait_poses_time,
|
||
'left_render': self.left_render_time,
|
||
'right_render': self.right_render_time,
|
||
'submit': self.submit_time,
|
||
'sync_wait': self.vr_sync_wait_time,
|
||
'total_render': self.left_render_time + self.right_render_time,
|
||
'gpu_scene_render': self.gpu_scene_render_ms,
|
||
'gpu_pre_submit': self.gpu_pre_submit_ms,
|
||
'gpu_post_submit': self.gpu_post_submit_ms,
|
||
'gpu_total_render': self.gpu_total_render_ms,
|
||
'gpu_compositor_render': self.gpu_compositor_render_ms,
|
||
'gpu_frame_interval': self.gpu_client_frame_interval_ms
|
||
},
|
||
'vr_info': {
|
||
'eye_resolution': self.current_eye_resolution,
|
||
'recommended_resolution': self.recommended_eye_resolution,
|
||
'display_frequency': self.vr_display_frequency,
|
||
'vsync_enabled': self.vr_vsync_enabled,
|
||
'target_frame_time_ms': self.target_frame_time_ms,
|
||
'vsync_to_photons_ms': self.vsync_to_photons_ms,
|
||
'vsync_window_ms': self.vsync_window_ms,
|
||
'async_reprojection': self.async_reprojection_enabled,
|
||
'motion_smoothing': self.motion_smoothing_enabled,
|
||
'gpu_timing_enabled': self.enable_gpu_timing,
|
||
'gpu_timing_failures': self.gpu_timing_failure_count
|
||
}
|
||
}
|
||
|
||
def test_pipeline_monitoring(self):
|
||
"""测试管线监控功能 - 用于调试和验证"""
|
||
print("🔧 正在测试VR管线监控功能...")
|
||
|
||
try:
|
||
# 测试基本信息获取
|
||
print("📊 基本信息:")
|
||
print(f" 当前分辨率: {self.current_eye_resolution}")
|
||
print(f" 显示频率: {self.vr_display_frequency} Hz")
|
||
print(f" 目标帧时间: {self.target_frame_time_ms:.2f}ms")
|
||
|
||
# Running Start模式信息
|
||
print("🎯 Running Start模式:")
|
||
print(f" 预测时间: {self.vr_manager.use_prediction_time * 1000:.1f}ms")
|
||
print(f" 模式: Valve Running Start - 帧开始时获取姿态")
|
||
|
||
# 测试管线统计
|
||
if self.enable_pipeline_monitoring:
|
||
pipeline_stats = self._get_pipeline_stats()
|
||
print("⚙️ 管线统计:")
|
||
print(f" waitGetPoses历史: {len(self.wait_poses_times)}帧")
|
||
print(f" 渲染历史: {len(self.render_times)}帧")
|
||
print(f" 提交历史: {len(self.submit_times)}帧")
|
||
|
||
# 测试性能报告
|
||
print("📋 生成详细性能报告:")
|
||
self._print_performance_report()
|
||
|
||
print("✅ 管线监控功能测试完成")
|
||
else:
|
||
print("⚠️ 管线监控已禁用,无法测试统计功能")
|
||
|
||
except Exception as e:
|
||
print(f"❌ 测试管线监控功能时发生错误: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
|
||
def set_prediction_time(self, prediction_time_ms):
|
||
"""设置预测时间(仅用于update_task策略)
|
||
|
||
Args:
|
||
prediction_time_ms: 预测时间,单位毫秒(通常8-16ms)
|
||
"""
|
||
prediction_time_s = prediction_time_ms / 1000.0
|
||
if prediction_time_s < 0.005 or prediction_time_s > 0.020:
|
||
print(f"⚠️ 预测时间超出推荐范围(5-20ms): {prediction_time_ms}ms")
|
||
|
||
old_time = self.vr_manager.use_prediction_time * 1000
|
||
self.vr_manager.use_prediction_time = prediction_time_s
|
||
print(f"✓ VR预测时间已设置: {old_time:.1f}ms → {prediction_time_ms:.1f}ms")
|
||
|
||
# ========== 诊断工具方法 ==========
|
||
|
||
def _print_render_callback_diagnostics(self):
|
||
"""输出渲染回调诊断信息 - 包含优化效果分析"""
|
||
try:
|
||
print(f"🔍 DrawCallback渲染诊断:")
|
||
|
||
# 回调次数统计
|
||
left_count = self.left_render_count
|
||
right_count = self.right_render_count
|
||
print(f" 渲染次数: 左眼={left_count}, 右眼={right_count}")
|
||
|
||
if left_count == 0 and right_count == 0:
|
||
print(f" ❌ VR缓冲区未被渲染 - 这是严重问题!")
|
||
return
|
||
|
||
# 渲染次数平衡性检查
|
||
if abs(left_count - right_count) > 5:
|
||
print(f" ⚠️ 左右眼渲染次数不平衡: 差异={abs(left_count - right_count)}")
|
||
else:
|
||
print(f" ✓ 左右眼渲染次数平衡")
|
||
|
||
# 🔧 真实渲染时间分析 - 显示优化效果
|
||
left_render_time = self.left_render_time
|
||
right_render_time = self.right_render_time
|
||
total_render_time = left_render_time + right_render_time
|
||
|
||
print(f" ⏱️ 精确渲染时间测量:")
|
||
print(f" 左眼cbdata.upcall(): {left_render_time:.2f}ms")
|
||
print(f" 右眼cbdata.upcall(): {right_render_time:.2f}ms")
|
||
print(f" 总计: {total_render_time:.2f}ms")
|
||
|
||
# 渲染性能评估
|
||
if total_render_time > 16.0: # 超过60FPS时间
|
||
print(f" 🔴 渲染时间过长: {total_render_time:.1f}ms (目标<13.9ms@72Hz)")
|
||
print(f" 建议: 检查RenderPipeline优化是否生效")
|
||
elif total_render_time > 10.0:
|
||
print(f" 🟡 渲染时间偏高: {total_render_time:.1f}ms (可接受)")
|
||
else:
|
||
print(f" 🟢 渲染性能良好: {total_render_time:.1f}ms")
|
||
|
||
# 🔧 渲染管线优化状态检查
|
||
self._check_rendering_optimizations()
|
||
|
||
# OpenGL状态诊断
|
||
self._diagnose_opengl_state()
|
||
|
||
except Exception as e:
|
||
print(f" 渲染回调诊断失败: {e}")
|
||
|
||
def _check_rendering_optimizations(self):
|
||
"""检查渲染优化状态"""
|
||
try:
|
||
print(f" 🔧 渲染优化状态:")
|
||
|
||
# 检查RenderPipeline优化
|
||
if hasattr(self.vr_manager.world, 'render_pipeline') and self.vr_manager.world.render_pipeline:
|
||
print(f" RenderPipeline: 已检测并优化")
|
||
else:
|
||
print(f" RenderPipeline: 未检测到(使用基础Panda3D)")
|
||
|
||
# 检查GPU同步优化
|
||
if hasattr(self.vr_manager, '_smart_sync_logged'):
|
||
last_sync_frame = getattr(self.vr_manager, '_last_gpu_sync_frame', 0)
|
||
current_frame = self.frame_count
|
||
frames_since_sync = current_frame - last_sync_frame
|
||
print(f" 智能GPU同步: 已启用 (距离上次同步: {frames_since_sync}帧)")
|
||
else:
|
||
print(f" 智能GPU同步: 未初始化")
|
||
|
||
# 检查对象池状态
|
||
matrix_pool_status = self.vr_manager.get_object_pool_status()
|
||
print(f" 对象池: Mat4={matrix_pool_status['matrix_pool_size']}/{matrix_pool_status['matrix_pool_capacity']}")
|
||
|
||
# 检查垃圾回收控制
|
||
gc_status = self.get_debug_status()
|
||
if gc_status['gc_disabled']:
|
||
print(f" GC控制: 已启用手动模式 (间隔:{gc_status['manual_gc_interval']}帧)")
|
||
else:
|
||
print(f" GC控制: 自动模式")
|
||
|
||
except Exception as e:
|
||
print(f" 优化状态检查失败: {e}")
|
||
|
||
def _diagnose_opengl_state(self):
|
||
"""诊断OpenGL渲染状态"""
|
||
try:
|
||
# 检查VR缓冲区状态
|
||
if hasattr(self.vr_manager, 'vr_left_eye_buffer') and self.vr_manager.vr_left_eye_buffer:
|
||
left_gsg = self.vr_manager.vr_left_eye_buffer.getGsg()
|
||
left_valid = self.vr_manager.vr_left_eye_buffer.isValid()
|
||
print(f" 左眼缓冲区: {'有效' if left_valid else '无效'}")
|
||
|
||
if hasattr(self.vr_manager, 'vr_right_eye_buffer') and self.vr_manager.vr_right_eye_buffer:
|
||
right_gsg = self.vr_manager.vr_right_eye_buffer.getGsg()
|
||
right_valid = self.vr_manager.vr_right_eye_buffer.isValid()
|
||
print(f" 右眼缓冲区: {'有效' if right_valid else '无效'}")
|
||
|
||
# 检查纹理准备状态
|
||
if hasattr(self.vr_manager, 'textures_prepared'):
|
||
print(f" 纹理准备状态: {'已准备' if self.vr_manager.textures_prepared else '未准备'}")
|
||
|
||
# 检查纹理ID缓存
|
||
if hasattr(self.vr_manager, 'left_texture_id') and hasattr(self.vr_manager, 'right_texture_id'):
|
||
left_id = self.vr_manager.left_texture_id or 0
|
||
right_id = self.vr_manager.right_texture_id or 0
|
||
print(f" 纹理ID缓存: 左眼={left_id}, 右眼={right_id}")
|
||
|
||
if left_id == 0 or right_id == 0:
|
||
print(f" ⚠️ 检测到无效的纹理ID,这可能导致提交失败")
|
||
else:
|
||
print(f" ✓ 纹理ID缓存正常")
|
||
|
||
# 检查场景渲染状态
|
||
if hasattr(self.vr_manager.world, 'render') and self.vr_manager.world.render:
|
||
render_children = len(self.vr_manager.world.render.getChildren())
|
||
print(f" 场景节点数: {render_children}")
|
||
if render_children == 0:
|
||
print(f" ⚠️ 场景为空,可能导致渲染时间异常短")
|
||
|
||
except Exception as e:
|
||
print(f" OpenGL状态诊断失败: {e}")
|
||
|
||
# ========== 调试控制方法 ==========
|
||
|
||
def enable_debug_output(self):
|
||
"""启用调试输出"""
|
||
self.debug_output_enabled = True
|
||
print("✓ VR调试输出已启用")
|
||
|
||
def disable_debug_output(self):
|
||
"""禁用调试输出"""
|
||
self.debug_output_enabled = False
|
||
print("✓ VR调试输出已禁用")
|
||
|
||
def set_debug_mode(self, mode):
|
||
"""设置调试模式
|
||
|
||
Args:
|
||
mode: 'brief' 或 'detailed'
|
||
"""
|
||
if mode in ['brief', 'detailed']:
|
||
self.debug_mode = mode
|
||
print(f"✓ VR调试模式设置为: {mode}")
|
||
else:
|
||
print("⚠️ 调试模式只能是 'brief' 或 'detailed'")
|
||
|
||
def toggle_debug_output(self):
|
||
"""切换调试输出状态"""
|
||
self.debug_output_enabled = not self.debug_output_enabled
|
||
status = "启用" if self.debug_output_enabled else "禁用"
|
||
print(f"✓ VR调试输出已{status}")
|
||
return self.debug_output_enabled
|
||
|
||
def get_debug_status(self):
|
||
"""获取调试状态"""
|
||
return {
|
||
'debug_enabled': self.debug_output_enabled,
|
||
'debug_mode': self.debug_mode,
|
||
'performance_monitoring': self.performance_monitoring,
|
||
'report_interval_frames': self.performance_report_interval,
|
||
'report_interval_seconds': self.performance_report_interval / 60, # 假设60fps
|
||
'gc_control_enabled': self.vr_manager._gc_control_enabled,
|
||
'gc_disabled': self.vr_manager._gc_disabled,
|
||
'manual_gc_interval': self.vr_manager._manual_gc_interval,
|
||
}
|
||
|
||
# ========== 配置方法 ==========
|
||
|
||
def set_performance_check_interval(self, interval):
|
||
"""设置性能检查间隔
|
||
|
||
Args:
|
||
interval: 检查间隔(秒),建议0.1-2.0之间
|
||
"""
|
||
if 0.1 <= interval <= 5.0:
|
||
self.performance_check_interval = interval
|
||
print(f"✓ 性能监控间隔设置为 {interval:.1f} 秒")
|
||
else:
|
||
print("⚠️ 性能监控间隔应在0.1-5.0秒之间")
|
||
|
||
def set_frame_time_history_size(self, size):
|
||
"""设置帧时间历史记录大小
|
||
|
||
Args:
|
||
size: 历史记录大小(帧数),建议30-300之间
|
||
"""
|
||
if 10 <= size <= 1000:
|
||
self.max_frame_time_history = size
|
||
# 清理超出的历史记录
|
||
if len(self.frame_times) > size:
|
||
self.frame_times = self.frame_times[-size:]
|
||
print(f"✓ 帧时间历史记录大小设置为 {size} 帧")
|
||
else:
|
||
print("⚠️ 帧时间历史记录大小应在10-1000帧之间")
|
||
|
||
def set_performance_report_interval(self, frames):
|
||
"""设置性能报告输出间隔
|
||
|
||
Args:
|
||
frames: 帧数间隔,建议300-7200之间(5秒-2分钟@60fps)
|
||
"""
|
||
if 300 <= frames <= 7200:
|
||
# 修改_update_vr中的报告间隔
|
||
print(f"✓ 性能报告间隔设置为每 {frames} 帧(约 {frames/60:.1f} 秒@60fps)")
|
||
# 这里可以添加一个实例变量来控制
|
||
self.performance_report_interval = frames
|
||
else:
|
||
print("⚠️ 性能报告间隔应在300-7200帧之间")
|
||
|
||
# ========== 查询方法 ==========
|
||
|
||
def get_performance_stats(self):
|
||
"""获取详细的性能统计信息"""
|
||
stats = {
|
||
'vr_fps': self.vr_fps,
|
||
'frame_count': self.frame_count,
|
||
'submit_failures': self.submit_failures,
|
||
'pose_failures': self.pose_failures,
|
||
'cpu_usage': self.cpu_usage,
|
||
'memory_usage': self.memory_usage,
|
||
'gpu_usage': self.gpu_usage,
|
||
'gpu_memory_usage': self.gpu_memory_usage,
|
||
}
|
||
|
||
# 计算帧时间统计
|
||
if self.frame_times:
|
||
stats['frame_time_avg'] = sum(self.frame_times) / len(self.frame_times)
|
||
stats['frame_time_min'] = min(self.frame_times)
|
||
stats['frame_time_max'] = max(self.frame_times)
|
||
stats['frame_time_95th'] = sorted(self.frame_times)[int(len(self.frame_times) * 0.95)]
|
||
else:
|
||
stats['frame_time_avg'] = 0
|
||
stats['frame_time_min'] = 0
|
||
stats['frame_time_max'] = 0
|
||
stats['frame_time_95th'] = 0
|
||
|
||
return stats
|
||
|
||
def get_current_performance_summary(self):
|
||
"""获取当前性能摘要(简短版本)"""
|
||
stats = self.get_performance_stats()
|
||
|
||
summary = f"VR性能: {stats['vr_fps']:.1f}fps"
|
||
|
||
if stats['frame_time_avg'] > 0:
|
||
summary += f" | 帧时间: {stats['frame_time_avg']:.1f}ms"
|
||
|
||
if self.psutil_available:
|
||
summary += f" | CPU: {stats['cpu_usage']:.0f}%"
|
||
summary += f" | 内存: {stats['memory_usage']:.0f}%"
|
||
|
||
# 显示GPU信息,如果库不可用则显示提示
|
||
if self.gputil_available or self.nvidia_ml_available:
|
||
summary += f" | GPU: {stats['gpu_usage']:.0f}%"
|
||
else:
|
||
summary += " | GPU: N/A"
|
||
|
||
return summary
|
||
|
||
def get_performance_monitoring_config(self):
|
||
"""获取当前性能监控配置"""
|
||
return {
|
||
'enabled': self.performance_monitoring,
|
||
'check_interval': self.performance_check_interval,
|
||
'frame_history_size': self.max_frame_time_history,
|
||
'report_interval': self.performance_report_interval,
|
||
'psutil_available': self.psutil_available,
|
||
'gputil_available': self.gputil_available,
|
||
'nvidia_ml_available': self.nvidia_ml_available
|
||
}
|
||
|
||
def print_performance_monitoring_status(self):
|
||
"""输出性能监控状态"""
|
||
config = self.get_performance_monitoring_config()
|
||
|
||
print("🔧 ===== VR性能监控配置 =====")
|
||
print(f" 监控状态: {'✅ 启用' if config['enabled'] else '❌ 禁用'}")
|
||
print(f" 检查间隔: {config['check_interval']:.1f} 秒")
|
||
print(f" 帧时间历史: {config['frame_history_size']} 帧")
|
||
print(f" 报告间隔: {config['report_interval']} 帧")
|
||
|
||
print(f" 可用库:")
|
||
print(f" psutil (CPU/内存): {'✅' if config['psutil_available'] else '❌'}")
|
||
print(f" GPUtil (GPU): {'✅' if config['gputil_available'] else '❌'}")
|
||
print(f" NVIDIA-ML (GPU): {'✅' if config['nvidia_ml_available'] else '❌'}")
|
||
print("=============================")
|
||
|
||
# ========== 控制方法 ==========
|
||
|
||
def enable_performance_monitoring(self):
|
||
"""启用性能监控"""
|
||
self.performance_monitoring = True
|
||
print("✓ VR性能监控已启用")
|
||
|
||
def disable_performance_monitoring(self):
|
||
"""禁用性能监控"""
|
||
self.performance_monitoring = False
|
||
print("✓ VR性能监控已禁用")
|
||
|
||
def force_performance_report(self):
|
||
"""强制输出一次性能报告"""
|
||
print("🔄 手动触发性能报告...")
|
||
self._print_performance_report()
|
||
|
||
def reset_performance_counters(self):
|
||
"""重置性能计数器"""
|
||
self.frame_count = 0
|
||
self.last_fps_check = 0
|
||
self.last_fps_time = 0
|
||
self.vr_fps = 0
|
||
self.submit_failures = 0
|
||
self.pose_failures = 0
|
||
self.frame_times.clear()
|
||
print("✅ 性能计数器已重置")
|