gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] gnash libbase/Makefile.am testsuite/libbase/Mak...


From: Rob Savoye
Subject: [Gnash-commit] gnash libbase/Makefile.am testsuite/libbase/Mak...
Date: Fri, 07 Mar 2008 01:02:22 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Rob Savoye <rsavoye>    08/03/07 01:02:21

Modified files:
        libbase        : Makefile.am 
        testsuite/libbase: Makefile.am 
        .              : ChangeLog 
Added files:
        libbase        : memory.h memory.cpp 
        testsuite/libbase: memtest.cpp 

Log message:
                * testsuite/libbase/memtest.cpp: New test case for the Memory
                debugger for use by maintainers.
                * testsuite/libbase/Makefile.am: Add new memory testv case.
                * libbase/memory.{h,cpp}: New Memory class for analysing memory
                allocation to find leaks and bloat.
                * libbase/makefile.am: Add memory.*.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/Makefile.am?cvsroot=gnash&r1=1.96&r2=1.97
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/memory.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/memory.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/libbase/Makefile.am?cvsroot=gnash&r1=1.35&r2=1.36
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/libbase/memtest.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.5834&r2=1.5835

Patches:
Index: libbase/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/libbase/Makefile.am,v
retrieving revision 1.96
retrieving revision 1.97
diff -u -b -r1.96 -r1.97
--- libbase/Makefile.am 21 Jan 2008 20:55:44 -0000      1.96
+++ libbase/Makefile.am 7 Mar 2008 01:02:20 -0000       1.97
@@ -85,6 +85,7 @@
        lirc.cpp        \
        log.cpp \
        membuf.cpp \
+       memory.cpp \
        network.cpp \
        postscript.cpp \
        rc.cpp \
@@ -118,6 +119,7 @@
        image.h \
        jpeg.h \
        membuf.h \
+       memory.h \
        network.h \
        lirc.h \
        log.h \

Index: testsuite/libbase/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/testsuite/libbase/Makefile.am,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -b -r1.35 -r1.36
--- testsuite/libbase/Makefile.am       21 Jan 2008 23:26:50 -0000      1.35
+++ testsuite/libbase/Makefile.am       7 Mar 2008 01:02:20 -0000       1.36
@@ -44,6 +44,7 @@
        URLTest \
        RcTest \
        IntTypesTest \
+       memtest \
        $(NULL)
 
 if CURL
@@ -72,6 +73,9 @@
 IntTypesTest_SOURCES = IntTypesTest.cpp
 IntTypesTest_CPPFLAGS = -DSRCDIR="$(srcdir)"
 
+# Test the Memory class
+memtest_SOURCES = memtest.cpp
+
 # LogTest_SOURCES = TCXXLog.cpp
 # LogTest_CPPFLAGS = '-DBUILDDIR="$(abs_builddir)"'
 

Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.5834
retrieving revision 1.5835
diff -u -b -r1.5834 -r1.5835
--- ChangeLog   6 Mar 2008 20:29:09 -0000       1.5834
+++ ChangeLog   7 Mar 2008 01:02:20 -0000       1.5835
@@ -1,3 +1,12 @@
+2008-03-06  Rob Savoye  <address@hidden>
+
+       * testsuite/libbase/memtest.cpp: New test case for the Memory
+       debugger for use by maintainers.
+       * testsuite/libbase/Makefile.am: Add new memory testv case.
+       * libbase/memory.{h,cpp}: New Memory class for analysing memory
+       allocation to find leaks and bloat.
+       * libbase/makefile.am: Add memory.*.
+
 2008-03-06 Sandro Santilli <address@hidden>
 
        * server/array.cpp: there's no such thing as an Array.size member, and

Index: libbase/memory.h
===================================================================
RCS file: libbase/memory.h
diff -N libbase/memory.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libbase/memory.h    7 Mar 2008 01:02:19 -0000       1.1
@@ -0,0 +1,111 @@
+// 
+//   Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+// 
+// 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 3 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//
+// This class is a memory allocation tracker used to optimize
+// the memory usage and find memory leaks.
+//
+#ifndef __MEMORY_H__
+#define __MEMORY_H__
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+// If we don't have support for mallinfo(), this code is useless
+#if HAVE_MALLINFO
+
+#include <cstdlib>
+#include <malloc.h>
+
+namespace gnash {
+  
+class Memory {
+public:
+
+    // Borrowed from malloc.h and trimmed down.
+    struct small_mallinfo {
+        int line;     // line number of this data sample
+        int arena;    // non-mmapped space allocated from system
+        int uordblks; // total allocated space
+        int fordblks; // total free space
+    };
+    DSOEXPORT Memory();
+    DSOEXPORT Memory(int size);
+    DSOEXPORT ~Memory();
+
+    // Start collecting statistics. This can effect performance
+    void startStats();
+    
+    // Stop collecting statistics
+    void endStats() { addStats();_collecting = false; };
+
+    // Erase all collected data and reset collections.
+    void reset();
+
+    // checkpoint()
+    void startCheckpoint() { _checkpoint[0] = mallinfo(); };
+    bool endCheckpoint();
+    
+    // Add or retrieve mallinfo data
+    int addStats();
+    int addStats(int line);
+    int addStats(struct small_mallinfo *x);
+    int addStats(struct small_mallinfo *x, int line);
+    struct small_mallinfo *getStats() { return _info; };
+    struct small_mallinfo *operator[](int x) { return _info + x; };
+    int totalStats() { return _index; };
+
+    // Analyze memory usage
+    bool analyze();
+
+    // Dump the differences of bytes allocated between two samples
+    int diffStats();
+    int diffStats(int x, int y);
+    
+    // Dump the vector of stored classes
+    void dump(struct mallinfo *x);
+    void dump(struct small_mallinfo *x);
+    void dump();
+private:
+    bool                _collecting;
+    // For data logging, we want to store as little as possible
+    // so we don't impact the system too hard. Data logging memory
+    // allocations can generate a huge amount of data, so we have
+    // to be careful. We also can't use STL, as that does more
+    // memory allocations, which will confuse our statistics
+    // gathering.
+    struct small_mallinfo *_info;
+    // Since we aren't using STL, we have to store how much
+    // data storage we have ourselves.
+    size_t              _size;
+    int                 _index;
+    // For checkpoints, we want the all the data
+    struct mallinfo     _checkpoint[2];
+};
+
+} // end of gnash namespace
+
+#endif // end of HAVE_MALLINFO
+
+// end of __MEMORY_H__
+#endif
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:

Index: libbase/memory.cpp
===================================================================
RCS file: libbase/memory.cpp
diff -N libbase/memory.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libbase/memory.cpp  7 Mar 2008 01:02:20 -0000       1.1
@@ -0,0 +1,307 @@
+// 
+//   Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+// 
+// 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 3 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//
+// This class is a memory allocation tracker used to optimize
+// the memory usage and find memory leaks.
+//
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+// If we don't have support for mallinfo(), this code is useless
+#if HAVE_MALLINFO
+
+#include <cstdlib>
+#include <malloc.h>
+#include <vector>
+
+#include "log.h"
+#include "memory.h"
+
+using namespace std;
+
+namespace gnash {
+  
+RcInitFile& rcfile = gnash::RcInitFile::getDefaultInstance();
+
+
+const int DATALOG_SIZE = 1024;
+
+Memory::Memory() 
+    : _collecting(false),
+      _info(0),
+      _size(0),
+      _index(0)
+{
+//    GNASH_REPORT_FUNCTION;
+}
+
+
+Memory::Memory(int size) 
+    : _collecting(false)
+{
+//    GNASH_REPORT_FUNCTION;
+    _size = size;
+    _info = new struct small_mallinfo[DATALOG_SIZE];
+    reset();
+}
+
+Memory::~Memory()
+{
+//    GNASH_REPORT_FUNCTION;
+    if (_info) {
+        delete _info;
+    }
+    _index = 0;
+    _size = 0;
+}
+
+// Erase all collected data and reset collections.
+void
+Memory::reset()
+{
+//    GNASH_REPORT_FUNCTION;
+    if (_info) {
+        memset(_info, 0, _size);
+    }
+    _index = 0;
+}
+
+
+void
+Memory::startStats()
+{
+//    GNASH_REPORT_FUNCTION;
+    _collecting = true;
+    if (_info == 0) {
+        log_debug("Allocating buffer for %d data samples",
+                  DATALOG_SIZE);
+        _info = new struct small_mallinfo[DATALOG_SIZE];
+        reset();
+    }
+}
+    
+int
+Memory::addStats(int line)
+{
+//    GNASH_REPORT_FUNCTION;
+    if (_info) {
+        struct small_mallinfo *ptr = _info + _index;        
+        addStats(ptr, line);
+    }
+    
+    return _index;
+}
+
+int
+Memory::addStats()
+{
+//    GNASH_REPORT_FUNCTION;
+    if (_info) {
+        struct small_mallinfo *ptr = _info + _index;        
+        addStats(ptr, 0);
+    }
+    
+    return _index;
+}
+
+
+int
+Memory::addStats(struct small_mallinfo *ptr)
+{
+//    GNASH_REPORT_FUNCTION;
+    return addStats(ptr, 0);
+}
+
+int
+Memory::addStats(struct small_mallinfo *ptr, int line)
+{
+//    GNASH_REPORT_FUNCTION;
+    struct mallinfo mal = mallinfo();
+
+//    dump(&mal);
+    if ((ptr) && (_index < DATALOG_SIZE)) {
+        ptr->line = line;
+        ptr->arena = mal.arena;
+        ptr->uordblks = mal.uordblks;
+        ptr->fordblks = mal.fordblks;
+        _index++;
+    }
+    
+    return _index;
+}
+
+// return true if we haven't leaked any memory
+bool
+Memory::endCheckpoint()
+{
+//    GNASH_REPORT_FUNCTION;
+    _checkpoint[1] = mallinfo();
+    if (_checkpoint[1].uordblks == _checkpoint[0].uordblks) {
+        return true;
+    }
+
+    return false;
+}
+
+// Dump the differences of bytes allocated between two samples
+int
+Memory::diffStats()
+{
+//    GNASH_REPORT_FUNCTION;
+    return diffStats(_index - 1, _index - 2);
+}
+
+int
+Memory::diffStats(int x, int y)
+{
+//    GNASH_REPORT_FUNCTION;
+    if ((_info) && (x < DATALOG_SIZE) && (y < DATALOG_SIZE)) {
+        return (_info[x].uordblks - _info[y].uordblks);
+    }
+    return -1;
+}
+    
+
+// Analyze memory usage
+bool
+Memory::analyze()
+{
+//    GNASH_REPORT_FUNCTION;
+
+    int accumulate_allocated = 0;
+    int accumulate_freed = 0;
+
+    // System memory is what we get from brk(), the lowest level
+    // system call used by both malloc() or new().
+    cerr << endl << "System memory allocated in bytes: "
+         << _info->arena << endl;
+    int diff_arena = (_info + _index - 1)->arena - _info->arena;
+    if (diff_arena) {
+        cerr << "System memory change in bytes: " << diff_arena << endl;
+    }    
+
+    int total_allocated = (_info + _index - 1)->uordblks - _info->uordblks;
+    cerr << "Total bytes allocated: " << total_allocated << endl;
+
+    if (_index > 1) {
+        for (int i=1; i<_index; i++) {
+            // See what was allocated between samples
+            struct small_mallinfo *ptr = _info + i;
+            int diff_allocated = (ptr->uordblks) - (ptr - 1)->uordblks;
+            if (diff_allocated > 0) {
+                accumulate_allocated += diff_allocated;
+                if (ptr->line && (ptr - 1)->line) {
+                    cerr << "Allocated " << diff_allocated
+                         << " bytes Between lines: " << (ptr - 1)->line
+                         << " and " << ptr->line << endl;
+                } else {
+                    cerr << "Allocated bytes: " << diff_allocated << endl;
+                }
+// same as diff_freed
+//             } else {
+//                 if (diff_allocated != 0) {
+//                     cerr << "\tnew heap bytes: " << diff_allocated << endl;
+//                 }
+            }
+
+            // See what was freed between samples
+            int diff_freed = ptr->fordblks - (ptr - 1)->fordblks;
+            if (diff_freed > 0) {
+                accumulate_freed += diff_freed;
+                if (ptr->line && (ptr - 1)->line) {
+                    cerr << "Freed " << diff_freed
+                         << " bytes Between lines: " << (ptr - 1)->line
+                         << " and " << ptr->line << endl;
+                } else {
+                    cerr << "Freed bytes: " << diff_freed << endl;
+                }
+// Same as diif_allocated
+//              } else {
+//                  if (diff_freed != 0) {
+//                      cerr << "\tnuked heap bytes: " << diff_freed << endl;
+//                  }
+            }
+        }
+    } else {
+        cerr << "Only have one sample" << endl;
+        dump();
+    }
+
+    // Sanity check on our calculations
+    if (total_allocated != (accumulate_allocated - accumulate_freed)) { 
+        log_error("Calculations don't equal");
+    } else {
+        log_debug("Zero memory leaks for this program");
+    }
+    if ((_checkpoint[0].uordblks != 0) && (_checkpoint[1].uordblks != 0)) {
+        if (_checkpoint[1].uordblks == _checkpoint[0].uordblks) {
+            cerr << "The last checkpoint status was: "
+                 << ((_checkpoint[1].uordblks == _checkpoint[0].uordblks)
+                 ? "passed" : "failed") << endl;
+        }
+    }
+}
+    
+
+// Dump the vector of stored classes
+void
+Memory::dump(struct mallinfo *ptr)
+{
+//    GNASH_REPORT_FUNCTION;
+    cerr << "\tstruct mallinfo: Non-mmapped space allocated from system is: \""
+         << ptr->arena << "\"" << endl;
+    cerr << "\tstruct mallinfo: Total allocated space  is: \""
+         << ptr->uordblks << "\"" << endl;
+    cerr << "\tstruct mallinfo: Total free space  is: \""
+         << ptr->fordblks << "\"" << endl;
+}
+
+// Dump the vector of stored classes
+void
+Memory::dump(struct small_mallinfo *ptr)
+{
+//    GNASH_REPORT_FUNCTION;
+    cerr << "\tLine number of sample: " << ptr->line << endl;
+    cerr << "\tNon-mmapped space allocated from system is: \""
+         << ptr->arena << "\"" << endl;
+    cerr << "\tTotal allocated space  is: \""
+         << ptr->uordblks << "\"" << endl;
+    cerr << "\tTotal free space  is: \""
+         << ptr->fordblks << "\"" << endl;
+}
+
+void
+Memory::dump()
+{
+//    GNASH_REPORT_FUNCTION;
+
+    for (int i=0; i<_index; i++) {
+        cerr << "Mallinfo index: " << i << endl;
+        dump(_info + i);
+    }
+}
+
+} // end of gnash namespace
+
+#endif // end of HAVE_MALLINFO
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:

Index: testsuite/libbase/memtest.cpp
===================================================================
RCS file: testsuite/libbase/memtest.cpp
diff -N testsuite/libbase/memtest.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ testsuite/libbase/memtest.cpp       7 Mar 2008 01:02:20 -0000       1.1
@@ -0,0 +1,177 @@
+// 
+//   Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+// 
+// 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 3 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include <vector>
+#include <string>
+
+#include "log.h"
+#include "memory.h"
+
+#ifdef HAVE_DEJAGNU_H
+#include "dejagnu.h"
+#else
+#include "check.h"
+#endif
+
+TestState runtest;
+
+long *test_leak();
+long *test_noleak();
+
+using namespace std;
+using namespace gnash;
+
+const int INTARRAYSIZE = 10;
+
+int
+main (int /*argc*/, char** /*argv*/) {
+    RcInitFile& rc = RcInitFile::getDefaultInstance();
+
+    LogFile& dbglogfile = LogFile::getDefaultInstance();
+    dbglogfile.setVerbosity();
+
+    int diff = 0;
+    
+    // Parse the test config file
+    if (rc.parseFile("gnashrc")) {
+        runtest.pass ("rc.parseFile()");
+    } else {
+        runtest.fail ("rc.parseFile()");
+    }
+
+// If we don't have support for mallinfo(), this code is useless
+#if HAVE_MALLINFO
+    Memory mem;
+
+    mem.startStats();
+    mem.addStats(__LINE__);             // take a sample
+    mem.addStats(__LINE__);             // take a sample
+    diff = mem.diffStats();
+    if (mem.diffStats() == 0) {
+        runtest.pass("No allocations yet");
+    } else {
+        runtest.fail("No allocations yet");
+    }
+    
+    Memory m1;
+    mem.addStats(__LINE__);             // take a sample
+    diff = mem.diffStats();
+    if (diff == 16) {
+        runtest.pass("Memory");
+    } else {
+        runtest.fail("Memory");
+    }
+    
+    char *x = new char[120];
+    mem.addStats(__LINE__);             // take a sample
+    if (mem.diffStats() == 104) {
+        runtest.pass("Buffer allocation");
+    } else {
+        runtest.fail("Buffer allocation");
+    }
+    
+    vector<string> sv;
+    sv.push_back("Hello World");
+    mem.addStats(__LINE__);             // take a sample
+    if (mem.diffStats() == 64) {
+        runtest.pass("First string allocated");
+    } else {
+        runtest.fail("First string allocated");
+    }
+
+    sv.push_back("Aloha");
+    delete x;
+    mem.addStats(__LINE__);             // take a sample
+    if (mem.diffStats() == -104) {
+        runtest.pass("Second string allocated");
+    } else {
+        runtest.fail("Second string allocated");
+    }
+
+    sv.push_back("Guten Tag");
+    mem.addStats(__LINE__);             // take a sample
+    if (mem.diffStats() == 40) {
+        runtest.pass("Third string allocated");
+    } else {
+        runtest.fail("Third string allocated");
+    }
+
+    mem.startCheckpoint();
+    test_leak();
+    if (mem.endCheckpoint()) {
+        runtest.fail("leak");
+    } else {
+        runtest.pass("leak");
+    }    
+    mem.addStats(__LINE__);             // take a sample
+    if (mem.diffStats() == 40) {
+        runtest.pass("test_leak");
+    } else {
+        runtest.fail("test_leak");
+    }
+
+    mem.startCheckpoint();
+    test_noleak();
+    mem.addStats(__LINE__);             // take a sample
+    if (mem.endCheckpoint()) {
+        runtest.pass("noleak");
+    } else {
+        runtest.fail("noleak");
+    }
+    if (mem.diffStats() == 0) {
+        runtest.pass("test_noleak");
+    } else {
+        runtest.fail("test_noleak");
+    }
+
+    
+    mem.endStats();
+
+//    mem.dump();    
+
+    mem.analyze();
+#else
+    runtest.untested("No support for mallinfo()");
+#endif // end of HAVE_MALLINFO
+}
+
+// Allocate memory and forget to clean it up.
+long *
+test_leak()
+{
+    long *x = new long[INTARRAYSIZE];
+    for (int i=0; i<INTARRAYSIZE; i++) {
+        x[i] = i;
+    }
+    return x;
+}
+
+// Clean up after the other testcase
+long *
+test_noleak()
+{
+    long *x = test_leak();
+    delete x;
+
+    return 0;
+}
+




reply via email to

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