Skip to content

Commit

Permalink
refactor: reduce memory consumption of CachedSource (#144)
Browse files Browse the repository at this point in the history
* refactor: init

* perf: faster lines iterator for `Rope` (#145)

* refactor: init

* refactor: faster lines

* refactor: try

* chore: clippy

* test: more

* chore: more

* perf

* finish

* finish
  • Loading branch information
h-a-n-a authored Dec 12, 2024
1 parent d85db3f commit 2b19331
Show file tree
Hide file tree
Showing 15 changed files with 1,731 additions and 270 deletions.
16 changes: 13 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 8 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ readme = "README.md"
include = ["/src/**/*.rs", "/*.toml", "/LICENSE", "/README.md"]

[lints.rust]
unsafe_code = "warn"
unsafe_code = "warn"
missing_docs = "warn"

[lints.clippy]
dbg_macro = "warn"
todo = "warn"
dbg_macro = "warn"
todo = "warn"
unimplemented = "warn"
print_stdout = "warn"
print_stderr = "warn"
print_stdout = "warn"
print_stderr = "warn"

[[bench]]
name = "bench"
name = "bench"
path = "benches/bench.rs"
harness = false

Expand All @@ -36,6 +36,8 @@ dyn-clone = "1"
rustc-hash = "1"
dashmap = "5"
memchr = "2.6.4"
itertools = "0.13"


codspeed-criterion-compat = { version = "2.3.3", default-features = false, optional = true }
static_assertions = "1.1.0"
Expand Down
37 changes: 10 additions & 27 deletions src/cached_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::{
stream_and_get_source_and_map, stream_chunks_of_raw_source,
stream_chunks_of_source_map, StreamChunks,
},
rope::Rope,
MapOptions, Source, SourceMap,
};

Expand Down Expand Up @@ -50,8 +51,6 @@ use crate::{
/// ```
pub struct CachedSource<T> {
inner: Arc<T>,
cached_buffer: Arc<OnceLock<Vec<u8>>>,
cached_source: Arc<OnceLock<Arc<str>>>,
cached_hash: Arc<OnceLock<u64>>,
cached_maps:
Arc<DashMap<MapOptions, Option<SourceMap>, BuildHasherDefault<FxHasher>>>,
Expand All @@ -62,8 +61,6 @@ impl<T> CachedSource<T> {
pub fn new(inner: T) -> Self {
Self {
inner: Arc::new(inner),
cached_buffer: Default::default(),
cached_source: Default::default(),
cached_hash: Default::default(),
cached_maps: Default::default(),
}
Expand All @@ -77,17 +74,15 @@ impl<T> CachedSource<T> {

impl<T: Source + Hash + PartialEq + Eq + 'static> Source for CachedSource<T> {
fn source(&self) -> Cow<str> {
let cached = self
.cached_source
.get_or_init(|| self.inner.source().into());
Cow::Borrowed(cached)
self.inner.source()
}

fn rope(&self) -> Rope<'_> {
self.inner.rope()
}

fn buffer(&self) -> Cow<[u8]> {
let cached = self
.cached_buffer
.get_or_init(|| self.inner.buffer().to_vec());
Cow::Borrowed(cached)
self.inner.buffer()
}

fn size(&self) -> usize {
Expand All @@ -109,7 +104,7 @@ impl<T: Source + Hash + PartialEq + Eq + 'static> Source for CachedSource<T> {
}
}

impl<T: Source + Hash + PartialEq + Eq + 'static> StreamChunks<'_>
impl<T: Source + Hash + PartialEq + Eq + 'static> StreamChunks
for CachedSource<T>
{
fn stream_chunks<'a>(
Expand All @@ -122,9 +117,7 @@ impl<T: Source + Hash + PartialEq + Eq + 'static> StreamChunks<'_>
let cached_map = self.cached_maps.entry(options.clone());
match cached_map {
Entry::Occupied(entry) => {
let source = self
.cached_source
.get_or_init(|| self.inner.source().into());
let source = self.rope();
if let Some(map) = entry.get() {
#[allow(unsafe_code)]
// SAFETY: We guarantee that once a `SourceMap` is stored in the cache, it will never be removed.
Expand Down Expand Up @@ -162,8 +155,6 @@ impl<T> Clone for CachedSource<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
cached_buffer: self.cached_buffer.clone(),
cached_source: self.cached_source.clone(),
cached_hash: self.cached_hash.clone(),
cached_maps: self.cached_maps.clone(),
}
Expand Down Expand Up @@ -196,17 +187,14 @@ impl<T: std::fmt::Debug> std::fmt::Debug for CachedSource<T> {
) -> Result<(), std::fmt::Error> {
f.debug_struct("CachedSource")
.field("inner", self.inner.as_ref())
.field("cached_buffer", &self.cached_buffer.get().is_some())
.field("cached_source", &self.cached_source.get().is_some())
.field("cached_hash", self.cached_hash.as_ref())
.field("cached_maps", &(!self.cached_maps.is_empty()))
.finish()
}
}

#[cfg(test)]
mod tests {
use std::borrow::Borrow;

use crate::{
ConcatSource, OriginalSource, RawSource, ReplaceSource, SourceExt,
SourceMapSource, WithoutOriginalOptions,
Expand Down Expand Up @@ -247,11 +235,6 @@ mod tests {
source.size();
source.map(&map_options);

assert_eq!(clone.cached_source.get().unwrap().borrow(), source.source());
assert_eq!(
*clone.cached_buffer.get().unwrap(),
source.buffer().to_vec()
);
assert_eq!(
*clone.cached_maps.get(&map_options).unwrap().value(),
source.map(&map_options)
Expand Down
20 changes: 17 additions & 3 deletions src/concat_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
helpers::{get_map, GeneratedInfo, OnChunk, OnName, OnSource, StreamChunks},
linear_map::LinearMap,
source::{Mapping, OriginalLocation},
BoxSource, MapOptions, Source, SourceExt, SourceMap,
BoxSource, MapOptions, Rope, Source, SourceExt, SourceMap,
};

/// Concatenate multiple [Source]s to a single [Source].
Expand Down Expand Up @@ -109,6 +109,20 @@ impl Source for ConcatSource {
}
}

fn rope(&self) -> Rope<'_> {
let children = self.children();
if children.len() == 1 {
children[0].rope()
} else {
let mut rope = Rope::new();
for child in children {
let child_rope = child.rope();
rope.append(child_rope);
}
rope
}
}

fn buffer(&self) -> Cow<[u8]> {
let children = self.children();
if children.len() == 1 {
Expand Down Expand Up @@ -155,8 +169,8 @@ impl PartialEq for ConcatSource {
}
impl Eq for ConcatSource {}

impl<'a> StreamChunks<'a> for ConcatSource {
fn stream_chunks(
impl StreamChunks for ConcatSource {
fn stream_chunks<'a>(
&'a self,
options: &MapOptions,
on_chunk: OnChunk<'_, 'a>,
Expand Down
3 changes: 3 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ pub type Result<T> = result::Result<T, Error>;
pub enum Error {
/// a JSON parsing related failure
BadJson(simd_json::Error),
/// rope related failure
Rope(&'static str),
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::BadJson(err) => write!(f, "bad json: {err}"),
Error::Rope(err) => write!(f, "rope error: {err}"),
}
}
}
Expand Down
Loading

0 comments on commit 2b19331

Please sign in to comment.