📈 The fastest map possible in Rust, where keys are integers and the capacity is fixed (faster than Vec!)

Overview

cargo crates.io codecov Hits-of-Code Lines of code License docs.rs

It is an alternative on-heap implementation of a map with keys of type usize and a fixed capacity. It works much faster than a standard HashMap because it allocates memory for all keys at once and then the cost of get() is O(1). Obviously, with this design, the cost of iter() increases because the iterator has to jump through empty keys. However, there is a supplementary function next_key(), which returns the next available key in the map. It is recommended to use it in order to ensure sequential order of the keys, which will guarantee O(1) cost of next() in iterators.

If usize keys are placed sequentially, the only true competitor of ours is std::vec::Vec. We beat it too, see the benchmarking results below.

First, add this to Cargo.toml:

[dependencies]
emap = "0.0.13"

Then, use it like a standard hash map... well, almost:

use emap::Map;
let mut m : Map<&str> = Map::with_capacity_init(100); // allocation on heap
m.insert(m.next_key(), "foo");
m.insert(m.next_key(), "bar");
assert_eq!(2, m.len());

If more than 100 keys will be added to the map, it will panic. The map doesn't increase its size automatically, like Vec does (this is one of the reasons why we are faster).

Read the API documentation. The struct emap::Map is designed as closely similar to std::collections::HashMap as possible.

Benchmark

There is a summary of a simple benchmark, where we compared emap::Map with Vec, changing the total capacity CAP of them (horizontal axis). We applied the same interactions (benchmark.rs) to them both and measured how fast they performed. In the following table, the numbers over 1.0 indicate performance gain of Map against Vec, while the numbers below 1.0 demonstrate performance loss.

4 16 256 4096
i ∈ 0..CAP {M.insert(i, &"Hello, world!")} 1.08 1.91 2.26 2.21
i ∈ 0..CAP {M.insert(i, &"大家好"); s ∈ M.values() {sum += s.len()}} 1.04 0.56 0.50 0.35
i ∈ 0..CAP {M.insert(i, &42); s ∈ M.into_values() {sum += s}} 1.02 0.76 0.35 0.35
i ∈ 0..CAP {M.insert(i, &42); s ∈ M.keys() {sum += s}} 1.05 0.65 0.34 0.35
i ∈ 0..CAP {M.insert(i, &42); s ∈ M.values() {sum += s}} 1.14 0.61 0.50 0.52
i ∈ 0..CAP {M.insert(i, &42)}; M.clear(); M.len(); 1.14 2.20 6.37 7.85
i ∈ 0..CAP {M.insert(i, &42)}; i ∈ CAP-1..0 {M.remove(&i)} 1.21 1.90 2.23 2.31

The experiment was performed on 30-04-2023. There were 10000 repetition cycles. The entire benchmark took 509s.

How to Contribute

First, install Rust and then:

$ cargo test -vv

If everything goes well, fork repository, make changes, send us a pull request. We will review your changes and apply them to the master branch shortly, provided they don't violate our quality standards. To avoid frustration, before sending us your pull request please run cargo test again. Also, run cargo fmt and cargo clippy.

Also, before you start making changes, run benchmarks:

$ rustup run nightly cargo bench

Then, after the changes you make, run it again. Compare the results. If your changes degrade performance, think twice before submitting a pull request.

You might also like...
Rust based magic-string with source map chains support

enhanced-magic-string Rust implementation of https://www.npmjs.com/package/magic-string with original sourcemap chain support. license. This project i

Parallel pipelined map over iterators.

plmap Parallel pipelined map over iterators for rust. Documentation docs.rs/plmap Example Parallel pipelined mapping: // Import the iterator extension

A parser for the .map file included in the aimware leak
A parser for the .map file included in the aimware leak

a utility I wrote to parse the map file included with the recent aimware self-leak. there is also an IDAPython script to import the symbol information into IDA.

A typed map which can make sure item exist.

Certain Map A typed map which can make sure item exist. What Problem Does It Solve In Rust, we often use Service abstraction for modular structure des

In this repository you can find modules with code and comments that explain rust syntax and all about Rust lang.
In this repository you can find modules with code and comments that explain rust syntax and all about Rust lang.

Learn Rust What is this? In this repository you can find modules with code and comments that explain rust syntax and all about Rust lang. This is usef

A comprehensive and FREE Online Rust hacking tutorial utilizing the x64, ARM64 and ARM32 architectures going step-by-step into the world of reverse engineering Rust from scratch.
A comprehensive and FREE Online Rust hacking tutorial utilizing the x64, ARM64 and ARM32 architectures going step-by-step into the world of reverse engineering Rust from scratch.

FREE Reverse Engineering Self-Study Course HERE Hacking Rust A comprehensive and FREE Online Rust hacking tutorial utilizing the x64, ARM64 and ARM32

An API for getting questions from http://either.io implemented fully in Rust, using reqwest and some regex magic. Provides asynchronous and blocking clients respectively.

eithers_rust An API for getting questions from http://either.io implemented fully in Rust, using reqwest and some regex magic. Provides asynchronous a

Fast and simple datetime, date, time and duration parsing for rust.

speedate Fast and simple datetime, date, time and duration parsing for rust. speedate is a lax† RFC 3339 date and time parser, in other words, it pars

Comments
Releases(0.0.13)
  • 0.0.13(Apr 30, 2023)

  • 0.0.12(Apr 30, 2023)

    See #66, release log:

    • ce64855f48f53389a906f55aa26bf142fe30d40b by @yegor256: #66 doc
    • 15addff44694c78f1c666e7b9b71275bc791cc05 by @yegor256: #66 example
    • a12a2f3618c89ea549301c5a497600145708224e by @yegor256: #66 iter_mut()
    • 640675f4ef382dfb2b43ab7596b418d2c9cb9657 by @yegor256: #66 moved functions
    • 70c6856e72615f55a1eb3db6bc19e2b614631518 by @yegor256: Merge pull request #64 from ye...
    • 9198184c81b2e88b391d908596e86eb782eebcdc by @yegor256: new version in README
    • 885db21c79621866137cb15b40a7a4b8743d6be2 by @yegor256: assert_boundaries()
    • b61da1713a8693f7c08c7c50c78c2c4413fa1a02 by @yegor256: extra test

    Released by Rultor 1.74.7, see build log

    Source code(tar.gz)
    Source code(zip)
  • 0.0.11(Apr 30, 2023)

    See #63, release log:

    • 07ad8217088b068e8c9ec6600cc9dd92c81e4285 by @yegor256: #63 tested and fixed
    • c05a6f2b93b532e76802659f30651aabd884d5c0 by @yegor256: Merge pull request #62 from ye...
    • 353379c333a7fb68f18058a8172c108212bb271d by @yegor256: new benchmark results
    • 2983616d626f2f9c2c4d06e9ad1249afa5808ebd by @yegor256: Merge pull request #61 from ye...

    Released by Rultor 1.74.7, see build log

    Source code(tar.gz)
    Source code(zip)
  • 0.0.10(Apr 30, 2023)

    See #60, release log:

    • 85e91b302f7fb48b146bcc0cec367199db3bfd15 by @yegor256: #60 branch
    • 8947e1a6ae6ad96f5ccd15bea64cbf90fb842f6b by @yegor256: #60 _some
    • 82fcb4d4940fddd5c62a6c562ecd84182b0df914 by @yegor256: #60 _none
    • 6e509c6c6946a92ce7663a9bd0000ece7cbbc632 by @yegor256: Merge pull request #59 from ye...
    • 79c3baacf4925724d12f286a77d4f4c566bb6369 by @yegor256: new version in README
    • 956b0f34122a388d52dca6cfa755882649340010 by @yegor256: Merge pull request #58 from ye...
    • 31403d66b440138b61f89e3afa09b6f570fb4a64 by @yegor256: new benchmark results

    Released by Rultor 1.74.7, see build log

    Source code(tar.gz)
    Source code(zip)
  • 0.0.9(Apr 30, 2023)

    See #57, release log:

    • 3651b7c3c4d9fe7f408d845e0d11862357e3316d by @yegor256: iter
    • 67ab4dac6abc8b5954485e465cf90b8cb523dead by @yegor256: bench
    • fa7cca4f86169e7d13d027500deb1c2e54029b72 by @yegor256: Merge pull request #55 from ye...
    • 121b65aa51a1cac8a1cf353ad6d222a3042eb9bc by @yegor256: new benchmark results
    • 1291e102b974b307e228b0c373bf04a3d607d193 by @yegor256: Merge pull request #54 from ye...

    Released by Rultor 1.74.7, see build log

    Source code(tar.gz)
    Source code(zip)
  • 0.0.8(Apr 26, 2023)

    See #52, release log:

    • 08afae084560ba04c30e194068463dbe30a775c5 by @yegor256: #52 less deps
    • dba77a7a9b89785c9feaedc40de3260aa1b47290 by @yegor256: Merge pull request #51 from ye...
    • 5d6b2e244f47270123a352a1d56a7fc52bb9cf4c by @yegor256: new version in README
    • 72c54f4739e3af1ee98231cbb81d25942cd892c4 by @yegor256: Merge pull request #50 from ye...

    Released by Rultor 1.74.7, see build log

    Source code(tar.gz)
    Source code(zip)
  • 0.0.7(Apr 26, 2023)

    See #39, release log:

    • 4cd44fbbd0ec5b303d218b708c1cefe7145ab2ef by @yegor256: Merge pull request #49 from ye...
    • 3351b72ac0f2aa203d48c8cd8eab02a35ab5213b by @yegor256: new benchmark results
    • f095cd972b7dcb7eac99de99675ae601efb260b7 by @yegor256: allocation fix
    • 2c8507be590dd5bc546224f24ca2bafc4e5ea9e4 by @yegor256: error with sizing
    • f529169155683a5dcf0ac689e8747744c3bea4ac by @yegor256: dont drop
    • e0b04bb3a7074bd4bc4f291a8d09c8ed954435be by @yegor256: #39 test fix
    • c073f7112fe9e6ce805334ecd3aa2cbfc162b8d7 by @yegor256: #39 println removed
    • 5a1681dccc9132e77687391086c45591d7d179ca by @yegor256: #39 init in clone
    • abe3c3b43a236242c6d8a4e17c39d9084339ee64 by @yegor256: #39 init in clone
    • b8c73961be612ca7d4e5c873ac6aab168b04dd65 by @yegor256: #39 perf fix
    • 6049f4d1fcb1a578b16fef63a0dc219672cc629c by @yegor256: #39 Map.initialized
    • 105db94bbc3e4462d16bf3802b4b4cb8aebb490a by @yegor256: #39 with_capacity
    • 42439e864d5baf9bcec9147c856c04b7021c0a06 by @yegor256: #39 cap reverted
    • 116a795763e519447399a8311d304b0655ac1410 by @yegor256: #39 cap-1
    • 2111767b15f15ede5bbcaf81188eb1739f4f3f41 by @yegor256: #39 test disabled
    • ffbaea1f54a4ad57b6010385c124377211c5f925 by @yegor256: clippy warning off
    • 3545fc8aea969a7e9ae3d7a358419c704f76daaf by @yegor256: simple check
    • 357ffd317e1502b7d2964823c5f73ef10baca872 by @yegor256: #39 check for insert, remove, ...
    • d8d9e2d5f5a855da6b7676d5481ebabcdf2026c8 by @yegor256: Merge pull request #38 from ye...
    • 1e6c352fc1ea64a8a01152143772d3f047886e72 by @yegor256: new benchmark results
    • and 3 more...

    Released by Rultor 1.74.7, see build log

    Source code(tar.gz)
    Source code(zip)
  • 0.0.6(Apr 26, 2023)

    See #36, release log:

    • 7fbc4552305efc5d100a74e229076bcca463d619 by @yegor256: #36 next_key_gte()
    • 78170a6954ace9b3bf7843eaa476d6ba45a5d874 by @yegor256: Merge pull request #35 from ye...
    • 182c4edc190113aa5c2cdd331fa614768f6d5fd5 by @yegor256: new benchmark results
    • 86d1d6a82932357bd43d991915f9ef141b732c2f by @yegor256: #31 insert test with strings
    • 2205e85776286546e6b670d5a7e1648b58ee8b79 by @yegor256: Merge pull request #34 from ye...
    • 33693ddd0811ed71188947e6af68e8f891323418 by @yegor256: new version in README
    • f854d7b5881fca1a487a498738d8457439b941b3 by @yegor256: tags fix

    Released by Rultor 1.74.7, see build log

    Source code(tar.gz)
    Source code(zip)
  • 0.0.5(Apr 26, 2023)

    See #31, release log:

    • 8d5efe50674c5b7da1aa3b2b7493940c674c1dde by @yegor256: #31 ptr::read() in keys()
    • 86b21c037ef18883860aeb50df4e16e515ee5479 by @yegor256: Merge pull request #33 from ye...
    • 2252f44324c0515c0934f210994a10836f7ba80e by @yegor256: new benchmark results
    • 1e8fa864d6bc68c7fdcfd16f921dff2a631dfda4 by @yegor256: #31 test for keys()
    • bb469bca677a889819d336c9140ece2043c72341 by @yegor256: #31 a bit faster value iterato...
    • b908a58712103bd149a82cf708e6d3a846652c6f by @yegor256: #31 key()
    • 8d641f72890f849519b88a05807e5e5387bbcb06 by @yegor256: Merge pull request #30 from ye...
    • af5d570e00e29be981eb18cc3b22b1ee0809f36f by @yegor256: new benchmark results
    • 6fb0b418391fbe8c78eae620130e8bddc2ec6b1b by @yegor256: doc
    • 1bc31748751cb94ee8c6a82ea686961ece577352 by @yegor256: values
    • ba04916e53c44bf18c29644622f87ce5bb7f46bf by @yegor256: doc
    • 901ba69947da3581dccfa78d586d8f3f67376b60 by @yegor256: Merge pull request #28 from ye...
    • 5cc13b382fe064e4cb14c14e2fd645c82950b1d3 by @rultor: new version in README

    Released by Rultor 1.74.7, see build log

    Source code(tar.gz)
    Source code(zip)
  • 0.0.4(Apr 25, 2023)

    See #25, release log:

    • 760c98b643f58b42c19afd5505bf1434bc14faee by @yegor256: 1024
    • 8aa19cda5174029f258111899bbfebf45572a1cc by @yegor256: blackbox
    • 4e770542473499500ed3eb1f0efd7c6e9a5143c0 by @yegor256: Merge pull request #24 from ye...
    • 6ebc3009521128342c2a7625f06c504ac98c7958 by @yegor256: new benchmark results
    • 27bb63000c8eadc213de502504c078c58a1c58e2 by @yegor256: ref
    • c06b1796b37d90b79b89447764d95d8e6a7209d5 by @yegor256: Option instead of Item
    • 01cc53d319de198883cd4bceeb4ddcbba943ce59 by @yegor256: Merge pull request #22 from ye...
    • ff18bf6ddc0e7f74f8b88b8ee6a276ceaa4f1703 by @yegor256: new benchmark results
    • 2a37b952d1429706746159663d325a51448fec12 by @yegor256: Merge pull request #21 from ye...
    • 059cd2acf0f125039cbbc8c945eb0723c0586c5d by @yegor256: new version in README
    • ccd375e26e0122d691f55b04a0949ab4949ff432 by @yegor256: keys by value, not by ref
    • 3e401c13088429c270a5c36d4da5d6fe63dd3f3c by @yegor256: simplified
    • 99d66f9e4d81a858ce0b11538246e04702061ad4 by @yegor256: simplified
    • 1f32127122e80ed63ba057308d0d38a376d8526d by @yegor256: ptr::write
    • 2065e8049a03c0f4ebacb54fa54f29493c97fd94 by @yegor256: ptr::write
    • 2cc5b1edbdd56ed7fc9f7ff2fce4147f840e9cf4 by @yegor256: simplified
    • 44e2ccb1141091e953018ab94eb7b7f614eda317 by @yegor256: simplified
    • 1dc75387f9a732966ddc123a950ed44951402dbd by @yegor256: simplified
    • a579ebbb27d2aa60ed1bbccedcabcca20781166c by @yegor256: less unsafe
    • 3c9d46f4499529b04fa0edec50e17b0d27d1f965 by @yegor256: Merge pull request #19 from ye...
    • and 19 more...

    Released by Rultor 1.74.7, see build log

    Source code(tar.gz)
    Source code(zip)
  • 0.0.3(Apr 25, 2023)

    See #14, release log:

    • 26605efc7882afe7a0a9e4e5bd3e11b852228dec by @yegor256: #14 protect
    • 088f18926e4f7b8f593a2be30f263c25933e36fe by @yegor256: #14 all
    • 1be124565295dd74e67ae91e59a18eb3013756e8 by @yegor256: rename
    • 0d5a2f7dfd56284a53b653095c13a0135d7a244b by @yegor256: more tests
    • 66250244e806625979d524677d87be7cc6632b89 by @yegor256: doc
    • 2267b20d68cc7a87bbdade6857b1b02338d98cb5 by @yegor256: Merge pull request #13 from ye...
    • a7ca4b07a01402d6d7e2697595f851852cb0580e by @yegor256: new benchmark results
    • 128b2afdc07431e8ce50d0b1e10af541f43f1495 by @yegor256: bench
    • f314337c43a220cf4c55b7cdfb1530588ddce3d9 by @yegor256: Merge pull request #12 from ye...
    • c269ac458093d99e444fec80466b19cc8fcda08e by @yegor256: new benchmark results
    • 6955552d07bdf0206a597d90f2128acf7436cb73 by @yegor256: test
    • a37bb58c67e8fb476ab2dae9fb1f487d3d2c804b by @yegor256: test
    • 7224f8c9f783f9ffbc07bd60c7e96d056f563399 by @yegor256: merge
    • d9f12b929fb8aa3f8cf6ae69c54a15504bf55219 by @yegor256: push
    • c47ded4a40cb0f92bbea47bbd3968dc3239030f8 by @yegor256: #3 no panic
    • ffbb6ff38fa1cf8839d66ef49da673d723169c04 by @yegor256: #3 values() and into_values()
    • 3fb374d8bdada5f631ac9e1f94e0c5a2698cd9b5 by @yegor256: #3 no panic
    • d46cde4bc310eddfffb05277a948b973c2d46fbb by @yegor256: #3 no panic
    • 26c5ca2581294cd0ffdb201b597bd02769c721f9 by @yegor256: #3 raw pointer
    • d34fea5c489e12d61bfd9a6d5cf19aeba2d43296 by @yegor256: #3 we are a bit faster than Ve...
    • and 16 more...

    Released by Rultor 1.74.7, see build log

    Source code(tar.gz)
    Source code(zip)
  • 0.0.2(Apr 23, 2023)

    See #3, release log:

    • cb794e7917790353db86ad1ecadd169a0639f29f by @yegor256: #3 assume_init()
    • 9e29682acc467328c295b10403ee8325f642fe30 by @yegor256: Merge pull request #7 from yeg...
    • 13c71e3cdb4670e765308dfa5d9b6c3fabb71050 by @yegor256: new benchmark results
    • 0ba0d48160dacd3f3218b3c005dcc5235a74f7b4 by @yegor256: #3 all-features off
    • b456e64a49b66b4afa21616133aa90b2e948c3d3 by @yegor256: #3 next_key()
    • 49feb1eb58d815b2fbd9a8419f2b7dcabf84c03d by @yegor256: #3 --all-features for tarpauli...
    • 4150b347ab7b8240354421ab1916eab8937f4b8c by @yegor256: Merge pull request #4 from yeg...
    • 6caab2010a5ae822097ecb9ce54f305065f4fd1b by @yegor256: new version in README
    • 8c698f3fa2dbc3638d36a281274253af761edee0 by @yegor256: #3 benchmark

    Released by Rultor 1.74.7, see build log

    Source code(tar.gz)
    Source code(zip)
  • 0.0.1(Apr 23, 2023)

    See #1, release log:

    • 7446871c4f95a1165f30b78a121fb603e1321548 by @yegor256: #1 test fix
    • 8e18e939ca19dcc421af4c5d35db7bb08a8d95f9 by @yegor256: #1 skeleton

    Released by Rultor 1.74.7, see build log

    Source code(tar.gz)
    Source code(zip)
Owner
Yegor Bugayenko
Author of "Elegant Objects" book series (buy them on Amazon); architect of @objectionary; founder of @zerocracy; creator of @zold-io
Yegor Bugayenko
A Rust crate that implements a range map data structure backed by a Vec.

range_map_vec This crate implements a range map data structure backed by a Vec using binary search. Docs and usage can be found in the corresponding r

Microsoft 9 Sep 8, 2023
Rust implementations of finite-field arithmetic based on big integers with configurable limb sizes

multiprecision TODO: rewrite readme implement CIOS for 16-bit limbs All operations are in little-endian form (where the digit in memory at the smalles

Geometry 4 Mar 30, 2024
Rust crates with map and set with interval keys (ranges x..y).

This crates implements map and set with interval keys (ranges x..y). IntervalMap is implemented using red-black binary tree, where each node contains

Timofey Prodanov 8 Aug 23, 2022
Tests + experiments that aim to answer questions of optimisation + what's possible w/ Rust.

rust-experiments Resources TheDevMethod: Rust YT tutorials Introduction to Rust - Part 15: Futures How to use Mutex and Atomically Reference Counted A

DeGatchi 1 Jun 17, 2022
A collection of crates to make minecraft development (client, server) with rust possible.

rust-craft rust-craft is a collection of crates to make minecraft development (client, server) with rust possible. Motivation There's no better way of

João Victor 15 Mar 23, 2023
A simpler and 5x faster alternative to HashMap in Rust, which doesn't use hashing and doesn't use heap

At least 5x faster alternative of HashMap, for very small maps. It is also faster than FxHashMap, hashbrown, ArrayMap, and nohash-hasher. The smaller

Yegor Bugayenko 12 Apr 19, 2023
Linux daemon to bind keys and macros to your controller's buttons

makima Makima is a daemon for Linux to bind your controller's buttons to key sequences and macros. Features: Configure your keybindings through a simp

null 48 Jun 14, 2023
A faster Arc.

Trc Trc is a performant heap-allocated smart pointer for Rust that implements thread reference counting. Trc stands for: Thread Reference Counted. Trc

Eric Buehler 19 Jul 12, 2023
A fast and flexible LRU map.

A fast and flexible LRU map This repository contains a fast and flexible LRU map. Blazingly fast. Up to twice as fast as the lru crate, and with less

Koute 67 Jan 1, 2023
A Rust implementation of generic prefix tree (trie) map with wildcard capture support

prefix_tree_map A Rust implementation of generic prefix tree (trie) map with wildcard capture support. Design Trie is a good data structure for storin

EAimTY 3 Dec 6, 2022