Commit 947bbe37 authored by Sergio Pérez's avatar Sergio Pérez
Browse files

Timed Run:

* Measured the generation time of the different graph edges
* Added EKnife.timedRun to evaluate the slicer against all the possible slicing criteria of a program
* Added intraprocedural bencher suite
parent 787ed139
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -61,7 +61,6 @@ public class DotFactory {
		edgeNameMap.put("flow", List.of(Edge.Type.Flow));
		edgeNameMap.put("objectflow", List.of(Edge.Type.ObjectFlow));
		edgeNameMap.put("value", List.of(Edge.Type.Value));
		edgeNameMap.put("valuestructure", List.of(Edge.Type.ValueStructure));
		edgeNameMap.put("totaldefinition", List.of(Edge.Type.TotalDefinition));
		edgeNameMap.put("call", List.of(Edge.Type.Call));
		edgeNameMap.put("input", List.of(Edge.Type.Input));
+1 −1
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@ import edg.graph.LAST;
public class EDGFactory {
	private final LAST last;
	private EDG edg;
	private boolean interproceduralGraph = false;
	private boolean interproceduralGraph = true;

	public EDGFactory(LAST last)
	{
+362 −0
Original line number Diff line number Diff line
@@ -154,6 +154,368 @@ public class EKnife
		CodeFactory.createCode(Language.Erlang, a.outputFile, edg, slice);
	}

	private static void timedRun(Args a)
	{
		// CONFIGURE MEASURED DIMENSIONS
		boolean measureGenerationTime = true;
		boolean measureNodes = false;
		boolean performAllSCs = true;
		/*******************************************************/
		/*** MEASUREMENT OF GENERATION TIME (100 executions) ***/
		/*******************************************************/
		int numberOfIterations = 100;

		if (measureGenerationTime) {
	//		double StructuralTime[] = new double[100];
	//		double CFGTime[] = new double[100];
	//		double ValueTime[] = new double[100];
	//		double ControlTime[] = new double[100];
	//		double FlowTime[] = new double[100];

			double totalStructural, totalCFG, totalValue, totalComposite, totalControl, totalFlow;
			totalStructural = totalCFG = totalValue = totalComposite = totalControl = totalFlow = 0.0;

			for (int i = -1; i < numberOfIterations; i++) {

				final LAST last = LASTFactory.createLAST(Language.Erlang, a.inputPath, true);
				final EDG edg = new EDGFactory(last).createEDG();

				if (i == -1)
					continue;

				totalStructural += edg.getGenerationTime().getStructureTime();
				totalCFG += edg.getGenerationTime().getControlFlowTime();
				totalValue += edg.getGenerationTime().getValueTime();
				totalComposite += edg.getGenerationTime().getCompositeTime();
				totalControl += edg.getGenerationTime().getControlTime();
				totalFlow += edg.getGenerationTime().getFlowTime();

//			StructuralTime[i] = edg.getGenerationTime().getStructureTime();
//			CFGTime[i] = edg.getGenerationTime().getControlFlowTime();
//			ValueTime[i] = edg.getGenerationTime().getValueTime();
//			ControlTime[i] = edg.getGenerationTime().getControlTime();
//			FlowTime[i] = edg.getGenerationTime().getFlowTime();
			}

//		double totalStructural, totalCFG, totalValue, totalControl, totalFlow;
//		totalStructural = totalCFG = totalValue = totalControl = totalFlow = 0.0;
//		for (int i = 0; i < 100; i++){
//			totalStructural += StructuralTime[i];
//			totalCFG += CFGTime[i];
//			totalValue += ValueTime[i];
//			totalControl += ControlTime[i];
//			totalFlow += FlowTime[i];
//		}
			// INTRAPROCEDURAL GENERATION TIME
			// TIME MEASSUREMENT:
			printGenerationTime(a.file, numberOfIterations, totalStructural, totalCFG, totalValue,
					totalComposite, totalControl, totalFlow, false);
			printGenerationTime(a.file, numberOfIterations, totalStructural, totalCFG, totalValue,
					totalComposite, totalControl, totalFlow, true);
		}

		final LAST last = LASTFactory.createLAST(Language.Erlang, a.inputPath, true);
		final EDG edg = new EDGFactory(last).createEDG();
		/*****************************/
		/*** MEASUREMENT OF NODES: ***/
		/*****************************/
		if (measureNodes) {
			int SDGNodeCounter = countSDGNodes(edg);
			int EDGNodeCounter = countEDGNodes(edg);

			printNodeCounter(a.file, SDGNodeCounter, EDGNodeCounter);
		}
		/**************************/
		/*** MEASUREMENT OF SCs ***/
		/**************************/
		if (performAllSCs) {

			// SC SELECTION
			List<Node> clauses = edg.getNodes(Node.Type.Clause);
			clauses.removeIf(c -> edg.getParent(c).getType() != Node.Type.Routine);

			printTitle("/Users/serperu/Desktop/SlicerOutput/Times/slicingStatistics.txt", a.file);

			for (Node clause : clauses) {
				List<Node> descendants = edg.getDescendants(clause);
				descendants.add(clause);

				List<Node> resultNodes = new LinkedList<>();
				List<Node> nonResultNodes = new LinkedList<>();

				for (Node n : descendants)
					if (n.getType() == Node.Type.Result) {
						if (edg.getNodeFromRes(n).getType() != Node.Type.Callee)
							resultNodes.add(n);
					} else
						nonResultNodes.add(n);
				nonResultNodes.add(clause);
				resultNodes.add(edg.getResFromNode(clause));


				// IGNORE FUNCTIONS WITHOUT COMPOSITE STRUCTURES
				if (nonResultNodes.stream()
						.noneMatch(
								n -> { if (n.getType() == Node.Type.DataConstructor)
											return true;
										if (n.getType() == Node.Type.List)
											if (edg.getChildren(n).size() != 0 || edg.getParent(n).getType() == Node.Type.List)
												return true;
										return false;})) {
					System.out.println("File Name: " + a.file);
					int functionArity = edg.getChildrenNonResult(edg.getChild(clause, Node.Type.Parameters)).size();
					System.out.println("Function " + edg.getParent(clause).getName() + "/" + functionArity + " has no valid slicing criteria.");
					continue;
				}

				/* FILTER SC NODES BY A CRITERION (REMOVE LITERALS) */
				resultNodes.removeIf(n -> edg.getNodeFromRes(n).getType() == Node.Type.Literal);

				/* SPECIFIC FILTER FOR BENCH1.ERL */
				// TODO: Detect and generalise the scenario
				if (a.file.equals("bench1.erl"))
					resultNodes.removeIf(sc -> edg.getAncestor(sc, Node.Type.Equality) != null &&
							edg.getChild(
									edg.getAncestor(sc, Node.Type.Equality), Node.Type.Pattern)
									.getName().equals("Database"));
				/* *********** */

				SlicingCriterionState[] allCriteriaStandard = new SlicingCriterionState[resultNodes.size()];
				SlicingCriterionState[] allCriteriaConstrained = new SlicingCriterionState[resultNodes.size()];

				// CONFIGURE MEASURED DIMENSIONS
				boolean measureSlicingPerformance = false;
				boolean measureSlicingTime = true;

				final SlicingAlgorithm standardAlgorithm = new AdaptedStandardAlgorithm(edg);
				final SlicingAlgorithm constrainedAlgorithm = new ConstrainedAlgorithm(edg);

				int scCounter = 0;
				int scConstrainedImprovements = 0;

				for (Node SC : resultNodes) {
					// INITIALIZATIONS
						// PERFORMANCE
					double standardSlicePercentage = 0.0;
					double constrainedSlicePercentage = 0.0;
						// TIME
					double standardTimeMean = 0.0;
					double constrainedTimeMean = 0.0;

					// MEASURE TIME FOR EACH SC
					if (measureSlicingTime) {
						for (int j = -1; j < numberOfIterations; j++) {
							long initialStandardTime = System.nanoTime();
							standardAlgorithm.slice(SC);
							long finalStandardTime = System.nanoTime();

							long initialConstrainedTime = System.nanoTime();
							constrainedAlgorithm.slice(SC);
							long finalConstrainedTime = System.nanoTime();

							if (j == -1)
								continue;

							standardTimeMean += (finalStandardTime - initialStandardTime) / (numberOfIterations * 1000000.0);
							constrainedTimeMean += (finalConstrainedTime - initialConstrainedTime) / (numberOfIterations * 1000000.0);
						}
						standardTimeMean /= numberOfIterations;
						constrainedTimeMean /= numberOfIterations;
					}

					// MEASURE PERFORMARNCE
					final Set<Node> standardSlice = standardAlgorithm.slice(SC);
					final Set<Node> constrainedSlice = constrainedAlgorithm.slice(SC);


					if (measureSlicingPerformance) {
						standardSlice.removeIf(n -> n.getType() == Node.Type.Result ||
								n.getType() == Node.Type.Routine || n.getType() == Node.Type.Module
								|| n.getType() == Node.Type.Root);
						standardSlicePercentage = standardSlice.size() * 100.0 / nonResultNodes.size();

						constrainedSlice.removeIf(n -> n.getType() == Node.Type.Result ||
								n.getType() == Node.Type.Routine || n.getType() == Node.Type.Module
								|| n.getType() == Node.Type.Root);
						constrainedSlicePercentage = constrainedSlice.size() * 100.0 / nonResultNodes.size();

						if (constrainedSlice.size() < standardSlice.size())
							scConstrainedImprovements++;

						if (standardSlicePercentage < constrainedSlicePercentage)
							throw new IllegalStateException("The SDG cannot be more precise than the EDG");

					}
					allCriteriaStandard[scCounter] = new SlicingCriterionState(standardSlicePercentage, standardTimeMean);
					allCriteriaConstrained[scCounter] = new SlicingCriterionState(constrainedSlicePercentage, constrainedTimeMean);
					scCounter++;
				}
				int arity = edg.getChildrenNonResult(edg.getChild(clause, Node.Type.Parameters)).size();
				printSlicingResults(edg.getParent(clause).getName() + "/" + arity,
					resultNodes.size(), allCriteriaStandard, allCriteriaConstrained,
						scConstrainedImprovements, measureSlicingPerformance, measureSlicingTime);
			}
		}
//		DotFactory.createDot(new File("/Users/serperu/Desktop/SlicerOutput/graphSliced.dot"), edg, SC, slice, edgeFlags);
//		CodeFactory.createCode(Language.Erlang, a.outputFile, edg, slice);
	}

	public static int countSDGNodes(EDG edg) {
		Node root = edg.getRootNode();
		return countSDGNodes(edg, root);
	}

	public static int countSDGNodes(EDG edg, Node node) {
		int counter = 1;
		List<Node> children = edg.getChildren(node);
		for (Node child : children) {
			if (child.getType() == Node.Type.Result)
				continue;
			if (child.getType() == Node.Type.List ||child.getType() == Node.Type.DataConstructor)
				counter++;
			else {
				counter += countSDGNodes(edg, child);
			}
		}
		return counter;
	}

	public static int countEDGNodes(EDG edg) {
		Set<Node> nodes = new HashSet<>();
		nodes.addAll(edg.vertexSet());
		nodes.removeIf(n -> n.getType() == Node.Type.Result);
		return nodes.size();
	}

	public static void printGenerationTime(String programName, int numberOfIterations, double totalStructural,
										   double totalCFG, double totalValue, double totalComposite,
										   double totalControl, double totalFlow, boolean isEDG) {
		FileWriter timeFileWriter;
		PrintWriter timeWriter = null;
		try {
			String graphName = isEDG ? "EDG" : "SDG";
			timeFileWriter = new FileWriter("/Users/serperu/Desktop/SlicerOutput/Times/generationTime"+graphName+".txt", true);
			timeWriter = new PrintWriter(timeFileWriter);
			timeWriter.println("---------------------------");
			timeWriter.println("-------- "+graphName+" TIME ---------");
			timeWriter.println("---------------------------");
			timeWriter.println("Program Name: " + programName);
			timeWriter.println("---------------------------");
//			timeWriter.println("StructuralTime: " + totalStructural  / StructuralTime.length + " ms");
//			timeWriter.println("ControlFlowTime: " + totalCFG / CFGTime.length + " ms");
//			timeWriter.println("ValueTime: " + totalValue / ValueTime.length + " ms");
//			timeWriter.println("ControlTime: " + totalControl / ControlTime.length + " ms");
//			timeWriter.println("FlowTime: " + totalFlow / FlowTime.length + " ms");
//			double TotalTime = (totalStructural + totalCFG + totalValue + totalControl + totalFlow) / StructuralTime.length;
//			timeWriter.println("TOTAL TIME: " + TotalTime + " ms\n");
			timeWriter.println("StructuralTime: " + totalStructural / numberOfIterations + " ms");
			timeWriter.println("ControlFlowTime: " + totalCFG / numberOfIterations + " ms");
			if (!isEDG)
				totalValue -= totalComposite; // SDG Time ignores Composite Structures Generation
			timeWriter.println("ValueTime: " + totalValue / numberOfIterations + " ms");
			timeWriter.println("ControlTime: " + totalControl / numberOfIterations + " ms");
			timeWriter.println("FlowTime: " + totalFlow / numberOfIterations + " ms");
			double TotalTime = (totalStructural + totalCFG + totalValue + totalControl + totalFlow) / numberOfIterations;
			timeWriter.println("TOTAL TIME: " + TotalTime + " ms\n");

		} catch (IOException e) {
			System.out.println("FILE NOT FOUND ERROR");
		} finally {
			if (timeWriter != null)
				timeWriter.close();
		}
	}

	public static void printNodeCounter(String programName, int SDGNodes, int EDGNodes) {
		FileWriter timeFileWriter;
		PrintWriter timeWriter = null;
		try {
			timeFileWriter = new FileWriter("/Users/serperu/Desktop/SlicerOutput/Times/programSizes.txt", true);
			timeWriter = new PrintWriter(timeFileWriter);
			timeWriter.println("---------------------------");
			timeWriter.println("Program Name: " + programName);
			timeWriter.println("---------------------------");
			timeWriter.println(" SDG Nodes: " + SDGNodes);
			timeWriter.println(" EDG Nodes: " + EDGNodes + "\n");
		} catch (IOException e) {
			System.out.println("FILE NOT FOUND ERROR");
		} finally {
			if (timeWriter != null)
				timeWriter.close();
		}
	}

	public static void printTitle(String outputFile, String fileName) {
		FileWriter timeFileWriter;
		PrintWriter timeWriter = null;
		try {
			timeFileWriter = new FileWriter(outputFile, true);
			timeWriter = new PrintWriter(timeFileWriter);
			timeWriter.println("*******************************");
			timeWriter.println("* Program Name: " + fileName + " *");
			timeWriter.println("*******************************");
		} catch (IOException e) {
			System.out.println("FILE NOT FOUND ERROR");
		} finally {
			if (timeWriter != null)
				timeWriter.close();
		}
	}

	public static void printSlicingResults(String funName, int numberOfSCs, SlicingCriterionState[] standard,
										   SlicingCriterionState[] constrained, int improvements, boolean performance,
										   boolean time) {

		FileWriter timeFileWriter;
		PrintWriter timeWriter = null;
		try {
			timeFileWriter = new FileWriter("/Users/serperu/Desktop/SlicerOutput/Times/slicingStatistics.txt", true);
			timeWriter = new PrintWriter(timeFileWriter);
			timeWriter.println("\t++++++++++++++++++++++++++++");
			timeWriter.println("\t+ Function Name: " + funName + " +");
			timeWriter.println("\t++++++++++++++++++++++++++++");
			timeWriter.println("\t Number of SCs: " + numberOfSCs);

			double standardAlgorithmAvgPerformance = 0.0;
			double standardAlgorithmAvgTime = 0.0;

			for (int k = 0; k < numberOfSCs; k++) {
				standardAlgorithmAvgPerformance += standard[k].getPerformance();
				standardAlgorithmAvgTime += standard[k].getTime();
			}
			timeWriter.println("\t\t----------------------");
			timeWriter.println("\t\t- Standard Algorithm -");
			timeWriter.println("\t\t----------------------");
			if (performance)
				timeWriter.println("\t\t Average Performance: " + (standardAlgorithmAvgPerformance / numberOfSCs) + " % \n");
			if (time)
				timeWriter.println("\t\t Average Time: " + (standardAlgorithmAvgTime / numberOfSCs) + " ms \n");

			double constrainedAlgorithmAvgPerformance = 0.0;
			double constrainedAlgorithmAvgTime = 0.0;

			for (int k = 0; k < numberOfSCs; k++) {
				constrainedAlgorithmAvgPerformance += constrained[k].getPerformance();
				constrainedAlgorithmAvgTime += constrained[k].getTime();
			}
			timeWriter.println("\t\t-------------------------");
			timeWriter.println("\t\t- Constrained Algorithm -");
			timeWriter.println("\t\t-------------------------");
			if (performance) {
				timeWriter.println("\t\t Average Performance: " + (constrainedAlgorithmAvgPerformance / numberOfSCs) + " % \n");
				timeWriter.println("\t\t Obtained smaller slices: " + improvements + " times\n");
			}
			if (time)
				timeWriter.println("\t\t Average Time: " + (constrainedAlgorithmAvgTime / numberOfSCs) +  " ms\n");

		} catch (IOException e) {
			System.out.println("FILE NOT FOUND ERROR");
		} finally {
			if (timeWriter != null)
				timeWriter.close();
		}
	}

	static class Args {
		enum GraphFormat { PDF, DOT }