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

perf: inner use BoxSource is better #119

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/Bench.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ concurrency:

jobs:
benchmark:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4

Expand All @@ -35,7 +35,7 @@ jobs:
run: cargo codspeed build --features codspeed

- name: Run benchmark
uses: CodSpeedHQ/action@v1
uses: CodSpeedHQ/action@v3
timeout-minutes: 30
with:
run: cargo codspeed run
Expand Down
36 changes: 17 additions & 19 deletions src/cached_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{
stream_and_get_source_and_map, stream_chunks_of_raw_source,
stream_chunks_of_source_map, StreamChunks,
},
MapOptions, Source, SourceMap,
BoxSource, MapOptions, Source, SourceExt, SourceMap,
};

/// It tries to reused cached results from other methods to avoid calculations,
Expand Down Expand Up @@ -48,20 +48,20 @@ use crate::{
/// "Hello World\nconsole.log('test');\nconsole.log('test2');\nHello2\n"
/// );
/// ```
pub struct CachedSource<T> {
inner: Arc<T>,
pub struct CachedSource {
inner: BoxSource,
cached_buffer: Arc<OnceLock<Vec<u8>>>,
cached_source: Arc<OnceLock<Arc<str>>>,
cached_size: Arc<OnceLock<usize>>,
cached_maps:
Arc<DashMap<MapOptions, Option<SourceMap>, BuildHasherDefault<FxHasher>>>,
}

impl<T> CachedSource<T> {
impl CachedSource {
/// Create a [CachedSource] with the original [Source].
pub fn new(inner: T) -> Self {
pub fn new<T: Source + 'static>(inner: T) -> Self {
Self {
inner: Arc::new(inner),
inner: SourceExt::boxed(inner),
cached_buffer: Default::default(),
cached_source: Default::default(),
cached_size: Default::default(),
Expand All @@ -70,12 +70,12 @@ impl<T> CachedSource<T> {
}

/// Get the original [Source].
pub fn original(&self) -> &T {
pub fn original(&self) -> &dyn Source {
&self.inner
}
}

impl<T: Source + Hash + PartialEq + Eq + 'static> Source for CachedSource<T> {
impl Source for CachedSource {
fn source(&self) -> Cow<str> {
let cached = self
.cached_source
Expand Down Expand Up @@ -116,9 +116,7 @@ impl<T: Source + Hash + PartialEq + Eq + 'static> Source for CachedSource<T> {
}
}

impl<T: Source + Hash + PartialEq + Eq + 'static> StreamChunks<'_>
for CachedSource<T>
{
impl StreamChunks<'_> for CachedSource {
fn stream_chunks<'a>(
&'a self,
options: &MapOptions,
Expand Down Expand Up @@ -152,7 +150,7 @@ impl<T: Source + Hash + PartialEq + Eq + 'static> StreamChunks<'_>
}
Entry::Vacant(entry) => {
let (generated_info, map) = stream_and_get_source_and_map(
&self.inner as &T,
&self.inner,
options,
on_chunk,
on_source,
Expand All @@ -165,7 +163,7 @@ impl<T: Source + Hash + PartialEq + Eq + 'static> StreamChunks<'_>
}
}

impl<T: Source> Clone for CachedSource<T> {
impl Clone for CachedSource {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
Expand All @@ -177,27 +175,27 @@ impl<T: Source> Clone for CachedSource<T> {
}
}

impl<T: Hash> Hash for CachedSource<T> {
impl Hash for CachedSource {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.inner.hash(state);
}
}

impl<T: PartialEq> PartialEq for CachedSource<T> {
impl PartialEq for CachedSource {
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner
self.inner.as_ref() == other.inner.as_ref()
}
}

impl<T: Eq> Eq for CachedSource<T> {}
impl Eq for CachedSource {}

impl<T: std::fmt::Debug> std::fmt::Debug for CachedSource<T> {
impl std::fmt::Debug for CachedSource {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> Result<(), std::fmt::Error> {
f.debug_struct("CachedSource")
.field("inner", self.inner.as_ref())
.field("inner", &self.inner)
.field("cached_buffer", &self.cached_buffer.get().is_some())
.field("cached_source", &self.cached_source.get().is_some())
.field("cached_maps", &(!self.cached_maps.is_empty()))
Expand Down
8 changes: 4 additions & 4 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use crate::{
type InnerSourceContentLine<'a> =
RefCell<LinearMap<OnceCell<Option<Vec<WithIndices<&'a str>>>>>>;

pub fn get_map<'a, S: StreamChunks<'a>>(
stream: &'a S,
pub fn get_map<'a>(
stream: &'a dyn StreamChunks<'a>,
options: &'a MapOptions,
) -> Option<SourceMap> {
let mut mappings_encoder = create_encoder(options.columns);
Expand Down Expand Up @@ -1084,8 +1084,8 @@ pub fn stream_chunks_of_combined_source_map<'a>(
)
}

pub fn stream_and_get_source_and_map<'a, S: StreamChunks<'a>>(
input_source: &'a S,
pub fn stream_and_get_source_and_map<'a>(
input_source: &'a dyn StreamChunks<'a>,
options: &MapOptions,
on_chunk: OnChunk<'_, 'a>,
on_source: OnSource<'_, 'a>,
Expand Down
40 changes: 21 additions & 19 deletions src/replace_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{
hash::{Hash, Hasher},
sync::{
atomic::{AtomicBool, Ordering},
Arc, Mutex, MutexGuard, OnceLock,
Mutex, MutexGuard, OnceLock,
},
};

Expand All @@ -13,7 +13,8 @@ use rustc_hash::FxHashMap as HashMap;
use crate::{
helpers::{get_map, split_into_lines, GeneratedInfo, StreamChunks},
linear_map::LinearMap,
MapOptions, Mapping, OriginalLocation, Source, SourceMap,
BoxSource, MapOptions, Mapping, OriginalLocation, Source, SourceExt,
SourceMap,
};

/// Decorates a Source with replacements and insertions of source code,
Expand All @@ -35,8 +36,8 @@ use crate::{
///
/// assert_eq!(source.source(), "start1\nstart2\nreplaced!\nend1\nend2");
/// ```
pub struct ReplaceSource<T> {
inner: Arc<T>,
pub struct ReplaceSource {
inner: BoxSource,
inner_source_code: OnceLock<Box<str>>,
replacements: Mutex<Vec<Replacement>>,
/// Whether `replacements` is sorted.
Expand Down Expand Up @@ -82,20 +83,20 @@ impl Replacement {
}
}

impl<T> ReplaceSource<T> {
impl ReplaceSource {
/// Create a [ReplaceSource].
pub fn new(source: T) -> Self {
pub fn new<T: Source + 'static>(source: T) -> Self {
Self {
inner: Arc::new(source),
inner: SourceExt::boxed(source),
inner_source_code: OnceLock::new(),
replacements: Mutex::new(Vec::new()),
is_sorted: AtomicBool::new(true),
}
}

/// Get the original [Source].
pub fn original(&self) -> &T {
&self.inner
pub fn original(&self) -> BoxSource {
self.inner.clone()
}

fn replacements(&self) -> MutexGuard<Vec<Replacement>> {
Expand All @@ -113,7 +114,7 @@ impl<T> ReplaceSource<T> {
}
}

impl<T: Source> ReplaceSource<T> {
impl ReplaceSource {
fn get_inner_source_code(&self) -> &str {
self
.inner_source_code
Expand Down Expand Up @@ -174,7 +175,7 @@ impl<T: Source> ReplaceSource<T> {
}
}

impl<T: Source + Hash + PartialEq + Eq + 'static> Source for ReplaceSource<T> {
impl Source for ReplaceSource {
fn source(&self) -> Cow<str> {
self.sort_replacement();

Expand Down Expand Up @@ -233,13 +234,13 @@ impl<T: Source + Hash + PartialEq + Eq + 'static> Source for ReplaceSource<T> {
}
}

impl<T: std::fmt::Debug> std::fmt::Debug for ReplaceSource<T> {
impl std::fmt::Debug for ReplaceSource {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> Result<(), std::fmt::Error> {
f.debug_struct("ReplaceSource")
.field("inner", self.inner.as_ref())
.field("inner", &self.inner)
.field(
"inner_source_code",
&self
Expand Down Expand Up @@ -283,7 +284,7 @@ fn check_content_at_position(
}
}

impl<'a, T: Source> StreamChunks<'a> for ReplaceSource<T> {
impl<'a> StreamChunks<'a> for ReplaceSource {
fn stream_chunks(
&'a self,
options: &crate::MapOptions,
Expand Down Expand Up @@ -698,7 +699,7 @@ impl<'a, T: Source> StreamChunks<'a> for ReplaceSource<T> {
}
}

impl<T: Source> Clone for ReplaceSource<T> {
impl Clone for ReplaceSource {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
Expand All @@ -709,7 +710,7 @@ impl<T: Source> Clone for ReplaceSource<T> {
}
}

impl<T: Hash> Hash for ReplaceSource<T> {
impl Hash for ReplaceSource {
fn hash<H: Hasher>(&self, state: &mut H) {
self.sort_replacement();
"ReplaceSource".hash(state);
Expand All @@ -720,13 +721,14 @@ impl<T: Hash> Hash for ReplaceSource<T> {
}
}

impl<T: PartialEq> PartialEq for ReplaceSource<T> {
impl PartialEq for ReplaceSource {
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner && *self.replacements() == *other.replacements()
self.inner.as_ref() == other.inner.as_ref()
&& *self.replacements() == *other.replacements()
}
}

impl<T: Eq> Eq for ReplaceSource<T> {}
impl Eq for ReplaceSource {}

#[cfg(test)]
mod tests {
Expand Down