diff --git a/jastadd-mquat-eris/src/main/java/de/tudresden/inf/st/mquat/eris/ErisMQuATBuilder.java b/jastadd-mquat-eris/src/main/java/de/tudresden/inf/st/mquat/eris/ErisMQuATBuilder.java index fccb0a82b6cfb79ca9fa1888fcfa358fc1219f30..461f4e7e7f6bb21847c74e5ecf9349ccd46d8b24 100644 --- a/jastadd-mquat-eris/src/main/java/de/tudresden/inf/st/mquat/eris/ErisMQuATBuilder.java +++ b/jastadd-mquat-eris/src/main/java/de/tudresden/inf/st/mquat/eris/ErisMQuATBuilder.java @@ -5,7 +5,6 @@ import de.tudresden.inf.st.mquat.jastadd.model.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -14,7 +13,7 @@ public class ErisMQuATBuilder { private static final Logger logger = LogManager.getLogger(ErisMQuATBuilder.class); - static Root createModel(ERISModel erisModel, boolean USE_CURRENT_CONFIG) { + static Root createModel(ERISModel erisModel) { Root root = new Root(); @@ -37,6 +36,7 @@ public class ErisMQuATBuilder { Property indexAttributeCount = new Property(new Name("indexAttributeCount"), "flag"); Property indexOrderPreserving = new Property(new Name("indexOrderPreserving"), "flag"); Property direct = new Property(new Name("isDirect"), "flag"); + Property index = new Property(new Name("isIndex"), "flag"); accessPath.addProperty(dynamic); accessPath.addProperty(attributeCount); accessPath.addProperty(attributeNull); @@ -45,6 +45,7 @@ public class ErisMQuATBuilder { accessPath.addProperty(indexAttributeCount); accessPath.addProperty(indexOrderPreserving); accessPath.addProperty(direct); + accessPath.addProperty(index); // add energy benchmark properties Map<Integer, Property> insertProperties = new HashMap<>(); @@ -101,7 +102,11 @@ public class ErisMQuATBuilder { ); boolean isDirect = erisAccessPath.getAddressingMode().equals("direct"); multiResource.addCurrentResourceValue( - new CurrentResourceValue(direct.createRef(), new LiteralExpression(isDirect?1D:0D)) + new CurrentResourceValue(direct.createRef(), new LiteralExpression(isDirect ? 1D : 0D)) + ); + boolean isIndex = erisAccessPath.getAddressingMode().equals("index"); + multiResource.addCurrentResourceValue( + new CurrentResourceValue(index.createRef(), new LiteralExpression(isIndex ? 1D : 0D)) ); // add all the attribute stat values @@ -148,208 +153,166 @@ public class ErisMQuATBuilder { SoftwareModel softwareModel = new SoftwareModel(); - if (USE_CURRENT_CONFIG) { - for (ERISContainer erisContainer : erisModel.getErisContainers()) { - for (ERISLivingPartition livingPartition : erisContainer.getPartitionList()) { - for (ERISLPConfiguration config : livingPartition.getConfigurations()) { - // ignore the default config for now - boolean foundAttribute = false; - for (ERISAttribute attribute : config.getAttributesAndKeys()) { - System.out.println(attribute.getName()); - if (!attribute.isSystem()) { - foundAttribute = true; - } - } - if (!foundAttribute) continue; - - // create a component for every config - Component component = new Component(); - String configName = "Config_"; - for (ERISAttribute attribute : config.getAttributesAndKeys()) { - configName += attribute.getName(); - } - component.setName(new Name(configName)); - - Implementation implementation = new Implementation(); - implementation.setName(new Name("accessPathSelector")); - - Instance accessPathInstance = new Instance(new Name("accessPath")); - - ResourceRequirement resourceRequirement = new ResourceRequirement(); - resourceRequirement.addInstance(accessPathInstance); - resourceRequirement.setResourceTypeRef(accessPath.createRef()); - implementation.setResourceRequirement(resourceRequirement); - + // for each container, living partition, and attribute, create a software component and a request + for (ERISContainer erisContainer : erisModel.getErisContainers()) { + for (ERISAttribute attribute : erisContainer.getAttributeList()) { - // create the requirements - // the number of attributes - implementation.addClause(new Clause(ClauseType.REQUIRING, new PropertyResourceDesignator(accessPathInstance.createRef(), attributeCount.createRef()), ClauseComparator.GE, new LiteralExpression(config.getAttributesAndKeys().size()))); + // ignore linkage attributes + if (attribute.isLinkage()) continue; - boolean canBeNull = false; - boolean canBeUndefined = false; - // collect the requirements of all contained attributes - for (ERISAttribute attribute : livingPartition.getAttributes()) { - canBeNull = canBeNull | !attribute.isNotNull(); - canBeUndefined = canBeUndefined | !attribute.isNotUndefined(); - } - - if (canBeNull) { - implementation.addClause(new Clause(ClauseType.REQUIRING, new PropertyResourceDesignator(accessPathInstance.createRef(), attributeNull.createRef()), ClauseComparator.EQ, new LiteralExpression(canBeNull ? 1 : 0))); - } - if (canBeUndefined) { - implementation.addClause(new Clause(ClauseType.REQUIRING, new PropertyResourceDesignator(accessPathInstance.createRef(), attributeUndefined.createRef()), ClauseComparator.EQ, new LiteralExpression(canBeUndefined ? 1 : 0))); - } - - // create the provisions - - java.util.List<Expression> attributeExpressions = new ArrayList<>(); - - for (ERISAttribute attribute : livingPartition.getAttributes()) { - Expression expression = buildRuntimeProvision(insertProperties, linkProperties, lookupProperties, scanProperties, accessPathInstance, attribute); - - attributeExpressions.add(expression); - } + for (ERISLivingPartition erisLivingPartition : erisContainer.getPartitionList()) { - Expression expression = attributeExpressions.remove(0); - for (Expression ex : attributeExpressions) { - expression = new AddExpression(ex, expression); + ERISAttributeStatistics statistics = null; + // ignore attribute if all stats are zero + for (ERISAttribute attribute1 : erisLivingPartition.getAttributes()) { + if (attribute1.getId() == attribute.getId()) { + statistics = attribute1.getStatistics(); } - - implementation.addClause(new Clause(ClauseType.PROVIDING, new SoftwareDesignator(new Opt<>(), runtime.createRef()), ClauseComparator.EQ, expression)); - - component.addImplementation(implementation); - - // create a request - Request request = new Request(); - request.setTarget(component.createRef()); - - root.addRequest(request); - - softwareModel.addComponent(component); - } - } - } - } else { - // for each container, living partition, and attribute, create a software component and a request - for (ERISContainer erisContainer : erisModel.getErisContainers()) { - for (ERISAttribute attribute : erisContainer.getAttributeList()) { - - // ignore linkage attributes - if (attribute.isLinkage()) continue; - - - - for (ERISLivingPartition erisLivingPartition : erisContainer.getPartitionList()) { - - ERISAttributeStatistics statistics = null; - // ignore attribute if all stats are zero - for (ERISAttribute attribute1 : erisLivingPartition.getAttributes()) { - if (attribute1.getId() == attribute.getId()) { - statistics = attribute1.getStatistics(); - } - } - if (statistics.getInserts() == 0 - && statistics.getLookups() == 0 - && statistics.getLinks() == 0 - && statistics.getScans() == 0) { - logger.debug("counters are all zero for attribute {}", attribute.getId()); - continue; - } else { - logger.debug("in lp {} in cont {}: {} {} {} {}", erisLivingPartition.getLocalId(), erisContainer.getId(), statistics.getScans(), statistics.getLookups(), statistics.getInserts(), statistics.getLinks()); - } - - if (erisLivingPartition.isAdaptationScheduled()) { - logger.debug("Skipping living partition {}, because an adaptation is already scheduled", erisLivingPartition.getLocalId()); - continue; - } - - // create a new top-level software component and two implementations, one of which enforces direct access - Component component = new Component(); - Component directComponent = new Component(); - component.setName(new Name(createName(erisContainer, erisLivingPartition, attribute))); - directComponent.setName(new Name("direct_" + createName(erisContainer, erisLivingPartition, attribute))); - Implementation implementation = new Implementation(); - Implementation directImplementation = new Implementation(); - implementation.setName(new Name("accessPathSelector")); - directImplementation.setName(new Name("directAccessPathSelector")); - - // create the requirement for an access path - Instance accessPathInstance = new Instance(new Name("accessPath_" + attribute.getName())); - Instance directAccessPathInstance = new Instance(new Name("directAccessPath_" + attribute.getName())); - ResourceRequirement resourceRequirement = new ResourceRequirement(); - ResourceRequirement directResourceRequirement = new ResourceRequirement(); - resourceRequirement.addInstance(accessPathInstance); - directResourceRequirement.addInstance(directAccessPathInstance); - resourceRequirement.setResourceTypeRef(accessPath.createRef()); - directResourceRequirement.setResourceTypeRef(accessPath.createRef()); - implementation.setResourceRequirement(resourceRequirement); - directImplementation.setResourceRequirement(directResourceRequirement); - - // ensure access path properties - // on a per-attribute access path configuration, only the null and undefined checks have to be done - if (!attribute.isNotNull()) { - implementation.addClause(new Clause( - ClauseType.REQUIRING, - new PropertyResourceDesignator(accessPathInstance.createRef(), attributeNull.createRef()), - ClauseComparator.EQ, - new LiteralExpression(1D) - )); - directImplementation.addClause(new Clause( - ClauseType.REQUIRING, - new PropertyResourceDesignator(directAccessPathInstance.createRef(), attributeNull.createRef()), - ClauseComparator.EQ, - new LiteralExpression(1D) - )); - } - if (!attribute.isNotUndefined()) { - implementation.addClause(new Clause( - ClauseType.REQUIRING, - new PropertyResourceDesignator(accessPathInstance.createRef(), attributeUndefined.createRef()), - ClauseComparator.EQ, - new LiteralExpression(1D) - )); - directImplementation.addClause(new Clause( - ClauseType.REQUIRING, - new PropertyResourceDesignator(directAccessPathInstance.createRef(), attributeUndefined.createRef()), - ClauseComparator.EQ, - new LiteralExpression(1D) - )); - } - - // create the provisions - Expression expression = buildRuntimeProvision(insertProperties, linkProperties, lookupProperties, scanProperties, accessPathInstance, attribute); - implementation.addClause(new Clause(ClauseType.PROVIDING, new SoftwareDesignator(new Opt<>(), runtime.createRef()), ClauseComparator.EQ, expression)); - - - Expression directExpression = buildRuntimeProvision(insertProperties, linkProperties, lookupProperties, scanProperties, directAccessPathInstance, attribute); - directImplementation.addClause(new Clause(ClauseType.PROVIDING, new SoftwareDesignator(new Opt<>(), runtime.createRef()), ClauseComparator.EQ, directExpression)); + if (statistics.getInserts() == 0 + && statistics.getLookups() == 0 + && statistics.getLinks() == 0 + && statistics.getScans() == 0) { + logger.debug("counters are all zero for attribute {}", attribute.getId()); + continue; + } + if (erisLivingPartition.isAdaptationScheduled()) { + logger.debug("Skipping living partition {}, because an adaptation is already scheduled", erisLivingPartition.getLocalId()); + continue; + } - // add an additional requirement to only allow direct access paths for the direct implementation - directImplementation.addClause(new Clause( + // create a new top-level software component and two implementations, one of which enforces direct access + Component indexComponent = new Component(); + Component directOrIndirectComponent = new Component(); + indexComponent.setName(new Name("index_" + createName(erisContainer, erisLivingPartition, attribute))); + directOrIndirectComponent.setName(new Name("direct_or_indirect_" + createName(erisContainer, erisLivingPartition, attribute))); + Implementation indexImplementation = new Implementation(); + Implementation directOrIndirectImplementation = new Implementation(); + indexImplementation.setName(new Name("indexAccessPathSelector")); + directOrIndirectImplementation.setName(new Name("directOrIndirectAccessPathSelector")); + + // create the requirement for an access path + Instance indexAccessPathInstance = new Instance(new Name("indexAccessPath_" + attribute.getName())); + Instance directOrIndirectAccessPathInstance = new Instance(new Name("directOrIndirectAccessPath_" + attribute.getName())); + ResourceRequirement indexResourceRequirement = new ResourceRequirement(); + ResourceRequirement directOrIndirectResourceRequirement = new ResourceRequirement(); + indexResourceRequirement.addInstance(indexAccessPathInstance); + directOrIndirectResourceRequirement.addInstance(directOrIndirectAccessPathInstance); + indexResourceRequirement.setResourceTypeRef(accessPath.createRef()); + directOrIndirectResourceRequirement.setResourceTypeRef(accessPath.createRef()); + indexImplementation.setResourceRequirement(indexResourceRequirement); + directOrIndirectImplementation.setResourceRequirement(directOrIndirectResourceRequirement); + + // ensure access path properties + // on a per-attribute access path configuration, only the null and undefined checks have to be done + if (!attribute.isNotNull()) { + indexImplementation.addClause(new Clause( + ClauseType.REQUIRING, + new PropertyResourceDesignator(indexAccessPathInstance.createRef(), attributeNull.createRef()), + ClauseComparator.EQ, + new LiteralExpression(1D) + )); + directOrIndirectImplementation.addClause(new Clause( + ClauseType.REQUIRING, + new PropertyResourceDesignator(directOrIndirectAccessPathInstance.createRef(), attributeNull.createRef()), + ClauseComparator.EQ, + new LiteralExpression(1D) + )); + } + if (!attribute.isNotUndefined()) { + indexImplementation.addClause(new Clause( ClauseType.REQUIRING, - new PropertyResourceDesignator(directAccessPathInstance.createRef(), direct.createRef()), + new PropertyResourceDesignator(indexAccessPathInstance.createRef(), attributeUndefined.createRef()), ClauseComparator.EQ, new LiteralExpression(1D) )); + directOrIndirectImplementation.addClause(new Clause( + ClauseType.REQUIRING, + new PropertyResourceDesignator(directOrIndirectAccessPathInstance.createRef(), attributeUndefined.createRef()), + ClauseComparator.EQ, + new LiteralExpression(1D) + )); + } - component.addImplementation(implementation); - directComponent.addImplementation(directImplementation); - softwareModel.addComponent(component); - softwareModel.addComponent(directComponent); - - // create the requests - Request request = new Request(); - request.setTarget(component.createRef()); - request.setName(new Name("request_" + createName(erisContainer, erisLivingPartition, attribute))); - root.addRequest(request); - Request directRequest = new Request(); - directRequest.setTarget(directComponent.createRef()); - directRequest.setName(new Name("direct_request_" + createName(erisContainer, erisLivingPartition, attribute))); - root.addRequest(directRequest); + // create the provisions +// if (!as || as->lookups < 1) { +// return -1; +// } +// AccessPathBechmarkInfo* bmiref = Eris::instance->accessPathManager->getAccessPathPerformance(refCandidate->factory, refCandidate->dynamic); +// double refdiff = AccessPathBechmarkInfo::getTimeForSize(&bmiref->lookupTimes, as->count) - AccessPathBechmarkInfo::getTimeForSize(&bmi->lookupTimes, as->count); +// score += as->lookups * refdiff; +// if (as->inserts > 0) { +// score -= as->inserts * AccessPathBechmarkInfo::getTimeForSize(&bmi->insertTimes, as->count); +// } + + // ref is the best direct or indirect access path + // score = ref.lookuptime*this.count - this.lookuptime*this.count - this.inserts*this.insertTime + // because we do not know ref.lookuptime here, we omit this part. it is irrelevant for selecting the index + // access path, anyway. It is required later during the decision IF the index should be built. So the actual + // score is: + // score = -this.lookupTime*this.numLookups - this.insertTime*this.numInserts + + + // get the statistics + ERISAttributeStatistics attStats = attribute.getStatistics(); + + int num_lookups = attStats.getLookups(); + int num_inserts = attStats.getInserts(); + int num_scans = attStats.getScans(); + int num_links = attStats.getLinks(); + int att_count = attStats.getCount(); + + // get the correct size + int lookupsize = getLookupSize(lookupProperties, att_count); + { + MultExpression negatedLoopups = new MultExpression(new LiteralExpression(-num_lookups), new PropertyResourceDesignator(indexAccessPathInstance.createRef(), lookupProperties.get(lookupsize).createRef())); + MultExpression inserts = new MultExpression(new LiteralExpression(num_inserts), new PropertyResourceDesignator(indexAccessPathInstance.createRef(), insertProperties.get(lookupsize).createRef())); + Expression indexExpression = new SubExpression(negatedLoopups, inserts); + indexImplementation.addClause(new Clause(ClauseType.PROVIDING, new SoftwareDesignator(new Opt<>(), runtime.createRef()), ClauseComparator.EQ, indexExpression)); } + + { + MultExpression loopups = new MultExpression(new LiteralExpression(num_lookups), new PropertyResourceDesignator(directOrIndirectAccessPathInstance.createRef(), lookupProperties.get(lookupsize).createRef())); + MultExpression inserts = new MultExpression(new LiteralExpression(num_inserts), new PropertyResourceDesignator(directOrIndirectAccessPathInstance.createRef(), insertProperties.get(lookupsize).createRef())); + MultExpression scans = new MultExpression(new MultExpression(new LiteralExpression(num_scans), new PropertyResourceDesignator(directOrIndirectAccessPathInstance.createRef(), scanProperties.get(lookupsize).createRef())), new LiteralExpression(att_count)); + MultExpression links = new MultExpression(new LiteralExpression(num_links), new PropertyResourceDesignator(directOrIndirectAccessPathInstance.createRef(), linkProperties.get(lookupsize).createRef())); + + Expression directOrIndirectExpression = new AddExpression(loopups, new AddExpression(inserts, new AddExpression(scans, links))); + directOrIndirectImplementation.addClause(new Clause(ClauseType.PROVIDING, new SoftwareDesignator(new Opt<>(), runtime.createRef()), ClauseComparator.EQ, directOrIndirectExpression)); + } + + // add an additional requirement to only index access paths for the direct implementation + indexImplementation.addClause(new Clause( + ClauseType.REQUIRING, + new PropertyResourceDesignator(indexAccessPathInstance.createRef(), index.createRef()), + ClauseComparator.EQ, + new LiteralExpression(1D) + )); + + // add an additional requirement to only allow direct or indirect access paths for the direct implementation + directOrIndirectImplementation.addClause(new Clause( + ClauseType.REQUIRING, + new PropertyResourceDesignator(directOrIndirectAccessPathInstance.createRef(), index.createRef()), + ClauseComparator.EQ, + new LiteralExpression(0D) + )); + + indexComponent.addImplementation(indexImplementation); + directOrIndirectComponent.addImplementation(directOrIndirectImplementation); + softwareModel.addComponent(indexComponent); + softwareModel.addComponent(directOrIndirectComponent); + + // create the requests + Request indexRequest = new Request(); + indexRequest.setTarget(indexComponent.createRef()); + indexRequest.setName(new Name("index_request_" + createName(erisContainer, erisLivingPartition, attribute))); + root.addRequest(indexRequest); + Request directOrIndirectRequest = new Request(); + directOrIndirectRequest.setTarget(directOrIndirectComponent.createRef()); + directOrIndirectRequest.setName(new Name("request_" + createName(erisContainer, erisLivingPartition, attribute))); + root.addRequest(directOrIndirectRequest); } } } @@ -365,27 +328,6 @@ public class ErisMQuATBuilder { return root; } - private static Expression buildRuntimeProvision(Map<Integer, Property> insertProperties, Map<Integer, Property> linkProperties, Map<Integer, Property> lookupProperties, Map<Integer, Property> scanProperties, Instance accessPathInstance, ERISAttribute attribute) { - // get the statistics - ERISAttributeStatistics attStats = attribute.getStatistics(); - - int num_lookups = attStats.getLookups(); - int num_inserts = attStats.getInserts(); - int num_scans = attStats.getScans(); - int num_links = attStats.getLinks(); - int att_count = attStats.getCount(); - - // get the correct size - int lookupsize = getLookupSize(lookupProperties, att_count); - - MultExpression loopups = new MultExpression(new LiteralExpression(num_lookups), new PropertyResourceDesignator(accessPathInstance.createRef(), lookupProperties.get(lookupsize).createRef())); - MultExpression inserts = new MultExpression(new LiteralExpression(num_inserts), new PropertyResourceDesignator(accessPathInstance.createRef(), insertProperties.get(lookupsize).createRef())); - MultExpression scans = new MultExpression(new LiteralExpression(num_scans), new PropertyResourceDesignator(accessPathInstance.createRef(), scanProperties.get(lookupsize).createRef())); - MultExpression links = new MultExpression(new LiteralExpression(num_links), new PropertyResourceDesignator(accessPathInstance.createRef(), linkProperties.get(lookupsize).createRef())); - - return new AddExpression(loopups, new AddExpression(inserts, new AddExpression(scans, links))); - } - private static int getLookupSize(Map<Integer, Property> lookupProperties, int att_count) { // get the correct size int lookupsize = 0; @@ -402,8 +344,6 @@ public class ErisMQuATBuilder { private static String createName(ERISContainer container, ERISLivingPartition partition, ERISAttribute attribute) { // TODO use ID instead of name for attribute if possible return container.getId() + "_" + partition.getNodeId() + "_" + partition.getLocalId() + "_" + attribute.getId() + "_" + attribute.getName(); - - //return "Container_" + container.getId() + "_Node_" + partition.getNodeId() + "_LP_" + partition.getLocalId() + "_Attribute_" + attribute.getId() + "_" + attribute.getName(); } } diff --git a/jastadd-mquat-eris/src/main/java/de/tudresden/inf/st/mquat/eris/ErisTask.java b/jastadd-mquat-eris/src/main/java/de/tudresden/inf/st/mquat/eris/ErisTask.java index 2ad476485ea7b8bfb4d5c4b4582e162919ecd2bf..5f3b3093301814c6edbfa9df5d50ed0b85b2f078 100644 --- a/jastadd-mquat-eris/src/main/java/de/tudresden/inf/st/mquat/eris/ErisTask.java +++ b/jastadd-mquat-eris/src/main/java/de/tudresden/inf/st/mquat/eris/ErisTask.java @@ -2,6 +2,7 @@ package de.tudresden.inf.st.mquat.eris; import de.tudresden.inf.st.mquat.benchmark.SolverFactory; import de.tudresden.inf.st.mquat.eris.coupling.ERISConnector; +import de.tudresden.inf.st.mquat.jastadd.model.MquatWriteSettings; import de.tudresden.inf.st.mquat.jastadd.model.Root; import de.tudresden.inf.st.mquat.jastadd.model.Solution; import de.tudresden.inf.st.mquat.solving.SolvingException; @@ -20,7 +21,9 @@ public class ErisTask extends TimerTask { try { ERISConnector erisConnector = new ERISConnector(); erisConnector.read(); - Root model = ErisMQuATBuilder.createModel(erisConnector.getErisModel(), false); + Root model = ErisMQuATBuilder.createModel(erisConnector.getErisModel()); + + System.out.println(model.print(new MquatWriteSettings(" "))); ILPExternalSolver solver = (ILPExternalSolver) SolverFactory.getSolverByName("ilp-glpk"); @@ -28,6 +31,8 @@ public class ErisTask extends TimerTask { Solution solution = solver.solve(model); + System.out.println(solution.print(new MquatWriteSettings(" "))); + if (solution.getNumAssignment() > 0) { logger.info("Found solution. Sending now..."); erisConnector.write(solution);