From a99c8dbb5fb25d25f3ce4f0848d1c9b6a5c43f49 Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Fri, 31 Jul 2026 15:36:02 +0200 Subject: [PATCH 1/2] Update `doSaveModule` to use map lookups instead of linear searches --- .../compiler/lang/rascalcore/check/Import.rsc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/Import.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/Import.rsc index 6b39268e7ef..f08e7535863 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/Import.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/Import.rsc @@ -421,16 +421,20 @@ ModuleStatus doSaveModule(set[MODID] component, map[MODID,set[MODID]] m_imports, if(isEmpty(component)) return ms; //println("doSaveModule: , , , "); - component_scopes = component; //{ getModuleScope(mid, moduleScopes, pcfg) | MODID mid <- component }; + set[MODID] componentScopes = component; //{ getModuleScope(mid, moduleScopes, pcfg) | MODID mid <- component }; + map[str, MODID] componentScopesByUri = (); set[MODID] filteredModuleScopes = {}; + map[str, MODID] filteredModuleScopesByUri = (); loc2moduleName = invertUnique(ms.moduleLocs); bool isContainedInComponentScopes(loc inner, map[loc,loc] m){ - return any(cs <- component_scopes, isContainedIn(inner, cs, m)); + inner = m[inner] ? inner; + return inner.uri in componentScopesByUri ? isContainedIn(inner, componentScopesByUri[inner.uri]) : false; }; bool isContainedInFilteredModuleScopes(loc inner, map[loc,loc] m){ - return any(cs <- filteredModuleScopes, isContainedIn(inner, cs, m)); + inner = m[inner] ? inner; + return inner.uri in filteredModuleScopesByUri ? isContainedIn(inner, filteredModuleScopesByUri[inner.uri]) : false; }; for(currentModule <- component){ @@ -443,9 +447,12 @@ ModuleStatus doSaveModule(set[MODID] component, map[MODID,set[MODID]] m_imports, bom = makeBom(currentModule, ms); + componentScopesByUri = (s.uri: s | loc s <- componentScopes, loc s := tm.logical2physical[s] ? s); + extendedModuleScopes = {m | MODID m <- extends, hasProperty(m, ms, checked())}; extendedModuleScopes += {*tm.paths[ems,importPath()] | MODID ems <- extendedModuleScopes}; // add imports of extended modules filteredModuleScopes = {m | MODID m <- (currentModule + imports), hasProperty(m, ms, checked())} + extendedModuleScopes; + filteredModuleScopesByUri = (m.uri: m | loc m <- filteredModuleScopes, loc m := tm.logical2physical[m] ? m); TModel m1 = tmodel(); m1.version = getCurrentTplVersion(); @@ -455,7 +462,7 @@ ModuleStatus doSaveModule(set[MODID] component, map[MODID,set[MODID]] m_imports, m1.facts = (key : tm.facts[key] | key <- tm.facts, isContainedInFilteredModuleScopes(key, tm.logical2physical)); - m1.specializedFacts = (key : tm.specializedFacts[key] | key <- tm.specializedFacts, isContainedInComponentScopes(key, tm.logical2physical), any(fms <- filteredModuleScopes, isContainedIn(key, fms))); + m1.specializedFacts = (key : tm.specializedFacts[key] | key <- tm.specializedFacts, isContainedInComponentScopes(key, tm.logical2physical), isContainedInFilteredModuleScopes(key, tm.logical2physical)); m1.facts += m1.specializedFacts; m1.messages = [msg | msg <- tm.messages, isContainedIn(msg.at, currentModule, tm.logical2physical)]; From 880892ce3ee7ad6e344708b092729e2f7b1d4d77 Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Tue, 4 Aug 2026 13:44:09 +0200 Subject: [PATCH 2/2] Update `doSaveModule` to reduce the number of field lookups --- .../compiler/lang/rascalcore/check/Import.rsc | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/Import.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/Import.rsc index f08e7535863..f4658794402 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/Import.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/Import.rsc @@ -447,12 +447,20 @@ ModuleStatus doSaveModule(set[MODID] component, map[MODID,set[MODID]] m_imports, bom = makeBom(currentModule, ms); - componentScopesByUri = (s.uri: s | loc s <- componentScopes, loc s := tm.logical2physical[s] ? s); + // Lookup fields only once to save interpreter time (significant) + paths = tm.paths; + facts = tm.facts; + specializedFacts = tm.specializedFacts; + useDef = tm.useDef; + logical2physical = tm.logical2physical; + definitions = tm.definitions; + + componentScopesByUri = (s.uri: s | loc s <- componentScopes, loc s := logical2physical[s] ? s); extendedModuleScopes = {m | MODID m <- extends, hasProperty(m, ms, checked())}; - extendedModuleScopes += {*tm.paths[ems,importPath()] | MODID ems <- extendedModuleScopes}; // add imports of extended modules + extendedModuleScopes += {*paths[ems,importPath()] | MODID ems <- extendedModuleScopes}; // add imports of extended modules filteredModuleScopes = {m | MODID m <- (currentModule + imports), hasProperty(m, ms, checked())} + extendedModuleScopes; - filteredModuleScopesByUri = (m.uri: m | loc m <- filteredModuleScopes, loc m := tm.logical2physical[m] ? m); + filteredModuleScopesByUri = (m.uri: m | loc m <- filteredModuleScopes, loc m := logical2physical[m] ? m); TModel m1 = tmodel(); m1.version = getCurrentTplVersion(); @@ -460,15 +468,15 @@ ModuleStatus doSaveModule(set[MODID] component, map[MODID,set[MODID]] m_imports, m1.modelName = moduleId2moduleName(currentModule); m1.moduleLocs = (m1.modelName : currentModule); - m1.facts = (key : tm.facts[key] | key <- tm.facts, isContainedInFilteredModuleScopes(key, tm.logical2physical)); + m1.facts = (key : facts[key] | key <- facts, isContainedInFilteredModuleScopes(key, logical2physical)); - m1.specializedFacts = (key : tm.specializedFacts[key] | key <- tm.specializedFacts, isContainedInComponentScopes(key, tm.logical2physical), isContainedInFilteredModuleScopes(key, tm.logical2physical)); + m1.specializedFacts = (key : specializedFacts[key] | key <- specializedFacts, isContainedInComponentScopes(key, logical2physical), isContainedInFilteredModuleScopes(key, logical2physical)); m1.facts += m1.specializedFacts; - m1.messages = [msg | msg <- tm.messages, isContainedIn(msg.at, currentModule, tm.logical2physical)]; + m1.messages = [msg | msg <- tm.messages, isContainedIn(msg.at, currentModule, logical2physical)]; ms.messages[currentModule] = toSet(m1.messages); - filteredModuleScopePaths = {ml.path |loc ml <- filteredModuleScopes}; + // filteredModuleScopePaths = {ml.path |loc ml <- filteredModuleScopes}; m1.scopes = tm.scopes; // m1.scopes // = ( inner : tm.scopes[inner] @@ -487,23 +495,23 @@ ModuleStatus doSaveModule(set[MODID] component, map[MODID,set[MODID]] m_imports, m1.store[key_common_keyword_fields] = tm.store[key_common_keyword_fields] ? []; - m1.paths = { tup | tuple[MODID from, PathRole pathRole, MODID to] tup <- tm.paths, tup.from == currentModule || tup.from in filteredModuleScopes /*|| tup.from in filteredModuleScopePaths*/ }; + m1.paths = { tup | tuple[MODID from, PathRole pathRole, MODID to] tup <- paths, tup.from == currentModule || tup.from in filteredModuleScopes /*|| tup.from in filteredModuleScopePaths*/ }; keepRoles = variableRoles + keepInTModelRoles; m1.useDef = { - | <- tm.useDef, - isContainedIn(u, currentModule, tm.logical2physical) - || (tm.definitions[d]? && tm.definitions[d].idRole in keepRoles) + | <- useDef, + isContainedIn(u, currentModule, logical2physical) + || (definitions[d]? && definitions[d].idRole in keepRoles) }; // Filter model for current module and replace functions in defType by their defined type defs = for(tup: <- tm.defines){ - if( ( idRole in variableRoles ? ( isContainedInComponentScopes(defined, tm.logical2physical) + if( ( idRole in variableRoles ? ( isContainedInComponentScopes(defined, logical2physical) ) : ( idRole in keepInTModelRoles - && ( isContainedInComponentScopes(defined, tm.logical2physical) - || isContainedInFilteredModuleScopes(defined, tm.logical2physical) + && ( isContainedInComponentScopes(defined, logical2physical) + || isContainedInFilteredModuleScopes(defined, logical2physical) ) ) ) @@ -518,11 +526,12 @@ ModuleStatus doSaveModule(set[MODID] component, map[MODID,set[MODID]] m_imports, m1.define2id = tm.define2id; // Remove default expressions and fragments + // (Relatively expensive: can take >50% of the execution time of this function) m1 = visit(m1) { case kwField(AType atype, str fieldName, str definingModule, Expression _defaultExp) => kwField(atype, fieldName, definingModule) case loc l : if(!isEmpty(l.fragment)) insert l[fragment=""]; }; - m1.logical2physical = tm.logical2physical; + m1.logical2physical = logical2physical; ms = deleteProperty(currentModule, ms, tpl_saved()); ms = addTModel(currentModule, m1, ms); // println("TModel for :"); iprintln(m1);