Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support array-style syntax for setting stack arena size per-callsite #9

Closed
tnballo opened this issue Nov 2, 2021 · 2 comments
Closed
Labels
enhancement New feature or request

Comments

@tnballo
Copy link
Owner

tnballo commented Nov 2, 2021

The current method for setting stack arena size via the SG_MAX_STACK_ELEMS environment variable has the advantage of keeping APIs compatible with BTreeMap/BTreeSet. For example, a new map can be declared in the usual way:

let map: SGMap<usize, usize> = SGMap::new();
assert_eq!(map.capacity(), 1024); // Assuming `SG_MAX_STACK_ELEMS == 1024` (default)

But this has the disadvantage of being a fixed, global setting. It'd be awesome if we could additionally support the array-style type declaration syntax used by crates like smallvec and tinyvec. This would allow unique stack arena sizes for each callsite, like so:

let default_map: SGMap<usize, usize> = SGMap::new();
assert_eq!(default_map.capacity(), 1024); // Assuming `SG_MAX_STACK_ELEMS == 1024` (default)

let little_map: SGMap<[(usize, usize); 256]> = SGMap::new();
assert_eq!(little_map.capacity(), 256);

let big_map: SGMap<[(usize, usize); 8192]> = SGMap::new();
assert_eq!(big_map.capacity(), 8192);

Making this change will require a little refactoring, the types in src/tree/types.rs would likely have to become associated with the SGTree struct instead of being global?

@tnballo tnballo added the enhancement New feature or request label Nov 2, 2021
@tnballo
Copy link
Owner Author

tnballo commented Nov 10, 2021

Or a with_capacity constructor - potentially more ergonomic to use and cleaner to implement. Ex:

let little_map: SGMap<usize, usize> = SGMap::with_capacity(256);
assert_eq!(little_map.capacity(), 256);

@tnballo
Copy link
Owner Author

tnballo commented Dec 12, 2021

Branch v2.0.0 (release WIP) addresses this with const generics like so:

use core::mem::size_of_val;
use scapegoat::SGMap;

let small_map: SGMap<u64, u64, 100> = SGMap::new(); // 100 item capacity
let big_map: SGMap<u64, u64, 2_048> = SGMap::new(); // 2,048 item capacity

#[cfg(target_pointer_width = "64")]
{
    assert_eq!(size_of_val(&small_map), 2_696); // 2.7 KB
    assert_eq!(size_of_val(&big_map), 53_344);  // 53.3 KB
}

A bit of experimentation and research led to this design being the best solution!

@tnballo tnballo mentioned this issue Dec 16, 2021
@tnballo tnballo closed this as completed Dec 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant