Skip to content

Use faster hash maps and precomputed hashes in hot paths - #15279

Open
C0W0 wants to merge 1 commit into
terry/app-3587-lazy-user-block-completed-fieldsfrom
terry/app-3587-hash-improvement
Open

Use faster hash maps and precomputed hashes in hot paths#15279
C0W0 wants to merge 1 commit into
terry/app-3587-lazy-user-block-completed-fieldsfrom
terry/app-3587-hash-improvement

Conversation

@C0W0

@C0W0 C0W0 commented Aug 18, 2026

Copy link
Copy Markdown

Description

Stacked on #15162. Follow-up performance pass that reduces hashing overhead in a few hot paths:

  • Adds a generic Hashed<K> utility (crates/warp_util/src/hashed.rs) that pairs a key with its precomputed hash, so repeated lookups against the same hasher (e.g. hashbrown's raw_entry().from_hash(..)) can skip rehashing.
  • TaskStore::root_task_id is now Hashed<TaskId>, and TaskStore's backing map switched to hashbrown::HashMap to use raw_entry.
  • AIConversation's tasks_by_id map switched to hashbrown::HashMap.
  • Swapped std HashMap/HashSet for rustc-hash's FxHashMap/FxHashSet in a few other hot paths that don't need DoS-resistant hashing: AIBlock::requested_action_ids, BlockList::block_id_to_block_index, and AppContext's window/cursor-position maps. Since these keys are not from user input, we do not need DoS resistant hashing and can instead opt for better performance offered by rustc-hash.
  • Declared hashbrown as a workspace dependency and referenced it (and rustc-hash) from app/Cargo.toml via workspace = true for consistency with the rest of the manifest. hashbrown would not change the behaviour, as call stack tracing has already confirmed that, at least in the Rust standard library we use Mac, it is already the underlying implementation of HashMap, so using it to replace std::collection::HashMap simply allows us to access more API with the same underlying implementation.

No behavior changes are intended; this is purely a performance/internal refactor.

Linked Issue

Testing

  • Added unit tests for Hashed<K> in crates/warp_util/src/hashed_tests.rs.
  • Ran existing test suites for the touched modules: ai::agent::task_store (32 tests), ai::blocklist::block (104 tests), terminal::model::blocks (65 tests) — all passing.
  • Ran ./script/format and cargo clippy on the touched crates (warp, warp_util, warpui_core) with no new warnings.
  • I have manually tested my changes locally with ./script/run

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

CHANGELOG-NONE

Co-Authored-By: Warp agent@warp.dev

@cla-bot cla-bot Bot added the cla-signed label Aug 18, 2026
@oz-for-oss

oz-for-oss Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

@C0W0

I'm starting a first review of this pull request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

@C0W0
C0W0 requested a review from acarl005 August 18, 2026 19:02

@oz-for-oss oz-for-oss Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Overview

This PR switches selected hot-path maps and sets to hashbrown/rustc-hash and adds Hashed<K> for precomputed-hash lookups. No approved spec context was present, and the security pass did not find a diff-backed security issue.

Concerns

  • The new Hashed<K> tests include one case that combines multiple independent behavior contracts, contrary to the repo's unit-test guidance.
  • AIBlock::handle_updated_output still rebuilds the complete action-ID set inside the per-action loop, so the touched hot path remains unnecessarily O(n²).

Verdict

Found: 0 critical, 1 important, 1 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

}

#[test]
fn derefs_and_compares_as_the_key() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ [IMPORTANT] This test combines deref, equality, accessors, and consumption in one case. The repo test guidance calls for one behavior per test; split these assertions into focused tests so failures identify the broken contract.


for action in output.actions() {
let new_action_ids: HashSet<AIAgentActionId> =
let new_action_ids: FxHashSet<AIAgentActionId> =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 [SUGGESTION] This still rebuilds the full action-ID set inside the per-action loop, making the touched hot path O(n²). Collect it once before for action in output.actions() and reuse it.

- Add a generic Hashed<K> utility in warp_util that pairs a key with
  its precomputed hash, so repeated lookups against the same hasher
  (e.g. hashbrown's raw_entry().from_hash) can skip rehashing.
- Use Hashed<TaskId> for TaskStore's root_task_id, and switch its
  backing map to hashbrown::HashMap to access raw_entry.
- Switch AIConversation's tasks_by_id map to hashbrown::HashMap.
- Swap std HashMap/HashSet for FxHashMap/FxHashSet (rustc-hash) in a
  few other hot paths: AIBlock's requested_action_ids, BlockList's
  block_id_to_block_index, and AppContext's window/cursor maps.
- Declare hashbrown as a workspace dependency and reference it (and
  rustc-hash) from app/Cargo.toml via workspace = true for consistency.

Co-Authored-By: Warp <agent@warp.dev>

C0W0 commented Aug 18, 2026

Copy link
Copy Markdown
Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant