[ASTERIXDB-3356][RT] Add min/max cardinality to plan
- user model changes: no
- storage format changes: no
- interface changes: no
Details:
- Add min and max cardinality from profile to plan
- Add test to check format of plan with profile annotations
Change-Id: Ibdacf4e6b156a3b6ef15b4420f4102c122f8af1d
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/18174
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Contrib: Ian Maxon <imaxon@uci.edu>
Reviewed-by: Ian Maxon <imaxon@uci.edu>
Reviewed-by: Vijay Sarathy <vijay.sarathy@couchbase.com>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
index 9d62c52..e6b4662 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
@@ -831,9 +831,10 @@
List<Parameter> newParams = setFormatInAccept(fmt) ? params
: upsertParam(params, QueryServiceRequestParameters.Parameter.FORMAT.str(), ParameterTypeEnum.STRING,
fmt.extension());
-
- newParams = upsertParam(newParams, QueryServiceRequestParameters.Parameter.PLAN_FORMAT.str(),
- ParameterTypeEnum.STRING, DEFAULT_PLAN_FORMAT);
+ String planFormatKey = QueryServiceRequestParameters.Parameter.PLAN_FORMAT.str();
+ if (!newParams.stream().anyMatch(p -> p.getName().equals(planFormatKey))) {
+ newParams = upsertParam(newParams, planFormatKey, ParameterTypeEnum.STRING, DEFAULT_PLAN_FORMAT);
+ }
final Optional<String> maxReadsOptional = extractMaxResultReads(str);
if (maxReadsOptional.isPresent()) {
newParams = upsertParam(newParams, QueryServiceRequestParameters.Parameter.MAX_RESULT_READS.str(),
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/profiled.xml b/asterixdb/asterix-app/src/test/resources/runtimets/profiled.xml
index d3664d4..b3f222a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/profiled.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/profiled.xml
@@ -45,6 +45,14 @@
</compilation-unit>
</test-case>
<test-case FilePath="profile">
+ <compilation-unit name="plansleep">
+ <parameter name="profile" value="timings" type="string"/>
+ <parameter name="optimized-logical-plan" value="true" type="string"/>
+ <parameter name="plan-format" value="json" type="string"/>
+ <output-dir compare="Clean-JSON">plansleep</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="profile">
<compilation-unit name="non-unary-subplan">
<parameter name="profile" value="timings" type="string"/>
<output-dir compare="Text">non-unary-subplan</output-dir>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/plansleep/plansleep.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/plansleep/plansleep.1.ddl.sqlpp
new file mode 100644
index 0000000..aedce7b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/plansleep/plansleep.1.ddl.sqlpp
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+ * Description : Testing that "off" is supplied in request parameter "profile".
+ * Expected Res : Success with expected result not having "profile" field.
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use test;
+
+create type test.AddressType as
+{
+ number : bigint,
+ street : string,
+ city : string
+};
+
+create type test.CustomerType as
+ closed {
+ cid : bigint,
+ name : string,
+ age : bigint?,
+ address : AddressType?,
+ lastorder : {
+ oid : bigint,
+ total : float
+ }
+};
+
+create type test.OrderType as
+{
+ oid : bigint,
+ cid : bigint,
+ orderstatus : string,
+ orderpriority : string,
+ clerk : string,
+ total : float
+};
+
+create dataset Customers(CustomerType) primary key cid;
+
+create dataset Orders(OrderType) primary key oid;
+
+create dataset Customers2(CustomerType) primary key cid;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/plansleep/plansleep.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/plansleep/plansleep.2.update.sqlpp
new file mode 100644
index 0000000..07af22e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/plansleep/plansleep.2.update.sqlpp
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+load dataset Customers using localfs
+ ((`path`=`asterix_nc1://data/custord-tiny/customer-tiny-neg.adm`),
+ (`format`=`adm`));
+
+load dataset Orders using localfs
+ ((`path`=`asterix_nc1://data/custord-tiny/order-tiny.adm`),
+ (`format`=`adm`));
+
+load dataset Customers2 using localfs
+ ((`path`=`asterix_nc1://data/custord-tiny/customer-tiny.adm`),
+ (`format`=`adm`));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/plansleep/plansleep.3.plans.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/plansleep/plansleep.3.plans.sqlpp
new file mode 100644
index 0000000..6c35376
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/plansleep/plansleep.3.plans.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+-- compareunorderedarray=true
+USE test;
+
+SELECT count(*) AS customers, city
+FROM Customers c
+WHERE c.age <65
+GROUP BY c.address.city
+ORDER BY sleep(city,1700);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/plansleep/plansleep.90.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/plansleep/plansleep.90.ddl.sqlpp
new file mode 100644
index 0000000..f12a2b7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/plansleep/plansleep.90.ddl.sqlpp
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+drop dataverse test;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/plansleep/sleep.3.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/plansleep/sleep.3.regexjson
new file mode 100644
index 0000000..111ded8
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/plansleep/sleep.3.regexjson
@@ -0,0 +1,390 @@
+{
+ "optimizedLogicalPlan": {
+ "operator": "distribute-result",
+ "expressions": [
+ "$$48"
+ ],
+ "operatorId": "1.1",
+ "runtime-id": "R{.+}",
+ "min-time": "R{[0-9.]+}",
+ "max-time": "R{[0-9.]+}",
+ "physical-operator": "DISTRIBUTE_RESULT",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "exchange",
+ "operatorId": "1.2",
+ "runtime-id": "R{.+}",
+ "physical-operator": "ONE_TO_ONE_EXCHANGE",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates":"R{.+}",
+ "inputs": [
+ {
+ "operator": "project",
+ "variables": [
+ "$$48"
+ ],
+ "operatorId": "1.3",
+ "runtime-id": "R{.+}",
+ "min-time": "R{[0-9.]+}",
+ "max-time": "R{[0-9.]+}",
+ "min-cardinality": 3,
+ "max-cardinality": 3,
+ "physical-operator": "STREAM_PROJECT",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "exchange",
+ "operatorId": "1.4",
+ "runtime-id": "R{.+}",
+ "min-time": "R{[0-9.]+}",
+ "max-time": "R{[0-9.]+}",
+ "physical-operator": "SORT_MERGE_EXCHANGE [$$49(ASC) ]",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "order",
+ "order-by-list": [
+ {
+ "order": "ASC",
+ "expression": "$$49"
+ }
+ ],
+ "operatorId": "1.5",
+ "runtime-id": "R{.+}",
+ "min-time": "R{[0-9.]+}",
+ "max-time": "R{[0-9.]+}",
+ "physical-operator": "STABLE_SORT [$$49(ASC)]",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "exchange",
+ "operatorId": "1.6",
+ "runtime-id": "R{.+}",
+ "physical-operator": "ONE_TO_ONE_EXCHANGE",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "project",
+ "variables": [
+ "$$48",
+ "$$49"
+ ],
+ "operatorId": "1.7",
+ "runtime-id": "R{.+}",
+ "min-time": "R{[0-9.]+}",
+ "max-time": "R{[0-9.]+}",
+ "min-cardinality": 3,
+ "max-cardinality": 3,
+ "physical-operator": "STREAM_PROJECT",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "assign",
+ "variables": [
+ "$$49"
+ ],
+ "expressions": [
+ "sleep($$city, 1700)"
+ ],
+ "operatorId": "1.8",
+ "runtime-id": "R{.+}",
+ "min-time": "R{5.+}",
+ "max-time": "R{5.+}",
+ "min-cardinality": 3,
+ "max-cardinality": 3,
+ "physical-operator": "ASSIGN",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "project",
+ "variables": [
+ "$$city",
+ "$$48"
+ ],
+ "operatorId": "1.9",
+ "runtime-id": "R{.+}",
+ "min-time": "R{[0-9.]+}",
+ "max-time": "R{[0-9.]+}",
+ "min-cardinality": 3,
+ "max-cardinality": 3,
+ "physical-operator": "STREAM_PROJECT",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "assign",
+ "variables": [
+ "$$48"
+ ],
+ "expressions": [
+ "{\"customers\": $$52, \"city\": $$city}"
+ ],
+ "operatorId": "1.10",
+ "runtime-id": "R{.+}",
+ "min-time": "R{[0-9.]+}",
+ "max-time": "R{[0-9.]+}",
+ "min-cardinality": 3,
+ "max-cardinality": 3,
+ "physical-operator": "ASSIGN",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "exchange",
+ "operatorId": "1.11",
+ "runtime-id": "R{.+}",
+ "physical-operator": "ONE_TO_ONE_EXCHANGE",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "group-by",
+ "group-by-list": [
+ {
+ "variable": "$$city",
+ "expression": "$$56"
+ }
+ ],
+ "subplan": [
+ {
+ "operator": "aggregate",
+ "variables": [
+ "$$52"
+ ],
+ "expressions": [
+ "agg-sql-sum($$55)"
+ ],
+ "operatorId": "1.11.1",
+ "physical-operator": "AGGREGATE",
+ "execution-mode": "LOCAL",
+ "inputs": [
+ {
+ "operator": "nested-tuple-source",
+ "operatorId": "1.11.2",
+ "physical-operator": "NESTED_TUPLE_SOURCE",
+ "execution-mode": "LOCAL"
+ }
+ ]
+ }
+ ],
+ "operatorId": "1.12",
+ "runtime-id": "R{.+}",
+ "min-time": "R{[0-9.]+}",
+ "max-time": "R{[0-9.]+}",
+ "min-cardinality": 3,
+ "max-cardinality": 3,
+ "physical-operator": "SORT_GROUP_BY[$$56]",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "exchange",
+ "operatorId": "1.13",
+ "runtime-id": "R{.+}",
+ "min-time": "R{[0-9.]+}",
+ "max-time": "R{[0-9.]+}",
+ "physical-operator": "HASH_PARTITION_EXCHANGE [$$56]",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "group-by",
+ "group-by-list": [
+ {
+ "variable": "$$56",
+ "expression": "$$50"
+ }
+ ],
+ "subplan": [
+ {
+ "operator": "aggregate",
+ "variables": [
+ "$$55"
+ ],
+ "expressions": [
+ "agg-sql-count(1)"
+ ],
+ "operatorId": "1.13.1",
+ "physical-operator": "AGGREGATE",
+ "execution-mode": "LOCAL",
+ "inputs": [
+ {
+ "operator": "nested-tuple-source",
+ "operatorId": "1.13.2",
+ "physical-operator": "NESTED_TUPLE_SOURCE",
+ "execution-mode": "LOCAL"
+ }
+ ]
+ }
+ ],
+ "operatorId": "1.14",
+ "runtime-id": "R{.+}",
+ "min-time": "R{[0-9.]+}",
+ "max-time": "R{[0-9.]+}",
+ "physical-operator": "SORT_GROUP_BY[$$50]",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "exchange",
+ "operatorId": "1.15",
+ "runtime-id": "R{.+}",
+ "physical-operator": "ONE_TO_ONE_EXCHANGE",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "project",
+ "variables": [
+ "$$50"
+ ],
+ "operatorId": "1.16",
+ "runtime-id": "R{.+}",
+ "min-time": "R{[0-9.]+}",
+ "max-time": "R{[0-9.]+}",
+ "min-cardinality": 5,
+ "max-cardinality": 5,
+ "physical-operator": "STREAM_PROJECT",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "assign",
+ "variables": [
+ "$$50"
+ ],
+ "expressions": [
+ "$$c.getField(3).getField(2)"
+ ],
+ "operatorId": "1.17",
+ "runtime-id": "R{.+}",
+ "min-time": "R{[0-9.]+}",
+ "max-time": "R{[0-9.]+}",
+ "min-cardinality": 5,
+ "max-cardinality": 5,
+ "physical-operator": "ASSIGN",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "select",
+ "condition": "lt($$c.getField(2), 65)",
+ "operatorId": "1.18",
+ "runtime-id": "R{.+}",
+ "min-time": "R{[0-9.]+}",
+ "max-time": "R{[0-9.]+}",
+ "min-cardinality": 5,
+ "max-cardinality": 5,
+ "physical-operator": "STREAM_SELECT",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "project",
+ "variables": [
+ "$$c"
+ ],
+ "operatorId": "1.19",
+ "runtime-id": "R{.+}",
+ "min-time": "R{[0-9.]+}",
+ "max-time": "R{[0-9.]+}",
+ "min-cardinality": 10,
+ "max-cardinality": 10,
+ "physical-operator": "STREAM_PROJECT",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "exchange",
+ "operatorId": "1.20",
+ "runtime-id": "R{.+}",
+ "physical-operator": "ONE_TO_ONE_EXCHANGE",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "data-scan",
+ "variables": [
+ "$$51",
+ "$$c"
+ ],
+ "data-source": "test.Customers",
+ "operatorId": "1.21",
+ "runtime-id": "R{.+}",
+ "min-time": "R{[0-9.]+}",
+ "max-time": "R{[0-9.]+}",
+ "min-cardinality": 10,
+ "max-cardinality": 10,
+ "physical-operator": "DATASOURCE_SCAN",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "exchange",
+ "operatorId": "1.22",
+ "runtime-id": "R{.+}",
+ "physical-operator": "ONE_TO_ONE_EXCHANGE",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}",
+ "inputs": [
+ {
+ "operator": "empty-tuple-source",
+ "operatorId": "1.23",
+ "runtime-id": "R{.+}",
+ "physical-operator": "EMPTY_TUPLE_SOURCE",
+ "execution-mode": "PARTITIONED",
+ "optimizer-estimates": "R{.+}"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java
index d1a356c..36c33e6 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java
@@ -228,19 +228,32 @@
}
private class OperatorProfile {
- Map<String, Pair<Double, Double>> activities;
+ Map<String, Pair<Double, Double>> activityTimes;
+ Map<String, Pair<Long, Long>> activityCards;
OperatorProfile() {
- activities = new HashMap<>();
+ activityTimes = new HashMap<>();
+ activityCards = new HashMap<>();
+ }
+
+ void updateOperator(String extendedOpId, double time, long cardinality) {
+ updateMinMax(time, extendedOpId, activityTimes);
+ if (cardinality > 0) {
+ updateMinMax(cardinality, extendedOpId, activityCards);
+ }
}
void updateOperator(String extendedOpId, double time) {
- Pair<Double, Double> times = activities.computeIfAbsent(extendedOpId, i -> new Pair(time, time));
- if (times.getFirst() > time) {
- times.setFirst(time);
+ updateMinMax(time, extendedOpId, activityTimes);
+ }
+
+ private <T extends Comparable<T>> void updateMinMax(T comp, String id, Map<String, Pair<T, T>> opMap) {
+ Pair<T, T> times = opMap.computeIfAbsent(id, i -> new Pair(comp, comp));
+ if (times.getFirst().compareTo(comp) > 0) {
+ times.setFirst(comp);
}
- if (times.getSecond() < time) {
- times.setSecond(time);
+ if (times.getSecond().compareTo(comp) < 0) {
+ times.setSecond(comp);
}
}
}
@@ -257,6 +270,11 @@
for (JsonNode counters : task.get("counters")) {
OperatorProfile info = profiledOps.computeIfAbsent(counters.get("runtime-id").asText(),
i -> new OperatorProfile());
+ JsonNode card = counters.get("cardinality-out");
+ if (card != null) {
+ info.updateOperator(acIdFromName(counters.get("name").asText()).getLocalId(),
+ counters.get("run-time").asDouble(), counters.get("cardinality-out").asLong(-1));
+ }
info.updateOperator(acIdFromName(counters.get("name").asText()).getLocalId(),
counters.get("run-time").asDouble());
}
@@ -343,16 +361,26 @@
jsonGenerator.writeStringField("runtime-id", od);
OperatorProfile info = profile.get(od);
if (info != null) {
- if (info.activities.size() == 1) {
- Pair<Double, Double> minMax = info.activities.values().iterator().next();
+ if (info.activityTimes.size() == 1) {
+ Pair<Double, Double> minMax = info.activityTimes.values().iterator().next();
jsonGenerator.writeNumberField("min-time", minMax.first);
jsonGenerator.writeNumberField("max-time", minMax.second);
+ if (info.activityCards.size() > 0) {
+ Pair<Long, Long> minMaxCard = info.activityCards.values().iterator().next();
+ jsonGenerator.writeNumberField("min-cardinality", minMaxCard.first);
+ jsonGenerator.writeNumberField("max-cardinality", minMaxCard.second);
+ }
} else {
jsonGenerator.writeObjectFieldStart("times");
- for (Map.Entry<String, Pair<Double, Double>> ac : info.activities.entrySet()) {
- jsonGenerator.writeObjectFieldStart(ac.getKey());
- jsonGenerator.writeNumberField("min-time", ac.getValue().first);
- jsonGenerator.writeNumberField("max-time", ac.getValue().second);
+ for (String acId : info.activityTimes.keySet()) {
+ jsonGenerator.writeObjectFieldStart(acId);
+ jsonGenerator.writeNumberField("min-time", info.activityTimes.get(acId).first);
+ jsonGenerator.writeNumberField("max-time", info.activityTimes.get(acId).second);
+ Pair<Long, Long> cards = info.activityCards.get(acId);
+ if (cards != null) {
+ jsonGenerator.writeNumberField("min-cardinality", info.activityCards.get(acId).first);
+ jsonGenerator.writeNumberField("max-cardinality", info.activityCards.get(acId).second);
+ }
jsonGenerator.writeEndObject();
}
jsonGenerator.writeEndObject();