Skip to content

Conversation

@xezon
Copy link

@xezon xezon commented Jan 29, 2026

This change reduces the cost of ParticleSystemManager::findParticleSystem() by 80% using a hash map instead of linear search through the std::list.

Tested in Release with 100'000 iterations on a big test map, which took around 30 seconds to hit.

The ParticleSystem count was moderate around 700. The cost was reduced by around 80% in the test.

Original

100'000 iterations measured at 87 ms

This change

100'000 iterations measured at 18 ms

In unoptimized builds the performance gain will be even larger.

Out of addParticleSystem, removeParticleSystem and findParticleSystem, the removeParticleSystem shows to be the most expensive, because it still has a std::list search in it, naturally.

image Image from test in unoptimized build.

@xezon xezon added Minor Severity: Minor < Major < Critical < Blocker Performance Is a performance concern Gen Relates to Generals ZH Relates to Zero Hour labels Jan 29, 2026
@greptile-apps
Copy link

greptile-apps bot commented Jan 29, 2026

Greptile Overview

Greptile Summary

This PR optimizes ParticleSystemManager::findParticleSystem() by introducing a hash map (m_systemMap) alongside the existing linked list (m_allParticleSystemList), reducing lookup complexity from O(n) to O(1). The performance improvement is significant - 80% reduction in an 100k-iteration test with ~700 particle systems.

Key changes:

  • Added ParticleSystemID hash specialization in STLTypedefs.h
  • Added m_systemMap hash map to ParticleSystemManager class
  • Refactored findParticleSystem() to use hash map lookup instead of list iteration
  • Updated friend_addParticleSystem() and friend_removeParticleSystem() to maintain hash map synchronization
  • Added assertion in reset() to validate hash map cleanup

The implementation correctly maintains consistency between the list and hash map across all operations including serialization/deserialization (xfer). The list is retained for iteration operations while the hash map enables fast ID-based lookups.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The implementation is clean and correct. The hash map is properly synchronized with the list in all operations (add, remove, reset). Serialization works correctly because particle systems are created through createParticleSystem, which calls friend_addParticleSystem, automatically populating the hash map. The performance improvement is substantial and well-tested.
  • No files require special attention

Important Files Changed

Filename Overview
Core/GameEngine/Include/Common/STLTypedefs.h Added ParticleSystemID forward declaration and hash specialization for use in hash maps
Core/GameEngine/Include/GameClient/ParticleSys.h Added ParticleSystemIDMap hash map member to enable O(1) lookups by particle system ID
Core/GameEngine/Source/GameClient/System/ParticleSys.cpp Refactored findParticleSystem() to use hash map, updated add/remove operations to maintain hash map sync, added assertion for validation

Sequence Diagram

sequenceDiagram
    participant Client
    participant PSM as ParticleSystemManager
    participant List as m_allParticleSystemList
    participant Map as m_systemMap (new)
    
    Note over PSM,Map: Add Operation
    Client->>PSM: friend_addParticleSystem(ps)
    PSM->>List: push_back(ps)
    PSM->>Map: m_systemMap[ps->getSystemID()] = ps
    PSM->>PSM: ++m_particleSystemCount
    
    Note over PSM,Map: Find Operation (optimized)
    Client->>PSM: findParticleSystem(id)
    alt id == INVALID_PARTICLE_SYSTEM_ID
        PSM-->>Client: return nullptr
    else valid id
        PSM->>Map: find(id)
        Map-->>PSM: iterator
        PSM-->>Client: return it->second or nullptr
    end
    
    Note over PSM,Map: Remove Operation
    Client->>PSM: friend_removeParticleSystem(ps)
    PSM->>List: find(ps)
    PSM->>Map: erase(ps->getSystemID())
    PSM->>List: erase(it)
    PSM->>PSM: --m_particleSystemCount
Loading

DEBUG_ASSERTCRASH(particleSystemToAdd != nullptr, ("ParticleSystemManager::friend_addParticleSystem: ParticleSystem is null"));
m_allParticleSystemList.push_back(particleSystemToAdd);
m_systemMap[particleSystemToAdd->getSystemID()] = particleSystemToAdd;
++m_particleSystemCount;
Copy link

@Caball009 Caball009 Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do STLport hash maps store the container size?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes they do. Modern std::list also does :)

@xezon
Copy link
Author

xezon commented Jan 29, 2026

Fixed nasty VC6 compile error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Gen Relates to Generals Minor Severity: Minor < Major < Critical < Blocker Performance Is a performance concern ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants