[m-rev.] diff: Use version_hash_table for target_file timestamps cache.

Peter Wang novalazy at gmail.com
Mon Dec 5 17:28:02 AEDT 2022


This change improves the run time of a do-nothing build of Prince using
mmc --make on my machine from 1.46 s to 1.19 s.

compiler/make.make_info.m:
    Use version_hash_table for the target_file timestamps cache
    instead of a tree234 map.

compiler/make.util.m:
    Add function to initialised a target_file_timestamps.

    Conform to change in type.

compiler/make.module_target.m:
compiler/make.program_target.m:
compiler/make.top_level.m:
    Conform to change in type.

    Add a comment about a possible change.
---
 compiler/make.make_info.m      |  2 +-
 compiler/make.module_target.m  | 10 ++++++++--
 compiler/make.program_target.m |  2 +-
 compiler/make.top_level.m      |  2 +-
 compiler/make.util.m           | 21 +++++++++++++++------
 5 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/compiler/make.make_info.m b/compiler/make.make_info.m
index d5504b65a..3be860673 100644
--- a/compiler/make.make_info.m
+++ b/compiler/make.make_info.m
@@ -156,7 +156,7 @@
 
 :- type file_timestamps == map(string, maybe_error(timestamp)).
 
-:- type target_file_timestamps == map(target_file, timestamp).
+:- type target_file_timestamps == version_hash_table(target_file, timestamp).
 
 % NOTE Having version_arrays be indexed by uints, not ints
 % that just happen to never be negative, would avoid some casts
diff --git a/compiler/make.module_target.m b/compiler/make.module_target.m
index 8b79dcdbe..822cff343 100644
--- a/compiler/make.module_target.m
+++ b/compiler/make.module_target.m
@@ -219,6 +219,11 @@ make_module_target_file_main_path(ExtraOptions, Globals, TargetFile,
             Globals, to_sorted_list(ModulesToCheckSet),
             succeeded, DepsSucceeded, sparse_bitset.init, DepFiles0,
             !Info, !IO),
+        % NOTE: converting the dep_set to a plain set is relatively expensive,
+        % so it would be better to avoid it. Also, there should be a definite
+        % improvement if we could represent the dependency_status map with an
+        % array indexed by dependency_file_indexes, instead of a hash table
+        % indexed by dependency_file terms.
         dependency_file_index_set_to_plain_set(!.Info, DepFiles0,
             DepFilesSet0),
         ( if TargetType = module_target_int0 then
@@ -245,7 +250,7 @@ make_module_target_file_main_path(ExtraOptions, Globals, TargetFile,
         KeepGoing = !.Info ^ mki_keep_going,
         ( if
             DepsSucceeded = did_not_succeed,
-            KeepGoing= do_not_keep_going
+            KeepGoing = do_not_keep_going
         then
             DepsResult = deps_error
         else
@@ -824,7 +829,8 @@ record_made_target_given_maybe_touched_files(Globals, Succeeded, TargetFile,
     ),
 
     TargetFileTimestamps0 = !.Info ^ mki_target_file_timestamps,
-    map.delete(TargetFile, TargetFileTimestamps0, TargetFileTimestamps),
+    version_hash_table.delete(TargetFile,
+        TargetFileTimestamps0, TargetFileTimestamps),
     !Info ^ mki_target_file_timestamps := TargetFileTimestamps.
 
 :- pred update_target_status(dependency_status::in, target_file::in,
diff --git a/compiler/make.program_target.m b/compiler/make.program_target.m
index f9cc8a04e..b1716b072 100644
--- a/compiler/make.program_target.m
+++ b/compiler/make.program_target.m
@@ -747,7 +747,7 @@ make_java_files(Globals, MainModuleName, ObjModules, Succeeded, !Info, !IO) :-
             map.init, Timestamps),
         !Info ^ mki_file_timestamps := Timestamps,
         % For simplicity, clear out all target file timestamps.
-        !Info ^ mki_target_file_timestamps := map.init
+        !Info ^ mki_target_file_timestamps := init_target_file_timestamps
     ).
 
 :- pred out_of_date_java_modules(globals::in, list(module_name)::in,
diff --git a/compiler/make.top_level.m b/compiler/make.top_level.m
index d90fe86cf..a4ecc9c67 100644
--- a/compiler/make.top_level.m
+++ b/compiler/make.top_level.m
@@ -119,7 +119,7 @@ make_process_compiler_args(Globals, DetectedGradeFlags, Variables, OptionArgs,
 
         map.init(ModuleDependencies),
         map.init(FileTimestamps),
-        map.init(TargetTimestamps),
+        TargetTimestamps = init_target_file_timestamps,
         set.init(ErrorFileModules),
         MaybeImportingModule = maybe.no,
         MaybeStdoutLock = maybe.no,
diff --git a/compiler/make.util.m b/compiler/make.util.m
index a8830439e..94f7925c5 100644
--- a/compiler/make.util.m
+++ b/compiler/make.util.m
@@ -39,6 +39,8 @@
 % Timestamp handling.
 %
 
+:- func init_target_file_timestamps = target_file_timestamps.
+
     % Find the timestamp updated when a target is produced.
     %
 :- pred get_timestamp_file_timestamp(globals::in, target_file::in,
@@ -281,10 +283,14 @@
 :- import_module set.
 :- import_module string.
 :- import_module uint.
+:- import_module version_hash_table.
 
 %---------------------------------------------------------------------------%
 %---------------------------------------------------------------------------%
 
+init_target_file_timestamps =
+    version_hash_table.unsafe_init_default(target_file_hash).
+
 get_timestamp_file_timestamp(Globals, target_file(ModuleName, TargetType),
         MaybeTimestamp, !Info, !IO) :-
     ( if timestamp_extension(TargetType, TimestampOtherExt) then
@@ -338,7 +344,10 @@ get_target_timestamp(Globals, Search, TargetFile, MaybeTimestamp, !Info,
         % target_file. It avoids having to compute a file name for a
         % target_file first, before looking up the timestamp for that file.
         TargetFileTimestamps0 = !.Info ^ mki_target_file_timestamps,
-        ( if map.search(TargetFileTimestamps0, TargetFile, Timestamp) then
+        ( if
+            version_hash_table.search(TargetFileTimestamps0, TargetFile,
+                Timestamp)
+        then
             MaybeTimestamp = ok(Timestamp)
         else
             get_file_name(Globals, Search, TargetFile, FileName, !Info, !IO),
@@ -347,7 +356,7 @@ get_target_timestamp(Globals, Search, TargetFile, MaybeTimestamp, !Info,
             (
                 MaybeTimestamp = ok(Timestamp),
                 TargetFileTimestamps1 = !.Info ^ mki_target_file_timestamps,
-                map.det_insert(TargetFile, Timestamp,
+                version_hash_table.det_insert(TargetFile, Timestamp,
                     TargetFileTimestamps1, TargetFileTimestamps),
                 !Info ^ mki_target_file_timestamps := TargetFileTimestamps
             ;
@@ -567,7 +576,7 @@ make_remove_file(Globals, VerboseOption, FileName, !Info, !IO) :-
     !Info ^ mki_file_timestamps := FileTimestamps,
 
     % For simplicity, clear out all target file timestamps.
-    !Info ^ mki_target_file_timestamps := map.init.
+    !Info ^ mki_target_file_timestamps := init_target_file_timestamps.
 
 :- pred report_remove_file(string::in, io::di, io::uo) is det.
 
@@ -1136,7 +1145,7 @@ module_name_hash(SymName, Hash) :-
 dependency_file_hash(DepFile, Hash) :-
     (
         DepFile = dep_target(TargetFile),
-        Hash = target_file_hash(TargetFile)
+        target_file_hash(TargetFile, Hash)
     ;
         DepFile = dep_file(FileName),
         Hash = string.hash(FileName)
@@ -1153,9 +1162,9 @@ dependency_file_with_module_index_hash(DepFile, Hash) :-
         Hash = string.hash(FileName)
     ).
 
-:- func target_file_hash(target_file) = int.
+:- pred target_file_hash(target_file::in, int::out) is det.
 
-target_file_hash(TargetFile) = Hash :-
+target_file_hash(TargetFile, Hash) :-
     TargetFile = target_file(ModuleName, Type),
     module_name_hash(ModuleName, Hash0),
     Hash1 = module_target_type_to_nonce(Type),
-- 
2.38.0



More information about the reviews mailing list