1 /*
   2  * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 
  25 /*
  26  * @test
  27  * @key stress gc
  28  *
  29  * @summary converted from VM Testbase gc/gctests/MatrixJuggleGC.
  30  * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent]
  31  * VM Testbase readme:
  32  * ********************************
  33  * set TIMEOUT = 20
  34  * *******************************
  35  * This test creates a 2 dimensional matrix of (100X100)10,000 elements.
  36  * Each element in this matrix houses the address of a "Cell" that
  37  * occupies about 100 bytes. The total memory occupied by this structure is
  38  * about 1M.
  39  * Once this structure, has been built, 5 threads are let loose that
  40  * randomly choose an element in this matrix and set its contents to null
  41  * effectively creating 100bytes of garbage. The threads continue to act
  42  * until all 5 threads combined have "nulled out" half the cells in the matrix.
  43  * At this point, 5 refiller threads proceed to refill the empty
  44  * matrix elements with new cells.
  45  * Once the refiller threads have refilled all the empty matrix elements
  46  * with new cells, the cycle begins all over again with the 5 "emptier"
  47  * threads "nulling out" cells randomly.
  48  * This is repeated 50 times.  Every iteration produces  0.5 Meg
  49  * of garbage. The maximum amount of live memory at use at any time is 1Meg.
  50  * If no garbage collection takes place during any of the ten iterations,
  51  * the total amount(live + garbage) of heap space consumed at the end
  52  * of the program is 0.5*50 + 1 = 26Meg.
  53  * The test fails if an OutOfMemory Exception is thrown.
  54  *        -----------------------------        --------
  55  *       |     |     |     |     |     |       | 100  |
  56  *       |     |     |     |     |  *--|------>| bytes|
  57  *       |     |     |     |     |     |       --------
  58  *        -----------------------------
  59  *       .     .     .     .     .     .
  60  *       .     .     .     .     .     .
  61  *       .     .     .     .     .     .
  62  *       .
  63  *       |     |     |     |     |     |
  64  *       |     |     |     |     |     |
  65  *       |     |     |     |     |     |
  66  *        ------------------------------
  67  *       |     |     |     |     |     |
  68  *       |     |     |     |     |     |
  69  *       |     |     |     |     |     |
  70  *        ------------------------------
  71  *       |     |     |     |     |     |
  72  *       |     |     |     |     |     |
  73  *       |     |     |     |     |     |
  74  *        ------------------------------
  75  *       |     |     |     |     |     |
  76  *       |     |     |     |     |     |
  77  *       |     |     |     |     |     |
  78  *        -----------------------------
  79  *
  80  * @library /vmTestbase
  81  *          /test/lib
  82  * @run driver jdk.test.lib.FileInstaller . .
  83  * @run main/othervm gc.gctests.MatrixJuggleGC.MatrixJuggleGC -iterations 1000000
  84  */
  85 
  86 package gc.gctests.MatrixJuggleGC;
  87 
  88 import nsk.share.test.*;
  89 import nsk.share.gc.*;
  90 import java.util.Stack;
  91 import java.util.EmptyStackException;
  92 
  93 public class MatrixJuggleGC extends GCTestBase {
  94         private int threadCount = 5;
  95         private Matrix cm = new Matrix(100, 100);
  96         private Stack<IndexPair> emptiedLocations = new Stack<IndexPair>();
  97 
  98         private class CellEmptier extends Thread {
  99                 private boolean keepEmptying(){
 100                         int numberOfCells;
 101                         int matrixSize;
 102 
 103                         matrixSize = cm.returnArrayBound();
 104                         numberOfCells = (matrixSize + 1) * (matrixSize + 1) ;
 105                         if (cm.getCellCount() < numberOfCells/2)
 106                                 return true;
 107                         else
 108                                 return false;
 109                 }
 110 
 111                 public void run() {
 112                         int i, j, matrixSize,emptyCells;
 113 
 114                         matrixSize = cm.returnArrayBound();
 115                         while (keepEmptying()) {
 116                                 i = LocalRandom.nextInt(0, matrixSize);
 117                                 j = LocalRandom.nextInt(0, matrixSize);
 118                                 emptiedLocations.push(new IndexPair(i,j));
 119                                 cm.clear(i, j);
 120                         }
 121                 }
 122         }
 123 
 124         private class CellRefiller extends Thread {
 125                 public void run() {
 126                         int i, j, emptyCells;
 127                         while (!emptiedLocations.empty()) {
 128                                 try {
 129                                         IndexPair pair = emptiedLocations.pop();
 130                                         cm.repopulate(pair.getI(), pair.getJ());
 131                                 } catch (EmptyStackException e) {
 132                                         break;
 133                                 }
 134                         }
 135                 }
 136         }
 137 
 138         private class StackDump extends Thread {
 139                 public void run() {
 140                         int emptyCells;
 141                         while (true) {
 142                                 emptyCells = emptiedLocations.size();
 143                                 System.out.println("Number of empty cells = " + emptyCells);
 144                         }
 145                 }
 146         }
 147 
 148         private void runIteration() {
 149                 Thread emptierArray[] = new Thread[threadCount];
 150                 Thread fillerArray[]  = new Thread[threadCount];
 151                 for (int i = 0; i < threadCount; i++)
 152                         emptierArray[i] = new CellEmptier();
 153                 for (int i = 0; i < threadCount; i++)
 154                         emptierArray[i].start();
 155 
 156                 // wait for "emptier" threads to finish their job
 157 
 158                 int i = 0;
 159                 while (i < threadCount) {
 160                         try {
 161                                 emptierArray[i].join();
 162                         } catch(InterruptedException e) {}
 163                         i++;
 164                 }
 165 
 166                 // Now start refilling.
 167 
 168                 for (i = 0; i < threadCount; i++)
 169                         fillerArray[i] = new CellRefiller();
 170                 for (i = 0; i < threadCount; i++)
 171                         fillerArray[i].start();
 172 
 173                 i = 0;
 174                 while (i < threadCount ){
 175                         try {
 176                                 fillerArray[i].join();
 177                         } catch(InterruptedException e){}
 178                         i++;
 179                 }
 180                 // reset count of cells
 181                 cm.resetCellCount();
 182         }
 183 
 184         public void run() {
 185                 threadCount = runParams.getNumberOfThreads();
 186                 Stresser stresser = new Stresser(runParams.getStressOptions());
 187                 stresser.start(runParams.getIterations());
 188                 while (stresser.iteration())
 189                         runIteration();
 190                 stresser.finish();
 191         }
 192 
 193         public static void main(String args[]) {
 194                 GC.runTest(new MatrixJuggleGC(), args);
 195         }
 196 }