Git Product home page Git Product logo

caches-rs's Introduction

AL Liu

LinkedIn   email   email  

I am currently open to a full remote Rust software engineer position (Hong Kong on-site or Singapore (need visa sponsorship) on-site) in Blockchain Infrastructures, Distributed Database, Cloud Native platforms and etc. Reach out [email protected]

  • I am Al Liu, currently, I am coding for my dream :).
  • Rustacean. Rust is my favorite language. Zig is the language I want to learn in recent future.
  • I am interested in distributed infrastructure software development and Blockchain development.
  • Currently, I am reading the source code of NATS, pion/webrtc, and Dgraph.
  • What am I working on?
    • Blockchain Infra.
    • I am implementing multiple distributed consensus algorithms in Rust.

Projects

Network
  • memberlist: A highly customable, adaptable, runtime agnostic and WASM/WASI friendly Gossip protocol which helps manage cluster membership and member failure detection. Support QUIC, TCP/TLS/UDP.
  • ruserf: A highly customable, adaptable, runtime agnostic and WASM/WASI friendly decentralized solution for service discovery and orchestration that is lightweight, highly available, and fault tolerant.
  • WIP: ruraft: A highly customable, adaptable, runtime agnostic and WASM/WASI friendly Raft protocol implementation.
Database
  • skipdb: An embedded, in-memory, zero-copy, ACI, MVCC, almost lock-free and serializable snapshot isolation database engine.
  • skl: A lock-free thread-safe arena based skiplist impelementation for building memtable.
  • zallocator: Amortizes the cost of small allocations by allocating memory in bigger chunks.
  • fmmap: A flexible and convenient high-level mmap for zero-copy file I/O.
  • fs4: Extended utilities for working with files and filesystems in Rust. This is a fork of the fs2-rs crate, the aim for this fork is to support async and replace libc with rustix.
  • memmapix: A pure Rust library for cross-platform memory mapped IO, which replace libc with rustix.
Cache
  • stretto: A high performance thread-safe memory-bound Rust cache.
  • caches: This is a Rust implementation for popular caches (support no_std).
Development Tools
  • atomic-time: Atomic version std::time implementation.
  • wg: Golang like WaitGroup and AsyncWaitGroup implementation for sync/async Rust.

Wekatime States(Since May 12, 2021)

al8n

Languages and Tools

rust go dart javascript typescript python

al8n

Top Repositories

caches-rs's People

Contributors

al8n avatar direktor799 avatar flub avatar jaykickliter avatar pantsman0 avatar stevefan1999-personal avatar vlovich avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

caches-rs's Issues

Fix `miri test`

To improve the quality of this crate, we need all test cases pass cargo miri test.

WTinyLFUCache panics with misaligned pointer dereference in debug builds

Rust now checks for misaligned pointer access in debug builds, which it seems WTinyLFUCache is always doing.

% rustc -Vv
rustc 1.72.1 (d5c2e9c34 2023-09-13)
binary: rustc
commit-hash: d5c2e9c342b358556da91d61ed4133f6f50fc0c3
commit-date: 2023-09-13
host: aarch64-apple-darwin
release: 1.72.1
LLVM version: 16.0.5

(edit: note my host is aarch64, but this issue was also observed on an x86_64 Linux machine)

use caches::{
    Cache,
    WTinyLFUCache,
};

fn main() {
    let mut cache = WTinyLFUCache::<String, i64>::with_sizes(6, 4, 10, 5).unwrap();
    cache.get(&"blah".to_owned());
}
thread 'main' panicked at 'misaligned pointer dereference: address must be a multiple of 0x8 but is 0x600002110252', /Users/wfraser/.cargo/registry/src/index.crates.io-6f17d22bba15001f/caches-0.2.4/src/lfu/tinylfu/bloom.rs:109:22
stack backtrace:
   0: rust_begin_unwind
             at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/panicking.rs:593:5
   1: core::panicking::panic_nounwind_fmt
             at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/core/src/panicking.rs:96:14
   2: core::panicking::panic_misaligned_pointer_dereference
             at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/core/src/panicking.rs:175:5
   3: caches::lfu::tinylfu::bloom::Bloom::is_set
             at /Users/wfraser/.cargo/registry/src/index.crates.io-6f17d22bba15001f/caches-0.2.4/src/lfu/tinylfu/bloom.rs:109:22
   4: caches::lfu::tinylfu::bloom::Bloom::contains
             at /Users/wfraser/.cargo/registry/src/index.crates.io-6f17d22bba15001f/caches-0.2.4/src/lfu/tinylfu/bloom.rs:130:17
   5: caches::lfu::tinylfu::bloom::Bloom::contains_or_add
             at /Users/wfraser/.cargo/registry/src/index.crates.io-6f17d22bba15001f/caches-0.2.4/src/lfu/tinylfu/bloom.rs:141:12
   6: caches::lfu::tinylfu::TinyLFU<K,KH>::increment
             at /Users/wfraser/.cargo/registry/src/index.crates.io-6f17d22bba15001f/caches-0.2.4/src/lfu/tinylfu.rs:220:13
   7: <caches::lfu::wtinylfu::WTinyLFUCache<K,V,KH,FH,RH,WH> as caches::cache_api::Cache<K,V>>::get
             at /Users/wfraser/.cargo/registry/src/index.crates.io-6f17d22bba15001f/caches-0.2.4/src/lfu/wtinylfu.rs:550:9
   8: super_simple::main
             at ./src/main.rs:8:5
   9: core::ops::function::FnOnce::call_once
             at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
thread caused non-unwinding panic. aborting.

How do you choose a sample size for the cache ?

Is there a strategy for choosing the sample size for the cache ? Based on the example provided its the sum of all windows, but just wanted to check if there's a suggested way to choose the sample size, and what are the implications for choosing a bigger or smaller sample size ?

The parameter I am talking about is the one passed to the WTinyLFUCache::with_sizes function

pub fn with_sizes(
    window_cache_size: usize,
    protected_cache_size: usize,
    probationary_cache_size: usize,
    samples: usize
) -> Result<Self, WTinyLFUError>

Buggy behavior on ARC

let mut ent = self.recent_evict.map.remove(&key_ref).unwrap();

Seems to be buggy.

running 1 test
thread 'limited_cache::test::test_get_or_insert_default_and_edit_evicts_old_items_to_meet_capacity' panicked at C:\Users\steve\scoop\persist\rustup\.cargo\git\checkouts\caches-rs-f5b438d840965066\ff4eb24\src\lru\adaptive.rs:384:66:
called `Option::unwrap()` on a `None` value
stack backtrace:
   0: std::panicking::begin_panic_handler
             at /rustc/58eefc33adf769a1abe12ad94b3e6811185b4ce5/library\std\src\panicking.rs:617
   1: core::panicking::panic_fmt
             at /rustc/58eefc33adf769a1abe12ad94b3e6811185b4ce5/library\core\src\panicking.rs:67
   2: core::panicking::panic
             at /rustc/58eefc33adf769a1abe12ad94b3e6811185b4ce5/library\core\src\panicking.rs:117
   3: enum2$<core::option::Option<alloc::boxed::Box<caches::lru::raw::EntryNode<alloc::string::String,usize>,alloc::alloc::Global> > >::unwrap<alloc::boxed::Box<caches::lru::raw::EntryNode<alloc::string::String,usize>,alloc::alloc::Global> >
             at /rustc/58eefc33adf769a1abe12ad94b3e6811185b4ce5\library\core\src\option.rs:935
   4: caches::lru::adaptive::impl$4::put<alloc::string::String,usize,ahash::random_state::RandomState,ahash::random_state::RandomState,ahash::random_state::RandomState,ahash::random_state::RandomState>
             at C:\Users\steve\scoop\persist\rustup\.cargo\git\checkouts\caches-rs-f5b438d840965066\ff4eb24\src\lru\adaptive.rs:384
   5: rustls::limited_cache::LimitedCache<alloc::string::String,usize>::get_or_insert_default_and_edit<alloc::string::String,usize,rustls::limited_cache::test::test_get_or_insert_default_and_edit_evicts_old_items_to_meet_capacity::closure_env$4>
             at .\src\limited_cache.rs:38
   6: rustls::limited_cache::test::test_get_or_insert_default_and_edit_evicts_old_items_to_meet_capacity
             at .\src\limited_cache.rs:180
   7: rustls::limited_cache::test::test_get_or_insert_default_and_edit_evicts_old_items_to_meet_capacity::closure$0
             at .\src\limited_cache.rs:165
   8: core::ops::function::FnOnce::call_once<rustls::limited_cache::test::test_get_or_insert_default_and_edit_evicts_old_items_to_meet_capacity::closure_env$0,tuple$<> >
             at /rustc/58eefc33adf769a1abe12ad94b3e6811185b4ce5\library\core\src\ops\function.rs:250
   9: core::ops::function::FnOnce::call_once
             at /rustc/58eefc33adf769a1abe12ad94b3e6811185b4ce5/library\core\src\ops\function.rs:250
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
test limited_cache::test::test_get_or_insert_default_and_edit_evicts_old_items_to_meet_capacity ... FAILED

failures:

failures:
    limited_cache::test::test_get_or_insert_default_and_edit_evicts_old_items_to_meet_capacity

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 189 filtered out; finished in 0.07s
    #[test]
    fn test_get_or_insert_default_and_edit_evicts_old_items_to_meet_capacity() {
        let mut t = Test::new(3);

        t.get_or_insert_default_and_edit("abc".into(), |v| *v += 1);
        t.get_or_insert_default_and_edit("def".into(), |v| *v += 2);

        // evicts "abc"
        t.get_or_insert_default_and_edit("ghi".into(), |v| *v += 3);
        assert_eq!(t.get("abc"), None);

        // evicts "def"
        t.get_or_insert_default_and_edit("jkl".into(), |v| *v += 4);
        assert_eq!(t.get("def"), None);

        // evicts "ghi"
        t.get_or_insert_default_and_edit("abc".into(), |v| *v += 5);
        assert_eq!(t.get("ghi"), None);

        // evicts "jkl"
        t.get_or_insert_default_and_edit("def".into(), |v| *v += 6);

        assert_eq!(t.get("abc"), Some(&5));
        assert_eq!(t.get("def"), Some(&6));
        assert_eq!(t.get("ghi"), None);
        assert_eq!(t.get("jkl"), None);
    }
pub(crate) struct LimitedCache<K: Clone + Hash + Eq, V> {
    map: AdaptiveCache<K, V>,
}

impl<K, V> LimitedCache<K, V>
where
    K: Eq + Hash + Clone + core::fmt::Debug,
    V: Default,
{
    /// Create a new LimitedCache with the given rough capacity.
    pub(crate) fn new(capacity_order_of_magnitude: usize) -> Self {
        Self {
            map: AdaptiveCache::new(capacity_order_of_magnitude - 1).unwrap(),
        }
    }

    pub(crate) fn get_or_insert_default_and_edit(&mut self, k: K, edit: impl FnOnce(&mut V)) {
        if self.map.contains(&k) {
            edit(self.map.get_mut(&k).unwrap());
        } else {
            let mut val = V::default();
            edit(&mut val);

            // TODO: there seems to have a bug on caches-rs where if the key was recently removed
            self.map.remove(&k);
            self.map.put(k, val);
        }
    }

    pub(crate) fn insert(&mut self, k: K, v: V) {
        self.map.put(k, v);
    }

    pub(crate) fn get<'a, Q: ?Sized>(&'a mut self, k: &'a Q) -> Option<&V>
    where
        K: Borrow<Q>,
        KeyRef<K>: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.map.get(k)
    }

    pub(crate) fn get_mut<'a, Q: ?Sized>(&'a mut self, k: &'a Q) -> Option<&mut V>
    where
        K: Borrow<Q>,
        KeyRef<K>: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.map.get_mut(k)
    }

    pub(crate) fn remove<'a, Q: ?Sized>(&'a mut self, k: &'a Q) -> Option<V>
    where
        K: Borrow<Q>,
        KeyRef<K>: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.map.remove(k)
    }
}

Hidden KeyRef type complicates key lookup

Because keys are stored inside a KeyRef type, .get() can be complicated or inefficient. For instance, if I have a cache which stores the key as a Vec<u8>, I'd expect to be able to lookup a value a in the cache using a &[u8], but that's not possible:

error[E0277]: the trait bound `KeyRef<Vec<u8>>: Borrow<[u8]>` is not satisfied
  --> native/lib.rs:98:17
   |
98 |     match cache.get(key.as_slice()) {
   |                 ^^^ the trait `Borrow<[u8]>` is not implemented for `KeyRef<Vec<u8>>`
   |
   = help: the following implementations were found:
             <KeyRef<K> as Borrow<K>>

Many methods return lifetimes that are not tied to the lifetime of self

These use &'_ self when they should use &'a self (resp. mut).

Sample program that segfaults when it shouldn't compile:

//! ```cargo
//! [dependencies]
//! caches = { version = "0.2" }
//! ```

use caches::{Cache, RawLRU};

fn main() {
    let mut lru = RawLRU::new(2).unwrap();
    lru.put(1, "foo".to_string());
    lru.put(2, "bar".to_string());
    let iter = lru.iter();
    drop(lru);
    println!("{:?}", iter.collect::<Vec<_>>());
}

no_std compatability

How do you get the crate to compile in no_std environments?

running cargo check --no-default-features --features hashbrown give the following error importing std:

error[E0433]: failed to resolve: use of undeclared crate or module `std`
 --> src\lfu\tinylfu\bloom.rs:9:19
  |
9 | const LN_2: f64 = std::f64::consts::LN_2;
  |                   ^^^ use of undeclared crate or module `std`
  |
help: consider importing one of these items
  |
7 + use core::f32::consts;
  |
7 + use core::f64::consts;
  |
help: if you import `consts`, refer to it directly
  |
9 - const LN_2: f64 = std::f64::consts::LN_2;
9 + const LN_2: f64 = consts::LN_2;
  |

error[E0599]: no method named `clone` found for struct `CountMinSketch` in the current scope
   --> src\lfu\tinylfu.rs:156:27
    |
156 |             ctr: self.ctr.clone(),
    |                           ^^^^^ method not found in `CountMinSketch`
    |
   ::: src\lfu\tinylfu\sketch\count_min_sketch_core.rs:16:1
    |
16  | pub(crate) struct CountMinSketch {
    | -------------------------------- method `clone` not found for this struct
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
            candidate #1: `Clone`

Some errors have detailed explanations: E0433, E0599.
For more information about an error, try `rustc --explain E0433`.
error: could not compile `caches` (lib) due to 2 previous errors```

Running without `--features hashbrown` gives even more errors, enough that my terminal cut of the history.
https://gist.github.com/pantsman0/4d9e0178ba6270ef1e1915c39b1e3e75

bare metal support

According to #20 I understand this should be no_std compatible, but for me it seems like it isn't.

I'm on x86_64-unknown-none (no_std, alloc), and I'm using the dependency as follows.
caches = { git = "https://github.com/al8n/caches-rs", default-features = false, features = ["hashbrown"] } (bd2816c).
If I don't use the hashbrown feature, I get an error because of extern crate hashbrown.

I tried the latest commit (bd2816c) since I've noticed the new version 0.2.9 which is not published yet, but even with adding libm as dependency (and extern crate libm), I still get:

error[E0432]: unresolved import `libm`
  --> ~/.cargo/git/checkouts/caches-rs-c5090a8b4544925b/bd2816c/src/polyfill.rs:23:13
   |
23 |         use libm;
   |             ^^^^ no external crate `libm`

Is there anything I am missing?
Is there anything that can be done so I can use this library with no_std on x86_64-unknown-none?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.