{ "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: 11236\n", "First record: {'entry': {'operation': 'start_work', 'chain': 0, 'node': 'node_0', 'count': 500, 'next_release_us': 99799}, 'time': 0.0001}\n", "Operation types: ['start_work', 'get_next_executable', 'next_deadline', 'end_work', 'wait_for_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": "9f7b2b16a21a439c849b44f675f73fbc", "version_major": 2, "version_minor": 0 }, "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAJPRJREFUeJzt3X9w1/V9wPHXlx8GBJKYOkMyUwtiC3hBO1BEPcGZc2G7k1u7hvY4f+yinbgVW1ex3g0IFqNVe2Vn66bQKd6xKbt5867tzUbXsl4HUZysCmmvBipUCkwRoq7EH/nsD4/vTAUM8v1+ky/vx+Pue/nxfX/f7/fnk1/P+4RvyGVZlgUAAMkYNtgbAACgtAQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiRgz2BspZX19f7Nq1K8aNGxe5XG6wtwMADECWZfH6669HfX19DBuW5rUwAXgcdu3aFQ0NDYO9DQDgI9i5c2ecfvrpg72NQSEAj8O4ceMi4r1PoMrKykHeDQAwED09PdHQ0JD/OZ4iAXgcDv3at7KyUgACQJlJ+Z9vpfmLbwCAhAlAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAjAMpDLvXcrxJj3vzyeuQq9r6ONGei+C7mnQs51LGNKda4G4xwMRLl/jAtxHobq8Q1EofZUqLmG8tfDUF2vVHs6lnEUhwAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASEzZBGBbW1uce+65g70NAICyVzYBWGi33357XHjhhXHyySdHdXX1YG8HAKBkkg3At956Kz73uc/FwoULB3srAAAlVZQAnDNnTixatCgWL14cNTU1MX78+Ghra8vfv2PHjpg3b16MHTs2Kisro6WlJfbs2dNvjjvvvDNqa2tj3Lhx0draGgcPHvzAOqtXr44pU6bEqFGjYvLkyXHfffcNeI/Lly+Pr3zlK9HY2PiRjxMAoBwV7QrgmjVrYsyYMdHZ2Rl33XVX3HbbbdHR0RF9fX0xb9682LdvX6xfvz46Ojpi27ZtMX/+/Pxj161bF21tbdHe3h6bNm2Kurq6D8Td2rVrY+nSpXH77bdHV1dXtLe3x5IlS2LNmjXFOiQAgBPCiGJNPG3atFi2bFlERJx11lnx7W9/O5566qmIiHj++edj+/bt0dDQEBERDz/8cJx99tnxzDPPxHnnnRcrV66M1tbWaG1tjYiIFStWxJNPPtnvKuCyZcvim9/8ZnzmM5+JiIgJEybE1q1b4/7774+rr766KMfU29sbvb29+bd7enqKsg4AQDEV7QrgtGnT+r1dV1cXe/fuja6urmhoaMjHX0TE1KlTo7q6Orq6uiIioqurK2bOnNnv8bNmzcq//uabb0Z3d3e0trbG2LFj87cVK1ZEd3d3sQ4p7rjjjqiqqsrf3n8MAADlomhXAEeOHNnv7VwuF319fQWZ+4033oiIiFWrVn0gFIcPH16QNQ7n1ltvjZtuuin/dk9PjwgEAMpO0QLwSKZMmRI7d+6MnTt35uNp69atsX///pg6dWp+TGdnZ1x11VX5x23cuDH/em1tbdTX18e2bdtiwYIFJdt7RUVFVFRUlGw9AIBiKHkANjU1RWNjYyxYsCBWrlwZ77zzTtxwww0xe/bsmDFjRkRE3HjjjXHNNdfEjBkz4qKLLoq1a9fGli1bYuLEifl5li9fHosWLYqqqqpobm6O3t7e2LRpU7z22mv9rtIdyY4dO2Lfvn2xY8eOePfdd2Pz5s0RETFp0qQYO3ZsUY4dAGAoKHkA5nK5ePzxx+NLX/pSXHLJJTFs2LBobm6Oe++9Nz9m/vz50d3dHYsXL46DBw/GZz/72Vi4cGE88cQT+THXXnttnHzyyXH33XfHzTffHGPGjInGxsb48pe/PKB9LF26tN8zhj/96U9HRMSPfvSjmDNnTkGOFQBgKMplWZYN9ibKVU9PT1RVVcWBAweisrKyaOvkcu+9PNpHaqBjsuz/Xx7PXIXe19HGDHTfhdxTIec6ljHHO9dQ/hgP5DtNuX+MBzKuXI+vlB+/Qs01lL8ehup6Q+3zs1hK9fN7KEv2fwIBAEjVCRmA7e3t/f48zPtvc+fOHeztAQAMqpL/G8BSuP7666OlpeWw940ePbrEuwEAGFpOyACsqamJmpqawd4GAMCQdEL+ChgAgCMTgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkZMdgb4MNlWWHHfNjYgcx1rGsez5iB7ruQY0q9XqH2VK4fY+tZrxhz+Xoo//UoHlcAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIzYrA3wJHlcu+9zLLjG3No3EDGDHS9QuxroGM+bN+FXu/Dxgzl9Qoxz7GsV4gx1rNesdYr1+951hv45wIfnSuAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkpmwBsa2uLc889d7C3AQBQ9somAAtt3759sWDBgqisrIzq6upobW2NN954Y7C3BQBQdMkG4IIFC2LLli3R0dER3/ve9+I//uM/4otf/OJgbwsAoOiKEoBz5syJRYsWxeLFi6OmpibGjx8fbW1t+ft37NgR8+bNi7Fjx0ZlZWW0tLTEnj17+s1x5513Rm1tbYwbNy5aW1vj4MGDH1hn9erVMWXKlBg1alRMnjw57rvvvgHtr6urK/7t3/4tVq9eHTNnzoyLL7447r333njkkUdi165dx3XsAABDXdGuAK5ZsybGjBkTnZ2dcdddd8Vtt90WHR0d0dfXF/PmzYt9+/bF+vXro6OjI7Zt2xbz58/PP3bdunXR1tYW7e3tsWnTpqirq/tA3K1duzaWLl0at99+e3R1dUV7e3ssWbIk1qxZ86F727BhQ1RXV8eMGTPy72tqaophw4ZFZ2fnER/X29sbPT09/W4AAOVmRLEmnjZtWixbtiwiIs4666z49re/HU899VRERDz//POxffv2aGhoiIiIhx9+OM4+++x45pln4rzzzouVK1dGa2trtLa2RkTEihUr4sknn+x3FXDZsmXxzW9+Mz7zmc9ERMSECRNi69atcf/998fVV1991L3t3r07TjvttH7vGzFiRNTU1MTu3buP+Lg77rgjli9ffoxnAgBgaCnaFcBp06b1e7uuri727t0bXV1d0dDQkI+/iIipU6dGdXV1dHV1RcR7v6KdOXNmv8fPmjUr//qbb74Z3d3d0draGmPHjs3fVqxYEd3d3cU6pLj11lvjwIED+dvOnTuLthYAQLEU7QrgyJEj+72dy+Wir6+vIHMferbuqlWrPhCKw4cP/9DHjx8/Pvbu3dvvfe+8807s27cvxo8ff8THVVRUREVFxUfYMQDA0FHyZwFPmTIldu7c2e/q2datW2P//v0xderU/Jjf/bd4GzduzL9eW1sb9fX1sW3btpg0aVK/24QJEz50D7NmzYr9+/fHs88+m3/fv//7v0dfX98HghIA4ERTtCuAR9LU1BSNjY2xYMGCWLlyZbzzzjtxww03xOzZs/NPyrjxxhvjmmuuiRkzZsRFF10Ua9eujS1btsTEiRPz8yxfvjwWLVoUVVVV0dzcHL29vbFp06Z47bXX4qabbjrqHqZMmRLNzc1x3XXXxd///d/H22+/HX/1V38Vn//856O+vr6oxw8AMNhKfgUwl8vF448/Hqecckpccskl0dTUFBMnToxHH300P2b+/PmxZMmSWLx4cUyfPj1eeumlWLhwYb95rr322li9enU8+OCD0djYGLNnz46HHnpoQFcAI957FvHkyZPjsssuiz/+4z+Oiy++OB544IGCHisAwFCUy7IsG+xNlKuenp6oqqqKAwcORGVlZcHnz+Xee3m0j9BAxhwaN5AxA12vEPsa6JiBfIYWcr0PGzOU1yvEPMeyXiHGWM96xVqvXL/nWW/gnwsf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jx+f3X333fn79+/fn1VUVGT/9E//VIQjKA+FPs/vt337dgH4PsU814c8/fTTWURkL730UmE2XYZKcZ4PHDiQRUT25JNPFmbTZahY5/nXv/519vu///vZCy+8kJ1xxhkCMCvOub766quzefPmFWW/Jzq/Ai6it956K5599tloamrKv2/YsGHR1NQUGzZsOOxjNmzY0G98RMQf/dEf5cdv3749du/e3W9MVVVVzJw584hznuiKcZ45vFKd6wMHDkQul4vq6uqC7LvclOI8v/XWW/HAAw9EVVVVnHPOOYXbfBkp1nnu6+uLK6+8Mm6++eY4++yzi7P5MlPMz+kf//jHcdppp8WnPvWpWLhwYbz66quFP4ATkAAsoldeeSXefffdqK2t7ff+2tra2L1792Efs3v37qOOP/TyWOY80RXjPHN4pTjXBw8ejFtuuSW+8IUvFOU/gC8HxTzP3/ve92Ls2LExatSo+Na3vhUdHR1x6qmnFvYAykSxzvM3vvGNGDFiRCxatKjwmy5TxTrXzc3N8fDDD8dTTz0V3/jGN2L9+vUxd+7cePfddwt/ECeYEYO9AYBD3n777WhpaYksy+Lv/u7vBns7J6RLL700Nm/eHK+88kqsWrUqWlpaorOzM0477bTB3toJ4dlnn42//du/jf/6r/+KXC432Ns54X3+85/Pv97Y2BjTpk2LM888M3784x/HZZddNog7G/pcASyiU089NYYPHx579uzp9/49e/bE+PHjD/uY8ePHH3X8oZfHMueJrhjnmcMr5rk+FH8vvfRSdHR0JHv1L6K453nMmDExadKkuOCCC+K73/1ujBgxIr773e8W9gDKRDHO809+8pPYu3dvfPzjH48RI0bEiBEj4qWXXoq//uu/jk984hNFOY5yUKrv0xMnToxTTz01XnzxxePf9AlOABbRSSedFNOnT4+nnnoq/76+vr546qmnYtasWYd9zKxZs/qNj4jo6OjIj58wYUKMHz++35ienp7o7Ow84pwnumKcZw6vWOf6UPz98pe/jCeffDI+9rGPFecAykQpP6f7+vqit7f3+Dddhopxnq+88sr42c9+Fps3b87f6uvr4+abb44nnniieAczxJXqc/rXv/51vPrqq1FXV1eYjZ/IBvtZKCe6Rx55JKuoqMgeeuihbOvWrdkXv/jFrLq6Otu9e3eWZVl25ZVXZl/72tfy43/6059mI0aMyO65556sq6srW7Zs2WH/DEx1dXX2+OOPZz/72c+yefPm+TMwRTjPr776avbcc89l3//+97OIyB555JHsueeey37zm9+U/PiGkkKf67feeiu74oorstNPPz3bvHlzvz/n0NvbOyjHOBQU+jy/8cYb2a233ppt2LAh+9WvfpVt2rQp+/M///OsoqIie+GFFwblGIeCYnzv+F2eBfyeQp/r119/PfvqV7+abdiwIdu+fXv25JNPZn/wB3+QnXXWWdnBgwcH5RjLiQAsgXvvvTf7+Mc/np100knZ+eefn23cuDF/3+zZs7Orr7663/h169Zln/zkJ7OTTjopO/vss7Pvf//7/e7v6+vLlixZktXW1mYVFRXZZZddlv3iF78oxaEMaYU+zw8++GAWER+4LVu2rARHM7QV8lwf+jM7h7v96Ec/KtERDU2FPM+//e1vsz/90z/N6uvrs5NOOimrq6vLrrjiiuzpp58u1eEMWYX+3vG7BOD/K+S5/t///d/s8ssvz37v934vGzlyZHbGGWdk1113XT4oObpclmXZ4Fx7BABgMPg3gAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAifk/9D1VW6bEYXUAAAAASUVORK5CYII=", "text/html": [ "\n", "