Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- Nothing yet!
### Fixed

- Improve performance of scanning source files ([#15270](https://github.com/tailwindlabs/tailwindcss/pull/15270))

## [4.0.0-beta.4] - 2024-11-29

Expand Down
24 changes: 11 additions & 13 deletions crates/oxide/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,11 @@ impl Scanner {
pub fn scan(&mut self) -> Vec<String> {
init_tracing();
self.prepare();
self.check_for_new_files();
self.compute_candidates();

let mut candidates: Vec<String> = self.candidates.clone().into_iter().collect();

candidates.sort();
let mut candidates: Vec<String> = self.candidates.clone().into_par_iter().collect();

candidates.par_sort();
candidates
}

Expand Down Expand Up @@ -140,7 +138,7 @@ impl Scanner {
let extractor = Extractor::with_positions(&content[..], Default::default());

let candidates: Vec<(String, usize)> = extractor
.into_iter()
.into_par_iter()
.map(|(s, i)| {
// SAFETY: When we parsed the candidates, we already guaranteed that the byte slices
// are valid, therefore we don't have to re-check here when we want to convert it back
Expand All @@ -156,7 +154,7 @@ impl Scanner {
self.prepare();

self.files
.iter()
.par_iter()
.filter_map(|x| Path::from(x.clone()).canonicalize().ok())
.map(|x| x.to_string())
.collect()
Expand Down Expand Up @@ -201,14 +199,15 @@ impl Scanner {

if !changed_content.is_empty() {
let candidates = parse_all_blobs(read_all_files(changed_content));
self.candidates.extend(candidates);
self.candidates.par_extend(candidates);
}
}

// Ensures that all files/globs are resolved and the scanner is ready to scan
// content for candidates.
fn prepare(&mut self) {
if self.ready {
self.check_for_new_files();
return;
}

Expand Down Expand Up @@ -455,12 +454,10 @@ fn read_all_files(changed_content: Vec<ChangedContent>) -> Vec<Vec<u8>> {

#[tracing::instrument(skip_all)]
fn parse_all_blobs(blobs: Vec<Vec<u8>>) -> Vec<String> {
let input: Vec<_> = blobs.iter().map(|blob| &blob[..]).collect();
let input = &input[..];

let mut result: Vec<String> = input
let mut result: Vec<_> = blobs
.par_iter()
.map(|input| Extractor::unique(input, Default::default()))
.flat_map(|blob| blob.par_split(|x| matches!(x, b'\n')))
.map(|blob| Extractor::unique(blob, Default::default()))
.reduce(Default::default, |mut a, b| {
a.extend(b);
a
Expand All @@ -473,6 +470,7 @@ fn parse_all_blobs(blobs: Vec<Vec<u8>>) -> Vec<String> {
unsafe { String::from_utf8_unchecked(s.to_vec()) }
})
.collect();
result.sort();

result.par_sort();
result
}