private void batchEstimateDataAndMemory(boolean useRuntimeMaxJvmHeap, String outputDir, int reduceBase) throws IOException {
		//File mDataOutputFile = new File(outputDir, "eDataMappers.txt");
		//File rDataOutputFile = new File(outputDir, "eDataReducers.txt");
		
		File mJvmOutputFile = new File(outputDir, "eJvmMappers.txt");
		File rJvmOutputFile = new File(outputDir, "eJvmReducers.txt");
		
		if(!mJvmOutputFile.getParentFile().exists()) 
			mJvmOutputFile.getParentFile().mkdirs();
		
		//PrintWriter mDataWriter = new PrintWriter(new BufferedWriter(new FileWriter(mDataOutputFile)));
		//PrintWriter rDataWriter = new PrintWriter(new BufferedWriter(new FileWriter(rDataOutputFile)));
		
		PrintWriter mJvmWriter = new PrintWriter(new BufferedWriter(new FileWriter(mJvmOutputFile)));
		PrintWriter rJvmWriter = new PrintWriter(new BufferedWriter(new FileWriter(rJvmOutputFile)));
		
		//displayMapDataTitle(mDataWriter);
		//displayReduceDataTitle(rDataWriter);
		
		displayMapJvmCostTitle(mJvmWriter);
		displayReduceJvmCostTitle(rJvmWriter);
		
		for(int splitMB = 64; splitMB <= 256; splitMB = splitMB * 2) {
		
			for(int xmx = 1000; xmx <= 4000; xmx = xmx + 1000) {
				for(int ismb = 200; ismb <= 800; ismb = ismb + 200) {
					for(int reducer = reduceBase; reducer <= reduceBase * 2; reducer = reducer * 2) {
						for(int xms = 0; xms <= 1; xms++) {
							
							//--------------------------Estimate the data flow---------------------------
							//-----------------for debug-------------------------------------------------
						    //System.out.println("[xmx = " + xmx + ", xms = " + xms + ", ismb = " + 
							//		ismb + ", RN = " + reducer + "]");
							//if(xmx != 4000 || ismb != 400 || reducer != 16 || xms != 1)
							//	continue;
							//if(xmx != 4000 || xms != 1 || ismb != 1000 || reducer != 9)
							//	continue;
							//---------------------------------------------------------------------------
							
							Configuration conf = new Configuration();
							
							long newSplitSize = splitMB * 1024 * 1024l;
							conf.set("io.sort.mb", String.valueOf(ismb));
							
							if(xms == 0)
								conf.set("mapred.child.java.opts", "-Xmx" + xmx + "m");
							else
								conf.set("mapred.child.java.opts", "-Xmx" + xmx + "m" + " -Xms" + xmx + "m");
							
							conf.set("mapred.reduce.tasks", String.valueOf(reducer));
							
							
							conf.set("split.size", String.valueOf(newSplitSize));
							setNewConf(conf);
							
							// -------------------------Estimate the data flow-------------------------
							List<Mapper> eMappers = estimateMappers();	//don't filter the mappers with small split size
							List<Reducer> eReducers = estimateReducers(eMappers, useRuntimeMaxJvmHeap);
							
							String fileName = conf.getConf("mapred.child.java.opts").replaceAll(" ", "") + "-ismb" + ismb + "-RN" + reducer;
							displayMapperDataResult(eMappers, fileName , outputDir + File.separator + "eDataflow" + splitMB);
							displayReducerDataResult(eReducers, fileName, outputDir + File.separator + "eDataflow" + splitMB);
							
							// -------------------------Estimate the memory cost-------------------------
							InitialJvmCapacity gcCap = computeInitalJvmCapacity();
							
							if(!gcCap.getError().isEmpty()) {
								System.err.println(gcCap.getError() + " [xmx = " + xmx + ", xms = " + xms + ", ismb = " + 
										ismb + ", RN = " + reducer + "]");
							}
							else {
								//filter the estimated mappers with low split size
								List<MapperEstimatedJvmCost> eMappersMemory = estimateMappersMemory(eMappers, gcCap);
								List<ReducerEstimatedJvmCost> eReducersMemory = estimateReducersMemory(eReducers, gcCap);
								
								
								displayMapperJvmCostResult(eMappersMemory, gcCap, mJvmWriter);
								displayReducerJvmCostResult(eReducersMemory, gcCap, rJvmWriter);
							}
							
							
						}
					}
				}
			}
			
		}
		
		
		mJvmWriter.close();
		rJvmWriter.close();
		
	}