[gparted] Cache looked up major, minor numbers in BlockSpecial class (#767842)



commit 003d6eff943b3ce37e90100f660eaceda8519421
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Tue Jul 12 08:05:53 2016 +0100

    Cache looked up major, minor numbers in BlockSpecial class (#767842)
    
    Creation of every BlockSpecial object used to result in a stat() OS
    call.  On one of my test VMs debugging with 4 disks and a few partitions
    on each, GParted refresh generated 541 calls to stat() in the
    BlockSpecial(name) constructor.  However there were only 45 unique
    names.  So on average each name was stat()ed approximately 12 times.
    
    Cache the major, minor number associated with each name after starting
    with a cleared cache for each GParted refresh.  This reduces these
    direct calls to stat() to just the 45 unique names.
    
    Bug 767842 - File system usage missing when tools report alternate block
                 device names

 include/BlockSpecial.h |    2 ++
 src/BlockSpecial.cc    |   37 +++++++++++++++++++++++++++++++++++++
 src/GParted_Core.cc    |    3 +++
 3 files changed, 42 insertions(+), 0 deletions(-)
---
diff --git a/include/BlockSpecial.h b/include/BlockSpecial.h
index 3635a27..71f3357 100644
--- a/include/BlockSpecial.h
+++ b/include/BlockSpecial.h
@@ -41,6 +41,8 @@ public:
        Glib::ustring m_name;   // E.g. Block special file {"/dev/sda1", 8, 1},
        unsigned long m_major;  // plain file {"FILENAME", 0, 0} and empty object
        unsigned long m_minor;  // {"", 0, 0}.
+
+       static void clear_cache();
 };
 
 // Operator overloading > The Decision between Member and Non-member
diff --git a/src/BlockSpecial.cc b/src/BlockSpecial.cc
index ebd29f0..ed6ff71 100644
--- a/src/BlockSpecial.cc
+++ b/src/BlockSpecial.cc
@@ -20,28 +20,65 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <map>
 
 namespace GParted
 {
 
+struct MM_Number
+{
+       unsigned long m_major;
+       unsigned long m_minor;
+};
+
+typedef std::map<Glib::ustring, MM_Number> MMNumberMapping;
+
+// Associative array caching name to major, minor number pairs
+// E.g.
+//     mm_number_cache["/dev/sda"]  = {8, 0}
+//     mm_number_cache["/dev/sda1"] = {8, 1}
+//     mm_number_cache["proc"]      = {0, 0}
+//     mm_number_cache["sysfs"]     = {0, 0}
+static MMNumberMapping mm_number_cache;
+
 BlockSpecial::BlockSpecial() : m_name( "" ), m_major( 0UL ), m_minor( 0UL )
 {
 }
 
 BlockSpecial::BlockSpecial( const Glib::ustring & name ) : m_name( name ), m_major( 0UL ), m_minor( 0UL )
 {
+       MMNumberMapping::const_iterator mm_num_iter = mm_number_cache.find( name );
+       if ( mm_num_iter != mm_number_cache.end() )
+       {
+               // Use already cached major, minor pair
+               m_major = mm_num_iter->second.m_major;
+               m_minor = mm_num_iter->second.m_minor;
+               return;
+       }
+
+       MM_Number pair = {0UL, 0UL};
+       // Call stat(name, ...) to get the major, minor pair
        struct stat sb;
        if ( stat( name.c_str(), &sb ) == 0 && S_ISBLK( sb.st_mode ) )
        {
                m_major = major( sb.st_rdev );
                m_minor = minor( sb.st_rdev );
+               pair.m_major = m_major;
+               pair.m_minor = m_minor;
        }
+       // Add new cache entry for name to major, minor pair
+       mm_number_cache[name] = pair;
 }
 
 BlockSpecial::~BlockSpecial()
 {
 }
 
+void BlockSpecial::clear_cache()
+{
+       mm_number_cache.clear();
+}
+
 bool operator==( const BlockSpecial & lhs, const BlockSpecial & rhs )
 {
        if ( lhs.m_major > 0UL && lhs.m_minor > 0UL )
diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc
index 6d7bc9d..ade2ab4 100644
--- a/src/GParted_Core.cc
+++ b/src/GParted_Core.cc
@@ -166,6 +166,9 @@ void GParted_Core::set_devices_thread( std::vector<Device> * pdevices )
        std::vector<Device> &devices = *pdevices;
        devices .clear() ;
        Device temp_device ;
+       BlockSpecial::clear_cache();            // MUST BE FIRST.  Cache of name to major, minor
+                                               // numbers incrementally loaded when BlockSpecial
+                                               // objects are created in the following caches.
        Proc_Partitions_Info pp_info( true ) ;  //Refresh cache of proc partition information
        FS_Info fs_info( true ) ;  //Refresh cache of file system information
        DMRaid dmraid( true ) ;    //Refresh cache of dmraid device information


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