changeset 8329:c91b59532f32

load-path.cc (load_path::dir_info::update): smarter handling of relative names
author John W. Eaton <jwe@octave.org>
date Mon, 17 Nov 2008 22:30:39 -0500
parents c2d126754a49
children 8303f0e912bc
files src/ChangeLog src/load-path.cc src/load-path.h
diffstat 3 files changed, 82 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Tue Nov 18 02:40:37 2008 +0100
+++ b/src/ChangeLog	Mon Nov 17 22:30:39 2008 -0500
@@ -1,3 +1,18 @@
+2008-11-17  John W. Eaton  <jwe@octave.org>
+
+	* load-path.h (load_path::dir_info::abs_dir_name): New data member.
+	(load_path::dir_info::dir_info, load_path::dir_info::operator =):
+	Copy abs_dir_name.
+	(load_path::abs_dir_cache_type, load_path::dir_cache_iterator,
+	load_path::const_dir_cache_iterator): New typedefs.
+	(load_path::abs_dir_cache): New static data member.
+	(load_path::dir_info:dir_info): New constructor.
+	* load-path.cc (load_path::abs_dir_cache): Define new static data
+	member.
+	(load_path::dir_info::update): Look in abs_dir_cache for relative
+	directory names.
+	(load_path::dir_info::initialize): Update abs_dir_cache here.
+
 2008-11-13  John W. Eaton  <jwe@octave.org>
 
 	* ov-int8.h, ov-int16.h, ov-int32.h, ov-int64.h, ov-uint8.h,
--- a/src/load-path.cc	Tue Nov 18 02:40:37 2008 +0100
+++ b/src/load-path.cc	Mon Nov 17 22:30:39 2008 -0500
@@ -47,26 +47,59 @@
 load_path::hook_fcn_ptr load_path::remove_hook = execute_pkg_del;
 std::string load_path::command_line_path;
 std::string load_path::sys_path;
+load_path::abs_dir_cache_type load_path::abs_dir_cache;
 
 void
 load_path::dir_info::update (void)
 {
   if (is_relative)
-    initialize ();
+    {
+      std::string abs_name
+	= octave_env::make_absolute (dir_name, octave_env::getcwd ());
+
+      abs_dir_cache_iterator p = abs_dir_cache.find (abs_name);
+
+      if (p != abs_dir_cache.end ())
+	{
+	  // The directory is in the cache of all directories we have
+	  // visited (indexed by its absolute name).  If it is out of
+	  // date, initialize it.  Otherwise, copy the info from the
+	  // cache.  By doing that, we avoid unnecessary calls to stat
+	  // that can slow things down tremendously for large
+	  // directories.
+
+	  const dir_info& di = p->second;
+
+	  file_stat fs (dir_name);
+
+	  if (fs)
+	    {
+	      if (fs.mtime () != di.dir_mtime)
+		initialize ();
+	      else
+		*this = di;
+
+	      return;
+	    }
+	  else
+	    {
+	      std::string msg = fs.error ();
+	      warning ("load_path: %s: %s", dir_name.c_str (), msg.c_str ());
+	    }
+	}
+    }
+
+  file_stat fs (dir_name);
+
+  if (fs)
+    {
+      if (fs.mtime () != dir_mtime)
+	initialize ();
+    }
   else
     {
-      file_stat fs (dir_name);
-
-      if (fs)
-	{
-	  if (fs.mtime () != dir_mtime)
-	    initialize ();
-	}
-      else
-	{
-	  std::string msg = fs.error ();
-	  warning ("load_path: %s: %s", dir_name.c_str (), msg.c_str ());
-	}
+      std::string msg = fs.error ();
+      warning ("load_path: %s: %s", dir_name.c_str (), msg.c_str ());
     }
 }
 
@@ -82,6 +115,11 @@
       dir_mtime = fs.mtime ();
 
       get_file_list (dir_name);
+
+      std::string abs_name
+	= octave_env::make_absolute (dir_name, octave_env::getcwd ());
+
+      abs_dir_cache[abs_name] = *this;      
     }
   else
     {
--- a/src/load-path.h	Tue Nov 18 02:40:37 2008 +0100
+++ b/src/load-path.h	Mon Nov 17 22:30:39 2008 -0500
@@ -251,10 +251,16 @@
     typedef method_file_map_type::const_iterator const_method_file_map_iterator;
     typedef method_file_map_type::iterator method_file_map_iterator;
 
+    // This default constructor is only provided so we can create a
+    // std::map of dir_info objects.  You should not use this
+    // constructor for any other purpose.
+    dir_info (void) { }
+
     dir_info (const std::string& d) : dir_name (d) { initialize (); }
 
     dir_info (const dir_info& di)
-      : dir_name (di.dir_name), is_relative (di.is_relative),
+      : dir_name (di.dir_name), abs_dir_name (di.abs_dir_name),
+	is_relative (di.is_relative),
 	dir_mtime (di.dir_mtime), all_files (di.all_files),
 	fcn_files (di.fcn_files),
 	private_file_map (di.private_file_map),
@@ -267,6 +273,7 @@
       if (&di != this)
 	{
 	  dir_name = di.dir_name;
+	  abs_dir_name = di.abs_dir_name;
 	  is_relative = di.is_relative;
 	  dir_mtime = di.dir_mtime;
 	  all_files = di.all_files;
@@ -281,6 +288,7 @@
     void update (void);
 
     std::string dir_name;
+    std::string abs_dir_name;
     bool is_relative;
     octave_time dir_mtime;
     string_vector all_files;
@@ -346,6 +354,11 @@
   typedef dir_info_list_type::const_iterator const_dir_info_list_iterator;
   typedef dir_info_list_type::iterator dir_info_list_iterator;
 
+  typedef std::map<std::string, dir_info> abs_dir_cache_type;
+
+  typedef abs_dir_cache_type::const_iterator const_abs_dir_cache_iterator;
+  typedef abs_dir_cache_type::iterator abs_dir_cache_iterator;
+
   typedef std::list<file_info> file_info_list_type;
 
   typedef file_info_list_type::const_iterator const_file_info_list_iterator;
@@ -387,6 +400,8 @@
 
   static std::string sys_path;
 
+  static abs_dir_cache_type abs_dir_cache;
+
   static bool instance_ok (void);
 
   const_dir_info_list_iterator find_dir_info (const std::string& dir) const;