Skip to content

Commit

Permalink
dont clone module cache entry
Browse files Browse the repository at this point in the history
  • Loading branch information
JoshuaBatty committed Jul 23, 2024
1 parent 1ea636b commit e59ef82
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 25 deletions.
2 changes: 1 addition & 1 deletion sway-core/src/language/ty/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub struct TyModule {

#[derive(Clone, Debug)]
pub struct TySubmodule {
pub module: TyModule,
pub module: Arc<TyModule>,
pub mod_name_span: Span,
}

Expand Down
4 changes: 2 additions & 2 deletions sway-core/src/language/ty/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ impl CollectTypesMetadata for TyProgram {
for module in std::iter::once(&self.root).chain(
self.root
.submodules_recursive()
.map(|(_, submod)| &submod.module),
.map(|(_, submod)| &*submod.module),
) {
for node in module.all_nodes.iter() {
let is_generic_function = node.is_generic_function(decl_engine);
Expand Down Expand Up @@ -531,7 +531,7 @@ impl CollectTypesMetadata for TyProgram {
for module in std::iter::once(&self.root).chain(
self.root
.submodules_recursive()
.map(|(_, submod)| &submod.module),
.map(|(_, submod)| &*submod.module),
) {
for node in module.all_nodes.iter() {
if node.is_test_function(decl_engine) {
Expand Down
38 changes: 33 additions & 5 deletions sway-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,9 +460,10 @@ pub(crate) fn is_ty_module_cache_up_to_date(
) -> bool {
let query_engine = engines.qe();
let key = ModuleCacheKey::new(path.clone(), include_tests);
let entry = query_engine.get_module_cache_entry(&key);
let cache = query_engine.module_cache.read();
let entry = cache.get(&key);
match entry {
Some(entry) => match entry.typed {
Some(entry) => match &entry.typed {
Some(typed) => {
let cache_up_to_date = build_config
.as_ref()
Expand Down Expand Up @@ -493,38 +494,61 @@ pub(crate) fn is_parse_module_cache_up_to_date(
include_tests: bool,
build_config: Option<&BuildConfig>,
) -> bool {
let n1 = std::time::Instant::now();
let split_points = ["sway-lib-core", "sway-lib-std", "libraries"];
eprintln!("⏱️ split_points took: {:?}", n1.elapsed());

let n2 = std::time::Instant::now();
let relevant_path = path
.iter()
.skip_while(|&comp| !split_points.contains(&comp.to_str().unwrap()))
.collect::<PathBuf>();
eprintln!("⏱️ relevant_path took: {:?}", n2.elapsed());

let n3 = std::time::Instant::now();
let query_engine = engines.qe();
eprintln!("⏱️ query_engine took: {:?}", n3.elapsed());

let n4 = std::time::Instant::now();
let key = ModuleCacheKey::new(path.clone(), include_tests);
let entry = query_engine.get_module_cache_entry(&key);
eprintln!("⏱️ key took: {:?}", n4.elapsed());

let n5 = std::time::Instant::now();
// let entry = query_engine.get_module_cache_entry(&key);
let cache = query_engine.module_cache.read();
let entry = cache.get(&key);
eprintln!("⏱️ entry took: {:?}", n5.elapsed());

let res = match entry {
Some(entry) => {
// Let's check if we can re-use the dependency information
// we got from the cache.
let n6 = std::time::Instant::now();
let cache_up_to_date = build_config
.as_ref()
.and_then(|x| x.lsp_mode.as_ref())
.and_then(|lsp| {
eprintln!("⏱️ cache_up_to_date lsp_mode: {:?}", n6.elapsed());
// First try to get the file version from lsp if it exists
lsp.file_versions.get(path.as_ref())
})
.map_or_else(
|| {
let n7 = std::time::Instant::now();
// Otherwise we can safely read the file from disk here, as the LSP has not modified it, or we are not in LSP mode.
// Check if the file has been modified or if its hash is the same as the last compilation
let modified_time = std::fs::metadata(path.as_path())
.ok()
.and_then(|m| m.modified().ok());
eprintln!("⏱️ cache_up_to_date modified_time: {:?}", n7.elapsed());

let n8 = std::time::Instant::now();
entry.parsed.modified_time == modified_time || {
let src = std::fs::read_to_string(path.as_path()).unwrap();
let mut hasher = DefaultHasher::new();
src.hash(&mut hasher);
let hash = hasher.finish();
eprintln!("⏱️ cache_up_to_date hash: {:?}", n8.elapsed());
hash == entry.common.hash
}
},
Expand All @@ -533,16 +557,20 @@ pub(crate) fn is_parse_module_cache_up_to_date(
!version.map_or(false, |v| v > entry.parsed.version.unwrap_or(0))
},
);
eprintln!("⏱️ cache_up_to_date took: {:?}", n6.elapsed());

// Look at the dependencies recursively to make sure they have not been
// modified either.
if cache_up_to_date {
let n9 = std::time::Instant::now();
//eprintln!("num dependencies for path {:?}: {}", path, entry.dependencies.len());

entry.common.dependencies.iter().all(|path| {
let res = entry.common.dependencies.iter().all(|path| {
// eprint!("checking dep path {:?} ", path);
is_parse_module_cache_up_to_date(engines, path, include_tests, build_config)
})
});
eprintln!("⏱️ is_parse_module_cache_up_to_date: {:?}", n9.elapsed());
res
} else {
false
}
Expand Down
31 changes: 22 additions & 9 deletions sway-core/src/query_engine/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use parking_lot::RwLock;
use parking_lot::{RwLock, RwLockReadGuard};
use std::{
collections::HashMap,
ops::{Deref, DerefMut},
Expand Down Expand Up @@ -46,7 +46,7 @@ pub struct ParsedModuleInfo {

#[derive(Clone, Debug)]
pub struct TypedModuleInfo {
pub module: TyModule,
pub module: Arc<TyModule>,
pub modified_time: Option<SystemTime>,
pub version: Option<u64>,
}
Expand Down Expand Up @@ -94,7 +94,7 @@ impl ModuleCacheEntry {
}

#[derive(Debug, Default, Clone)]
struct ModuleCacheMap(HashMap<ModuleCacheKey, ModuleCacheEntry>);
pub struct ModuleCacheMap(HashMap<ModuleCacheKey, ModuleCacheEntry>);

impl Deref for ModuleCacheMap {
type Target = HashMap<ModuleCacheKey, ModuleCacheEntry>;
Expand Down Expand Up @@ -142,16 +142,26 @@ pub struct FunctionCacheEntry {
#[derive(Debug, Default, Clone)]
pub struct QueryEngine {
// We want the below types wrapped in Arcs to optimize cloning from LSP.
module_cache: Arc<RwLock<ModuleCacheMap>>,
pub module_cache: Arc<RwLock<ModuleCacheMap>>,
programs_cache: Arc<RwLock<ProgramsCacheMap>>,
function_cache: Arc<RwLock<FunctionsCacheMap>>,
}

impl QueryEngine {
pub fn get_module_cache_entry(&self, key: &ModuleCacheKey) -> Option<ModuleCacheEntry> {
let cache = self.module_cache.read();
cache.get(key).cloned()
}
// pub fn get_module_cache_entry(&self, key: &ModuleCacheKey) -> Option<(RwLockReadGuard<'_, ModuleCacheMap>, &ModuleCacheEntry)> {
// let cache = self.module_cache.read();
// cache.get(key).map(|entry| (cache, entry))
// }

// pub fn get_module_cache_entry(&self, key: &ModuleCacheKey) -> Option<&ModuleCacheEntry> {
// let cache = self.module_cache.read();
// cache.get(key)
// }

// pub fn get_module_cache_entry(&self, key: &ModuleCacheKey) -> Option<ModuleCacheEntry> {
// let cache = self.module_cache.read();
// cache.get(key).cloned()
// }

pub fn update_or_insert_parsed_module_cache_entry(&self, entry: ModuleCacheEntry) {
let path = entry.common.path.clone();
Expand All @@ -167,8 +177,11 @@ impl QueryEngine {
}

pub fn get_programs_cache_entry(&self, path: &Arc<PathBuf>) -> Option<ProgramsCacheEntry> {
let now = std::time::Instant::now();
let cache = self.programs_cache.read();
cache.get(path).cloned()
let res = cache.get(path).cloned();
eprintln!("⏱️ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!get_programs_cache_entry took: {:?}", now.elapsed());
res
}

pub fn insert_programs_cache_entry(&self, entry: ProgramsCacheEntry) {
Expand Down
15 changes: 8 additions & 7 deletions sway-core/src/semantic_analysis/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ impl ty::TyModule {
source_id: Option<&SourceId>,
engines: &Engines,
build_config: Option<&BuildConfig>,
) -> Option<ty::TyModule> {
) -> Option<Arc<ty::TyModule>> {
// Check if the module is already in the cache
if let Some(source_id) = source_id {
let path = engines.se().get_path(&source_id);
Expand All @@ -275,7 +275,8 @@ impl ty::TyModule {
.collect::<PathBuf>();

let key: ModuleCacheKey = ModuleCacheKey::new(path.clone().into(), include_tests);
if let Some(entry) = engines.qe().get_module_cache_entry(&key) {
let cache = engines.qe().module_cache.read();
if let Some(entry) = cache.get(&key) {
// We now need to check if the module is up to date, if not, we need to recompute it so
// we will return None, otherwise we will return the cached module.

Expand All @@ -284,7 +285,7 @@ impl ty::TyModule {

// Let's check if we can re-use the dependency information
// we got from the cache.
if let Some(typed) = entry.typed {
if let Some(typed) = &entry.typed {
let is_up_to_date = is_ty_module_cache_up_to_date(
engines,
&path.into(),
Expand All @@ -301,7 +302,7 @@ impl ty::TyModule {
status, relevant_path, is_up_to_date
);
if is_up_to_date {
return Some(typed.module);
return Some(typed.module.clone());
}
}
} else {
Expand All @@ -321,7 +322,7 @@ impl ty::TyModule {
kind: TreeType,
parsed: &ParseModule,
build_config: Option<&BuildConfig>,
) -> Result<Self, ErrorEmitted> {
) -> Result<Arc<Self>, ErrorEmitted> {
let ParseModule {
submodules,
tree,
Expand Down Expand Up @@ -458,13 +459,13 @@ impl ty::TyModule {
}
}

let ty_module = Self {
let ty_module = Arc::new(Self {
span: span.clone(),
submodules,
namespace: ctx.namespace.clone(),
all_nodes,
attributes: attributes.clone(),
};
});

// Cache the ty module
if let Some(source_id) = span.source_id() {
Expand Down
2 changes: 1 addition & 1 deletion sway-core/src/semantic_analysis/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl TyProgram {

let program = TyProgram {
kind,
root,
root: (*root).clone(),
declarations,
configurables,
storage_slots: vec![],
Expand Down

0 comments on commit e59ef82

Please sign in to comment.