rambrain
testManagedFileSwap.cpp
Go to the documentation of this file.
1 /* rambrain - a dynamical physical memory extender
2  * Copyright (C) 2015 M. Imgrund, A. Arth
3  * mimgrund (at) mpifr-bonn.mpg.de
4  * arth (at) usm.uni-muenchen.de
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "tester.h"
22 
23 #include "cyclicManagedMemory.h"
24 #include "managedFileSwap.h"
25 #include "managedPtr.h"
26 #include "managedDummySwap.h"
27 #include "dummyManagedMemory.h"
28 #include <gtest/gtest.h>
29 #include <sys/stat.h>
30 #include "common.h"
31 #include <chrono>
32 
33 using namespace rambrain;
34 
39 TEST ( managedFileSwap, Unit_LazyPffree )
40 {
41  const unsigned int dblamount = 1024;
42  const unsigned int dblsize = dblamount * sizeof ( double );
43  const unsigned int swapmem = dblsize * 10;
44  managedFileSwap swap ( swapmem, "/tmp/rambrainswap-%d-%d" );
45  cyclicManagedMemory manager ( &swap, dblsize * 10 );
46 
47 
48  //Allocate 100 doubles:
49  managedPtr<managedPtr<double>> arr ( 100, dblamount );
50  adhereTo<managedPtr<double>> glue ( arr );
51  managedPtr<double> *field = glue;
52 
53  //Initialize them
54  for ( int n = 0; n < 100; ++n ) {
55  adhereTo<double> locGlue ( field[n] );
56  double *loc = locGlue;
57  *loc = n;
58  };
59 
60  tester test;
61  test.startNewTimeCycle();
62  test.addTimeMeasurement();
63  //Check for consistency, 10 times
64  for ( int m = 0; m < 1000; ++m ) {
65  for ( int n = 0; n < 100; ++n ) {
66  const adhereTo<double> locGlue ( field[n] );
67  const double *loc = locGlue;
68  EXPECT_EQ ( n, *loc );
69  };
70  }
71  test.addTimeMeasurement();
72  //Check for consistency, this time getting non-const ptr:
73  for ( int m = 0; m < 1000; ++m ) {
74  for ( int n = 0; n < 100; ++n ) {
75  adhereTo<double> locGlue ( field[n] );
76  double *loc = locGlue;
77  EXPECT_EQ ( n, *loc );
78  };
79  }
80  test.addTimeMeasurement();
81 
82  std::vector<int64_t> durations = test.getDurationsForCurrentCycle();
83  infomsgf ( "Const access ran for %ld ms", durations[0] );
84  infomsgf ( "Non-Const access ran for %ld ms", durations[1] );
85  infomsgf ( "Non-Const access cost %g as much time as const access", 1.0 * durations[1] / durations[0] );
86  EXPECT_TRUE ( durations[1] > durations[0] );
87 }
88 
92 TEST ( managedFileSwap, Unit_ManualSwapping ) //This screws default manager, as byte accounting is done asynchronously (invoked by managedFileSwap...)
93 {
94  const unsigned int dblamount = 100;
95  const unsigned int dblsize = dblamount * sizeof ( double );
96  const unsigned int swapmem = dblsize * 10;
97  managedFileSwap swap ( swapmem, "/tmp/rambrainswap-%d-%d" );
98  //Protect default manager from manipulations:
99  managedDummySwap dummyswap ( gig );
100  cyclicManagedMemory dummymanager ( &dummyswap, gig );
101 
102  ASSERT_EQ ( mib, swap.getSwapSize() );
103  ASSERT_EQ ( 0u, swap.getUsedSwap() );
104 #ifdef PARENTAL_CONTROL
105  managedMemoryChunk *chunk = new managedMemoryChunk ( 0, 1 );
106 #else
107  managedMemoryChunk *chunk = new managedMemoryChunk ( 1 );
108 #endif
109  chunk->status = MEM_ALLOCATED;
110  chunk->locPtr = malloc ( dblsize );
111  chunk->size = dblsize;
112 
113  pthread_mutex_lock ( & ( managedMemory::stateChangeMutex ) );
114  EXPECT_TRUE ( swap.swapOut ( chunk ) );
115 
116  swap.waitForCleanExit();
117  ASSERT_EQ ( mib, swap.getSwapSize() );
118  ASSERT_EQ ( dblsize, swap.getUsedSwap() );
119 
120  EXPECT_TRUE ( swap.swapIn ( chunk ) ) ;
121  swap.waitForCleanExit();
122  ASSERT_EQ ( mib, swap.getSwapSize() );
123  ASSERT_EQ ( 0u, swap.getUsedSwap() );
124 
125  pthread_mutex_unlock ( & ( managedMemory::stateChangeMutex ) );
126  free ( chunk->locPtr );
127  delete chunk;
128 }
129 
133 TEST ( managedFileSwap, Unit_ManualMultiSwapping )
134 {
135  const unsigned int dblamount = 100;
136  const unsigned int dblsize = dblamount * sizeof ( double );
137  const unsigned int swapmem = dblsize * 10;
138  managedFileSwap swap ( swapmem, "/tmp/rambrainswap-%d-%d" );
139 
140  //Protect default manager from manipulations:
141  managedDummySwap dummyswap ( gig );
142  cyclicManagedMemory dummymanager ( &dummyswap, gig );
143 
144  ASSERT_EQ ( mib, swap.getSwapSize() );
145  ASSERT_EQ ( 0u, swap.getUsedSwap() );
146 
147  pthread_mutex_lock ( & ( managedMemory::stateChangeMutex ) );
148  managedMemoryChunk *chunks[2];
149  for ( int i = 0; i < 2; ++i ) {
150 #ifdef PARENTAL_CONTROL
151  chunks[i] = new managedMemoryChunk ( 0, i + 1 );
152 #else
153  chunks[i] = new managedMemoryChunk ( i + 1 );
154 #endif
155 
156  chunks[i]->status = MEM_ALLOCATED;
157  chunks[i]->locPtr = malloc ( dblsize );
158  chunks[i]->size = dblsize;
159  }
160 
161  swap.swapOut ( chunks, 2 );
162  swap.waitForCleanExit();
163  ASSERT_EQ ( mib, swap.getSwapSize() );
164  ASSERT_EQ ( 2 * dblsize, swap.getUsedSwap() );
165  swap.swapIn ( chunks, 2 );
166  swap.waitForCleanExit();
167  ASSERT_EQ ( mib, swap.getSwapSize() );
168  ASSERT_EQ ( 0u, swap.getUsedSwap() );
169 
170  for ( int i = 0; i < 2; ++i ) {
171  if ( chunks[i]->status == MEM_SWAPPED ) {
172  free ( chunks[i]->swapBuf );
173  } else {
174  free ( chunks[i]->locPtr );
175  }
176  delete chunks[i];
177  }
178  pthread_mutex_unlock ( & ( managedMemory::stateChangeMutex ) );
179 }
180 
184 TEST ( managedFileSwap, Unit_ManualSwappingDelete )
185 {
186  const unsigned int dblamount = 100;
187  const unsigned int dblsize = dblamount * sizeof ( double );
188  const unsigned int swapmem = dblsize * 10;
189  managedFileSwap swap ( swapmem, "/tmp/rambrainswap-%d-%d" );
190 
191  //Protect default manager from manipulations:
192  managedDummySwap dummyswap ( gig );
193  cyclicManagedMemory dummymanager ( &dummyswap, gig );
194 
195  ASSERT_EQ ( mib, swap.getSwapSize() );
196  ASSERT_EQ ( 0u, swap.getUsedSwap() );
197  pthread_mutex_lock ( & ( managedMemory::stateChangeMutex ) );
198 #ifdef PARENTAL_CONTROL
199  managedMemoryChunk *chunk = new managedMemoryChunk ( 0, 1 );
200 #else
201  managedMemoryChunk *chunk = new managedMemoryChunk ( 1 );
202 #endif
203  chunk->status = MEM_ALLOCATED;
204  chunk->locPtr = malloc ( dblsize );
205  chunk->size = dblsize;
206 
207  swap.swapOut ( chunk );
208  swap.waitForCleanExit();
209 
210  ASSERT_EQ ( mib, swap.getSwapSize() );
211  ASSERT_EQ ( dblsize, swap.getUsedSwap() );
212 
213  swap.swapDelete ( chunk );
214  swap.waitForCleanExit();
215 
216  ASSERT_EQ ( mib, swap.getSwapSize() );
217  ASSERT_EQ ( 0u, swap.getUsedSwap() );
218 
219  delete chunk;
220  pthread_mutex_unlock ( & ( managedMemory::stateChangeMutex ) );
221 }
225 TEST ( managedFileSwap, Unit_SimpleSwapping )
226 {
227  const unsigned int memsize = 15 * sizeof ( double );
228  const unsigned int swapsize = 10 * memsize;
229 
230  ASSERT_NO_THROW (
231  managedFileSwap swap ( swapsize, "rambrainswap-%d-%d" );
232  cyclicManagedMemory manager ( &swap, memsize );
233 
234  managedPtr<double> ptr1 ( 10 );
235  managedPtr<double> ptr2 ( 10 );
236  );
237 }
238 
242 TEST ( managedFileSwap, Unit_SwapSize )
243 {
244  const unsigned int dblamount = 100;
245  const unsigned int dblsize = dblamount * sizeof ( double );
246  const unsigned int swapmem = dblsize * 10;
247  const unsigned int memsize = dblsize * 1.5;
248  managedFileSwap swap ( swapmem, "/tmp/rambrainswap-%d-%d" );
249  cyclicManagedMemory manager ( &swap, memsize );
250 
251  ASSERT_EQ ( mib, swap.getSwapSize() );
252  ASSERT_EQ ( 0u, swap.getUsedSwap() );
253 
254  managedPtr<double> *ptr1 = new managedPtr<double> ( dblamount );
255 
256  ASSERT_EQ ( mib, swap.getSwapSize() );
257  ASSERT_EQ ( 0u, swap.getUsedSwap() );
258 
259  ptr1->setUse();
260 
261  ASSERT_EQ ( mib, swap.getSwapSize() );
262  ASSERT_EQ ( 0u, swap.getUsedSwap() );
263 
264  ptr1->unsetUse();
265 
266  managedPtr<double> *ptr2 = new managedPtr<double> ( dblamount );
267 
268  ASSERT_EQ ( mib, swap.getSwapSize() );
269  ASSERT_EQ ( dblsize, swap.getUsedSwap() );
270 
271  ptr2->setUse();
272 
273  ASSERT_EQ ( mib, swap.getSwapSize() );
274  ASSERT_EQ ( dblsize, swap.getUsedSwap() );
275 
276  ptr2->unsetUse();
277 
278  ASSERT_EQ ( mib, swap.getSwapSize() );
279  ASSERT_EQ ( dblsize, swap.getUsedSwap() );
280 
281  delete ptr1;
282 
283  ASSERT_EQ ( mib, swap.getSwapSize() );
284  ASSERT_EQ ( 0u, swap.getUsedSwap() );
285 
286  delete ptr2;
287 }
288 
292 TEST ( managedFileSwap, Integration_RandomAccess )
293 {
294  global_bytesize oneswap = 1024 * 1024 * ( global_bytesize ) 16;
295  global_bytesize totalswap = 16 * oneswap;
296  tester test;
297  test.setSeed ( );
298 
299  managedFileSwap swap ( totalswap, "./rambrainswap-%d-%d", oneswap );
300  cyclicManagedMemory manager ( &swap, oneswap );
301 
302  /*ASSERT_EQ ( 0, manager.getSwappedMemory() ); //Deallocated all pointers
303  ASSERT_EQ ( 0, swap.getUsedSwap() );
304  ASSERT_EQ ( 16, swap.all_space.size() );
305  ASSERT_EQ ( 16, swap.free_space.size() );*/
306  infomsgf ( "%ld total swap in %ld swapfiles", swap.getSwapSize(), swap.all_space.size() );
307 
308  global_bytesize obj_size = 102400 * sizeof ( double );
309  global_bytesize obj_no = totalswap / obj_size * .9;
310 
311 
312  managedPtr<double> **objmask = ( managedPtr<double> ** ) malloc ( sizeof ( managedPtr<double> * ) *obj_no );
313  for ( unsigned int n = 0; n < obj_no; ++n ) {
314  objmask[n] = NULL;
315  }
316  for ( unsigned int n = 0; n < 10 * obj_no; ++n ) {
317  global_bytesize no = test.random ( obj_no );
318 
319  if ( objmask[no] == NULL ) {
320  ASSERT_TRUE ( manager.checkCycle() );
321  objmask[no] = new managedPtr<double> ( 102400 );
322  {
323  adhereTo<double> objoloc ( *objmask[no] );
324  double *darr = objoloc;
325  darr[0] = no;
326  }
327 
328  } else {
329  {
330  adhereTo<double> objoloc ( *objmask[no] );
331  double *darr = objoloc;
332  ASSERT_EQ ( no, darr[0] );
333  }
334  delete objmask[no];
335  objmask[no] = NULL;
336  }
337 
338  }
339  for ( unsigned int n = 0; n < obj_no; ++n ) {
340  if ( objmask[n] != NULL ) {
341  delete objmask[n];
342  }
343  }
344  free ( objmask );
345 
346 #ifdef SWAPSTATS
347  manager.printSwapstats();
348 #endif
349 
350 }
354 TEST ( managedFileSwap, Integration_RandomAccessVariousSize )
355 {
356  global_bytesize oneswap = 1024 * 1024 * ( global_bytesize ) 16;
357  global_bytesize totalswap = 32 * oneswap;
358  tester test;
359  test.setSeed();
360 
361  managedFileSwap swap ( totalswap, "./rambrainswap-%d-%d", oneswap );
362  cyclicManagedMemory manager ( &swap, oneswap );
363 
364  /*ASSERT_EQ ( 0, manager.getSwappedMemory() ); //Deallocated all pointers
365  * ASSERT_EQ ( 0, swap.getUsedSwap() );
366  * ASSERT_EQ ( 16, swap.all_space.size() );
367  * ASSERT_EQ ( 16, swap.free_space.size() );*/
368  infomsgf ( "%ld total swap in %ld swapfiles", swap.getSwapSize(), swap.all_space.size() );
369 
370  global_bytesize obj_size = 102400 * sizeof ( double );
371  global_bytesize obj_no = totalswap / obj_size * 2;
372 
373  managedPtr<double> **objmask = ( managedPtr<double> ** ) malloc ( sizeof ( managedPtr<double> * ) *obj_no );
374  for ( unsigned int n = 0; n < obj_no; ++n ) {
375  objmask[n] = NULL;
376  }
377  for ( unsigned int n = 0; n < 10 * obj_no; ++n ) {
378 
379  global_bytesize no = test.random ( obj_no );
380  ASSERT_TRUE ( manager.checkCycle() );
381  if ( objmask[no] == NULL ) {
382 
383  unsigned int varsize = ( test.random() + 0.5 ) * 102400;
384  if ( ( varsize + 102400 * 2. ) *sizeof ( double ) > swap.getFreeSwap() ) {
385  continue;
386  }
387  objmask[no] = new managedPtr<double> ( varsize );
388  {
389  adhereTo<double> objoloc ( *objmask[no] );
390  double *darr = objoloc;
391  for ( unsigned int k = 0; k < varsize; k++ ) {
392  darr[k] = k + varsize;
393  }
394  }
395 
396  } else {
397  {
398  adhereTo<double> objoloc ( *objmask[no] );
399  double *darr = objoloc;
400  for ( int k = 0; k < darr[0]; k++ ) {
401  ASSERT_EQ ( k + darr[0], darr[k] );
402  }
403 
404  }
405  delete objmask[no];
406  objmask[no] = NULL;
407  }
408  }
409  for ( unsigned int n = 0; n < obj_no; ++n ) {
410  if ( objmask[n] != NULL ) {
411  delete objmask[n];
412  }
413  }
414  free ( objmask );
415 
416 #ifdef SWAPSTATS
417  manager.printSwapstats();
418 #endif
419 
420 }
421 
425 TEST ( managedFileSwap, Unit_SwapAllocation )
426 {
427  unsigned int oneswap = 1024 * 1024 * 16;
428  unsigned int totalswap = 16 * oneswap;
429  managedFileSwap swap ( totalswap, "/tmp/rambrainswap-%d-%d", oneswap );
430  char firstname[70];
431  snprintf ( firstname, 70, "/tmp/rambrainswap-%d-%d", getpid(), 0 );
432 
433  for ( int n = 0; n < 16; n++ ) {
434  char fname[70];
435  snprintf ( fname, 70, "/tmp/rambrainswap-%d-%d", getpid(), n );
436  struct stat mstat;
437  stat ( fname, &mstat );
438  ASSERT_TRUE ( S_ISREG ( mstat.st_mode ) );
439  ASSERT_EQ ( 0, mstat.st_size );
440 
441  }
442  ASSERT_EQ ( 16u, swap.all_space.size() );
443  ASSERT_EQ ( 16u, swap.free_space.size() );
444 
445  cyclicManagedMemory manager ( &swap, 1024 * 10 );
446  manager.setPreemptiveUnloading ( false );
447  {
448  managedPtr<double> testarr ( 1024 ); //80% RAM full.
449  for ( int n = 0; n < 16; n++ ) {
450  char fname[70];
451  snprintf ( fname, 70, "/tmp/rambrainswap-%d-%d", getpid(), n );
452  struct stat mstat;
453  stat ( fname, &mstat );
454  ASSERT_TRUE ( S_ISREG ( mstat.st_mode ) );
455  ASSERT_EQ ( 0, mstat.st_size );
456 
457  }
458  managedPtr<double> testarr2 ( 1024 ); //80% RAM full., swap out occurs.
459  struct stat first;
460  stat ( firstname, &first );
461  ASSERT_TRUE ( S_ISREG ( first.st_mode ) );
462  ASSERT_EQ ( ( ( unsigned int ) ( ( 1024 * 1024 * 16 ) * swap.swapFileResizeFrac ) ), first.st_size ); // should be 1/16th pageFileSize
463  for ( int n = 1; n < 16; n++ ) {
464  char fname[70];
465  snprintf ( fname, 70, "/tmp/rambrainswap-%d-%d", getpid(), n );
466  struct stat mstat;
467  stat ( fname, &mstat );
468  ASSERT_TRUE ( S_ISREG ( mstat.st_mode ) );
469  ASSERT_EQ ( 0, mstat.st_size );
470 
471  }
472  managedPtr<double> testarr3 ( 1024 );
473  ASSERT_EQ ( 8 * 1024u * 2, manager.getSwappedMemory() );
474  stat ( firstname, &first );
475  ASSERT_TRUE ( S_ISREG ( first.st_mode ) );
476  ASSERT_EQ ( ( ( unsigned int ) ( ( 1024 * 1024 * 16 ) * swap.swapFileResizeFrac ) ), first.st_size ); //Size should not change.
477  for ( int n = 1; n < 16; n++ ) {
478  char fname[70];
479  snprintf ( fname, 70, "/tmp/rambrainswap-%d-%d", getpid(), n );
480  struct stat mstat;
481  stat ( fname, &mstat );
482  ASSERT_TRUE ( S_ISREG ( mstat.st_mode ) );
483  ASSERT_EQ ( 0, mstat.st_size );
484 
485  }
486 
487  swap.waitForCleanExit();
488  }
489 
490  ASSERT_EQ ( 0, manager.getSwappedMemory() ); //Deallocated all pointers
491  ASSERT_EQ ( 0, swap.getUsedSwap() );
492  ASSERT_EQ ( 16, swap.all_space.size() );
493  ASSERT_EQ ( 16, swap.free_space.size() );
494 
495  //Start to fill up swap with chunks that are below window size:
496  // Wsize = 1MB , 10KiB Objects in RAM, 100 fit exactly in one swapFile.
497  //let us have objects that fill RAM completely:
498  const unsigned int tenkbdoublearrsize = 1024 / 8 * 10;
499  const unsigned int doublearrsize = tenkbdoublearrsize * sizeof ( double );
500  managedPtr<double> *ptarr[1641];
501  for ( unsigned int n = 0; n < 1639; n++ ) { // Create just as much as fit into RAM+1 swapfile
502  ptarr[n] = new managedPtr<double> ( tenkbdoublearrsize );
503  ASSERT_TRUE ( manager.checkCycle() );
504  };
505  ASSERT_EQ ( doublearrsize, manager.getUsedMemory() );
506  ASSERT_EQ ( doublearrsize * 1638, manager.getSwappedMemory() );
507  for ( unsigned int n = 1; n < 1639; n++ ) { // Create just as much as fit into RAM+1 swapfile
508  delete ptarr[n];
509  };
510  ASSERT_EQ ( 0, manager.getUsedMemory() );
511  ASSERT_EQ ( doublearrsize, manager.getSwappedMemory() );
512  delete ptarr[0];
513 
514  //Fill up over pagefile boundary:
515  for ( unsigned int n = 0; n < 1641; n++ ) { // Create just as much as fit into RAM+1 swapfile
516  ptarr[n] = new managedPtr<double> ( tenkbdoublearrsize );
517  };
518  ASSERT_EQ ( doublearrsize, manager.getUsedMemory() );
519  ASSERT_EQ ( doublearrsize * 1640, manager.getSwappedMemory() );
520  for ( unsigned int n = 0; n < 1641; n++ ) { // Create just as much as fit into RAM+1 swapfile
521  delete ptarr[n];
522  };
523  ASSERT_EQ ( 0, manager.getUsedMemory() );
524  ASSERT_EQ ( 0, manager.getSwappedMemory() );
525  ASSERT_EQ ( 16, swap.all_space.size() );
526  ASSERT_EQ ( 16, swap.free_space.size() );
527 
528 #ifdef SWAPSTATS
529  manager.printSwapstats();
530 #endif
531 }
532 
533 
534 TEST ( managedFileSwap, Unit_SwapReadAllocatedChunk )
535 {
536  const unsigned int oneswap = mib;
537  const unsigned int dblamount = 10;
538  const unsigned int arrsize = dblamount * sizeof ( double );
539  managedFileSwap swap ( oneswap, "/tmp/rambrainswap-%d-%d", oneswap );
540  cyclicManagedMemory manager ( &swap, arrsize * 1.5 );
541 
542  managedPtr<double> ptr1 ( dblamount );
543 
544  ASSERT_EQ ( arrsize, manager.getUsedMemory() );
545  ASSERT_EQ ( 0, manager.getSwappedMemory() );
546 
547  managedPtr<double> ptr2 ( dblamount );
548 
549  ASSERT_EQ ( arrsize, manager.getUsedMemory() );
550  ASSERT_EQ ( arrsize, manager.getSwappedMemory() );
551 
552  {
553  ADHERETOLOCCONST ( double, ptr1, locptr1 );
554  }
555 
556  ASSERT_EQ ( arrsize, manager.getUsedMemory() );
557  ASSERT_EQ ( arrsize, manager.getSwappedMemory() );
558 
559  ASSERT_NO_THROW ( managedPtr<double> ptr3 ( dblamount );
560  ASSERT_EQ ( arrsize, manager.getUsedMemory() );
561  ASSERT_EQ ( 2 * arrsize, manager.getSwappedMemory() ); );
562 }
563 
567 TEST ( managedFileSwap, Unit_SwapSingleIsland )
568 {
569  const unsigned int oneswap = mib;
570  const unsigned int dblamount = oneswap / sizeof ( double );
571  const unsigned int smalldblamount = dblamount * .2;
572  const unsigned int bigdblamount = dblamount - smalldblamount;
573  managedFileSwap swap ( oneswap, "/tmp/rambrainswap-%d-%d", oneswap );
574  cyclicManagedMemory manager ( &swap, oneswap );
575  manager.setPreemptiveUnloading ( false ); //Preemptive swapout kills us here.
576  ASSERT_EQ ( mib, swap.getSwapSize() );
577 
578  //ASSERT_NO_THROW (
579  managedPtr<double> ptr1 ( bigdblamount ); // To fill up swap
580 
581  ASSERT_EQ ( ( bigdblamount ) * sizeof ( double ), manager.getUsedMemory() );
582  ASSERT_EQ ( 0, manager.getSwappedMemory() );
583  managedPtr<double> ptr2 ( bigdblamount ); // To fill up memory
584 
585  ASSERT_EQ ( ( bigdblamount ) * sizeof ( double ), manager.getUsedMemory() );
586  ASSERT_EQ ( ( bigdblamount ) * sizeof ( double ), manager.getSwappedMemory() );
587 
588  managedPtr<double> ptr3 ( smalldblamount ); // Can fit in swap
589 
590  ASSERT_EQ ( ( smalldblamount + bigdblamount ) * sizeof ( double ), manager.getUsedMemory() );
591  ASSERT_EQ ( ( bigdblamount ) * sizeof ( double ), manager.getSwappedMemory() );
592 
593  swap.waitForCleanExit();
594  managedPtr<double> ptr4 ( smalldblamount ); // Can fit in remaining memory
595 
596 
597  ASSERT_EQ ( ( smalldblamount + bigdblamount ) * sizeof ( double ), manager.getUsedMemory() );
598  ASSERT_EQ ( ( smalldblamount + bigdblamount ) * sizeof ( double ), manager.getSwappedMemory() );
599 
600  ASSERT_EQ ( MEM_SWAPPED, ptr1.chunk->status );
601  ASSERT_EQ ( MEM_ALLOCATED, ptr2.chunk->status );
602  ASSERT_EQ ( MEM_SWAPPED, ptr3.chunk->status );
603  ASSERT_EQ ( MEM_ALLOCATED, ptr4.chunk->status );
604  //);
605 }
606 
607 
611 TEST ( managedFileSwap, Unit_SwapNextAndSingleIsland )
612 {
613  const unsigned int oneswap = mib;
614  const unsigned int dblamount = oneswap / sizeof ( double );
615  const unsigned int smalldblamount = dblamount * .1;
616  const unsigned int bigdblamount = dblamount - 2 * smalldblamount;
617  managedFileSwap swap ( oneswap, "/tmp/rambrainswap-%d-%d", oneswap );
618  cyclicManagedMemory manager ( &swap, oneswap );
619  manager.setPreemptiveUnloading ( false ); //Preemptive swapout kills us here.
620 
621  ASSERT_EQ ( mib, swap.getSwapSize() );
622 
623  ASSERT_NO_THROW (
624  managedPtr<double> ptr1 ( bigdblamount ); // To fill up swap
625 
626  ASSERT_EQ ( ( bigdblamount ) * sizeof ( double ), manager.getUsedMemory() );
627  ASSERT_EQ ( 0, manager.getSwappedMemory() );
628 
629  managedPtr<double> ptr2 ( smalldblamount ); // Can fit in swap
630 
631  ASSERT_EQ ( ( bigdblamount + smalldblamount ) * sizeof ( double ), manager.getUsedMemory() );
632  ASSERT_EQ ( ( 0 ) * sizeof ( double ), manager.getSwappedMemory() );
633 
634  managedPtr<double> ptr3 ( bigdblamount ); // To fill up memory
635 
636  ASSERT_EQ ( ( bigdblamount + smalldblamount ) * sizeof ( double ), manager.getUsedMemory() );
637  ASSERT_EQ ( ( bigdblamount ) * sizeof ( double ), manager.getSwappedMemory() );
638 
639  managedPtr<double> ptr4 ( smalldblamount ); // Can fit in swap
640 
641  ASSERT_EQ ( ( bigdblamount + 2 * smalldblamount ) * sizeof ( double ), manager.getUsedMemory() );
642  ASSERT_EQ ( ( bigdblamount ) * sizeof ( double ), manager.getSwappedMemory() );
643 
644  managedPtr<double> ptr5 ( 2 * smalldblamount ); // Can fit in remaining memory
645 
646  ASSERT_EQ ( ( bigdblamount + 2 * smalldblamount ) * sizeof ( double ), manager.getUsedMemory() );
647  ASSERT_EQ ( ( bigdblamount + 2 * smalldblamount ) * sizeof ( double ), manager.getSwappedMemory() );
648 
649  ASSERT_EQ ( MEM_SWAPPED, ptr1.chunk->status );
650  ASSERT_EQ ( MEM_SWAPPED, ptr2.chunk->status );
651  ASSERT_EQ ( MEM_ALLOCATED, ptr3.chunk->status );
652  ASSERT_EQ ( MEM_SWAPPED, ptr4.chunk->status );
653  ASSERT_EQ ( MEM_ALLOCATED, ptr5.chunk->status );
654  );
655 }
656 
660 TEST ( managedFileSwap, Integration_MatrixTranspose )
661 {
662  const unsigned int size = 1000;
663  const unsigned int memlines = 10;
664  const unsigned int mem = size * sizeof ( double ) * memlines;
665  const unsigned int swapmem = size * size * sizeof ( double ) * 2;
666 
667  managedFileSwap swap ( swapmem, "/tmp/rambrainswap-%d-%d" );
668  cyclicManagedMemory manager ( &swap, mem );
669 
670  // Allocate and set
671  managedPtr<double> *rows[size];
672  for ( unsigned int i = 0; i < size; ++i ) {
673  rows[i] = new managedPtr<double> ( size );
674  adhereTo<double> rowloc ( *rows[i] );
675  double *rowdbl = rowloc;
676  for ( unsigned int j = 0; j < size; ++j ) {
677  rowdbl[j] = i * size + j;
678  }
679  }
680 
681  // Transpose
682  for ( unsigned int i = 0; i < size; ++i ) {
683  adhereTo<double> rowloc1 ( *rows[i] );
684  double *rowdbl1 = rowloc1;
685  for ( unsigned int j = i + 1; j < size; ++j ) {
686  adhereTo<double> rowloc2 ( *rows[j] );
687  double *rowdbl2 = rowloc2;
688 
689  double buffer = rowdbl1[j];
690  rowdbl1[j] = rowdbl2[i];
691  rowdbl2[i] = buffer;
692  }
693  }
694 
695  // Check result
696  for ( unsigned int i = 0; i < size; ++i ) {
697  adhereTo<double> rowloc ( *rows[i] );
698  const double *rowdbl = rowloc;
699  for ( unsigned int j = 0; j < size; ++j ) {
700  ASSERT_EQ ( j * size + i, rowdbl[j] );
701  }
702  }
703 
704  // Delete
705  for ( unsigned int i = 0; i < size; ++i ) {
706  delete rows[i];
707  }
708 }
709 
711 TEST ( managedFileSwap, Unit_SwapPolicy )
712 {
713  const unsigned int size = mib;
714  const unsigned int swapmem = 1 * mib;
715 
716  managedFileSwap swap ( swapmem, "/tmp/rambrainswap1-%d-%d" );
717  EXPECT_EQ ( swapPolicy::fixed, swap.getSwapPolicy() );
718  EXPECT_EQ ( mib, swap.getFreeSwap() );
719  cyclicManagedMemory manager ( &swap, size );
720 
721  managedPtr<char> d1 ( mib );
722  managedPtr<char> d2 ( mib );
723  EXPECT_THROW (
725 
726  managedFileSwap swap2 ( swapmem, "/tmp/rambrainswap2-%d-%d" );
727  cyclicManagedMemory manager2 ( &swap2, size );
729 
730  managedPtr<char> e1 ( mib );
731  {
732  ADHERETOLOC ( char, e1, data );
733  data[1337] = 0x42;
734  }
735  managedPtr<char> e2 ( mib );
736  {
737  ADHERETOLOC ( char, e2, data );
738  data[42] = 0x13;
739  }
740  EXPECT_NO_THROW (
741  managedPtr<char> e3 ( mib ) );
742  {
743  ADHERETOLOC ( char, e2, data );
744  EXPECT_EQ ( 0x13, data[42] ) ;
745  }
746  {
747  ADHERETOLOC ( char, e1, data );
748  EXPECT_EQ ( 0x42, data[1337] ) ;
749  }
750 
751 }
752 
753 #ifdef SWAPSTATS
754 TEST ( managedFileSwap, Unit_CheckSwapStats )
756 {
757  const unsigned int amount = 1E3;
758  const unsigned int countMem = 10;
759  const unsigned int countSwap = 100;
760  const unsigned int count = countMem + countSwap;
761  const global_bytesize mem = amount * countMem * sizeof ( double );
762  const global_bytesize swapmem = amount * countSwap * sizeof ( double );
763 
764  managedFileSwap swap ( swapmem, "./rambrainswap-%d-%d" );
765  cyclicManagedMemory manager ( &swap, mem );
766 
767  manager.setPreemptiveUnloading ( false );
768  manager.setPreemptiveLoading ( false );
769 
770  EXPECT_EQ ( 0, manager.n_swap_out );
771  EXPECT_EQ ( 0, manager.n_swap_in );
772  EXPECT_EQ ( 0, manager.swap_out_scheduled_bytes );
773  EXPECT_EQ ( 0, manager.swap_in_scheduled_bytes );
774  EXPECT_EQ ( 0, manager.swap_out_bytes );
775  EXPECT_EQ ( 0, manager.swap_in_bytes );
776  EXPECT_EQ ( 0, manager.swap_out_bytes_last );
777  EXPECT_EQ ( 0, manager.swap_in_bytes_last );
778 
779  managedPtr<double> *ptrs[count];
780  for ( unsigned int i = 0; i < countMem; ++i ) {
781  ptrs[i] = new managedPtr<double> ( amount );
782  managedPtr<double> *dat = ptrs[i];
783  ADHERETOLOC ( double, dat, loc );
784  for ( unsigned int j = 0; j < amount; ++j ) {
785  loc[j] = i * amount + j;
786  }
787 
788  }
789 
790  swap.waitForCleanExit();
791 
792  EXPECT_EQ ( 0, manager.n_swap_out );
793  EXPECT_EQ ( 0, manager.n_swap_in );
794  EXPECT_EQ ( 0, manager.swap_out_scheduled_bytes );
795  EXPECT_EQ ( 0, manager.swap_in_scheduled_bytes );
796  EXPECT_EQ ( 0, manager.swap_out_bytes );
797  EXPECT_EQ ( 0, manager.swap_in_bytes );
798  EXPECT_EQ ( 0, manager.swap_out_bytes_last );
799  EXPECT_EQ ( 0, manager.swap_in_bytes_last );
800 
801  for ( unsigned int i = countMem; i < count; ++i ) {
802  ptrs[i] = new managedPtr<double> ( amount );
803  managedPtr<double> *dat = ptrs[i];
804  ADHERETOLOC ( double, dat, loc );
805  for ( unsigned int j = 0; j < amount; ++j ) {
806  loc[j] = i * amount + j;
807  }
808  }
809 
810  swap.waitForCleanExit();
811 
812  EXPECT_GE ( countSwap, manager.n_swap_out );
813  EXPECT_EQ ( 0, manager.n_swap_in );
814  EXPECT_EQ ( amount * countSwap * sizeof ( double ), manager.swap_out_scheduled_bytes );
815  EXPECT_EQ ( 0, manager.swap_in_scheduled_bytes );
816  EXPECT_EQ ( amount * countSwap * sizeof ( double ), manager.swap_out_bytes );
817  EXPECT_EQ ( 0, manager.swap_in_bytes );
818 
819  double sum = 0.0;
820  for ( unsigned int i = 0; i < count; ++i ) {
821  managedPtr<double> *dat = ptrs[i];
822  ADHERETOLOC ( double, dat, loc );
823  for ( unsigned int j = 0; j < amount; ++j ) {
824  sum += loc[j];
825  }
826  }
827 
828  swap.waitForCleanExit();
829 
830  EXPECT_GE ( countSwap + count, manager.n_swap_out );
831  EXPECT_GE ( count, manager.n_swap_in );
832  EXPECT_EQ ( amount * ( countSwap + count ) * sizeof ( double ), manager.swap_out_scheduled_bytes );
833  EXPECT_EQ ( amount * count * sizeof ( double ), manager.swap_in_scheduled_bytes );
834  EXPECT_EQ ( amount * ( countSwap + count ) * sizeof ( double ), manager.swap_out_bytes );
835  EXPECT_EQ ( amount * count * sizeof ( double ), manager.swap_in_bytes );
836 
837  tester test;
838  test.setSeed();
839 
840  sum = 0.0;
841  for ( unsigned int i = 0; i < count; ++i ) {
842  managedPtr<double> *dat = ptrs[test.random ( ( int ) count )];
843  ADHERETOLOC ( double, dat, loc );
844  for ( unsigned int j = 0; j < amount; ++j ) {
845  sum += loc[j];
846  }
847  }
848 
849  swap.waitForCleanExit();
850 
851 
852  EXPECT_LE ( manager.swap_out_bytes, manager.swap_out_scheduled_bytes );
853  EXPECT_LE ( manager.swap_in_bytes , manager.swap_in_scheduled_bytes );
854 
855  for ( unsigned int i = 0; i < count; ++i ) {
856  delete ptrs[i];
857  }
858 }
859 #endif
860 
861 
865 TEST ( managedFileSwap, Unit_EmptySizeSwapped )
866 {
867  managedFileSwap swap ( sizeof ( double ) * 100, "./rambrainswap-%d-%d" );
868  cyclicManagedMemory managedMemory ( & swap, sizeof ( double ) * 15 ) ;
869 
870  managedPtr<double> ptr1 ( 10 );
871  {
872  ADHERETOLOC ( double, ptr1, loc );
873  for ( int i = 0; i < 10; ++i ) {
874  loc[i] = i;
875  }
876  }
877 
878  ASSERT_NO_FATAL_FAILURE (
879  managedPtr<double> ptr2 ( 0 );
880  managedPtr<double> ptr3 ( 15 );
881  );
882 
883  {
884  ADHERETOLOC ( double, ptr1, loc );
885  for ( int i = 0; i < 10; ++i ) {
886  ASSERT_EQ ( i, loc[i] );
887  }
888  }
889 }
890 
891 
895 TEST ( managedFileSwap, Unit_EmptySizeFillsUp )
896 {
897  managedFileSwap swap ( sizeof ( double ) * 100, "./rambrainswap-%d-%d" );
898  cyclicManagedMemory managedMemory ( & swap, sizeof ( double ) * 10 ) ;
899 
900  managedPtr<double> ptr1 ( 10 );
901  {
902  ADHERETOLOC ( double, ptr1, loc );
903  for ( int i = 0; i < 10; ++i ) {
904  loc[i] = i;
905  }
906  }
907 
908  ASSERT_NO_FATAL_FAILURE (
909  managedPtr<double> ptr2 ( 0 );
910  );
911 
912  {
913  ADHERETOLOC ( double, ptr1, loc );
914  for ( int i = 0; i < 10; ++i ) {
915  ASSERT_EQ ( i, loc[i] );
916  }
917  }
918 }
919 
921 
Exception for errors with the memory.
Definition: exceptions.h:87
global_bytesize getSwappedMemory() const
returns current swap usage
void addTimeMeasurement()
Saves the current timestamp.
Definition: tester.cpp:36
IGNORE_TEST_WARNINGS
void * locPtr
pointer to the actual data in RAM
Main class to fetch memory that is managed by rambrain for actual usage.
Definition: managedPtr.h:48
global_bytesize getUsedMemory() const
returns current ram usage
virtual global_bytesize getUsedSwap() const
Simple getter.
Definition: managedSwap.h:86
void setSeed(unsigned int seed=time(NULL))
Set a new seed for random number generation.
Definition: tester.cpp:64
int random(int max) const
Get a random number (integer)
Definition: tester.cpp:74
void startNewTimeCycle()
Starts a new cycle of time measurements.
Definition: tester.cpp:89
Main class to allocate memory that is managed by the rambrain memory defaultManager.
Definition: managedMemory.h:54
virtual global_bytesize getSwapSize() const
Simple getter.
Definition: managedSwap.h:82
bool checkCycle()
checks whether the scheduler believes to be sane and prints an error message if not ...
virtual swapPolicy getSwapPolicy() const
Definition: managedSwap.h:95
An implementation of managedSwap that is capable of kernel asynchronousIO.
uint64_t global_bytesize
Definition: common.h:65
std::vector< int64_t > getDurationsForCurrentCycle() const
Take the current cycle of time measurements and calculate all durations in betwen.
Definition: tester.cpp:186
virtual global_bytesize getFreeSwap() const
Simple getter.
Definition: managedSwap.h:90
const global_bytesize gig
Definition: common.h:69
static pthread_mutex_t stateChangeMutex
A basic class to be used by tests. Provides helper methods and functionality e.g. time measurements...
Definition: tester.h:32
manages all managed Chunks of raw memory
void waitForCleanExit()
Function waits for all asynchronous IO to complete. The wait is implemented non-performant as a norma...
Definition: managedSwap.cpp:46
void printSwapstats() const
print statistic about the number, size and efficiency of swapping actions
bool setPreemptiveUnloading(bool preemptive)
sets whether scheduler should swap out elements without strict need
virtual global_bytesize swapOut(managedMemoryChunk **chunklist, unsigned int nchunks)
Trigger swap out of the chunks pointed to by chunklist.
scheduler working with a double linked cycle. Details see paper.
virtual swapPolicy setSwapPolicy(swapPolicy newPolicy)
Definition: managedSwap.h:100
std::map< global_offset, pageFileLocation * > free_space
global_bytesize size
Size of actual object in bytes.
virtual void swapDelete(managedMemoryChunk *chunk)
Mark chunk as deleted.
A dummy swap that just copies swapped out chunks to a different location in ram.
TEST(managedFileSwap, Unit_LazyPffree)
std::map< global_offset, pageFileLocation * > all_space
Backend class to handle raw memory and interaction/storage with managedSwap.
Definition: managedMemory.h:68
const global_bytesize mib
Definition: common.h:68
virtual global_bytesize swapIn(managedMemoryChunk **chunklist, unsigned int nchunks)
Trigger swap in of the chunks pointed to by chunklist.