package water; import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import org.junit.*; import water.fvec.Frame; import water.fvec.Vec; import static water.util.FileUtils.*; import water.util.Log; @Ignore public class OOMTest extends TestUtil { @BeforeClass() public static void setup() { stall_till_cloudsize(1); } @Test public void testClean() throws InterruptedException { final int log_rows_per_chk = 6; final int nchks = 1024/(1<<log_rows_per_chk); // 1024/(1<<4) = 64 chunks Vec vcon = Vec.makeCon(0,1024,log_rows_per_chk); // New vector, Vec vrnd1 = vcon.makeRand(0x123456L); // Same shape as above, but rand fill Vec vrnd2 = vcon.makeRand(0x123456L); // Same shape as above, but rand fill vcon.remove(); // Fast access to all Values, outside of the DKV Value val1s[] = new Value[nchks]; Value val2s[] = new Value[nchks]; for( int i=0; i<nchks; i++ ) { val1s[i] = vrnd1.chunkIdx(i); val2s[i] = vrnd2.chunkIdx(i); } // Flag val1s as "last touched a long time ago" long ago = System.currentTimeMillis()-1000L*1000L; for( int i=0; i<nchks; i++ ) val1s[i].touchAt(ago); // Block until the Cleaner sleeps & take lock synchronized(Cleaner.THE_CLEANER) { // Sweep DKV, Cleaner should attempt to write out old chunks Cleaner.dirty_store(ago); Cleaner.kick_store_cleaner(); Cleaner.block_for_test(); Assert.assertTrue(Cleaner.dirty() != ago); // Cleaner is updated for( int i=0; i<nchks; i++ ) Assert.assertTrue(val1s[i].isPersisted()); // Chunks all hit disk // Tell the Cleaner the "DESIRED" cache level is ZERO. Then trigger // another Cleaner pass ... should write all out to disk. //long old_DESIRED = Cleaner.DESIRED; Cleaner.DESIRED = -1; // Flag: MemoryManager setGoals expects to force all out ago = System.currentTimeMillis()-1000L*1000L; // Sweep DKV, Cleaner should attempt to write out old chunks Cleaner.dirty_store(ago); Cleaner.kick_store_cleaner(); Cleaner.block_for_test(); Assert.assertTrue(Cleaner.dirty() != ago); // Cleaner is updated for( int i=0; i<nchks; i++ ) { Assert.assertTrue(val1s[i].isPersisted()); // Chunks all hit disk Assert.assertTrue(val1s[i].rawMem()==null);// Chunks all hit disk // Cannot assert on val2s - unless 5sec has past, they are too new to be written out. // So OS-schedluing specific on whether or not they hit disk Assert.assertTrue(val2s[i].isPersisted()); // Chunks all hit disk Assert.assertTrue(val2s[i].rawMem()==null);// Chunks all hit disk } } // Now touch all the data, forcing a reload. Confirm all reads the same. boolean id = TestUtil.isBitIdentical(new Frame(new String[]{"C1"}, new Vec[]{vrnd1}), new Frame(new String[]{"C1"}, new Vec[]{vrnd2})); Assert.assertTrue("Frames loaded from disk are equal", id); // All Chunks are recorded as being back-in-memory for( int i=0; i<nchks; i++ ) { Value v1 = vrnd1.chunkIdx(i); Value v2 = vrnd2.chunkIdx(i); Assert.assertTrue(v1.isPersisted()); Assert.assertTrue(v2.isPersisted()); Assert.assertTrue(v1.rawMem() != null || !v1._key.home()); Assert.assertTrue(v2.rawMem() != null || !v2._key.home()); } // Cleanup vrnd1.remove(); vrnd2.remove(); } // too slow for standard junit // repeatedly throws OOM exception purpose, which breaks many things. // tested now in gradle via the custom main() below @Test @Ignore public void testParseMemoryStress() { // "bigdata directory is not always available" if( locateFile("bigdata/laptop/usecases/cup98LRN_z.csv") == null ) return; if( locateFile("bigdata/laptop/usecases/cup98VAL_z.csv") == null ) return; ArrayList<Frame> frames = new ArrayList<>(); File ice = new File(water.H2O.ICE_ROOT.toString(),"ice" + water.H2O.API_PORT); String[] dirs = ice.list(); Assert.assertTrue(dirs == null || dirs.length==0); // ICE empty before we start Assert.assertTrue(MemoryManager.MEM_MAX <= 1536L*1024L*1024L); // No more than 1.5Gig of heap; forces swapping try { // Force much swap-to-disk for( int i=0; i<4; i++ ) { frames.add(parse_test_file(Key.make("F" + frames.size()), "bigdata/laptop/usecases/cup98LRN_z.csv")); frames.add(parse_test_file(Key.make("F" + frames.size()), "bigdata/laptop/usecases/cup98VAL_z.csv")); } } finally { dirs = ice.list(); Assert.assertNotNull("Swap directory not created; no swapping happened; test failed to stresss enough",dirs); Assert.assertTrue(dirs.length>0); // Much got swapped to disk Log.info("Deleting swap files at test end"); for( Frame fr : frames ) fr.delete(); // Cleanup swap-to-disk } // Assert nothing remains dirs = ice.list(); if (dirs.length > 0) { Log.info("Remaining swap files at test end:"); for (String dir : dirs) { Log.info(dir); } } Assert.assertTrue(dirs.length==0); } public static void main(String[] args) { stall_till_cloudsize(args, 1); try { // Disabling for good - it's not relevant anymore //new OOMTest().testParseMemoryStress(); // Throws on assertion error } catch( Throwable e ) { Log.err(e); StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); Log.err(sw); System.exit(-1); } System.exit(0); } }