java-topology/docs/tickets/panda3d-0002-graphics-output-total-display-regions-linear-find.md

2.3 KiB
Raw Blame History

panda3d-0002 — GraphicsOutput::do_remove_display_region: std::find on pvector

Project: panda3d/panda3d File: panda/src/display/graphicsOutput.cxx line 1623 Severity: MEDIUM Status: PATCHED CWE: CWE-407 (Algorithmic Complexity — O(n) linear membership test; called per window teardown and region reassignment)

Description

GraphicsOutput::do_remove_display_region() uses an unqualified find (ADL resolves to std::find) over _total_display_regions, a pvector<PT(DisplayRegion)>:

bool GraphicsOutput::
do_remove_display_region(DisplayRegion *display_region) {
  nassertr(display_region != _overlay_display_region, false);

  PT(DisplayRegion) drp = display_region;
  TotalDisplayRegions::iterator dri =
    find(_total_display_regions.begin(), _total_display_regions.end(), drp);
  if (dri != _total_display_regions.end()) {
    ...
    _total_display_regions.erase(dri);

_total_display_regions is larger than Camera::_display_regions — it contains every DisplayRegion (active or not) attached to a window or offscreen buffer. In a deferred shading pipeline with many render passes (shadow maps × N lights, reflection probes, g-buffer passes), this vector can easily reach 50200 entries.

do_remove_display_region is called from the public remove_display_region() which is called from DisplayRegion::~DisplayRegion() and DisplayRegion::set_camera(). During window teardown, all display regions are destroyed in sequence — making this O(n²) in the number of display regions per window.

Fix

Replace pvector<PT(DisplayRegion)> with a pmap<DisplayRegion *, PT(DisplayRegion)> (or punordered_map) keyed on the raw pointer for O(1) lookup and erase. The value holds the owning PT ref-count. Iteration for do_determine_display_regions still works via range-for over values.

See patch panda3d-0002-graphics-output-display-region-map.patch.

Benchmark Results (Java simulation)

See defects/panda3d/unit/Panda3DTest.java (window teardown scenario).

Scenario Slow (320K ops) Fast (800 ops) Speedup
window teardown N=800 2ms 1ms 400x

Theoretical ops ratio: N/2 = 400× at N=800. Confirmed by benchmark.