File: Memory_sizer.h

package info (click to toggle)
cgal 3.6.1-2
  • links: PTS
  • area: non-free
  • in suites: squeeze
  • size: 62,184 kB
  • ctags: 95,782
  • sloc: cpp: 453,758; ansic: 96,821; sh: 226; makefile: 120; xml: 2
file content (167 lines) | stat: -rw-r--r-- 5,740 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// Copyright (c) 2004  INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Profiling_tools/include/CGAL/Memory_sizer.h $
// $Id: Memory_sizer.h 46037 2008-10-02 13:30:56Z lsaboret $
// 
// Author(s)     : Sylvain Pion, Andreas Fabri

#ifndef CGAL_MEMORY_SIZER_H
#define CGAL_MEMORY_SIZER_H

#include <CGAL/basic.h>

// This has only been implemented for MacOSX/Darwin, Linux and VC++ for now.
#if !defined _MSC_VER && !defined __linux__ && !defined __APPLE__

#include <iostream>

CGAL_BEGIN_NAMESPACE

struct Memory_sizer
{
    typedef std::size_t   size_type;
    size_type virtual_size()  const { return 0; }
    size_type resident_size() const { return 0; }
};

CGAL_END_NAMESPACE

#else // defined _MSC_VER ||  defined __linux__ || defined __APPLE__

#if defined _MSC_VER
#  include <windows.h>
#  include "psapi.h"
#elif defined __linux__ 
#  include <fstream>
#  include <cstddef>
#  include <unistd.h>
#elif defined __APPLE__
#include <mach/task.h>
#include <mach/mach_init.h>
#endif

CGAL_BEGIN_NAMESPACE

// A class giving access to the memory currently used by the process.
// Both the virtual memory size and the resident size.
// I put it in a class instead of free functions for similarity with Timer,
// and in case we want to store some state.

struct Memory_sizer
{
    typedef std::size_t   size_type;

    size_type virtual_size()  const { return get(true); }
    size_type resident_size() const { return get(false); }

private:

  size_type get (bool virtual_size)  const 
  { 
#ifdef _MSC_VER
    DWORD pid = GetCurrentProcessId();
    size_type result;
    HANDLE hProcess;
    PROCESS_MEMORY_COUNTERS pmc;
    hProcess = OpenProcess(  PROCESS_QUERY_INFORMATION |
                                    PROCESS_VM_READ,
                                    FALSE, pid );
    if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) )
    {
      // PagefileUsage seems not very precise, thus check it against WorkingSetSize:
      size_t approximate_virtual_size = (std::max)(pmc.PagefileUsage, pmc.WorkingSetSize);
      
      result = (virtual_size)? approximate_virtual_size : pmc.WorkingSetSize;
    }

    CloseHandle( hProcess );
    return result;

#elif defined __linux__
    // Extract of "man proc" under Linux :
    //
    //            vsize %u Virtual memory size
    //
    //            rss %u Resident Set Size: number of pages
    //                   the process has in real memory,
    //                   minus 3 for administrative purposes.
    //                   This is just the pages which count
    //                   towards text, data, or stack space.
    //                   This does not include pages which
    //                   have not been demand-loaded in, or
    //                   which are swapped out.
    //
    // Note : the following may be buggy in case of space in the executable name...

    int pid;
    char name[1024];
    char state;
    int ppid, pgrp, session, tty, tpgid;
    unsigned flags, minflt, cminflt, majflt, cmajflt;
    int utime, stime, cutime, cstime, counter, priority, timeout;
    unsigned itrealvalue, starttime;
    size_type vsize = 0, rss = 0;

    std::ifstream f("/proc/self/stat");
    CGAL_assertion(f);

    f >> pid >> name >> state >> ppid >> pgrp >> session >> tty >> tpgid >> flags;
    f >> minflt >> cminflt >> majflt >> cmajflt >> utime >> stime >> cutime;
    f >> cstime >> counter >> priority >> timeout >> itrealvalue >> starttime;
    f >> vsize >> rss;

    return virtual_size ? vsize : rss * getpagesize();

#else // __APPLE__ is defined

    // http://miknight.blogspot.com/2005/11/resident-set-size-in-mac-os-x.html
		// This is highly experimental. But still better than returning 0.
		// It appears that we might need certain 'rights' to get access to the kernel
		// task... It works if you have admin rights apparently
		// (though non-root of course!). I haven't tested with non-admin user.
    // -- Samuel Hornus

    task_t task = MACH_PORT_NULL;
		// The task_for_pid() seems to be time consuming (looking at the source
		// in xnu-source/bsd/vm/vm_unix.c
		// TODO: so it may be a good idea to cache the resulting 'task'
    if (task_for_pid(current_task(), getpid(), &task) != KERN_SUCCESS)
        return 0;
		// It seems to me that after calling :
		// task_for_pid(current_task(), getpid(), &task)
		// we should have (task == current_task())
		// ==> TODO: Check if this is indeed the case
      
    struct task_basic_info t_info;
    mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
      
    task_info(task, TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);
		// TODO: test if the following line works...
    //task_info(current_task(), TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);
#if 0
    std::cerr << "PAGE SIZE IS " << getpagesize() << std::endl
    << " RESIDENT SIZE IS " << t_info.resident_size << std::endl
    << " VIRTUAL SIZE IS " << t_info.virtual_size << std::endl;
#endif
    return virtual_size ? t_info.virtual_size : t_info.resident_size;
#endif
  }
};

CGAL_END_NAMESPACE

#endif

#endif