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
|