Added the testCase and memory profiler
authorkim <kim@3cdefd35-fc62-479d-8e8d-bae585ffb9ca>
Wed, 7 Jan 2009 03:02:34 +0000 (03:02 +0000)
committerkim <kim@3cdefd35-fc62-479d-8e8d-bae585ffb9ca>
Wed, 7 Jan 2009 03:02:34 +0000 (03:02 +0000)
git-svn-id: svn+ssh://idea.nguyen.vg/svn/sxsi/trunk/TextCollection@27 3cdefd35-fc62-479d-8e8d-bae585ffb9ca

HeapProfiler.cpp [new file with mode: 0644]
HeapProfiler.h [new file with mode: 0644]
dependencies.mk
makefile
testTextCollection.cpp

diff --git a/HeapProfiler.cpp b/HeapProfiler.cpp
new file mode 100644 (file)
index 0000000..d3c46f8
--- /dev/null
@@ -0,0 +1,175 @@
+/***************************************************************************
+ *   Installs handlers for malloc(), realloc() and free()                  *
+ *                                                                         *
+ *   Copyright (C) 2006 by Niko Välimäki                                   *
+ *                                                                         *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
+ ***************************************************************************/
+
+#include "HeapProfiler.h"
+
+// Static data
+unsigned long HeapProfiler::consumption = 0, HeapProfiler::maxConsumption = 0;
+AllocatedBlocks HeapProfiler::blocks;
+
+// Override initialising hook from the C library.
+void (*__malloc_initialize_hook) (void) = HeapProfiler::InitHooks;
+
+// Variables to save original hooks.
+void *(*HeapProfiler::old_malloc_hook)(size_t, const void *);
+void (*HeapProfiler::old_free_hook)(void *, const void *);
+void *(*HeapProfiler::old_realloc_hook)(void *, size_t, const void *);
+
+unsigned long HeapProfiler::GetMaxHeapConsumption() {
+    return maxConsumption;
+}
+
+unsigned long HeapProfiler::GetHeapConsumption() {
+    return consumption;
+}
+
+void HeapProfiler::InitHooks(void) {
+    old_malloc_hook = __malloc_hook;
+    old_free_hook = __free_hook;
+    old_realloc_hook = __realloc_hook;
+    __malloc_hook = HeapProfiler::MallocHook;
+    __free_hook = HeapProfiler::FreeHook;
+    __realloc_hook = HeapProfiler::ReallocHook;
+}
+
+
+void *HeapProfiler::MallocHook (size_t size, const void *caller) {
+    void *result;
+    
+    /* Restore all old hooks */
+    __malloc_hook = old_malloc_hook;
+    __free_hook = old_free_hook;
+    __realloc_hook = old_realloc_hook;
+    
+    /* Call recursively */
+    result = malloc (size);
+    
+    blocks[result] = (unsigned long)size;
+    
+    consumption += (unsigned long)size;
+    if (consumption > maxConsumption)
+        maxConsumption = consumption;
+    
+    #ifdef DEBUG_HEAPPROFILER 
+        std::cout << "malloc(" << size << ") called from " << caller << " returns " << result << " (" << consumption << ", max " << maxConsumption << ")" << std::endl;
+    #endif
+    
+    /* Save underlying hooks */
+    old_malloc_hook = __malloc_hook;
+    old_free_hook = __free_hook;
+    old_realloc_hook = __realloc_hook;
+    
+    /* Restore our own hooks */
+    __malloc_hook = HeapProfiler::MallocHook;
+    __free_hook = HeapProfiler::FreeHook;
+    __realloc_hook = HeapProfiler::ReallocHook;
+    
+    return result;
+}
+
+void HeapProfiler::FreeHook (void *ptr, const void *caller) {
+    
+    /* Restore all old hooks */
+    __malloc_hook = old_malloc_hook;
+    __free_hook = old_free_hook;
+    __realloc_hook = old_realloc_hook;
+     
+    /* Call recursively */
+    free (ptr);
+    
+    AllocatedBlocks::iterator result = blocks.find(ptr);
+    if (result != blocks.end())
+    {
+        #ifdef DEBUG_HEAPPROFILER 
+            std::cout << "found: " << (*result).second << std::endl;
+        #endif
+        consumption -= (*result).second;
+        blocks.erase(result);
+    } else {
+        #ifdef DEBUG_HEAPPROFILER 
+            std::cout << "not found" << std::endl;
+        #endif
+    }
+
+    #ifdef DEBUG_HEAPPROFILER
+        std::cout << "free(" << ptr << ") called from " << caller << " (" << consumption << ", max " << maxConsumption << ")" << std::endl;
+    #endif
+    
+    /* Save underlying hooks */
+    old_malloc_hook = __malloc_hook;
+    old_free_hook = __free_hook;
+    old_realloc_hook = __realloc_hook;
+        
+    /* Restore our own hooks */
+    __malloc_hook = HeapProfiler::MallocHook;
+    __free_hook = HeapProfiler::FreeHook;
+    __realloc_hook = HeapProfiler::ReallocHook;
+}
+
+
+void *HeapProfiler::ReallocHook (void *ptr, size_t size, const void *caller) {
+    void *newptr;
+    
+    /* Restore all old hooks */
+    __malloc_hook = old_malloc_hook;
+    __free_hook = old_free_hook;
+    __realloc_hook = old_realloc_hook;
+     
+    /* Call recursively */
+    newptr = realloc(ptr, size);
+    
+    AllocatedBlocks::iterator result = blocks.find(ptr);
+    if (result != blocks.end())
+    {
+        #ifdef DEBUG_HEAPPROFILER 
+            std::cout << "found: " << (*result).second << std::endl;
+        #endif
+        consumption -= (*result).second;
+        blocks.erase(result);
+    } else {
+        #ifdef DEBUG_HEAPPROFILER 
+            std::cout << "not found" << std::endl;
+        #endif
+    }
+    
+    blocks[newptr] = (unsigned long)size;
+    consumption += (unsigned long)size;
+    if (consumption > maxConsumption)
+        maxConsumption = consumption;
+    
+    #ifdef DEBUG_HEAPPROFILER
+        std::cout << "realloc(" << ptr << ", " << size << ") called from " << caller << ", result " << newptr << " (" << consumption << ", max " << maxConsumption << ")" << std::endl;
+    #endif
+    
+    /* Save underlying hooks */
+    old_malloc_hook = __malloc_hook;
+    old_free_hook = __free_hook;
+    old_realloc_hook = __realloc_hook;
+        
+    /* Restore our own hooks */
+    __malloc_hook = HeapProfiler::MallocHook;
+    __free_hook = HeapProfiler::FreeHook;
+    __realloc_hook = HeapProfiler::ReallocHook;
+    
+    return newptr;
+}
+
diff --git a/HeapProfiler.h b/HeapProfiler.h
new file mode 100644 (file)
index 0000000..e1c0378
--- /dev/null
@@ -0,0 +1,56 @@
+/***************************************************************************
+ *   Installs handlers for malloc(), realloc() and free()                  *
+ *                                                                         *
+ *   Copyright (C) 2006 by Niko Välimäki                                   *
+ *                                                                         *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
+ ***************************************************************************/
+
+#ifndef _HEAPPROFILER_H_
+#define _HEAPPROFILER_H_
+
+#include <map>
+#include <iostream>
+#include <malloc.h>
+
+//#define DEBUG_HEAPPROFILER
+
+typedef std::map<void *, unsigned long> AllocatedBlocks;
+
+class HeapProfiler
+{
+public:
+    static unsigned long GetMaxHeapConsumption();
+    static unsigned long GetHeapConsumption();
+
+    // Prototypes for hooks
+    static void InitHooks(void);
+    static void *MallocHook(size_t, const void *);
+    static void FreeHook(void *, const void *);
+    static void *ReallocHook(void *, size_t, const void *);
+
+private:
+    static unsigned long consumption, maxConsumption;
+    // Variables to save original hooks.
+    static void *(*old_malloc_hook)(size_t, const void *);
+    static void (*old_free_hook)(void *, const void *);
+    static void *(*old_realloc_hook)(void *, size_t, const void *);
+    static AllocatedBlocks blocks;
+};
+
+
+#endif
index 4e40bc8..29c07af 100644 (file)
@@ -10,3 +10,4 @@ pos.o: pos.cpp pos.h rbtree.h handle.h
 rbtree.o: rbtree.cpp rbtree.h
 testTextCollection.o: testTextCollection.cpp CSA.h BitRank.h Tools.h \
   dynFMI.h bittree.h rbtree.h handle.h pos.h TextCollection.h
+HeapProfiler.o: HeapProfiler.h HeapProfiler.cpp 
\ No newline at end of file
index 0d90342..7c5bf06 100644 (file)
--- a/makefile
+++ b/makefile
@@ -1,10 +1,12 @@
 CC = g++
-CPPFLAGS = -Wall -ansi -pedantic -g
+CPPFLAGS = -Wall -ansi -pedantic -g -O2 -DNDEBUG
 
-testTextCollection_obs = testTextCollection.o TextCollection.o CSA.o Tools.o BitRank.o bittree.o handle.o pos.o rbtree.o dynFMI.o
+testTextCollection_obs = testTextCollection.o TextCollection.o CSA.o Tools.o BitRank.o bittree.o handle.o pos.o rbtree.o dynFMI.o 
 
-testTextCollection: $(testTextCollection_obs)
-       $(CC) -o testTextCollection $(testTextCollection_obs)
+all: $(testTextCollection_obs)
+
+testTextCollection: $(testTextCollection_obs) HeapProfiler.o
+       $(CC) -o testTextCollection $(testTextCollection_obs) HeapProfiler.o
 
 clean:
        rm -f core *.o *~ testTextCollection
index d89a328..dd37ff1 100644 (file)
@@ -1,5 +1,7 @@
 // Test driver for text collection
 #include <iostream>
+#include <cstdlib>
+#include "HeapProfiler.h"
 using std::cout;
 using std::endl;
 
@@ -28,47 +30,23 @@ void printFullResult(TextCollection::full_result fr)
 
 int main()
 {
-    uchar *text = (uchar*) "acabab";
-    TextCollection *csa = TextCollection::InitTextCollection(1);
-    csa->InsertText(text);
-    text = (uchar*) "abaca";
-    csa->InsertText(text);
-    text = (uchar*) "abacb";
-    csa->InsertText(text);
-
-    csa->MakeStatic();
-//    FILE *pFile = fopen ( "mysave.txt" , "rb" );
-//    csa->Load(pFile);
-    
-    text = csa->GetText(0);
-    cout << "Text 0: \"" << text << "\"" << endl;
-    delete [] text;
-    text = csa->GetText(1);
-    cout << "Text 1: \"" << text << "\"" << endl;
-    delete [] text;
-    text = csa->GetText(2);
-    cout << "Text 2: \"" << text << "\"" << endl;
-    delete [] text;
-    
-    text = csa->GetText(2, 2, 4);
-    cout << "Substring of Text 3: \"" << text << "\"" << endl;
-    delete [] text;
-    
-    printf("n:o contains: %u\n", csa->CountContains((uchar *)"ac"));
-    printf("n:o suffix: %u\n", csa->CountSuffix((uchar *)"b"));
-    printf("n:o equal: %u\n", csa->CountEqual((uchar *)"acabab"));
-    printf("is equal: %u\n", csa->IsEqual((uchar *)"abacb"));
-    
-    TextCollection::document_result dr;
-    dr = csa->Contains((uchar*)"ab");
-    printDocumentResult(dr);
-
-    TextCollection::full_result fr;
-    fr = csa->FullContains((uchar *)"ab");
-    printFullResult(fr);
-
-//    FILE *pFile2 = fopen ( "mysave.txt" , "wb" );
-//    csa->Save(pFile2);
-
-    delete csa;
+  std::string kbd;
+  uchar * str = (uchar*) "";
+
+  TextCollection *csa = TextCollection::InitTextCollection(64);
+  for(int i = 0; i<1000000; i++){
+    csa->InsertText(str);    
+  };
+  std::cerr << "Before MakeStatic() [press enter]\n";
+  std::cin >> kbd;
+  std::cerr << "heap usage: " << HeapProfiler::GetHeapConsumption()/(1024*1024) << " Mbytes" << std::endl;
+  csa->MakeStatic();
+  std::cerr << "After MakeStatic() [press enter]\n";
+  std::cin >> kbd;
+  std::cerr << "heap usage: " << HeapProfiler::GetHeapConsumption()/(1024*1024) << " Mbytes" << std::endl;
+  delete csa;
+  std::cerr << "After Delete [press enter]\n";
+  std::cerr << "heap usage: " << HeapProfiler::GetHeapConsumption()/(1024*1024) << " Mbytes" << std::endl;
+  std::cin >> kbd;
+  return 0;
 }