Skip to content

Commit f80bd6c

Browse files
authored
perf: using Arc<str> instead of String (#84)
1 parent 16dab53 commit f80bd6c

File tree

6 files changed

+83
-82
lines changed

6 files changed

+83
-82
lines changed

src/builder.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::env;
55
use std::fs;
66
use std::io::Read;
77
use std::path::{Path, PathBuf};
8+
use std::sync::Arc;
89

910
use debugid::DebugId;
1011
use rustc_hash::FxHashMap;
@@ -19,14 +20,14 @@ use crate::types::{RawToken, SourceMap, Token};
1920
/// objects is generally not very comfortable. As a general aid this
2021
/// type can help.
2122
pub struct SourceMapBuilder {
22-
file: Option<String>,
23-
name_map: FxHashMap<String, u32>,
24-
names: Vec<String>,
23+
file: Option<Arc<str>>,
24+
name_map: FxHashMap<Arc<str>, u32>,
25+
names: Vec<Arc<str>>,
2526
tokens: Vec<RawToken>,
26-
source_map: FxHashMap<String, u32>,
27-
source_root: Option<String>,
28-
sources: Vec<String>,
29-
source_contents: Vec<Option<String>>,
27+
source_map: FxHashMap<Arc<str>, u32>,
28+
source_root: Option<Arc<str>>,
29+
sources: Vec<Arc<str>>,
30+
source_contents: Vec<Option<Arc<str>>>,
3031
sources_mapping: Vec<u32>,
3132
debug_id: Option<DebugId>,
3233
}
@@ -52,7 +53,7 @@ impl SourceMapBuilder {
5253
/// Creates a new source map builder and sets the file.
5354
pub fn new(file: Option<&str>) -> SourceMapBuilder {
5455
SourceMapBuilder {
55-
file: file.map(str::to_owned),
56+
file: file.map(Into::into),
5657
name_map: FxHashMap::default(),
5758
names: vec![],
5859
tokens: vec![],
@@ -71,7 +72,7 @@ impl SourceMapBuilder {
7172
}
7273

7374
/// Sets the file for the sourcemap (optional)
74-
pub fn set_file<T: Into<String>>(&mut self, value: Option<T>) {
75+
pub fn set_file<T: Into<Arc<str>>>(&mut self, value: Option<T>) {
7576
self.file = value.map(Into::into);
7677
}
7778

@@ -81,7 +82,7 @@ impl SourceMapBuilder {
8182
}
8283

8384
/// Sets a new value for the source_root.
84-
pub fn set_source_root<T: Into<String>>(&mut self, value: Option<T>) {
85+
pub fn set_source_root<T: Into<Arc<str>>>(&mut self, value: Option<T>) {
8586
self.source_root = value.map(Into::into);
8687
}
8788

@@ -108,7 +109,7 @@ impl SourceMapBuilder {
108109
/// Changes the source name for an already set source.
109110
pub fn set_source(&mut self, src_id: u32, src: &str) {
110111
assert!(src_id != !0, "Cannot set sources for tombstone source id");
111-
self.sources[src_id as usize] = src.to_string();
112+
self.sources[src_id as usize] = src.into();
112113
}
113114

114115
/// Looks up a source name for an ID.
@@ -122,7 +123,7 @@ impl SourceMapBuilder {
122123
if self.sources.len() > self.source_contents.len() {
123124
self.source_contents.resize(self.sources.len(), None);
124125
}
125-
self.source_contents[src_id as usize] = contents.map(str::to_owned);
126+
self.source_contents[src_id as usize] = contents.map(Into::into);
126127
}
127128

128129
/// Returns the current source contents for a source.
@@ -272,7 +273,7 @@ impl SourceMapBuilder {
272273
prefix.push('/');
273274
}
274275
if source.starts_with(&prefix) {
275-
*source = source[prefix.len()..].to_string();
276+
*source = source[prefix.len()..].into();
276277
break;
277278
}
278279
}

src/decoder.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -187,26 +187,34 @@ pub fn decode_regular(rsm: RawSourceMap) -> Result<SourceMap> {
187187
}
188188
}
189189

190-
let sources = sources.into_iter().map(Option::unwrap_or_default).collect();
190+
let sources = sources
191+
.into_iter()
192+
.map(Option::unwrap_or_default)
193+
.map(Into::into)
194+
.collect();
191195

192196
// apparently we can encounter some non string types in real world
193197
// sourcemaps :(
194198
let names = names
195199
.into_iter()
196200
.map(|val| match val {
197-
Value::String(s) => s,
198-
Value::Number(num) => num.to_string(),
201+
Value::String(s) => s.into(),
202+
Value::Number(num) => num.to_string().into(),
199203
_ => "".into(),
200204
})
201-
.collect::<Vec<String>>();
205+
.collect::<Vec<_>>();
202206

203207
// file sometimes is not a string for unexplicable reasons
204208
let file = rsm.file.map(|val| match val {
205-
Value::String(s) => s,
209+
Value::String(s) => s.into(),
206210
_ => "<invalid>".into(),
207211
});
208212

209-
let mut sm = SourceMap::new(file, tokens, names, sources, rsm.sources_content);
213+
let source_content = rsm
214+
.sources_content
215+
.map(|x| x.into_iter().map(|v| v.map(Into::into)).collect::<Vec<_>>());
216+
217+
let mut sm = SourceMap::new(file, tokens, names, sources, source_content);
210218
sm.set_source_root(rsm.source_root);
211219
sm.set_debug_id(rsm.debug_id);
212220

src/ram_bundle.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ impl<'a> RamBundleModule<'a> {
7070
/// Returns a source view of the data.
7171
///
7272
/// This operation fails if the source code is not valid UTF-8.
73-
pub fn source_view(&self) -> Result<SourceView<'a>> {
73+
pub fn source_view(&self) -> Result<SourceView> {
7474
match std::str::from_utf8(self.data) {
75-
Ok(s) => Ok(SourceView::new(s)),
75+
Ok(s) => Ok(SourceView::new(s.into())),
7676
Err(e) => Err(Error::Utf8(e)),
7777
}
7878
}
@@ -361,7 +361,7 @@ impl<'a> SplitRamBundleModuleIter<'a> {
361361
fn split_module(
362362
&self,
363363
module: RamBundleModule<'a>,
364-
) -> Result<Option<(String, SourceView<'a>, SourceMap)>> {
364+
) -> Result<Option<(String, SourceView, SourceMap)>> {
365365
let module_offset = self
366366
.offsets
367367
.get(module.id())
@@ -377,7 +377,7 @@ impl<'a> SplitRamBundleModuleIter<'a> {
377377
return Err(Error::InvalidRamBundleEntry);
378378
}
379379

380-
let source: SourceView<'a> = module.source_view()?;
380+
let source: SourceView = module.source_view()?;
381381
let line_count = source.line_count() as u32;
382382
let ending_line = starting_line + line_count;
383383
let last_line_len = source
@@ -416,7 +416,7 @@ impl<'a> SplitRamBundleModuleIter<'a> {
416416
}
417417

418418
impl<'a> Iterator for SplitRamBundleModuleIter<'a> {
419-
type Item = Result<(String, SourceView<'a>, SourceMap)>;
419+
type Item = Result<(String, SourceView, SourceMap)>;
420420

421421
fn next(&mut self) -> Option<Self::Item> {
422422
while let Some(module_result) = self.ram_bundle_iter.next() {

src/sourceview.rs

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use std::borrow::Cow;
21
use std::fmt;
32
use std::slice;
43
use std::str;
54
use std::sync::atomic::AtomicUsize;
65
use std::sync::atomic::Ordering;
6+
use std::sync::Arc;
77
use std::sync::Mutex;
88

99
use if_chain::if_chain;
@@ -14,19 +14,13 @@ use crate::js_identifiers::{get_javascript_token, is_valid_javascript_identifier
1414
use crate::types::{idx_from_token, sourcemap_from_token, Token};
1515

1616
/// An iterator that iterates over tokens in reverse.
17-
pub struct RevTokenIter<'view, 'viewbase, 'map>
18-
where
19-
'viewbase: 'view,
20-
{
21-
sv: &'view SourceView<'viewbase>,
17+
pub struct RevTokenIter<'view, 'map> {
18+
sv: &'view SourceView,
2219
token: Option<Token<'map>>,
2320
source_line: Option<(&'view str, usize, usize, usize)>,
2421
}
2522

26-
impl<'view, 'viewbase, 'map> Iterator for RevTokenIter<'view, 'viewbase, 'map>
27-
where
28-
'viewbase: 'view,
29-
{
23+
impl<'view, 'map> Iterator for RevTokenIter<'view, 'map> {
3024
type Item = (Token<'map>, Option<&'view str>);
3125

3226
fn next(&mut self) -> Option<(Token<'map>, Option<&'view str>)> {
@@ -118,7 +112,7 @@ where
118112
}
119113

120114
pub struct Lines<'a> {
121-
sv: &'a SourceView<'a>,
115+
sv: &'a SourceView,
122116
idx: u32,
123117
}
124118

@@ -139,14 +133,14 @@ impl<'a> Iterator for Lines<'a> {
139133
///
140134
/// This type is used to implement fairly efficient source mapping
141135
/// operations.
142-
pub struct SourceView<'a> {
143-
source: Cow<'a, str>,
136+
pub struct SourceView {
137+
source: Arc<str>,
144138
processed_until: AtomicUsize,
145139
lines: Mutex<Vec<&'static str>>,
146140
}
147141

148-
impl<'a> Clone for SourceView<'a> {
149-
fn clone(&self) -> SourceView<'a> {
142+
impl Clone for SourceView {
143+
fn clone(&self) -> SourceView {
150144
SourceView {
151145
source: self.source.clone(),
152146
processed_until: AtomicUsize::new(0),
@@ -155,28 +149,28 @@ impl<'a> Clone for SourceView<'a> {
155149
}
156150
}
157151

158-
impl<'a> fmt::Debug for SourceView<'a> {
152+
impl fmt::Debug for SourceView {
159153
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
160154
f.debug_struct("SourceView")
161155
.field("source", &self.source())
162156
.finish()
163157
}
164158
}
165159

166-
impl<'a> SourceView<'a> {
160+
impl SourceView {
167161
/// Creates an optimized view of a given source.
168-
pub fn new(source: &'a str) -> SourceView<'a> {
162+
pub fn new(source: Arc<str>) -> SourceView {
169163
SourceView {
170-
source: Cow::Borrowed(source),
164+
source,
171165
processed_until: AtomicUsize::new(0),
172166
lines: Mutex::new(vec![]),
173167
}
174168
}
175169

176170
/// Creates an optimized view from a given source string
177-
pub fn from_string(source: String) -> SourceView<'static> {
171+
pub fn from_string(source: String) -> SourceView {
178172
SourceView {
179-
source: Cow::Owned(source),
173+
source: source.into(),
180174
processed_until: AtomicUsize::new(0),
181175
lines: Mutex::new(vec![]),
182176
}
@@ -264,7 +258,7 @@ impl<'a> SourceView<'a> {
264258
}
265259

266260
/// Returns an iterator over all lines.
267-
pub fn lines(&'a self) -> Lines<'a> {
261+
pub fn lines(&self) -> Lines {
268262
Lines { sv: self, idx: 0 }
269263
}
270264

@@ -273,10 +267,7 @@ impl<'a> SourceView<'a> {
273267
&self.source
274268
}
275269

276-
fn rev_token_iter<'this, 'map>(
277-
&'this self,
278-
token: Token<'map>,
279-
) -> RevTokenIter<'this, 'a, 'map> {
270+
fn rev_token_iter<'this, 'map>(&'this self, token: Token<'map>) -> RevTokenIter<'this, 'map> {
280271
RevTokenIter {
281272
sv: self,
282273
token: Some(token),
@@ -332,7 +323,7 @@ impl<'a> SourceView<'a> {
332323
#[test]
333324
#[allow(clippy::cognitive_complexity)]
334325
fn test_minified_source_view() {
335-
let view = SourceView::new("a\nb\nc");
326+
let view = SourceView::new("a\nb\nc".into());
336327
assert_eq!(view.get_line(0), Some("a"));
337328
assert_eq!(view.get_line(0), Some("a"));
338329
assert_eq!(view.get_line(2), Some("c"));
@@ -341,7 +332,7 @@ fn test_minified_source_view() {
341332

342333
assert_eq!(view.line_count(), 3);
343334

344-
let view = SourceView::new("a\r\nb\r\nc");
335+
let view = SourceView::new("a\r\nb\r\nc".into());
345336
assert_eq!(view.get_line(0), Some("a"));
346337
assert_eq!(view.get_line(0), Some("a"));
347338
assert_eq!(view.get_line(2), Some("c"));
@@ -350,7 +341,7 @@ fn test_minified_source_view() {
350341

351342
assert_eq!(view.line_count(), 3);
352343

353-
let view = SourceView::new("abc👌def\nblah");
344+
let view = SourceView::new("abc👌def\nblah".into());
354345
assert_eq!(view.get_line_slice(0, 0, 3), Some("abc"));
355346
assert_eq!(view.get_line_slice(0, 3, 1), Some("👌"));
356347
assert_eq!(view.get_line_slice(0, 3, 2), Some("👌"));
@@ -362,7 +353,7 @@ fn test_minified_source_view() {
362353
assert_eq!(view.get_line_slice(1, 0, 5), None);
363354
assert_eq!(view.get_line_slice(1, 0, 12), None);
364355

365-
let view = SourceView::new("a\nb\nc\n");
356+
let view = SourceView::new("a\nb\nc\n".into());
366357
assert_eq!(view.get_line(0), Some("a"));
367358
assert_eq!(view.get_line(1), Some("b"));
368359
assert_eq!(view.get_line(2), Some("c"));
@@ -371,6 +362,6 @@ fn test_minified_source_view() {
371362

372363
fn is_send<T: Send>() {}
373364
fn is_sync<T: Sync>() {}
374-
is_send::<SourceView<'static>>();
375-
is_sync::<SourceView<'static>>();
365+
is_send::<SourceView>();
366+
is_sync::<SourceView>();
376367
}

0 commit comments

Comments
 (0)