// @(#)root/memstat:$Id$
// Author: Anar Manafov (A.Manafov@gsi.de) and Rene Brun  23/09/2010

/*************************************************************************
* Copyright (C) 1995-2010, Rene Brun and Fons Rademakers.               *
* All rights reserved.                                                  *
*                                                                       *
* For the licensing terms see $ROOTSYS/LICENSE.                         *
* For the list of contributors see $ROOTSYS/README/CREDITS.             *
*************************************************************************/

//___________________________________________________________________________
// TMemStat records all the calls to malloc and free and write a TTree
// with the position where the memory is allocated/freed , as well as
// the number of bytes.
//
// To use the class TMemStat, add the following statement at the beginning
// of your script or program
//     TMemStat mm("gnubuiltin");
// or in an interactive session do something like:
//    root > TMemStat mm("gnubuiltin");
//    root > .x somescript.C
//    root > .q
//
// another (may be more practical way) is to modify $ROOTSYS/etc/system.rootrc
// and activate the variable
//    Root.TMemStat:           1
//
// The file collected by TMemStat is named memstat_ProcessID and can be analyzed and results shown
// by executing the static function Show.
// When TMemStat is active it recors every call to malloc/free in a ROOT Tree.
// You must be careful when running jobs with many millions (or more) of calls
// to malloc/free because the generated Tree may become very large.
// The TMemStat constructor TMemStat(const char* system, Int_t buffersize, Int_t maxcalls)
// has its 3 arguments optional:
//   -system refers to the internal algorithm to compute the back traces.
//    the recommended value is "gnubuiltin"
//   -buffersize is the number of calls to malloc or free that can be stored in one memory buffer.
//    when the buffer is full, the calls to malloc/free pointing to the same location
//    are eliminated and not written to the final Tree. The default value 100000
//    is such that between 50 and 90% of the calls are eliminated depending on the application.
//    You can set buffersize <=1 to keep every single call to malloc/free.
//   -maxcalls can set a limit for the maximum number of calls to be registered in the Tree.
//    The default value is 5000000.
// The 3 arguments can be set  in $ROOTSYS/etc/system.rootrc
//    Root.TMemStat.system      gnubuiltin
//    Root.TMemStat.buffersize  100000
//    Root.TMemStat.maxcalls    5000000
//
// TMemStat::Show creates 3 canvases.
// -In canvas1 it displays a dynamic histogram showing for pages (10 kbytes by default)
//  the percentage of the page used.
//  A summary pave shows the total memory still in use when the TMemStat object
//  goes out of scope and the average occupancy of the pages.
//  The average occupancy gives a good indication of the memory fragmentation.
//
// -In canvas2 it displays the histogram of memory leaks in decreasing order.
//  when moving the mouse on this canvas, a tooltip shows the backtrace for the leak
//  in the bin below the mouse.
//
// -In canvas3 it displays the histogram of the nbigleaks largest leaks (default is 20)
//    for each leak, the number of allocs and average alloc size is shown.
//
//
// Simply do:
//   root > TMemStat::Show()
// or specifying arguments
//   root > TMemStat::Show(0.1,20,"mydir/mymemstat.root");
//
// The first argument to Show is the percentage of the time of the original job
// that produced the file after which the display is updated. By default update=0.1,
// ie 10 time intervals will be shown.
// The second argument is nbigleaks.
// The third argument is the imput file name (result of TMemStat).
// If this argument is omitted, Show will take the most recent file
// generated by TMemStat.
//
// You can restrict the address range to be analyzed via TMemStatShow::SetAddressRange
// You can restrict the entry range to be analyzed via TMemStatShow::SetEntryRange
//
//___________________________________________________________________________

#include "TROOT.h"
#include "TDirectory.h"
#include "TMemStat.h"
#include "TMemStatBacktrace.h"
#include "TMemStatMng.h"
#include "TMemStatHelpers.h"

ClassImp(TMemStat)

using namespace std;
using namespace Memstat;

_INIT_TOP_STACK;

//______________________________________________________________________________
TMemStat::TMemStat(Option_t* option, Int_t buffersize, Int_t maxcalls): fIsActive(kFALSE)
{
   // Supported options:
   //    "gnubuiltin" - if declared, then MemStat will use gcc build-in function,
   //                      otherwise glibc backtrace will be used
   //
   // Note: Currently MemStat uses a hard-coded output file name (for writing) = "memstat.root";

   // It marks the highest used stack address.
   _GET_CALLER_FRAME_ADDR;

   //preserve context. When exiting will restore the current directory
   TDirectory::TContext context;

   Bool_t useBuiltin = kTRUE;
   // Define string in a scope, so that the deletion of it will be not recorded by YAMS
   {
      string opt(option);
      transform(opt.begin(), opt.end(), opt.begin(),
                Memstat::ToLower_t());

      useBuiltin = (opt.find("gnubuiltin") != string::npos) ? kTRUE : kFALSE;
   }

   TMemStatMng::GetInstance()->SetUseGNUBuiltinBacktrace(useBuiltin);
   TMemStatMng::GetInstance()->SetBufferSize(buffersize);
   TMemStatMng::GetInstance()->SetMaxCalls(maxcalls);
   TMemStatMng::GetInstance()->Enable();
   // set this variable only if "NEW" mode is active
   fIsActive = kTRUE;

}

//______________________________________________________________________________
TMemStat::~TMemStat()
{
   //destructor
   if (fIsActive) {
      TMemStatMng::GetInstance()->Disable();
      TMemStatMng::GetInstance()->Close();
   }
}

//______________________________________________________________________________
void TMemStat::Close()
{
   //close the TMemStat manager
   TMemStatMng::Close();
}

//______________________________________________________________________________
void TMemStat::Disable()
{
   //Disable memory statistics
   TMemStatMng::GetInstance()->Disable();
}

//______________________________________________________________________________
void TMemStat::Enable()
{
   //Enable memory statistics
   TMemStatMng::GetInstance()->Enable();
}

//______________________________________________________________________________
void TMemStat::Show(Double_t update, Int_t nbigleaks, const char* fname)
{
   //Show results
   TString action = TString::Format("TMemStatShow::Show(%g,%d,\"%s\");",update,nbigleaks,fname);
   gROOT->ProcessLine(action);
}
 TMemStat.cxx:1
 TMemStat.cxx:2
 TMemStat.cxx:3
 TMemStat.cxx:4
 TMemStat.cxx:5
 TMemStat.cxx:6
 TMemStat.cxx:7
 TMemStat.cxx:8
 TMemStat.cxx:9
 TMemStat.cxx:10
 TMemStat.cxx:11
 TMemStat.cxx:12
 TMemStat.cxx:13
 TMemStat.cxx:14
 TMemStat.cxx:15
 TMemStat.cxx:16
 TMemStat.cxx:17
 TMemStat.cxx:18
 TMemStat.cxx:19
 TMemStat.cxx:20
 TMemStat.cxx:21
 TMemStat.cxx:22
 TMemStat.cxx:23
 TMemStat.cxx:24
 TMemStat.cxx:25
 TMemStat.cxx:26
 TMemStat.cxx:27
 TMemStat.cxx:28
 TMemStat.cxx:29
 TMemStat.cxx:30
 TMemStat.cxx:31
 TMemStat.cxx:32
 TMemStat.cxx:33
 TMemStat.cxx:34
 TMemStat.cxx:35
 TMemStat.cxx:36
 TMemStat.cxx:37
 TMemStat.cxx:38
 TMemStat.cxx:39
 TMemStat.cxx:40
 TMemStat.cxx:41
 TMemStat.cxx:42
 TMemStat.cxx:43
 TMemStat.cxx:44
 TMemStat.cxx:45
 TMemStat.cxx:46
 TMemStat.cxx:47
 TMemStat.cxx:48
 TMemStat.cxx:49
 TMemStat.cxx:50
 TMemStat.cxx:51
 TMemStat.cxx:52
 TMemStat.cxx:53
 TMemStat.cxx:54
 TMemStat.cxx:55
 TMemStat.cxx:56
 TMemStat.cxx:57
 TMemStat.cxx:58
 TMemStat.cxx:59
 TMemStat.cxx:60
 TMemStat.cxx:61
 TMemStat.cxx:62
 TMemStat.cxx:63
 TMemStat.cxx:64
 TMemStat.cxx:65
 TMemStat.cxx:66
 TMemStat.cxx:67
 TMemStat.cxx:68
 TMemStat.cxx:69
 TMemStat.cxx:70
 TMemStat.cxx:71
 TMemStat.cxx:72
 TMemStat.cxx:73
 TMemStat.cxx:74
 TMemStat.cxx:75
 TMemStat.cxx:76
 TMemStat.cxx:77
 TMemStat.cxx:78
 TMemStat.cxx:79
 TMemStat.cxx:80
 TMemStat.cxx:81
 TMemStat.cxx:82
 TMemStat.cxx:83
 TMemStat.cxx:84
 TMemStat.cxx:85
 TMemStat.cxx:86
 TMemStat.cxx:87
 TMemStat.cxx:88
 TMemStat.cxx:89
 TMemStat.cxx:90
 TMemStat.cxx:91
 TMemStat.cxx:92
 TMemStat.cxx:93
 TMemStat.cxx:94
 TMemStat.cxx:95
 TMemStat.cxx:96
 TMemStat.cxx:97
 TMemStat.cxx:98
 TMemStat.cxx:99
 TMemStat.cxx:100
 TMemStat.cxx:101
 TMemStat.cxx:102
 TMemStat.cxx:103
 TMemStat.cxx:104
 TMemStat.cxx:105
 TMemStat.cxx:106
 TMemStat.cxx:107
 TMemStat.cxx:108
 TMemStat.cxx:109
 TMemStat.cxx:110
 TMemStat.cxx:111
 TMemStat.cxx:112
 TMemStat.cxx:113
 TMemStat.cxx:114
 TMemStat.cxx:115
 TMemStat.cxx:116
 TMemStat.cxx:117
 TMemStat.cxx:118
 TMemStat.cxx:119
 TMemStat.cxx:120
 TMemStat.cxx:121
 TMemStat.cxx:122
 TMemStat.cxx:123
 TMemStat.cxx:124
 TMemStat.cxx:125
 TMemStat.cxx:126
 TMemStat.cxx:127
 TMemStat.cxx:128
 TMemStat.cxx:129
 TMemStat.cxx:130
 TMemStat.cxx:131
 TMemStat.cxx:132
 TMemStat.cxx:133
 TMemStat.cxx:134
 TMemStat.cxx:135
 TMemStat.cxx:136
 TMemStat.cxx:137
 TMemStat.cxx:138
 TMemStat.cxx:139
 TMemStat.cxx:140
 TMemStat.cxx:141
 TMemStat.cxx:142
 TMemStat.cxx:143
 TMemStat.cxx:144
 TMemStat.cxx:145
 TMemStat.cxx:146
 TMemStat.cxx:147
 TMemStat.cxx:148
 TMemStat.cxx:149
 TMemStat.cxx:150
 TMemStat.cxx:151
 TMemStat.cxx:152
 TMemStat.cxx:153
 TMemStat.cxx:154
 TMemStat.cxx:155
 TMemStat.cxx:156
 TMemStat.cxx:157
 TMemStat.cxx:158
 TMemStat.cxx:159
 TMemStat.cxx:160
 TMemStat.cxx:161
 TMemStat.cxx:162
 TMemStat.cxx:163
 TMemStat.cxx:164
 TMemStat.cxx:165
 TMemStat.cxx:166
 TMemStat.cxx:167
 TMemStat.cxx:168