help-octave
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Octave suddenly slow


From: David Bateman
Subject: Re: Octave suddenly slow
Date: Tue, 18 Nov 2008 02:42:04 +0100
User-agent: Mozilla-Thunderbird 2.0.0.17 (X11/20081018)

Rob Mahurin wrote:
Adding 10^4 empty files to a directory makes octave open a couple seconds slower; adding 10^5 empty files makes it take eight minutes. I have heard of bugs in filesystems that cause this problem, but that doesn't seem to be the case since "ls | wc" is fast in the shell.

The filesystem bug I remember (or maybe an ls bug? or both?) was an inefficient sort in the code that lists the names of files in a directory. Poking through the code, I don't see anything like that.

Hmmmm ... dir_entry::read() seems to guess that it will live in a small directory. For the case I've outlined above, the attached patch should reduce the number of calls to Array::resize() from ~1000 to ~10. Not tested, though.


The conclusive manner to check would be with gprof. But that requires a static build with

CFLAGS="-g -pg -O2"
CXXFLAGS="-g -pg -O2"
FFLAGS="-g -pg -O2"
LDFLAGS="-g -pg -O2"
./configure --enable-static --disable-dl --disable-shared
I previously noticed that file_ops::tilde_expand consumed a lot of time in gprof at startup.

http://www.nabble.com/forum/ViewPost.jtp?post=12531612&framed=y

So perhaps the attached change to file_ops::tilde_expand might also help. For me with this change I see with the following with the command

time octave --eval quit

the wall times are

                Normal   1e4 files    1.1e5 files
With Patch       0.760    1.059         8.414
Without Patch    1.116    2.801        20.786

So for me the speeds are significantly faster with my patch (note this is without any packages installed). I don't think your patch is quite right as you start with a zero sized array with len not equal to zero. I prefer a patch like

--- a/liboctave/dir-ops.cc
+++ b/liboctave/dir-ops.cc
@@ -87,7 +87,7 @@
            {
              if (count >= len)
                {
-                 len += grow_size;
+                 len = (len == 0 ? grow_size : len * 2);
                  dirlist.resize (len);
                }

Adding this and my previous patch gives a startup time of

                Normal   1e4 files    1.1e5 files
With Patches     0.831    1.025         3.516
Without Patches  1.116    2.801        20.786

So the two patches together give a significant improvement. John added a slighly different change to dir_entry::read just now so I only committed my change to tilde_expand..

Regards
David


--
David Bateman                                address@hidden
35 rue Gambetta                              +33 1 46 04 02 18 (Home)
92100 Boulogne-Billancourt FRANCE            +33 6 72 01 06 33 (Mob)
# HG changeset patch
# User David Bateman <address@hidden>
# Date 1226971456 -3600
# Node ID a0b8453624afeb692861a40c276ab38d75a9a3f8
# Parent  d793ed7122be8e01b4f521e147c5337ef11ab9fa
Fast return case for file_ops::tilde_expand. Expontential dirlist resize in 
dir_entry::read

diff --git a/liboctave/ChangeLog b/liboctave/ChangeLog
--- a/liboctave/ChangeLog
+++ b/liboctave/ChangeLog
@@ -1,3 +1,14 @@
+2008-11-18  Robert S. Mahurin  <address@hidden>
+
+       * dir-ops.cc (string_vector dir_entry::read (void)): Expontential
+       resize of dirlist to avoid too many memory reallocations.
+
+2008-11-18  David Bateman  <address@hidden>
+
+       * file-ops.cc (std::string file_ops::tilde_expand (const 
+       std::string&)): Check if the string contains a tilde and fast 
+       return if not.
+
 2008-11-14  David Bateman  <address@hidden>
 
        * Array2.h (Array2<T> Array2<T>::index): Correct use of
diff --git a/liboctave/dir-ops.cc b/liboctave/dir-ops.cc
--- a/liboctave/dir-ops.cc
+++ b/liboctave/dir-ops.cc
@@ -87,7 +87,7 @@
            {
              if (count >= len)
                {
-                 len += grow_size;
+                 len = (len == 0 ? grow_size : len * 2);
                  dirlist.resize (len);
                }
 
diff --git a/liboctave/file-ops.cc b/liboctave/file-ops.cc
--- a/liboctave/file-ops.cc
+++ b/liboctave/file-ops.cc
@@ -768,53 +768,58 @@
 std::string
 file_ops::tilde_expand (const std::string& name)
 {
-  std::string result;
+  if (name.find ('~') == std::string::npos)
+    return name;
+  else
+    {
+      std::string result;
 
-  size_t name_len = name.length ();
+      size_t name_len = name.length ();
 
-  // Scan through S expanding tildes as we come to them.
+      // Scan through S expanding tildes as we come to them.
 
-  size_t pos = 0;
+      size_t pos = 0;
 
-  while (1)
-    {
-      if (pos > name_len)
-       break;
+      while (1)
+       {
+         if (pos > name_len)
+           break;
 
-      size_t len;
+         size_t len;
 
-      // Make START point to the tilde which starts the expansion.
+         // Make START point to the tilde which starts the expansion.
 
-      size_t start = tilde_find_prefix (name.substr (pos), len);
+         size_t start = tilde_find_prefix (name.substr (pos), len);
 
-      result.append (name.substr (pos, start));
+         result.append (name.substr (pos, start));
 
-      // Advance STRING to the starting tilde.
+         // Advance STRING to the starting tilde.
 
-      pos += start;
+         pos += start;
 
-      // Make FINI be the index of one after the last character of the
-      // username.
+         // Make FINI be the index of one after the last character of the
+         // username.
 
-      size_t fini = tilde_find_suffix (name.substr (pos));
+         size_t fini = tilde_find_suffix (name.substr (pos));
 
-      // If both START and FINI are zero, we are all done.
+         // If both START and FINI are zero, we are all done.
 
-      if (! (start || fini))
-       break;
+         if (! (start || fini))
+           break;
 
-      // Expand the entire tilde word, and copy it into RESULT.
+         // Expand the entire tilde word, and copy it into RESULT.
 
-      std::string tilde_word = name.substr (pos, fini);
+         std::string tilde_word = name.substr (pos, fini);
 
-      pos += fini;
+         pos += fini;
 
-      std::string expansion = tilde_expand_word (tilde_word);
+         std::string expansion = tilde_expand_word (tilde_word);
 
-      result.append (expansion);
+         result.append (expansion);
+       }
+
+      return result;
     }
-
-  return result;
 }
 
 // A vector version of the above.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]