HPCToolkit
LargeByteBuffer.cpp
Go to the documentation of this file.
1 // -*-Mode: C++;-*-
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL: https://hpctoolkit.googlecode.com/svn/branches/hpctoolkit-hpcserver/src/tool/hpcserver/LargeByteBuffer.cpp $
6 // $Id: LargeByteBuffer.cpp 4380 2013-10-16 06:34:29Z felipet1326@gmail.com $
7 //
8 // --------------------------------------------------------------------------
9 // Part of HPCToolkit (hpctoolkit.org)
10 //
11 // Information about sources of support for research and development of
12 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13 // --------------------------------------------------------------------------
14 //
15 // Copyright ((c)) 2002-2019, Rice University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met:
21 //
22 // * Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
24 //
25 // * Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // * Neither the name of Rice University (RICE) nor the names of its
30 // contributors may be used to endorse or promote products derived from
31 // this software without specific prior written permission.
32 //
33 // This software is provided by RICE and contributors "as is" and any
34 // express or implied warranties, including, but not limited to, the
35 // implied warranties of merchantability and fitness for a particular
36 // purpose are disclaimed. In no event shall RICE or contributors be
37 // liable for any direct, indirect, incidental, special, exemplary, or
38 // consequential damages (including, but not limited to, procurement of
39 // substitute goods or services; loss of use, data, or profits; or
40 // business interruption) however caused and on any theory of liability,
41 // whether in contract, strict liability, or tort (including negligence
42 // or otherwise) arising in any way out of the use of this software, even
43 // if advised of the possibility of such damage.
44 //
45 // ******************************************************* EndRiceCopyright *
46 
47 //***************************************************************************
48 //
49 // File:
50 // $HeadURL: https://hpctoolkit.googlecode.com/svn/branches/hpctoolkit-hpcserver/src/tool/hpcserver/LargeByteBuffer.cpp $
51 //
52 // Purpose:
53 // Stores and handles the pages of the file to abstract away the file is not
54 // stored entirely in one contiguous chunk of memory.
55 //
56 // Description:
57 // [The set of functions, macros, etc. defined in the file]
58 //
59 //***************************************************************************
60 #include "LargeByteBuffer.hpp"
61 #include "Constants.hpp"
62 #include "FileUtils.hpp"
63 #include "DebugUtils.hpp"
64 
65 
66 
67 #include <fcntl.h>
68 #include <sys/types.h>
69 #include <sys/sysctl.h>
70 #include <errno.h>
71 #include <unistd.h>
72 
73 #include <iostream>
74 #include <algorithm> //For min of two longs
75 
76 
77 using namespace std;
78 
79 namespace TraceviewerServer
80 {
81  static FileOffset mmPageSize; //= 1<<23;//1 << 30;
83  LargeByteBuffer::LargeByteBuffer(string sPath, int headerSize)
84  {
85  //string SPath = Path.string();
86 
87  /*int MapFlags = MAP_PRIVATE;
88  int MapProt = PROT_READ;*/
89 
90  fileSize = FileUtils::getFileSize(sPath);
91 
92  FileOffset osPageSize = getpagesize();
93  FileOffset pageSizeMultiple = lcm(osPageSize, lcm(headerSize, SIZE_OF_TRACE_RECORD));//The page size must be a multiple of this
94 
95  FileOffset ramSizeInBytes = getRamSize();
96 
97  const FileOffset _64_MEGABYTE = 1 << 26;
98  //This is a pretty arbitrary algorithm, but it works
99  mmPageSize = pageSizeMultiple * (_64_MEGABYTE/osPageSize);//This means it will get it close to 64 MB
100 
101  //We should take into account how many copies of this program are
102  //running on this node with something like MPI_COMM_WORLD, but I don't
103  //want to introduce MPI-specific code here. It's not worth it... Plus, there's
104  //a ton of paging stuff going on at the OS level that we don't really know
105  //the specifics of, so the amount of RAM may be less important than it seems.
106  double MAX_PORTION_OF_RAM_AVAILABLE = 0.60;//Use up to 60%
107  int MaxPages = (int)(ramSizeInBytes * MAX_PORTION_OF_RAM_AVAILABLE/mmPageSize);
108  VersatileMemoryPage::setMaxPages(MaxPages);
109 
110 
111  int FullPages = fileSize / mmPageSize;
112  int PartialPageSize = fileSize % mmPageSize;
113  numPages = FullPages + (PartialPageSize == 0 ? 0 : 1);
114  pageManagementList = new LRUList<VersatileMemoryPage>(numPages);
115 
116  FileDescriptor fd = open(sPath.c_str(), O_RDONLY);
117 
118  FileOffset sizeRemaining = fileSize;
119 
120  for (int i = 0; i < numPages; i++)
121  {
122  FileOffset mapping_len = min( mmPageSize, sizeRemaining);
123 
124  masterBuffer.push_back(VersatileMemoryPage(mmPageSize*i, mapping_len, fd, pageManagementList));
125 
126  sizeRemaining -= mapping_len;
127 
128  }
129 
130  }
131 
132  int LargeByteBuffer::getInt(FileOffset pos)
133  {
134  int Page = pos / mmPageSize;
135  int loc = pos % mmPageSize;
136  char* p2D = masterBuffer[Page].get() + loc;
137  int val = ByteUtilities::readInt(p2D);
138  return val;
139  }
140  Long LargeByteBuffer::getLong(FileOffset pos)
141  {
142  int Page = pos / mmPageSize;
143  int loc = pos % mmPageSize;
144  char* p2D = masterBuffer[Page].get() + loc;
145  Long val = ByteUtilities::readLong(p2D);
146  return val;
147 
148  }
149  //Could very well be a template, but we only use it for uint64_t
150  uint64_t LargeByteBuffer::lcm(uint64_t _a, uint64_t _b)
151  {
152  // LCM(a,b) = a*b/GCD(a,b) = (a/GCD(a,b))*b
153  // [a/GCD(a,b) is an integer and a*b might overflow]
154 
155  //We need the original values for later, so use temporary ones for the GCD computation
156  uint64_t a = _a, b = _b;
157  uint64_t t = 0;
158  while (b != 0)
159  {
160  t = b;
161  b = a % b;
162  a = t;
163  }
164  //GCD stored in a
165  return (_a/a)*_b;
166  }
167  uint64_t LargeByteBuffer::getRamSize()
168  {
169 #ifdef _SC_PHYS_PAGES
170  long pages = sysconf(_SC_PHYS_PAGES);
171  long page_size = sysconf(_SC_PAGE_SIZE);
172  return pages * page_size;
173 #else
174  int mib[2] = { CTL_HW, HW_MEMSIZE };
175  u_int namelen = sizeof(mib) / sizeof(mib[0]);
176  uint64_t ramSize;
177  size_t len = sizeof(ramSize);
178 
179  if (sysctl(mib, namelen, &ramSize, &len, NULL, 0) < 0)
180  {
181  cerr << "Could not obtain system memory size"<<endl;
183  }
184  DEBUGCOUT(2) << "Memory size : "<<ramSize<<endl;
185 
186  return ramSize;
187 #endif
188 
189  }
190 
191  FileOffset LargeByteBuffer::size()
192  {
193  return fileSize;
194  }
195  LargeByteBuffer::~LargeByteBuffer()
196  {
197  masterBuffer.clear();
198  delete pageManagementList;
199 
200  }
201 }
202 
static FileOffset mmPageSize
#define SIZE_OF_TRACE_RECORD
Definition: Constants.hpp:74
uint64_t FileOffset
Definition: FileUtils.hpp:78
#define DEBUGCOUT(a)
Definition: DebugUtils.hpp:72
#define NULL
Definition: ElfHelper.cpp:85