菜单

性能优化

相关源文件

本页介绍了优化 Dear ImGui 应用程序以获得最佳运行时性能的技术。它概述了内置优化、配置选项和最佳实践,以在使用 Dear ImGui 时实现高效渲染并最大限度地减少 CPU/GPU 使用。

核心性能原则

Dear ImGui 的设计将性能作为首要考虑因素。以下几个关键设计原则有助于其高效运行:

来源: imgui.cpp216-220

这些原则使 Dear ImGui 即使在具有复杂界面和大量 UI 元素的应用程序中也能保持良好的性能。

内存管理

内存分配策略

Dear ImGui 采用多种策略来最大限度地减少帧渲染期间的内存分配:

当渲染一个典型帧而没有创建新的窗口或小部件时:

  • 不发生堆分配
  • 内存从前一帧重用
  • 绘图缓冲区会增长但很少收缩

来源: imgui.cpp217 imgui_internal.h357-358

内存使用模式

Dear ImGui 中的内存主要用于:

组件描述优化
绘图缓冲区用于渲染的顶点和索引缓冲区采用增长策略预分配
窗口数据窗口状态、内容和绘图命令窗口被池化和重用
小部件状态活动小部件数据和状态帧之间保留最小状态
字体数据字符字形和纹理图集在所有上下文中共享

为避免性能问题,您应该:

  1. 以一致的顺序创建 UI 元素以允许内存重用
  2. 避免频繁创建/销毁窗口
  3. 使用 PushID()/PopID() 而不是生成长字符串 ID

来源: imgui.cpp214-220 imgui_internal.h352-358

渲染优化

绘图命令批处理

Dear ImGui 通过批处理相似的绘图命令来优化渲染

具有相同纹理、剪裁矩形和属性的命令会自动批处理,以最大限度地减少绘制调用。

来源: imgui_draw.cpp122-146

剪裁与剔除

Dear ImGui 使用多种技术来避免渲染不可见内容:

粗略剪裁

ImGui 首先尝试消除不可见的整个小部件或窗口

  • 折叠的标题/树不处理其子元素
  • 屏幕外的窗口可以完全跳过渲染
  • 带有滚动条的 BeginChild 只渲染可见项

剪刀矩形

当内容必须部分剪裁时

  • GPU 剪刀测试用于剪裁绘制命令
  • 文本被智能剪裁,以避免处理不可见的字符

使用 ImGuiListClipper 进行剔除

对于大型列表或表格,使用 ImGuiListClipper 对性能至关重要

来源: imgui_widgets.cpp196-204 imgui_tables.cpp156-184

小部件和布局优化

小部件效率

某些小部件比其他小部件更耗费性能

小部件性能特征优化技巧
基本小部件(按钮、文本等)非常高效可安全大量使用
输入字段激活时成本适中限制屏幕上活动输入控件的数量
表格多列时成本可能较高使用剪裁和固定列宽
具有许多节点的树形结构每个节点都有开销使用剪裁和延迟加载
自定义渲染取决于实现方式最小化绘制调用和状态更改

布局性能

布局计算在误用时可能开销很大

  1. 避免频繁更改样式 - 每次 PushStyleVar()/PopStyleVar() 都需要重新计算
  2. 谨慎使用自动调整大小 - 嵌套的自动调整大小窗口会强制进行多次布局遍历
  3. 注意带格式的 Text() 调用 - 字符串格式化有开销
  4. 明智地使用子窗口 - 每个子窗口都会增加渲染状态和潜在的绘制调用

来源: imgui_widgets.cpp266-321 imgui_tables.cpp156-184

表格优化

表格可能占用大量性能,特别是当行和列很多时。使用以下策略进行优化:

列表剪裁器使用

对于具有许多行的表格,请始终使用 ImGuiListClipper

列优化

  • 固定宽度列比可拉伸列更高效
  • 检查 TableNextColumn() 的返回值以跳过处理隐藏列
  • 对于复杂的单元格内容,使用返回值来避免不必要的计算

来源: imgui_tables.cpp156-184

字体和文本渲染

文本渲染可能是重要的性能因素。考虑以下优化措施:

字体配置技巧

  1. 保持字体图集大小合理(512x512 到 1024x1024)
  2. 限制加载的字体数量
  3. 只包含您需要的字形范围
  4. 考虑使用 ImGuiFreeType 以提高质量(会带来一定的性能开销)

文本渲染技巧

  1. 对于不需要格式化的字符串,使用 TextUnformatted()
  2. 缓存不经常更改的格式化字符串
  3. 对于非常大的文本块,考虑使用自定义小部件或剪裁

来源: imgui_draw.cpp182-245

后端特定优化

不同的渲染后端具有不同的性能特征

Vulkan/Metal/DirectX

现代图形 API 的技巧

  1. 确保您的后端正确重用顶点/索引缓冲区
  2. 考虑为在途帧资源使用双缓冲
  3. 最小化渲染管线状态更改
  4. 高效批处理渲染命令

OpenGL

对于 OpenGL 后端

  1. 注意 GL 状态更改,这可能开销很大
  2. 考虑对静态内容使用 VAO
  3. 最小化绑定纹理更改
  4. 在可用时使用现代 GL 特性

来源: examples/example_glfw_vulkan/main.cpp264-327

分析和调试工具

Dear ImGui 提供了多种工具来识别性能问题

使用指标窗口

指标窗口提供有价值的性能数据

  1. 使用 ImGui::ShowMetricsWindow() 打开
  2. 检查“Dear ImGui 统计”部分以获取帧时间和内存使用情况
  3. 审查绘制调用次数和顶点数量
  4. 分析活动窗口和小部件

来源: imgui.cpp96-98

常见性能陷阱

避免以下常见问题

  1. 频繁创建/销毁窗口

    • 而是使用 ImGui::Begin("Window", nullptr, ImGuiWindowFlags_NoDecoration)
  2. 热路径中的复杂格式化

    • 缓存格式化字符串或使用 TextUnformatted()
  3. 深度嵌套的窗口/组

    • 每个嵌套级别都会增加开销
  4. 没有剪裁的大型表格

    • 对于具有许多行的表格,请始终使用 ImGuiListClipper
  5. 使用不同 ID 重新创建相同 UI

    • 在帧之间保持一致的 UI 结构
  6. 低效的 ID 栈使用

    • 在可能的情况下使用 PushID(int) 而不是字符串 ID
  7. 过多的样式更改

    • 批量处理样式更改并最小化 PushStyleVar()/PopStyleVar() 调用
  8. 不检查可见性

    • 在进行昂贵的计算之前检查窗口可见性
  9. 过多的绘制回调

    • 自定义渲染可能破坏批处理,请明智使用
  10. 过度使用自动调整大小

    • 自动调整大小可能导致多次布局遍历

来源: imgui.cpp214-221 imgui_tables.cpp156-184 docs/TODO.txt52-108

总结

优化 Dear ImGui 应用程序涉及:

  1. 理解渲染模型以及命令是如何批处理的
  2. 适当的内存管理以避免帧渲染期间的分配
  3. 有效使用剪裁以避免处理不可见的元素
  4. 智能小部件使用,并了解其性能特征
  5. 使用适当的剪裁技术优化表格和列表
  6. 针对您的渲染系统的后端特定优化

当这些原则正确应用时,Dear ImGui 可以轻松处理包含数千个元素的复杂界面,同时保持出色的性能。