Pick the fix
A service builds a dict from user-chosen string keys and slows to a crawl. What is the most likely cause?
Choose an answer, then open Show answer below to check it.
Show answer
Answer: A Many keys collide, so lookups scan long chains
Right: crafted collisions push each lookup towards O(n).
That is why CPython salts string hashes per process: an attacker cannot predict which keys collide.
Why not the others?
- B Dicts are O(log n) per lookup. Lookups are O(1) on average; they are not tree-based.
- C Strings cannot be dict keys. Strings are the most common dict keys.
Illustrative
Toy table: bucket = key % size, grows by doubling at load 0.75. Real dicts use open addressing.
Text version
Grow at 0.75:
- 0: –; 1: –; 2: –; 3: 3. Insert 3 into bucket 3
- 0: –; 1: –; 2: –; 3: 3, 11. Insert 11 into bucket 3
- 0: –; 1: –; 2: –; 3: 3, 11, 19. Insert 19 into bucket 3
- 0: –; 1: –; 2: –; 3: 3, 11, 19; 4: –; 5: –; 6: –; 7: –. Load would pass 0.75: grow to 8 buckets, move 3 keys
- 0: –; 1: –; 2: –; 3: 3, 11, 19; 4: –; 5: –; 6: 6; 7: –. Insert 6 into bucket 6
- 0: –; 1: –; 2: –; 3: 3, 11, 19; 4: –; 5: –; 6: 6, 14; 7: –. Insert 14 into bucket 6
- 0: –; 1: –; 2: –; 3: 3, 11, 19; 4: –; 5: –; 6: 6, 14, 22; 7: –. Insert 22 into bucket 6
Buckets: 8, moved: 3, longest: 3.
Never grow:
- 0: –; 1: –; 2: –; 3: 3. Insert 3 into bucket 3
- 0: –; 1: –; 2: –; 3: 3, 11. Insert 11 into bucket 3
- 0: –; 1: –; 2: –; 3: 3, 11, 19. Insert 19 into bucket 3
- 0: –; 1: –; 2: 6; 3: 3, 11, 19. Insert 6 into bucket 2
- 0: –; 1: –; 2: 6, 14; 3: 3, 11, 19. Insert 14 into bucket 2
- 0: –; 1: –; 2: 6, 14, 22; 3: 3, 11, 19. Insert 22 into bucket 2
Buckets: 4, moved: 0, longest: 3.