{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import os\n", "import json\n", "\n", "import matplotlib.pyplot as plt\n", "from dataclasses import dataclass\n", "import numpy as np" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "this_dir = os.path.dirname(os.path.abspath(''))\n", "# results is in \"../results\"\n", "results_dir = os.path.join(this_dir, \"results\")" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "experiment_folder = \"casestudy_example\"\n", "experiment_name = \"cs_example_edf\"\n", "\n", "experiment_file = os.path.join(results_dir, experiment_folder, experiment_name + \".json\")\n", "if not os.path.exists(experiment_file):\n", " print(\"Experiment file not found: \", experiment_file)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "with open(experiment_file) as f:\n", " experiment_data_raw = json.load(f)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of records: 12035\n", "First record: {'entry': {'operation': 'start_work', 'chain': 0, 'node': 'node_0', 'count': 500, 'next_release_us': 99436}, 'time': 0.000101}\n", "Operation types: ['next_deadline', 'wait_for_work', 'get_next_executable', 'start_work', 'end_work']\n" ] } ], "source": [ "def pre_process_data(data):\n", " for record in data:\n", " record[\"time\"] = int(record[\"time\"])\n", "\n", " min_time = min([record[\"time\"] for record in data])\n", " for record in data:\n", " record[\"time\"] -= min_time\n", " record[\"time\"] /= (1000 * 1000)\n", "\n", " if record[\"entry\"][\"operation\"] == \"next_deadline\":\n", " #print(\"Record: \", record)\n", " record[\"entry\"][\"deadline\"] = int(record[\"entry\"][\"deadline\"])\n", " record[\"entry\"][\"deadline\"] -= min_time\n", " record[\"entry\"][\"deadline\"] /= (1000 * 1000)\n", "\n", " # data = sorted(data, key=lambda x: x[\"time\"])\n", " return data\n", "\n", "experiment_data = pre_process_data(experiment_data_raw)\n", "\n", "print(\"Number of records: \", len(experiment_data))\n", "print(\"First record: \", experiment_data[0])\n", "operation_types = list(set([record[\"entry\"][\"operation\"] for record in experiment_data]))\n", "print(\"Operation types: \", operation_types)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "@dataclass\n", "class Record:\n", " start_time: float\n", " end_time: float\n", " node_name: str\n", "\n", "@dataclass\n", "class RecordLine:\n", " node_name: str\n", " count: int\n", "\n", " def __eq__(self, other):\n", " return self.node_name == other.node_name and self.count == other.count\n", "\n", " def __hash__(self):\n", " return hash((self.node_name, self.count))\n", "\n", "def get_records(data) -> list[Record]:\n", " # used to match start_work and end_work records\n", " current_records: dict[RecordLine, Record] = {}\n", " records = []\n", " for record in data:\n", " if record[\"entry\"][\"operation\"] == \"start_work\":\n", " current_record = Record(start_time=record[\"time\"], node_name=record[\"entry\"][\"node\"], end_time=None)\n", " current_record_line = RecordLine(node_name=record[\"entry\"][\"node\"], count=record[\"entry\"][\"count\"])\n", " if current_record_line in current_records:\n", " raise Exception(\"Overlapping records\")\n", " current_records[current_record_line] = current_record\n", " elif record[\"entry\"][\"operation\"] == \"end_work\":\n", " current_record_line = RecordLine(node_name=record[\"entry\"][\"node\"], count=record[\"entry\"][\"count\"])\n", " if current_record_line not in current_records:\n", " raise Exception(\"No start record\")\n", " current_record = current_records[current_record_line]\n", " current_record.end_time = record[\"time\"]\n", " records.append(current_record)\n", " del current_records[current_record_line]\n", " return records\n", "\n", "records = get_records(experiment_data)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of nodes: 4\n" ] } ], "source": [ "num_nodes = len(set([record.node_name for record in records]))\n", "print(\"Number of nodes: \", num_nodes)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "5f9cc11846554ad4968929054ae2ba3c", "version_major": 2, "version_minor": 0 }, "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAJH9JREFUeJzt3X9w1/V9wPHXlx8GBJKYOkkyowWxBbygHSiinuDMubDdya1dQ3ucP3bRTtyKratY7wYEi9GqvbKzdVPoFO/YlN28edf2ZqNrWa+DKE5WhbRXAxUqBaZIoq7EH/nsjx7fMxM01e+PJO/H4+57JPl+vu/P+/3OF/K8T/gmuSzLsgAAIBmjyj0BAABKSwACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRmTLknMJz19/fHvn37YtKkSZHL5co9HQBgELIsi9deey3q6+tj1Kg0r4UJwI9g37590dDQUO5pAAAfwt69e+PUU08t9zTKQgB+BJMmTYqI3z6BKisryzwbAGAwent7o6GhIf91PEUC8CM4+m3fyspKAQgAw0zK/30rzW98AwAkTAACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgAOYblcYY4p5FjlOF8p517q9RVyrMGebzCG8/qG83PP+TwXBnvMYA3V/SzU+fjwBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYoZNALa1tcU555xT7mkAAAx7wyYAC+3QoUOxZMmSqKysjOrq6mhtbY3XX3+93NMCACi6ZANwyZIlsWPHjujo6Ijvfve78R//8R/xhS98odzTAgAouqIE4IIFC2LZsmWxfPnyqKmpidra2mhra8vfv2fPnli0aFFMnDgxKisro6WlJQ4cODBgjDvuuCMmT54ckyZNitbW1jhy5Mh7zrN+/fqYMWNGjBs3LqZPnx733nvvoObX1dUV//Zv/xbr16+PuXPnxkUXXRT33HNPPPzww7Fv376PtHYAgKGuaFcAN2zYEBMmTIjOzs64884749Zbb42Ojo7o7++PRYsWxaFDh2Lz5s3R0dERu3btisWLF+cfu2nTpmhra4v29vbYtm1b1NXVvSfuNm7cGCtXrozbbrsturq6or29PVasWBEbNmz4wLlt2bIlqqurY86cOfmPNTU1xahRo6Kzs7NwmwAAMASNKdbAs2bNilWrVkVExJlnnhnf+ta34sknn4yIiOeeey52794dDQ0NERHx0EMPxVlnnRVPP/10nHvuubF27dpobW2N1tbWiIhYs2ZNPPHEEwOuAq5atSq+8Y1vxKc//emIiJgyZUrs3Lkz7rvvvrjqqqved2779++PU045ZcDHxowZEzU1NbF///7jPq6vry/6+vry7/f29g52OwAAhoyiXQGcNWvWgPfr6uri4MGD0dXVFQ0NDfn4i4iYOXNmVFdXR1dXV0T89lu0c+fOHfD4efPm5d9+4403oru7O1pbW2PixIn525o1a6K7u7tYS4rbb789qqqq8rd3rwEAYLgo2hXAsWPHDng/l8tFf39/QcY++mrddevWvScUR48e/YGPr62tjYMHDw742Ntvvx2HDh2K2tra4z7ulltuiRtvvDH/fm9vrwgEAIadkr8KeMaMGbF3797Yu3dv/mM7d+6Mw4cPx8yZM/PH/P//i7d169b825MnT476+vrYtWtXTJs2bcBtypQpHziHefPmxeHDh+OZZ57Jf+zf//3fo7+//z1B+W4VFRVRWVk54AYAMNwU7Qrg8TQ1NUVjY2MsWbIk1q5dG2+//XZcf/31MX/+/PyLMm644Ya4+uqrY86cOXHhhRfGxo0bY8eOHTF16tT8OKtXr45ly5ZFVVVVNDc3R19fX2zbti1effXVAVfpjmXGjBnR3Nwc1157bfz93/99vPXWW/FXf/VX8bnPfS7q6+uLun4AgHIr+RXAXC4Xjz32WJx00klx8cUXR1NTU0ydOjUeeeSR/DGLFy+OFStWxPLly2P27Nnx4osvxtKlSweMc80118T69evjgQceiMbGxpg/f348+OCDg7oCGPHbVxFPnz49Lr300vjjP/7juOiii+L+++8v6FoBAIaiXJZlWbknMVz19vZGVVVV9PT0FOXbwblcxAd9dgZzTCHHKsf5Iko391Kvr5BjDfZ8gzGc1zecn3vO57kw2GMGa6juZ6HO92EV++v3cJDsbwIBAEjViAzA9vb2AT8e5t23hQsXlnt6AABlVfIXgZTCddddFy0tLce8b/z48SWeDQDA0DIiA7CmpiZqamrKPQ0AgCFpRH4LGACA4xOAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRlT7glwfFlWmGMKOZbzDd2xBnu+wRjO63M+5yv0WEP1fIMxnNdXyH3gvVwBBABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMABzicrnCHFPIsXK5wo41GKU8X6nnVMixyjGnUs+91GMNZryjY73fcaWe+3D/3BTimKE61lCc02CV4+8fxSEAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIzbAKwra0tzjnnnHJPAwBg2Bs2AVhol19+eZx22mkxbty4qKuriyuuuCL27dtX7mkBABRdsgF4ySWXxKZNm+LnP/95/Mu//Et0d3fHn/3Zn5V7WgAARVeUAFywYEEsW7Ysli9fHjU1NVFbWxttbW35+/fs2ROLFi2KiRMnRmVlZbS0tMSBAwcGjHHHHXfE5MmTY9KkSdHa2hpHjhx5z3nWr18fM2bMiHHjxsX06dPj3nvvHfQcv/zlL8f5558fp59+elxwwQXx1a9+NbZu3RpvvfXWh143AMBwULQrgBs2bIgJEyZEZ2dn3HnnnXHrrbdGR0dH9Pf3x6JFi+LQoUOxefPm6OjoiF27dsXixYvzj920aVO0tbVFe3t7bNu2Lerq6t4Tdxs3boyVK1fGbbfdFl1dXdHe3h4rVqyIDRs2/M5zPXToUGzcuDEuuOCCGDt27HGP6+vri97e3gE3AIBhJyuC+fPnZxdddNGAj5177rnZzTffnP3gBz/IRo8ene3Zsyd/344dO7KIyJ566qksy7Js3rx52fXXXz/g8XPnzs3OPvvs/PtnnHFG9o//+I8Djvna176WzZs3b9DzXL58eXbiiSdmEZGdf/752csvv/y+x69atSqLiPfcenp6Bn3O39VgPkOD/SwWaqyIwo41GKU8X6nnVMixyjGnUs+91GMNZryjY73fcaWe+3D/3BTimKE61lCc02CV4+9fMfT09BT96/dQV7QrgLNmzRrwfl1dXRw8eDC6urqioaEhGhoa8vfNnDkzqquro6urKyIiurq6Yu7cuQMeP2/evPzbb7zxRnR3d0dra2tMnDgxf1uzZk10d3cPeo433XRTPPvss/GDH/wgRo8eHVdeeWVkWXbc42+55Zbo6enJ3/bu3TvocwEADBVjijXw//9Wai6Xi/7+/oKM/frrr0dExLp1694TiqNHjx70OCeffHKcfPLJ8YlPfCJmzJgRDQ0NsXXr1gGx+W4VFRVRUVHx4ScOADAElPxVwDNmzIi9e/cOuHq2c+fOOHz4cMycOTN/TGdn54DHbd26Nf/25MmTo76+Pnbt2hXTpk0bcJsyZcqHmtfROO3r6/tQjwcAGC6KdgXweJqamqKxsTGWLFkSa9eujbfffjuuv/76mD9/fsyZMyciIm644Ya4+uqrY86cOXHhhRfGxo0bY8eOHTF16tT8OKtXr45ly5ZFVVVVNDc3R19fX2zbti1effXVuPHGG993Dp2dnfH000/HRRddFCeddFJ0d3fHihUr4owzzjju1T8AgJGi5FcAc7lcPPbYY3HSSSfFxRdfHE1NTTF16tR45JFH8scsXrw4VqxYEcuXL4/Zs2fHiy++GEuXLh0wzjXXXBPr16+PBx54IBobG2P+/Pnx4IMPDuoK4IknnhiPPvpoXHrppfHJT34yWltbY9asWbF582bf4gUARrxc9n6veuB99fb2RlVVVfT09ERlZWVRzpHL/fa1Uh/1mEKOlcv99s9CjVXquQ+1ORVyrHLMKaK0cy/k+QYz1mDGOzrW+41X6rkP98/NUPu7VcixhuKcBqvUz5diKcXX76Eu2d8EAgCQqhEZgO3t7QN+PMy7bwsXLiz39AAAyqrkLwIpheuuuy5aWlqOed/48eNLPBsAgKFlRAZgTU1N1NTUlHsaAABD0oj8FjAAAMcnAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIzptwT4P1lWWGOKeRYpT5fIccainMq5FhDcU6FHKsccx/MsUNx7s43dMcainMarFKvj+JxBRAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECcAjL5QpzTCHHKsf5Sjn3Uq+vkGMN9nyDMZzXN5yfe87nuTDYY5yPj0oAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRm2ARgW1tbnHPOOeWeBgDAsDdsArCQfvnLX0Zra2tMmTIlxo8fH2eccUasWrUq3nzzzXJPDQCg6MaUewLl8LOf/Sz6+/vjvvvui2nTpsXzzz8f1157bbzxxhtx9913l3t6AABFVZQrgAsWLIhly5bF8uXLo6amJmpra6OtrS1//549e2LRokUxceLEqKysjJaWljhw4MCAMe64446YPHlyTJo0KVpbW+PIkSPvOc/69etjxowZMW7cuJg+fXrce++9g5pfc3NzPPDAA3HZZZfF1KlT4/LLL4+vfOUr8eijj36kdQMADAdF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mjXxxBNPDLgKuGrVqvjGN74Rn/70pyMiYsqUKbFz586477774qqrrirKmm6//fZYvXp1UcYGACiVol0BnDVr1oD36+rq4uDBg9HV1RUNDQ35+IuImDlzZlRXV0dXV1dERHR1dcXcuXMHPH7evHn5t994443o7u6O1tbWmDhxYv62Zs2a6O7uLtaS4pZbbomenp78be/evUU7FwBAsRTtCuDYsWMHvJ/L5aK/v78gY7/++usREbFu3br3hOLo0aMLco5jqaioiIqKiqKNDwBQCiV/FfCMGTNi7969A66e7dy5Mw4fPhwzZ87MH9PZ2TngcVu3bs2/PXny5Kivr49du3bFtGnTBtymTJlSmoUAAAxTRbsCeDxNTU3R2NgYS5YsibVr18bbb78d119/fcyfPz/mzJkTERE33HBDXH311TFnzpy48MILY+PGjbFjx46YOnVqfpzVq1fHsmXLoqqqKpqbm6Ovry+2bdsWr776atx4440fOI89e/bEoUOHYs+ePfHOO+/E9u3bIyJi2rRpMXHixKKsHQBgKCh5AOZyuXjsscfii1/8Ylx88cUxatSoaG5ujnvuuSd/zOLFi6O7uzuWL18eR44cic985jOxdOnSePzxx/PHXHPNNXHiiSfGXXfdFTfddFNMmDAhGhsb40tf+tKg5rFy5coBrxj+1Kc+FRERP/zhD2PBggUFWSsAwFCUy7IsK/ckhqve3t6oqqqKnp6eqKysLMo5crmID/oMDeaYQo6Vy/32z0KNVeq5W19h5xThczOYeZVjr4bac284n6+QYxVyToNR6rEK+Xe5WErx9XuoS/Y3gQAApGpEBmB7e/uAHw/z7tvChQvLPT0AgLIq+f8BLIXrrrsuWlpajnnf+PHjSzwbAIChZUQGYE1NTdTU1JR7GgAAQ9KI/BYwAADHJwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEjOm3BPg/WVZYY4p5FilPl8hxxqKcyrkWENxToUcy9ydr1znK+RYhZzTYJR6rFKvjw/HFUAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhA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DgWF3ufXX389u+WWW7ItW7Zkv/zlL7Nt27Zlf/7nf55VVFRkzz//fFnWOFQU49+P/8+rgAu/z6+99lr2la98JduyZUu2e/fu7Iknnsj+4A/+IDvzzDOzI0eOlGWNw4kALIF77rknO+2007ITTjghO++887KtW7fm75s/f3521VVXDTh+06ZN2Sc+8YnshBNOyM4666zse9/73oD7+/v7sxUrVmSTJ0/OKioqsksvvTT7+c9/XoqlDGmF3ucHHnggi4j33FatWlWC1Qxthdzroz9m51i3H/7whyVa0dBUyH3+zW9+k/3pn/5pVl9fn51wwglZXV1ddvnll2dPPfVUqZYzpBX634//TwD+ViH3+X//93+zyy67LPu93/u9bOzYsdnpp5+eXXvttfmg5P3lsizLynPtEQCAcvB/AAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEvN/MtadhFAkxS0AAAAASUVORK5CYII=", "text/html": [ "\n", "