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(compile): code cache #26528

Merged
merged 25 commits into from
Nov 18, 2024
Merged
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7236756
perf(compile): use less memory
dsherret Oct 22, 2024
1928daf
working now with typescript
dsherret Oct 23, 2024
32913e7
Merge branch 'main' into perf_deno_compile_less_memory
dsherret Oct 23, 2024
788f4ab
Tell v8 that something is a string like before.
dsherret Oct 23, 2024
742ae3f
fix byonm issue
dsherret Oct 23, 2024
1ad5f62
Merge branch 'main' into perf_deno_compile_less_memory
dsherret Oct 23, 2024
fd13339
maybe fix ci
dsherret Oct 24, 2024
1e0dabd
do not store data urls in the binary
dsherret Oct 24, 2024
d7cd10b
switch to le because this is not network
dsherret Oct 24, 2024
c156944
review
dsherret Oct 24, 2024
938c3e0
perf(compile): code cache for initial load
dsherret Oct 24, 2024
0a7c050
use distinct strategies for compile
dsherret Oct 24, 2024
0957e09
use distinct strategies for compile
dsherret Oct 24, 2024
bad329a
tests
dsherret Oct 24, 2024
e9e4ad2
support --no-code-cache
dsherret Oct 24, 2024
8a910fd
lint
dsherret Oct 24, 2024
bc08455
Merge branch 'main' into perf_compile_code_cache
dsherret Oct 24, 2024
815be3a
remove unused use
dsherret Oct 24, 2024
ec0d0c7
fix test
dsherret Oct 24, 2024
1140105
Do not subtract with overflow when deserializing.
dsherret Oct 24, 2024
5b13157
maybe fix test failing because they had the same binary name
dsherret Oct 24, 2024
d360dda
Merge branch 'main' into perf_compile_code_cache
dsherret Nov 18, 2024
488f6dc
update after merge
dsherret Nov 18, 2024
0e38fab
lint
dsherret Nov 18, 2024
b1a784b
Merge branch 'main' into perf_compile_code_cache
dsherret Nov 18, 2024
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
Prev Previous commit
Next Next commit
use distinct strategies for compile
  • Loading branch information
dsherret committed Oct 24, 2024
commit 0957e0910bc50b6a97f0a62efaf3fcfa3a40082e
82 changes: 74 additions & 8 deletions cli/standalone/code_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ enum CodeCacheStrategy {
SubsequentRun(SubsequentRunCodeCacheStrategy),
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DenoCompileCodeCacheEntry {
pub source_hash: u64,
pub data: Vec<u8>,
Expand Down Expand Up @@ -80,6 +80,9 @@ impl CodeCache for DenoCompileCodeCache {
match &self.strategy {
CodeCacheStrategy::FirstRun(strategy) => {
if !strategy.is_finished.is_raised() {
// we keep track of how many times the cache is requested
// then serialize the cache when we get that number of
// "set" calls
strategy.data.lock().add_count += 1;
}
None
Expand Down Expand Up @@ -264,6 +267,18 @@ fn deserialize(
file_path: &Path,
cache_key: &str,
) -> Result<HashMap<String, DenoCompileCodeCacheEntry>, AnyError> {
// it's very important to use this below so that a corrupt cache file
// doesn't cause a memory allocation error
fn new_vec_sized<T: Clone>(
capacity: usize,
default_value: T,
) -> Result<Vec<T>, AnyError> {
let mut vec = Vec::new();
vec.try_reserve(capacity)?;
vec.resize(capacity, default_value);
Ok(vec)
}

let cache_file = std::fs::File::open(file_path)?;
let mut reader = BufReader::new(cache_file);
let mut header_bytes = vec![0; cache_key.len() + 4];
Expand All @@ -276,9 +291,7 @@ fn deserialize(
u32::from_le_bytes(header_bytes[cache_key.len()..].try_into()?) as usize;
// read the lengths for each entry found in the file
let entry_len_bytes_capacity = len * 8;
let mut entry_len_bytes = Vec::new();
entry_len_bytes.try_reserve(entry_len_bytes_capacity)?;
entry_len_bytes.resize(entry_len_bytes_capacity, 0);
let mut entry_len_bytes = new_vec_sized(entry_len_bytes_capacity, 0)?;
reader.read_exact(&mut entry_len_bytes)?;
let mut lengths = Vec::new();
lengths.try_reserve(len)?;
Expand All @@ -292,10 +305,7 @@ fn deserialize(
let mut map = HashMap::new();
map.try_reserve(len)?;
for len in lengths {
let mut buffer = Vec::new();
buffer.try_reserve(len)?;
buffer.resize(len, 0);

let mut buffer = new_vec_sized(len, 0)?;
reader.read_exact(&mut buffer)?;
let entry_data_hash_start_pos = buffer.len() - 8;
let expected_entry_data_hash =
Expand Down Expand Up @@ -331,3 +341,59 @@ fn deserialize(

Ok(map)
}

#[cfg(test)]
mod test {
use test_util::TempDir;

use super::*;
use std::fs::File;

#[test]
fn serialize_deserialize() {
let temp_dir = TempDir::new();
let cache_key = "cache_key";
let cache = {
let mut cache = HashMap::new();
cache.insert(
"specifier1".to_string(),
DenoCompileCodeCacheEntry {
source_hash: 1,
data: vec![1, 2, 3],
},
);
cache.insert(
"specifier2".to_string(),
DenoCompileCodeCacheEntry {
source_hash: 2,
data: vec![4, 5, 6],
},
);
cache
};
let file_path = temp_dir.path().join("cache.bin").to_path_buf();
serialize(&file_path, cache_key, &cache).unwrap();
let deserialized = deserialize(&file_path, cache_key).unwrap();
assert_eq!(cache, deserialized);
}

#[test]
fn serialize_deserialize_empty() {
let temp_dir = TempDir::new();
let cache_key = "cache_key";
let cache = HashMap::new();
let file_path = temp_dir.path().join("cache.bin").to_path_buf();
serialize(&file_path, cache_key, &cache).unwrap();
let deserialized = deserialize(&file_path, cache_key).unwrap();
assert_eq!(cache, deserialized);
}

#[test]
fn serialize_deserialize_corrupt() {
let temp_dir = TempDir::new();
let file_path = temp_dir.path().join("cache.bin").to_path_buf();
std::fs::write(&file_path, b"corrupttestingtestingtesting").unwrap();
let err = deserialize(&file_path, "cache-key").unwrap_err();
assert_eq!(err.to_string(), "Cache key mismatch");
}
}