Files
addr2line
adler
aead
aes
aes_gcm
aes_soft
ahash
aho_corasick
ansi_term
anyhow
approx
arrayref
arrayvec
asn1_der
asn1_der_derive
async_channel
async_executor
async_global_executor
async_io
async_mutex
async_process
async_std
collections
fs
future
io
net
option
os
path
pin
result
rt
stream
string
sync
task
unit
vec
async_task
async_trait
asynchronous_codec
atomic
atomic_waker
atty
backtrace
base58
base64
base_x
bincode
bip39
bitflags
bitvec
blake2
blake2_rfc
blake2b_simd
blake2s_simd
blake3
block_buffer
block_cipher
block_padding
blocking
bs58
bstr
bumpalo
byte_slice_cast
byteorder
bytes
cache_padded
cfg_if
chacha20
chacha20poly1305
chrono
cid
cipher
clap
concurrent_queue
const_fn
constant_time_eq
cpp_demangle
cpuid_bool
cranelift_bforest
cranelift_codegen
cranelift_codegen_shared
cranelift_entity
cranelift_frontend
cranelift_native
cranelift_wasm
crc32fast
crossbeam_channel
crossbeam_deque
crossbeam_epoch
crossbeam_utils
crunchy
crypto_mac
ct_logs
cuckoofilter
curve25519_dalek
data_encoding
data_encoding_macro
data_encoding_macro_internal
derive_more
digest
directories
directories_next
dirs_sys
dirs_sys_next
dns_parser
dyn_clonable
dyn_clonable_impl
dyn_clone
ed25519
ed25519_dalek
either
env_logger
environmental
erased_serde
errno
event_listener
exit_future
failure
failure_derive
fallible_iterator
fastrand
fdlimit
file_per_thread_logger
finality_grandpa
fixed_hash
flate2
fnv
fork_tree
form_urlencoded
frame_benchmarking
frame_benchmarking_cli
frame_executive
frame_metadata
frame_support
frame_support_procedural
frame_support_procedural_tools
frame_support_procedural_tools_derive
frame_system
frame_system_rpc_runtime_api
fs_swap
funty
futures
futures_channel
futures_core
futures_diagnose
futures_executor
futures_io
futures_lite
futures_macro
futures_rustls
futures_sink
futures_task
futures_timer
futures_util
async_await
compat
future
io
lock
sink
stream
task
generic_array
getrandom
ghash
gimli
globset
h2
handlebars
hash256_std_hasher
hash_db
hashbrown
heck
hex
hex_fmt
hmac
hmac_drbg
http
http_body
httparse
httpdate
humantime
hyper
hyper_rustls
idna
if_watch
impl_codec
impl_serde
impl_trait_for_tuples
indexmap
inflector
cases
camelcase
case
classcase
kebabcase
pascalcase
screamingsnakecase
sentencecase
snakecase
tablecase
titlecase
traincase
numbers
deordinalize
ordinalize
string
constants
deconstantize
demodulize
pluralize
singularize
suffix
foreignkey
instant
integer_sqrt
intervalier
iovec
ip_network
ipnet
itertools
itoa
js_sys
jsonrpc_client_transports
jsonrpc_core
jsonrpc_core_client
jsonrpc_derive
jsonrpc_http_server
jsonrpc_ipc_server
jsonrpc_pubsub
jsonrpc_server_utils
jsonrpc_ws_server
keccak
kv_log_macro
kvdb
kvdb_memorydb
kvdb_rocksdb
lazy_static
lazycell
leb128
libc
libm
libp2p
libp2p_core
libp2p_core_derive
libp2p_deflate
libp2p_dns
libp2p_floodsub
libp2p_gossipsub
libp2p_identify
libp2p_kad
libp2p_mdns
libp2p_mplex
libp2p_noise
libp2p_ping
libp2p_plaintext
libp2p_pnet
libp2p_request_response
libp2p_swarm
libp2p_tcp
libp2p_uds
libp2p_wasm_ext
libp2p_websocket
libp2p_yamux
librocksdb_sys
libz_sys
linked_hash_map
linked_hash_set
linregress
lock_api
log
lru
maplit
matchers
matches
matrixmultiply
memchr
memmap2
memoffset
memory_db
memory_units
merlin
minicbor
minicbor_derive
miniz_oxide
mio
mio_extras
mio_named_pipes
mio_uds
miow
more_asserts
multibase
multihash
multihash_derive
multistream_select
nalgebra
base
geometry
linalg
names
nb_connect
net2
node_template
node_template_runtime
nohash_hasher
num_bigint
num_complex
num_cpus
num_integer
num_rational
num_traits
object
once_cell
opaque_debug
openssl_probe
owning_ref
pallet_aura
pallet_authorship
pallet_balances
pallet_collection
pallet_exchange
pallet_grandpa
pallet_graph
pallet_nft
pallet_nftdao
pallet_randomness_collective_flip
pallet_session
pallet_sub
pallet_sudo
pallet_timestamp
pallet_transaction_payment
pallet_transaction_payment_rpc
pallet_transaction_payment_rpc_runtime_api
parity_db
parity_multiaddr
parity_scale_codec
parity_scale_codec_derive
parity_send_wrapper
parity_tokio_ipc
parity_util_mem
parity_util_mem_derive
parity_wasm
parity_ws
parking
parking_lot
parking_lot_core
paste
paste_impl
pbkdf2
pdqselect
percent_encoding
pest
pest_derive
pest_generator
pest_meta
pin_project
pin_project_lite
pin_utils
polling
poly1305
polyval
ppv_lite86
primitive_types
proc_macro2
proc_macro_crate
proc_macro_error
proc_macro_error_attr
proc_macro_hack
proc_macro_nested
prometheus
prost
prost_derive
psm
pwasm_utils
quick_error
quicksink
quote
radium
rand
rand_chacha
rand_core
rand_distr
raw_cpuid
rawpointer
rayon
rayon_core
ref_cast
ref_cast_impl
regalloc
regex
regex_automata
regex_syntax
region
remove_dir_all
retain_mut
ring
rocksdb
rpassword
rustc_demangle
rustc_hash
rustc_hex
rustls
rustls_native_certs
rw_stream_sink
ryu
safe_mix
salsa20
sc_basic_authorship
sc_block_builder
sc_chain_spec
sc_chain_spec_derive
sc_cli
sc_client_api
sc_client_db
sc_consensus
sc_consensus_aura
sc_consensus_babe
sc_consensus_epochs
sc_consensus_slots
sc_consensus_uncles
sc_executor
sc_executor_common
sc_executor_wasmi
sc_executor_wasmtime
sc_finality_grandpa
sc_informant
sc_keystore
sc_light
sc_network
sc_network_gossip
sc_offchain
sc_peerset
sc_proposer_metrics
sc_rpc
sc_rpc_api
sc_rpc_server
sc_service
sc_state_db
sc_telemetry
sc_tracing
sc_tracing_proc_macro
sc_transaction_graph
sc_transaction_pool
schnorrkel
scoped_tls
scopeguard
scroll
scroll_derive
sct
secp256k1
secrecy
serde
serde_derive
serde_json
sha1
sha2
sha3
sharded_slab
signal_hook
signal_hook_registry
signature
simba
slab
smallvec
snow
socket2
soketto
sp_allocator
sp_api
sp_api_proc_macro
sp_application_crypto
sp_arithmetic
sp_authorship
sp_block_builder
sp_blockchain
sp_chain_spec
sp_consensus
sp_consensus_aura
sp_consensus_babe
sp_consensus_slots
sp_consensus_vrf
sp_core
sp_database
sp_debug_derive
sp_externalities
sp_finality_grandpa
sp_inherents
sp_io
sp_keyring
sp_keystore
sp_offchain
sp_panic_handler
sp_rpc
sp_runtime
sp_runtime_interface
sp_runtime_interface_proc_macro
sp_serializer
sp_session
sp_staking
sp_state_machine
sp_std
sp_storage
sp_tasks
sp_timestamp
sp_tracing
sp_transaction_pool
sp_trie
sp_utils
sp_version
sp_wasm_interface
spin
stable_deref_trait
static_assertions
statrs
stream_cipher
strsim
structopt
structopt_derive
strum
strum_macros
substrate_bip39
substrate_fixed
substrate_frame_rpc_system
substrate_prometheus_endpoint
subtle
syn
synstructure
take_mut
tap
target_lexicon
tempfile
termcolor
textwrap
thiserror
thiserror_impl
thread_local
threadpool
time
tiny_keccak
tinyvec
tinyvec_macros
tokio
future
io
loom
macros
net
park
runtime
signal
stream
sync
task
time
util
tokio_codec
tokio_executor
tokio_io
tokio_named_pipes
tokio_reactor
tokio_rustls
tokio_service
tokio_sync
tokio_uds
tokio_util
toml
tower_service
tracing
tracing_attributes
tracing_core
tracing_futures
tracing_log
tracing_serde
tracing_subscriber
trie_db
trie_root
try_lock
twox_hash
typenum
ucd_trie
uint
unicase
unicode_bidi
unicode_normalization
unicode_segmentation
unicode_width
unicode_xid
universal_hash
unsigned_varint
untrusted
url
vec_arena
vec_map
void
waker_fn
want
wasm_bindgen
wasm_bindgen_backend
wasm_bindgen_futures
wasm_bindgen_macro
wasm_bindgen_macro_support
wasm_bindgen_shared
wasm_timer
wasmi
wasmi_validation
wasmparser
wasmtime
wasmtime_cache
wasmtime_cranelift
wasmtime_debug
wasmtime_environ
wasmtime_jit
wasmtime_obj
wasmtime_profiling
wasmtime_runtime
wast
wat
webpki
webpki_roots
winapi
wyz
x25519_dalek
yamux
zeroize
zeroize_derive
zstd
zstd_safe
zstd_sys
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// This module exists only to provide a separate page for the implementation
// documentation.

//! Notes on `sharded-slab`'s implementation and design.
//!
//! # Design
//!
//! The sharded slab's design is strongly inspired by the ideas presented by
//! Leijen, Zorn, and de Moura in [Mimalloc: Free List Sharding in
//! Action][mimalloc]. In this report, the authors present a novel design for a
//! memory allocator based on a concept of _free list sharding_.
//!
//! Memory allocators must keep track of what memory regions are not currently
//! allocated ("free") in order to provide them to future allocation requests.
//! The term [_free list_][freelist] refers to a technique for performing this
//! bookkeeping, where each free block stores a pointer to the next free block,
//! forming a linked list. The memory allocator keeps a pointer to the most
//! recently freed block, the _head_ of the free list. To allocate more memory,
//! the allocator pops from the free list by setting the head pointer to the
//! next free block of the current head block, and returning the previous head.
//! To deallocate a block, the block is pushed to the free list by setting its
//! first word to the current head pointer, and the head pointer is set to point
//! to the deallocated block. Most implementations of slab allocators backed by
//! arrays or vectors use a similar technique, where pointers are replaced by
//! indices into the backing array.
//!
//! When allocations and deallocations can occur concurrently across threads,
//! they must synchronize accesses to the free list; either by putting the
//! entire allocator state inside of a lock, or by using atomic operations to
//! treat the free list as a lock-free structure (such as a Treiber stack). In
//! both cases, there is a significant performance cost — even when the free
//! list is lock-free, it is likely that a noticeable amount of time will be
//! spent in compare-and-swap loops. Ideally, the global synchronzation point
//! created by the single global free list could be avoided as much as possible.
//!
//! The approach presented by Leijen, Zorn, and de Moura is to introduce
//! sharding and thus increase the granularity of synchronization significantly.
//! In mimalloc, the heap is _sharded_ so that each thread has its own
//! thread-local heap. Objects are always allocated from the local heap of the
//! thread where the allocation is performed. Because allocations are always
//! done from a thread's local heap, they need not be synchronized.
//!
//! However, since objects can move between threads before being deallocated,
//! _deallocations_ may still occur concurrently. Therefore, Leijen et al.
//! introduce a concept of _local_ and _global_ free lists. When an object is
//! deallocated on the same thread it was originally allocated on, it is placed
//! on the local free list; if it is deallocated on another thread, it goes on
//! the global free list for the heap of the thread from which it originated. To
//! allocate, the local free list is used first; if it is empty, the entire
//! global free list is popped onto the local free list. Since the local free
//! list is only ever accessed by the thread it belongs to, it does not require
//! synchronization at all, and because the global free list is popped from
//! infrequently, the cost of synchronization has a reduced impact. A majority
//! of allocations can occur without any synchronization at all; and
//! deallocations only require synchronization when an object has left its
//! parent thread (a relatively uncommon case).
//!
//! [mimalloc]: https://www.microsoft.com/en-us/research/uploads/prod/2019/06/mimalloc-tr-v1.pdf
//! [freelist]: https://en.wikipedia.org/wiki/Free_list
//!
//! # Implementation
//!
//! A slab is represented as an array of [`MAX_THREADS`] _shards_. A shard
//! consists of a vector of one or more _pages_ plus associated metadata.
//! Finally, a page consists of an array of _slots_, head indices for the local
//! and remote free lists.
//! ```text
//! ┌─────────────┐
//! │ shard 1     │
//! │             │    ┌─────────────┐        ┌────────┐
//! │ pages───────┼───▶│ page 1      │        │        │
//! ├─────────────┤    ├─────────────┤  ┌────▶│  next──┼─┐
//! │ shard 2     │    │ page 2      │  │     ├────────┤ │
//! ├─────────────┤    │             │  │     │XXXXXXXX│ │
//! │ shard 3     │    │ local_head──┼──┘     ├────────┤ │
//! └─────────────┘    │ remote_head─┼──┐     │        │◀┘
//!       ...          ├─────────────┤  │     │  next──┼─┐
//! ┌─────────────┐    │   page 3    │  │     ├────────┤ │
//! │ shard n     │    └─────────────┘  │     │XXXXXXXX│ │
//! └─────────────┘          ...        │     ├────────┤ │
//!                    ┌─────────────┐  │     │XXXXXXXX│ │
//!                    │ page n      │  │     ├────────┤ │
//!                    └─────────────┘  │     │        │◀┘
//!                                     └────▶│  next──┼───▶  ...
//!                                           ├────────┤
//!                                           │XXXXXXXX│
//!                                           └────────┘
//! ```
//!
//! The size of the first page in a shard is always a power of two, and every
//! subsequent page added after the first is twice as large as the page that
//! preceeds it.
//! ```text
//!
//!  pg.
//! ┌───┐   ┌─┬─┐
//! │ 0 │───▶ │ │
//! ├───┤   ├─┼─┼─┬─┐
//! │ 1 │───▶ │ │ │ │
//! ├───┤   ├─┼─┼─┼─┼─┬─┬─┬─┐
//! │ 2 │───▶ │ │ │ │ │ │ │ │
//! ├───┤   ├─┼─┼─┼─┼─┼─┼─┼─┼─┬─┬─┬─┬─┬─┬─┬─┐
//! │ 3 │───▶ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
//! └───┘   └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
//! ```
//! When searching for a free slot, the smallest page is searched first, and if
//! it is full, the search proceeds to the next page until either a free slot is
//! found or all available pages have been searched. If all available pages have
//! been searched and the maximum number of pages has not yet been reached, a
//! new page is then allocated.
//!
//! Since every page is twice as large as the previous page, and all page sizes
//! are powers of two, we can determine the page index that contains a given
//! address by shifting the address down by the smallest page size and
//! looking at how many twos places necessary to represent that number,
//! telling us what power of two page size it fits inside of. We can
//! determine the number of twos places by counting the number of leading
//! zeros (unused twos places) in the number's binary representation, and
//! subtracting that count from the total number of bits in a word.
//!
//! The formula for determining the page number that contains an offset is thus:
//! ```rust,ignore
//! WIDTH - ((offset + INITIAL_PAGE_SIZE) >> INDEX_SHIFT).leading_zeros()
//! ```
//! where `WIDTH` is the number of bits in a `usize`, and `INDEX_SHIFT` is
//! ```rust,ignore
//! INITIAL_PAGE_SIZE.trailing_zeros() + 1;
//!```
//![`MAX_THREADS`]: ../trait.Config.html#associatedconstant.MAX_THREADS