Skip to content

Commit

Permalink
misc: combine with enhancements from dfaust and CeleritasCelery (#2)
Browse files Browse the repository at this point in the history
Adds the enhancements proposed by:
- DKerp/get-size#11
- DKerp/get-size#13

Also adds support for `uuid`, `dashmap` and `serde_json`.
  • Loading branch information
nicmue authored Oct 26, 2023
1 parent 531b307 commit d33e44b
Show file tree
Hide file tree
Showing 14 changed files with 494 additions and 315 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
.DS_Store

/target
Cargo.lock

/get-size-derive/target
/get-size-derive/Cargo.lock
26 changes: 16 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
[package]
name = "get-size"
categories = ["memory-management", "caching"]
description = "Determine the size in bytes an object occupies inside RAM."
version = "0.1.4"
edition = "2021"
authors = ["Denis Kerp"]
readme = "README.md"
repository = "https://github.com/DKerp/get-size"
license = "MIT"
keywords = ["size", "heap", "ram", "cache", "memory"]
categories = ["memory-management", "caching"]
license = "MIT"
name = "get-size"
readme = "README.md"
version = "0.2.0"

[dependencies]
# get-size-derive = { version = "^0.1.3", optional = true }
get-size-derive = { path = "get-size-derive", optional = true }
dashmap = { version = "5", optional = true }
get-size-derive = { path = "./get-size-derive", optional = true }
serde_json = { version = "1", optional = true }
uuid = { version = "1", optional = true }

[dev-dependencies]
get-size = { path = ".", features = ["derive"] }
get-size = { path = ".", features = ["full"] }

[features]
default = []

full = ["derive", "dashmap", "serde_json", "uuid"]

dashmap = ["dep:dashmap"]
derive = ["get-size-derive"]
serde_json = ["dep:serde_json"]
uuid = ["dep:uuid"]

[package.metadata.docs.rs]
all-features = true
Expand Down
72 changes: 36 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,22 @@ The [`GetSize`] trait can be used to determine the size of an object inside the
We use [`GetSize`] to determine number of bytes occupied by both a `String` and a `Vec` of bytes. Note that the `Vec` has already allocated a capacity of `1024` bytes, and does thus correctly show a heap size of `1024`, even if only `1` byte is currently in use.

```rust
use get_size::GetSize;
use get_size::{GetSize, GetSizeNoTracker};

fn main() {
let value = String::from("Hello World!");

assert_eq!(String::get_stack_size(), std::mem::size_of::<String>());
assert_eq!(value.get_heap_size(), 12);
assert_eq!(value.get_heap_size(&mut GetSizeNoTracker), 12);

assert_eq!(value.get_size(), std::mem::size_of::<String>() + 12);
assert_eq!(value.get_size(&mut GetSizeNoTracker), std::mem::size_of::<String>() + 12);


let mut buffer = Vec::with_capacity(1024); // 1KB allocated on the heap.
buffer.push(1u8); // 1 byte in use.

assert_eq!(buffer.len(), 1);
assert_eq!(buffer.get_heap_size(), 1024);
assert_eq!(buffer.get_heap_size(&mut GetSizeNoTracker), 1024);
}
```

Expand All @@ -39,7 +39,7 @@ This library follows the idea that only bytes owned by a certain object should b
##### Example

```rust
use get_size::GetSize;
use get_size::{GetSize, GetSizeNoTracker};

#[derive(GetSize)]
struct Test<'a> {
Expand All @@ -51,14 +51,14 @@ fn main() {

// This string occupies 5 bytes at the heap, but a pointer is treated as not occupying
// anything at the heap.
assert_eq!(value.get_heap_size(), 5);
assert_eq!(GetSize::get_heap_size(&&value), 0); // Fully qualified syntax
assert_eq!(value.get_heap_size(&mut GetSizeNoTracker), 5);
assert_eq!(GetSize::get_heap_size(&&value, &mut GetSizeNoTracker), 0); // Fully qualified syntax

// WARNING: Duo to rust's automatic dereferencing, a simple pointer will be dereferenced
// to the original value, causing the borrowed bytes to be accounted for too.
assert_eq!((&value).get_heap_size(), 5);
assert_eq!((&value).get_heap_size(&mut GetSizeNoTracker), 5);
// The above gets rewritten by to compiler into:
// assert_eq!(value.get_heap_size(), 5);
// assert_eq!(value.get_heap_size(&mut GetSizeNoTracker), 5);

// Our derive macro uses fully qualified syntax, so auto-dereferencing does
// not occour.
Expand All @@ -68,7 +68,7 @@ fn main() {

// The String is now only borrowed, leading to its heap bytes not being
// accounted for.
assert_eq!(value.get_heap_size(), 0);
assert_eq!(value.get_heap_size(&mut GetSizeNoTracker), 0);
}
```

Expand All @@ -78,17 +78,17 @@ On the other hand references implemented as shared ownership are treated as owne

```rust
use std::sync::Arc;
use get_size::GetSize;
use get_size::{GetSize, GetSizeNoTracker};

fn main() {
let value = String::from("hello");
assert_eq!(value.get_heap_size(), 5);
assert_eq!(value.get_heap_size(&mut GetSizeNoTracker), 5);

// From a technical point of view, Arcs own the data they reference.
// Given so their heap data gets accounted for too.
// Note that an Arc does store the String's stack bytes also inside the heap.
let value = Arc::new(value);
assert_eq!(value.get_heap_size(), std::mem::size_of::<String>() + 5);
assert_eq!(value.get_heap_size(&mut GetSizeNoTracker), std::mem::size_of::<String>() + 5);
}
```

Expand All @@ -111,7 +111,7 @@ Note that the derive macro _does not support unions_. You have to manually imple
Deriving [`GetSize`] for a struct:

```rust
use get_size::GetSize;
use get_size::{GetSize, GetSizeNoTracker};

#[derive(GetSize)]
pub struct OwnStruct {
Expand All @@ -125,14 +125,14 @@ fn main() {
value2: 123,
};

assert_eq!(test.get_heap_size(), 5);
assert_eq!(test.get_heap_size(&mut GetSizeNoTracker), 5);
}
```

Deriving [`GetSize`] for an enum:

```rust
use get_size::GetSize;
use get_size::{GetSize, GetSizeNoTracker};

#[derive(GetSize)]
pub enum TestEnum {
Expand All @@ -151,26 +151,26 @@ pub enum TestEnumNumber {

fn main() {
let test = TestEnum::Variant1(1, 2, 3);
assert_eq!(test.get_heap_size(), 0);
assert_eq!(test.get_heap_size(&mut GetSizeNoTracker), 0);

let test = TestEnum::Variant2("Hello".into());
assert_eq!(test.get_heap_size(), 5);
assert_eq!(test.get_heap_size(&mut GetSizeNoTracker), 5);

let test = TestEnum::Variant3;
assert_eq!(test.get_heap_size(), 0);
assert_eq!(test.get_heap_size(&mut GetSizeNoTracker), 0);

let test = TestEnum::Variant4{x: "Hello".into(), y: "world".into()};
assert_eq!(test.get_heap_size(), 5 + 5);
assert_eq!(test.get_heap_size(&mut GetSizeNoTracker), 5 + 5);

let test = TestEnumNumber::One;
assert_eq!(test.get_heap_size(), 0);
assert_eq!(test.get_heap_size(&mut GetSizeNoTracker), 0);
}
```

The derive macro does also work with generics. The generated trait implementation will by default require all generic types to implement [`GetSize`] themselves, but this [can be changed](#ignoring-certain-generic-types).

```rust
use get_size::GetSize;
use get_size::{GetSize, GetSizeNoTracker};

#[derive(GetSize)]
struct TestStructGenerics<A, B> {
Expand All @@ -190,16 +190,16 @@ fn main() {
value2: 123,
};

assert_eq!(test.get_heap_size(), 5);
assert_eq!(test.get_heap_size(&mut GetSizeNoTracker), 5);

let test = String::from("Hello");
let test: TestEnumGenerics<String, u64> = TestEnumGenerics::Variant1(test);

assert_eq!(test.get_heap_size(), 5);
assert_eq!(test.get_heap_size(&mut GetSizeNoTracker), 5);

let test: TestEnumGenerics<String, u64> = TestEnumGenerics::Variant2(100);

assert_eq!(test.get_heap_size(), 0);
assert_eq!(test.get_heap_size(&mut GetSizeNoTracker), 0);
}
```

Expand All @@ -219,7 +219,7 @@ The idiomatic use case for this helper is if you use shared ownership and do not

```rust
use std::sync::Arc;
use get_size::GetSize;
use get_size::{GetSize, GetSizeNoTracker};

#[derive(GetSize)]
struct PrimaryStore {
Expand Down Expand Up @@ -248,8 +248,8 @@ fn main() {
};

// Note that Arc does also store the Vec's stack data on the heap.
assert_eq!(primary_data.get_heap_size(), Vec::<u8>::get_stack_size() + 1024);
assert_eq!(secondary_data.get_heap_size(), 0);
assert_eq!(primary_data.get_heap_size(&mut GetSizeNoTracker), Vec::<u8>::get_stack_size() + 1024);
assert_eq!(secondary_data.get_heap_size(&mut GetSizeNoTracker), 0);
}
```

Expand All @@ -260,7 +260,7 @@ But you may also use this as a band aid, if a certain struct fields type does no
Be aware though that this will result in an implementation which will return incorrect results, unless the heap size of that type is indeed always zero and can thus be ignored. It is therefor advisable to use one of the next two helper options instead.

```rust
use get_size::GetSize;
use get_size::{GetSize, GetSizeNoTracker};

// Does not implement GetSize!
struct TestStructNoGetSize {
Expand All @@ -286,7 +286,7 @@ fn main() {
};

// Note that the result is lower then it should be.
assert_eq!(test.get_heap_size(), 4);
assert_eq!(test.get_heap_size(&mut GetSizeNoTracker), 4);
}
```

Expand All @@ -295,7 +295,7 @@ fn main() {
In same cases you may be dealing with external types which allocate a fixed amount of bytes at the heap. In this case you may use the `size` attribute to always account the given field with a fixed value.

```rust
use get_size::GetSize;
use get_size::{GetSize, GetSizeNoTracker};

#[derive(GetSize)]
struct TestStruct {
Expand All @@ -310,7 +310,7 @@ fn main() {
buffer: Buffer1024::new(),
};

assert_eq!(test.get_heap_size(), 1024);
assert_eq!(test.get_heap_size(&mut GetSizeNoTracker), 1024);
}
```

Expand All @@ -323,7 +323,7 @@ The latter is especially usefull if you can make use of a certain trait to calcu
Note that unlike in other crates, the name of the function to be called is __not__ encapsulated by double-quotes ("), but rather given directly.

```rust
use get_size::GetSize;
use get_size::{GetSize, GetSizeNoTracker};

#[derive(GetSize)]
struct TestStruct {
Expand All @@ -349,7 +349,7 @@ fn main() {
buffer,
};

assert_eq!(test.get_heap_size(), 512);
assert_eq!(test.get_heap_size(&mut GetSizeNoTracker), 512);
}
```

Expand All @@ -358,7 +358,7 @@ fn main() {
If your struct uses generics, but the fields at which they are stored are ignored or get handled by helpers because the generic does not implement [`GetSize`], you will have to mark these generics with a special struct level `ignore` attribute. Otherwise the derived [`GetSize`] implementation would still require these generics to implement [`GetSize`], even through there is no need for it.

```rust
use get_size::GetSize;
use get_size::{GetSize, GetSizeNoTracker};

#[derive(GetSize)]
#[get_size(ignore(B, C, D))]
Expand Down Expand Up @@ -387,7 +387,7 @@ fn main() {
value4: 123,
};

assert_eq!(test.get_heap_size(), 5 + 100 + 50);
assert_eq!(test.get_heap_size(&mut GetSizeNoTracker), 5 + 100 + 50);
}
```

Expand Down
19 changes: 7 additions & 12 deletions get-size-derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
[package]
name = "get-size-derive"
categories = ["memory-management", "caching"]
description = "Derives the GetSize trait."
version = "0.1.3"
edition = "2021"
authors = ["Denis Kerp"]
readme = "README.md"
repository = "https://github.com/DKerp/get-size/tree/main/get-size-derive"
license = "MIT"
keywords = ["size", "heap", "ram", "cache", "memory"]
categories = ["memory-management", "caching"]
license = "MIT"
name = "get-size-derive"
readme = "README.md"
version = "0.2.0"

[lib]
proc-macro = true

[dependencies]
syn = { version = "^2", features = ["derive", "parsing"] }
quote = "^1"
attribute-derive = "^0.6"

[dev-dependencies]
get-size = { path = "../", features = ["derive"] }
quote = "^1"
syn = { version = "^2", features = ["derive", "parsing"] }
Loading

0 comments on commit d33e44b

Please sign in to comment.