Skip to content

Performance Issues in Velocity #8

Open

Description

@killeromg003

1. Excessive Lock Contention on Hot Paths

Multiple systems use std::shared_mutex and std::mutex on frequently accessed data:

  • systems::entities uses std::shared_mutex m_cache_mtx for entity caching (line 204 in systems.hpp)
  • systems::local uses std::shared_mutex m_mtx for snapshot access (line 246)

These locks are acquired on every frame for entity lookups and local player state checks. In a game running at 60-120+ FPS, this creates significant contention, especially when multiple subsystems (ESP, targeting, etc.) compete for reads simultaneously.

2. Unbounded Memory Growth in Material Caching

The systems::materials class maintains:

static inline std::unordered_map<std::uint64_t, std::uintptr_t> m_map{};

There's no evidence of cache eviction. As players encounter new material combinations, the map grows indefinitely without cleanup, leading to memory leaks and cache misses over extended gameplay sessions.

3. Inefficient Icon/SVG Caching

The systems::icons class stores multiple caches:

std::unordered_map<icon_key, icon, icon_key_hash> m_icons{};
std::unordered_map<std::uint32_t, std::string> m_hash_to_name{};
std::unordered_map<std::string, std::vector<std::byte>> m_pending_svgs{};

SVG decompilation (decompile_vsvg) happens on-demand with results stored in memory. Multiple lookups use hash computation + string comparison chains, and the icon_key_hash performs redundant hashing.

4. Repeated String Construction in Settings Initialization

In settings.hpp (lines 42-64, 134-159), initialization loops repeatedly construct strings:

for ( std::uint32_t i = 0; i < k_group_count; ++i )
{
    this->groups[ i ].init( std::string( "ragebot - " ) + weapon_names[ i ] );
}

This creates temporary string objects in a loop during initialization. While not on a hot path, it's wasteful.

5. Synchronous Tracing Without Result Caching

The systems::tracing class provides multiple overloaded trace() methods (lines 451-463). Each trace operation:

  • Allocates a trace_data structure on the stack (contains 0x80 array elements)
  • Performs full raycasts without caching results
  • Called potentially hundreds of times per frame for visibility checks, autowall calculations, etc.

No spatial partitioning or result caching is evident.

6. Input History Accumulation

The systems::input class maintains input_history_params with many fields (lines 94-120) and calls push_input_history() every frame. The underlying protobuf message proto::csgo_usercmd_pb likely accumulates history without bounds checking.

7. Unoptimized Entity Type Classification

systems::entities::classify_entity() (line 201) uses schema hash comparison but is called on every entity addition/removal. No symbol caching or hash table for schema classification is visible.

8. Redundant Configuration Serialization

The settings::changer::skin_map_field (lines 1045-1089) serializes/deserializes JSON on every config update without differential encoding. The loop at line 1075 iterates over all items and reconstructs JSON objects unnecessarily.

Recommendations

  1. Use lock-free data structures (atomics, concurrent queues) for frequently-read entity/player state
  2. Implement LRU cache eviction in material manager with max size limits
  3. Pre-compute icon hashes and use direct index lookups instead of nested map lookups
  4. Cache trace results with spatial grid acceleration for visibility checks
  5. Implement circular buffer for input history with fixed capacity
  6. Use value semantics or move semantics to reduce allocations in hot loops

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions