Преглед на файлове

AMBARI-5029. Improve Tez dag layout for a fully connected graph. (srimanth)

Srimanth Gunturi преди 11 години
родител
ревизия
19a336954b
променени са 2 файла, в които са добавени 143 реда и са изтрити 31 реда
  1. 59 5
      ambari-web/app/views/main/jobs/hive_job_details_tez_dag_view.js
  2. 84 26
      ambari-web/test/views/main/jobs/hive_job_details_tez_test.js

+ 59 - 5
ambari-web/app/views/main/jobs/hive_job_details_tez_dag_view.js

@@ -361,6 +361,32 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
         edgeType : e.get('edgeType')
       });
     });
+    // Sort nodes so that parents stay together
+    for ( var depth = 0; depth < depthToNodes.length; depth++) {
+      var nodes = depthToNodes[depth];
+      nodes.sort(function(n1, n2) {
+        var ck1 = '';
+        var ck2 = '';
+        if (n1.children) {
+          n1.children.forEach(function(c) {
+            ck1 += c.name;
+          });
+        }
+        if (n2.children) {
+          n2.children.forEach(function(c) {
+            ck2 += c.name;
+          });
+        }
+        if (ck1 < ck2) {
+          return -1
+        }
+        if (ck1 > ck2) {
+          return 1
+        }
+        return 0
+      });
+      depthToNodes[depth] = nodes;
+    }
 
     //
     // LAYOUT - Now with correct depth, we calculate layouts
@@ -402,7 +428,16 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
           updateNodeEffectiveWidth(node, xGap + node.width);
         }
         if (node.children && node.children.length > 0) {
-          updateNodeEffectiveWidth(node, node.children.length * (xGap + node.width));
+          // There can be dedicated or shared children.
+          // Dedicated children increase effective width of parent by their
+          // width.
+          // Shared children increase effective width of parent only by the
+          // fraction of parentage
+          var childrenWidth = 0;
+          node.children.forEach(function(child) {
+            childrenWidth += ((node.width + xGap) / child.parents.length);
+          });
+          updateNodeEffectiveWidth(node, Math.max(childrenWidth, (node.width+xGap)));
         } else {
           updateNodeEffectiveWidth(node, xGap + node.width);
         }
@@ -423,16 +458,22 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
         var node = nodes[nodeIndex];
         var parentsKey = null;
         if (node.parents != null && node.parents.length > 0) {
-          var parentStart = 0;
+          var parentMidX = 0;
           var parentsKey = '';
+          var childrenEffectiveWidth = -1;
           node.parents.forEach(function(parent) {
-            parentStart += (parent.x - ((parent.effectiveWidth - parent.width) / 2));
+            parentMidX += (parent.x + (parent.width / 2));
             parentsKey += (parent.id + '//');
+            if (childrenEffectiveWidth < 0) {
+              parent.children.forEach(function(c){
+                childrenEffectiveWidth += (c.effectiveWidth);
+              });
+            }
           });
-          parentStart = parentStart / node.parents.length;
+          parentMidX = parentMidX / node.parents.length;
           var parentCurrentX = parentCurrentXMap[parentsKey];
           if (parentCurrentX == null || parentCurrentX == undefined) {
-            parentCurrentX = parentStart - ((node.effectiveWidth - node.width) / 2) + (xGap / 2);
+            parentCurrentX = parentMidX - (childrenEffectiveWidth/2);
             parentCurrentXMap[parentsKey] = parentCurrentX;
           }
           currentX = parentCurrentX;
@@ -599,6 +640,19 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
       placement : 'left'
     });
 
+    if (App.supports.debugJobsDag) {
+      // Draws node bounding box - for debug purposes
+      node.append("rect").attr("width", function(n) {
+        return n.effectiveWidth;
+      }).attr("height", function(n) {
+        return n.height;
+      }).attr("x", function(n) {
+        return -1 * ((n.effectiveWidth - n.width) / 2);
+      }).attr("y", function(n) {
+        return 0;
+      }).attr("style", "opacity: 0.2;fill:yellow;");
+    }
+
     // Position in center
     var translateX = Math.round((width - canvasWidth) / 2);
     if (translateX > 0) {

+ 84 - 26
ambari-web/test/views/main/jobs/hive_job_details_tez_test.js

@@ -52,7 +52,7 @@ module.exports = {
    * and 5 nodes in row 3.
    *
    * Usage: <code>
-   *     var testDag = jobUtils._test_createTezDag_6x1x5();
+   *     var testDag = jobUtils.createTezDag_6x1x5();
    *     vertices = testDag.get('vertices');
    *     edges = testDag.get('edges');
    * </code>
@@ -70,33 +70,91 @@ module.exports = {
     var vertexJsons = [];
     var edgeJsons = [];
     // Row 1
-    var v1 = this._test_createVertex(1, 1, "FAILED", true, 30, [], [ 'e1' ], vertexJsons);
-    var v2 = this._test_createVertex(1, 2, "RUNNING", true, 2, [], [ 'e2' ], vertexJsons);
-    var v3 = this._test_createVertex(1, 3, "FAILED", true, 5, [], [ 'e3' ], vertexJsons);
-    var v4 = this._test_createVertex(1, 4, "FAILED", true, 10, [], [ 'e4' ], vertexJsons);
-    var v5 = this._test_createVertex(1, 5, "FAILED", true, 15, [], [ 'e5' ], vertexJsons);
-    var v6 = this._test_createVertex(1, 6, "FAILED", true, 20, [], [ 'e6' ], vertexJsons);
+    var v1 = this._createVertex(1, 1, "FAILED", true, 30, [], [ 'e1' ], vertexJsons);
+    var v2 = this._createVertex(1, 2, "RUNNING", true, 2, [], [ 'e2' ], vertexJsons);
+    var v3 = this._createVertex(1, 3, "FAILED", true, 5, [], [ 'e3' ], vertexJsons);
+    var v4 = this._createVertex(1, 4, "FAILED", true, 10, [], [ 'e4' ], vertexJsons);
+    var v5 = this._createVertex(1, 5, "FAILED", true, 15, [], [ 'e5' ], vertexJsons);
+    var v6 = this._createVertex(1, 6, "FAILED", true, 20, [], [ 'e6' ], vertexJsons);
     // Row 2
-    var v7 = this._test_createVertex(2, 1, "SUCCEEDED", false, 30, [ 'e1', 'e2', 'e3', 'e4', 'e5', 'e6' ], [ 'e7', 'e8', 'e9', 'e10', 'e11' ], vertexJsons);
+    var v7 = this._createVertex(2, 1, "SUCCEEDED", false, 30, [ 'e1', 'e2', 'e3', 'e4', 'e5', 'e6' ], [ 'e7', 'e8', 'e9', 'e10', 'e11' ], vertexJsons);
     // Row 3
-    var v8 = this._test_createVertex(3, 1, "FAILED", false, 30, [ 'e7' ], [], vertexJsons);
-    var v9 = this._test_createVertex(3, 2, "RUNNING", false, 2, [ 'e8' ], [], vertexJsons);
-    var v10 = this._test_createVertex(3, 3, "FAILED", false, 5, [ 'e9' ], [], vertexJsons);
-    var v11 = this._test_createVertex(3, 4, "FAILED", true, 10, [ 'e10' ], [], vertexJsons);
-    var v12 = this._test_createVertex(3, 5, "FAILED", true, 15, [ 'e11' ], [], vertexJsons);
+    var v8 = this._createVertex(3, 1, "FAILED", false, 30, [ 'e7' ], [], vertexJsons);
+    var v9 = this._createVertex(3, 2, "RUNNING", false, 2, [ 'e8' ], [], vertexJsons);
+    var v10 = this._createVertex(3, 3, "FAILED", false, 5, [ 'e9' ], [], vertexJsons);
+    var v11 = this._createVertex(3, 4, "FAILED", true, 10, [ 'e10' ], [], vertexJsons);
+    var v12 = this._createVertex(3, 5, "FAILED", true, 15, [ 'e11' ], [], vertexJsons);
     // Edges 1-2
-    this._test_createEdge('e1', 'BROADCAST', v1, v7, edgeJsons);
-    this._test_createEdge('e2', 'BROADCAST', v2, v7, edgeJsons);
-    this._test_createEdge('e3', 'BROADCAST', v3, v7, edgeJsons);
-    this._test_createEdge('e4', 'SCATTER_GATHER', v4, v7, edgeJsons);
-    this._test_createEdge('e5', 'SCATTER_GATHER', v5, v7, edgeJsons);
-    this._test_createEdge('e6', 'SCATTER_GATHER', v6, v7, edgeJsons);
+    this._createEdge('e1', 'BROADCAST', v1, v7, edgeJsons);
+    this._createEdge('e2', 'BROADCAST', v2, v7, edgeJsons);
+    this._createEdge('e3', 'BROADCAST', v3, v7, edgeJsons);
+    this._createEdge('e4', 'SCATTER_GATHER', v4, v7, edgeJsons);
+    this._createEdge('e5', 'SCATTER_GATHER', v5, v7, edgeJsons);
+    this._createEdge('e6', 'SCATTER_GATHER', v6, v7, edgeJsons);
     // Edges 2-3
-    this._test_createEdge('e7', 'SCATTER_GATHER', v7, v8, edgeJsons);
-    this._test_createEdge('e8', 'SCATTER_GATHER', v7, v9, edgeJsons);
-    this._test_createEdge('e9', 'SCATTER_GATHER', v7, v10, edgeJsons);
-    this._test_createEdge('e10', 'BROADCAST', v7, v11, edgeJsons);
-    this._test_createEdge('e11', 'BROADCAST', v7, v12, edgeJsons);
+    this._createEdge('e7', 'SCATTER_GATHER', v7, v8, edgeJsons);
+    this._createEdge('e8', 'SCATTER_GATHER', v7, v9, edgeJsons);
+    this._createEdge('e9', 'SCATTER_GATHER', v7, v10, edgeJsons);
+    this._createEdge('e10', 'BROADCAST', v7, v11, edgeJsons);
+    this._createEdge('e11', 'BROADCAST', v7, v12, edgeJsons);
+    vertexJsons.forEach(function(v) {
+      dagJson.vertices.push(v.id);
+    })
+    edgeJsons.forEach(function(e) {
+      dagJson.edges.push(e.id);
+    })
+    App.store.load(App.TezDag, dagJson);
+    App.store.loadMany(App.TezDagVertex, vertexJsons);
+    App.store.loadMany(App.TezDagEdge, edgeJsons);
+    return App.TezDag.find('dag1');
+  },
+
+  /**
+   * Creates a Tez DAG for test purposes with 6 nodes in row 1, 1 node in row 2
+   * and 5 nodes in row 3.
+   *
+   * Usage: <code>
+   *     var testDag = jobUtils.createTezDag_7x1_1x1();
+   *     vertices = testDag.get('vertices');
+   *     edges = testDag.get('edges');
+   * </code>
+   */
+  createTezDag_7x1_1x1 : function() {
+    var vertices = [];
+    var dagJson = {
+      id : 'dag1',
+      instance_id : 'dag1',
+      name : 'Test DAG 1',
+      stage : 'My stage',
+      vertices : [],
+      edges : []
+    };
+    var vertexJsons = [];
+    var edgeJsons = [];
+    // Row 1
+    var v1 = this._createVertex(1, 1, "FAILED", true, 30, [], [ 'e1' ], vertexJsons);
+    var v4 = this._createVertex(1, 4, "FAILED", true, 10, [], [ 'e4' ], vertexJsons);
+    var v6 = this._createVertex(1, 6, "FAILED", true, 20, [], [ 'e6' ], vertexJsons);
+    var v2 = this._createVertex(1, 2, "RUNNING", true, 2, [], [ 'e2' ], vertexJsons);
+    var v3 = this._createVertex(1, 3, "FAILED", true, 5, [], [ 'e3' ], vertexJsons);
+    var v5 = this._createVertex(1, 5, "FAILED", true, 15, [], [ 'e5' ], vertexJsons);
+    var v7 = this._createVertex(1, 7, "FAILED", true, 4, [], [ 'e7' ], vertexJsons);
+    // Row 2
+    var v8 = this._createVertex(2, 1, "SUCCEEDED", false, 30, [ 'e1', 'e2', 'e3', 'e4' ], [ 'e8' ], vertexJsons);
+    var v9 = this._createVertex(2, 2, "FAILED", false, 30, [ 'e5', 'e6', 'e7' ], ['e9'], vertexJsons);
+    // Row 3
+    var v10 = this._createVertex(3, 1, "RUNNING", false, 2, [ 'e8', 'e9' ], [], vertexJsons);
+    // Edges 1-2
+    this._createEdge('e1', 'BROADCAST', v1, v8, edgeJsons);
+    this._createEdge('e2', 'BROADCAST', v2, v8, edgeJsons);
+    this._createEdge('e3', 'BROADCAST', v3, v8, edgeJsons);
+    this._createEdge('e4', 'SCATTER_GATHER', v4, v8, edgeJsons);
+    this._createEdge('e5', 'SCATTER_GATHER', v5, v9, edgeJsons);
+    this._createEdge('e6', 'SCATTER_GATHER', v6, v9, edgeJsons);
+    this._createEdge('e7', 'SCATTER_GATHER', v7, v9, edgeJsons);
+    // Edges 2-3
+    this._createEdge('e8', 'SCATTER_GATHER', v8, v10, edgeJsons);
+    this._createEdge('e9', 'SCATTER_GATHER', v9, v10, edgeJsons);
     vertexJsons.forEach(function(v) {
       dagJson.vertices.push(v.id);
     })
@@ -149,10 +207,10 @@ module.exports = {
             ins.push('e_' + (r - 1) + c2 + '_' + r + c);
           }
         }
-        matrix[r][c] = this._test_createVertex(r, c, "RUNNING", true, (r + 1) * (c + 1), ins, outs, vertexJsons);
+        matrix[r][c] = this._createVertex(r, c, "RUNNING", true, (r + 1) * (c + 1), ins, outs, vertexJsons);
         if (r > 0) {
           for ( var c2 = 0; c2 < rowCounts[r - 1]; c2++) {
-            this._test_createEdge('e_' + (r - 1) + c2 + '_' + r + c, 'BROADCAST', matrix[r - 1][c2], matrix[r][c], edgeJsons);
+            this._createEdge('e_' + (r - 1) + c2 + '_' + r + c, 'BROADCAST', matrix[r - 1][c2], matrix[r][c], edgeJsons);
           }
         }
       }