export function collectFragmentEventsFromProfile()

in www/scripts/query_timeline/fragment_diagram.js [451:659]


export function collectFragmentEventsFromProfile() {
  rownum = 0;
  let max_namelen = 0;
  fragments = [];
  const all_nodes = [];
  const receiver_nodes = [];
  let color_idx = 0;
  try {
    // First pass: compute sizes
    const execution_profile = profile.child_profiles[2];
    const EXECUTION_PROFILE_NAME = execution_profile.profile_name.split(" ").slice(0,2)
        .join(" ");
    console.assert(EXECUTION_PROFILE_NAME === "Execution Profile");
    execution_profile.child_profiles.forEach((fp) => {

      if (fp.child_profiles !== undefined &&
          fp.child_profiles[0].event_sequences !== undefined) {
        let cp = fp.child_profiles[0];
        const fevents = fp.child_profiles[0].event_sequences[0].events;

        // Build list of timestamps that spans instances for each event
        for (let en = 0; en < fevents.length; ++en) {
          if (fevents[en].label.includes("AsyncCodegen")) {
            fevents[en].no_bar = true;
            continue;
          }
          fevents[en].ts_list = [ fevents[en].timestamp ];
        }
        for (let instance = 1; instance < fp.child_profiles.length; ++instance) {
          if (fp.child_profiles[instance].event_sequences !== undefined) {
            if (fp.child_profiles[instance].event_sequences[0].events.length ==
                fevents.length) {
              for (let en = 0; en < fevents.length; ++en) {
                if (fevents[en].no_bar) continue;
                fevents[en].ts_list.push(
                    fp.child_profiles[instance].event_sequences[0].events[en].timestamp);
              }
            } else {
              let en = 0, i = 0;
              while(i < fevents.length && en < fp.child_profiles[instance]
                  .event_sequences[0].events.length) {
                if (fevents[i].no_bar) {
                  if (fevents[i].label === fp.child_profiles[instance]
                      .event_sequences[0].events[en].label) { en++; }
                } else if (fp.child_profiles[instance].event_sequences[0]
                    .events[en].label === fevents[i].label) {
                  fevents[i].ts_list.push(fp.child_profiles[instance].event_sequences[0]
                      .events[en].timestamp);
                  ++en;
                }
                ++i;
              }
            }
          }
        }

        const fragment = {
          name: fp.profile_name,
          events: fevents,
          nodes: [ ],
          color: fragment_colors[color_idx]
        }
        // Pick a new color for each plan fragment
        color_idx = (color_idx + 1) % fragment_colors.length;
        set_maxts(Math.max(maxts, fevents[fevents.length - 1].timestamp));
        max_namelen = Math.max(max_namelen, fp.profile_name.length);
        const node_path = [];
        const node_stack = [];
        let node_name;
        cp.child_profiles.forEach(function get_plan_nodes(pp, index) {
          if (pp.node_metadata === undefined) return;
          node_path.push(index);
          //  pp.profile_name : "AGGREGATION_NODE (id=52)"
          let name_flds = pp.profile_name.split(/[()]/);
          //  name_flds : ["AGGREGATION_NODE ", "id=52", ""]
          let node_type = name_flds[0].trim();
          //  node_type: "AGGREGATION_NODE"
          let node_id = name_flds.length > 1 ?
              parseInt(name_flds[1].split(/[=]/)[1]) : 0;
          //  node_id: 52
          node_name = pp.profile_name.replace("_NODE", "").replace("_", " ")
              .replace("KrpcDataStreamSender", "SENDER")
              .replace("Hash Join Builder", "JOIN BUILD")
              .replace("join node_", "");
          if (node_type.indexOf("SCAN_NODE") >= 0) {
            let table_name = pp.info_strings.find(({ key }) => key === "Table Name")
                .value.split(/[.]/);
            node_name = node_name.replace("SCAN",
                `SCAN [${table_name[table_name.length - 1]}]`);
          }

          const IS_RECEIVER = node_type === "EXCHANGE_NODE" ||
              (node_type === "HASH_JOIN_NODE" && pp.num_children < 3);

          const IS_SENDER = (node_type === "Hash Join Builder" ||
                            node_type === "KrpcDataStreamSender");
          let parent_node;
          if (node_type === "PLAN_ROOT_SINK") {}
          else if (pp.node_metadata.data_sink_id !== undefined) {
            parent_node = receiver_nodes[node_id]; // Exchange sender dst
          } else if (pp.node_metadata.join_build_id !== undefined) {
            parent_node = receiver_nodes[node_id]; // Join sender dst
          } else if (node_stack.length > 0) {
            parent_node = node_stack[node_stack.length - 1];
          } else if (all_nodes.length) {
            parent_node = all_nodes[all_nodes.length - 1];
          }

          max_namelen = Math.max(max_namelen, node_name.length + node_stack.length + 1);

          let node_events;
          if (pp.event_sequences !== undefined) {
            node_events = pp.event_sequences[0].events;

            // Start the instance event list for each event with timestamps
            // from this instance
            for (let en = 0; en < node_events.length; ++en) {
              node_events[en].ts_list = [ node_events[en].timestamp ];
              if ((node_type === "HASH_JOIN_NODE" ||
                  node_type === "NESTED_LOOP_JOIN_NODE") && (en === 1 || en === 2)) {
                node_events[en].no_bar = true;
              }
            }
          }
          let node = {
              name: node_name,
              type: node_type,
              node_id: node_id,
              num_children: 0,
              child_index: 0,
              metadata: pp.node_metadata,
              parent_node: parent_node,
              events: node_events,
              path: node_path.slice(0),
              is_receiver: IS_RECEIVER,
              is_sender: IS_SENDER
          }

          if (IS_SENDER) {
            node.parent_node.sender_frag_index = fragments.length;
          }

          if (IS_RECEIVER) {
            receiver_nodes[node_id] = node;
          }

          if (parent_node !== undefined) {
            node.child_index = parent_node.num_children++;
          }

          all_nodes.push(node);

          fragment.nodes.push(node);

          if (pp.child_profiles !== undefined) {
            node_stack.push(node);
            pp.child_profiles.forEach(get_plan_nodes);
            node = node_stack.pop();
          }
          rownum++;
          node_path.pop();
        });

        // For each node, retrieve the instance timestamps for the remaining instances
        for (let ni = 0; ni < fragment.nodes.length; ++ni) {
          const node = fragment.nodes[ni];
          for (let cpn = 1; cpn < fp.child_profiles.length; ++cpn) {
            cp = fp.child_profiles[cpn];

            // Use the saved node path to traverse to the same position in this instance
            for (let pi = 0; pi < node.path.length; ++pi) {
              cp = cp.child_profiles[node.path[pi]];
            }
            console.assert(cp.node_metadata.data_sink_id === undefined ||
                           cp.profile_name.indexOf(`(dst_id=${node.node_id})`));
            console.assert(cp.node_metadata.plan_node_id === undefined ||
                           cp.node_metadata.plan_node_id === node.node_id);
            // Add instance events to this node
            if (cp.event_sequences !== undefined) {
              if (node.events.length === cp.event_sequences[0].events.length) {
                for (let en = 0; en < node.events.length; ++en) {
                  node.events[en].ts_list.push(cp.event_sequences[0].events[en].timestamp);
                }
              } else {
                let i = 0, en = 0;
                while(i < node.events.length && en < cp.event_sequences[0].events.length) {
                  if (node.events[i].label === cp.event_sequences[0].events[en].label) {
                    node.events[i].ts_list.push(cp.event_sequences[0].events[en].timestamp);
                    ++en; ++i;
                  } else {
                    ++i;
                  }
                }
              }
            }
          }
        }
        fragments.push(fragment);
      }
    });
    frag_name_width = (Math.max(2, (fragments.length - 1).toString().length) + 3)
        * CHAR_WIDTH;
    name_width = max_namelen * CHAR_WIDTH + (frag_name_width + 2);
    fragment_events_parse_successful = true;
  } catch(e) {
    fragment_events_parse_successful = false;
    console.log(e);
  }
}