1
0
Fork 0
llvm-premerge-checks/scripts/buildkite/analyze_jobs.ipynb
2020-07-30 09:32:50 +02:00

839 lines
57 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## License\n",
"\n",
"Copyright 2020 Google LLC\n",
"\n",
"Licensed under the the Apache License v2.0 with LLVM Exceptions (the \"License\");\n",
"you may not use this file except in compliance with the License.\n",
"You may obtain a copy of the License at\n",
"\n",
"https://llvm.org/LICENSE.txt\n",
"\n",
"Unless required by applicable law or agreed to in writing, software\n",
"distributed under the License is distributed on an \"AS IS\" BASIS,\n",
"WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
"See the License for the specific language governing permissions and\n",
"limitations under the License."
]
},
{
"cell_type": "code",
"execution_count": 724,
"metadata": {},
"outputs": [],
"source": [
"import requests\n",
"import os\n",
"import logging\n",
"import argparse\n",
"import json\n",
"import pandas as pd\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns"
]
},
{
"cell_type": "code",
"execution_count": 725,
"metadata": {},
"outputs": [],
"source": [
"cache_file = \"cache.json\"\n",
"token = f'Bearer {os.getenv(\"BUILDKITE_API_TOKEN\")}'\n",
"builds = []"
]
},
{
"cell_type": "code",
"execution_count": 726,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"loaded 13566 entries\n"
]
}
],
"source": [
"if os.path.exists(cache_file):\n",
" with open(cache_file) as f:\n",
" builds = json.load(f)\n",
" print(f'loaded {len(builds)} entries') "
]
},
{
"cell_type": "code",
"execution_count": 727,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"loading page 1\n",
"loading page 2\n",
"loading page 3\n",
"https://buildkite.com/llvm-project/llvm-master-build/builds/723 is running , skipping\n",
"https://buildkite.com/llvm-project/llvm-master-build/builds/721 is running , skipping\n",
"https://buildkite.com/llvm-project/llvm-master-build/builds/719 is running , skipping\n",
"loading page 4\n",
"https://buildkite.com/llvm-project/llvm-master-build/builds/717 is running , skipping\n",
"https://buildkite.com/llvm-project/llvm-master-build/builds/715 is running , skipping\n",
"loading page 5\n",
"loading page 6\n",
"loading page 7\n",
"loading page 8\n",
"loading page 9\n",
"loading page 10\n",
"13706 jobs in total\n",
"saved 13706 entries\n"
]
}
],
"source": [
"# load new jobs from Buildkite API\n",
"max_pages = 2000\n",
"if True:\n",
" existing = set()\n",
" for j in builds:\n",
" existing.add(j['id'])\n",
"\n",
" # uncomment to reset\n",
"# builds = []\n",
"# existing = set()\n",
" page = 1\n",
" stop = False\n",
" while page <= max_pages:\n",
" print('loading page', page)\n",
" re = requests.get('https://api.buildkite.com/v2/organizations/llvm-project/builds',\n",
" params={'page': page},\n",
" headers={'Authorization': token})\n",
" if re.status_code != 200:\n",
" print('response status', re.status_code, re)\n",
" break\n",
" x = re.json()\n",
" if x == []:\n",
" print('empty response')\n",
" break\n",
" for j in x:\n",
" if j['id'] in existing:\n",
"# print('found existing job', j['id'])\n",
" # load some more pages as some of them might be running before and wasn't added. \n",
" max_pages = min(page + 5, max_pages)\n",
" else:\n",
" # skip running jobs \n",
" if (j['state'] == 'running') or (j['state'] == 'scheduled'):\n",
" print(j['web_url'], 'is', j['state'], ', skipping')\n",
" continue\n",
" builds.append(j)\n",
" page += 1\n",
" print(len(builds), 'jobs in total') \n",
" with open(cache_file, 'w') as f:\n",
" json.dump(builds, f)\n",
" print(f'saved {len(builds)} entries')"
]
},
{
"cell_type": "code",
"execution_count": 728,
"metadata": {},
"outputs": [],
"source": [
"d = {\n",
" 'id': [],\n",
" 'number': [],\n",
" 'pipeline': [],\n",
"}\n",
"\n",
"jobs = {\n",
" 'pipeline': [],\n",
" 'name': [],\n",
" 'step_key': [],\n",
" 'state': [],\n",
" 'exit_status': [],\n",
" 'agent_id': [],\n",
" \n",
" 'agent_name': [],\n",
" 'runnable_at': [],\n",
" 'started_at': [],\n",
" 'wait_duration': [],\n",
" 'finished_at': [],\n",
" 'run_duration': [],\n",
"}\n",
"\n",
"sec = np.timedelta64(1, 's')\n",
"\n",
"for b in builds:\n",
" env = b['env']\n",
" if 'ph_windows_agents' not in env:\n",
" continue\n",
" if 'scripts_branch' not in env:\n",
" continue\n",
" d['id'].append(b['id'])\n",
" d['number'].append(b['number'])\n",
" d['pipeline'].append(b['pipeline']['slug'])\n",
" for x in b['jobs']:\n",
" if x['state'] in ['waiting_failed', 'canceled', 'skipped', 'broken']:\n",
" continue\n",
" try:\n",
" jobs['pipeline'].append(b['pipeline']['slug'])\n",
" jobs['name'].append(x['name'])\n",
" jobs['step_key'].append(x['step_key'] if 'step_key' in x else '')\n",
" jobs['state'].append(x['state'] )\n",
" jobs['exit_status'].append(x['exit_status'] if 'exit_status' in x else -1)\n",
" jobs['agent_id'].append(x['agent']['id'] if 'agent' in x else '')\n",
" jobs['agent_name'].append(x['agent']['name'] if 'agent' in x else '')\n",
" runnable = np.datetime64(x['runnable_at'].replace('Z', ''))\n",
" started = np.datetime64(x['started_at'].replace('Z', ''))\n",
" finished = np.datetime64(x['finished_at'].replace('Z', ''))\n",
" jobs['runnable_at'].append(runnable)\n",
" jobs['started_at'].append(started)\n",
" jobs['wait_duration'].append((started - runnable) / sec)\n",
" jobs['finished_at'].append(finished)\n",
" jobs['run_duration'].append((finished - started) / sec)\n",
" except Exception as e:\n",
" print(x)\n",
" raise e \n",
"jobs = pd.DataFrame(jobs)"
]
},
{
"cell_type": "code",
"execution_count": 729,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array(['llvm-master-build'], dtype=object)"
]
},
"execution_count": 729,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"jobs.pipeline.unique()"
]
},
{
"cell_type": "code",
"execution_count": 730,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>pipeline</th>\n",
" <th>name</th>\n",
" <th>step_key</th>\n",
" <th>state</th>\n",
" <th>exit_status</th>\n",
" <th>agent_id</th>\n",
" <th>agent_name</th>\n",
" <th>runnable_at</th>\n",
" <th>started_at</th>\n",
" <th>wait_duration</th>\n",
" <th>finished_at</th>\n",
" <th>run_duration</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>llvm-master-build</td>\n",
" <td>:seedling: setup</td>\n",
" <td>None</td>\n",
" <td>passed</td>\n",
" <td>0</td>\n",
" <td>f20d42d3-31cb-4e46-a3d6-699877e7b283</td>\n",
" <td>premerge-debian-77f64f444-fm624-1</td>\n",
" <td>2020-07-27 18:10:16</td>\n",
" <td>2020-07-27 18:15:44.928</td>\n",
" <td>328.928</td>\n",
" <td>2020-07-27 18:15:47.797</td>\n",
" <td>2.869</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>llvm-master-build</td>\n",
" <td>:windows: build and test windows</td>\n",
" <td>windows</td>\n",
" <td>passed</td>\n",
" <td>0</td>\n",
" <td>c9e48cee-e909-45b2-aa23-0d7335786499</td>\n",
" <td>we32n1b</td>\n",
" <td>2020-07-27 18:15:47</td>\n",
" <td>2020-07-28 01:36:57.687</td>\n",
" <td>26470.687</td>\n",
" <td>2020-07-28 02:26:08.750</td>\n",
" <td>2951.063</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>llvm-master-build</td>\n",
" <td>:seedling: setup</td>\n",
" <td>None</td>\n",
" <td>passed</td>\n",
" <td>0</td>\n",
" <td>f20d42d3-31cb-4e46-a3d6-699877e7b283</td>\n",
" <td>premerge-debian-77f64f444-fm624-1</td>\n",
" <td>2020-07-27 18:10:15</td>\n",
" <td>2020-07-27 18:15:34.989</td>\n",
" <td>319.989</td>\n",
" <td>2020-07-27 18:15:37.721</td>\n",
" <td>2.732</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>llvm-master-build</td>\n",
" <td>:windows: build and test windows</td>\n",
" <td>windows</td>\n",
" <td>passed</td>\n",
" <td>0</td>\n",
" <td>d4d0a0a4-255b-4fdd-8aba-abb00ba0bf34</td>\n",
" <td>we16c2b</td>\n",
" <td>2020-07-27 18:15:37</td>\n",
" <td>2020-07-28 03:13:59.996</td>\n",
" <td>32302.996</td>\n",
" <td>2020-07-28 04:14:12.521</td>\n",
" <td>3612.525</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>llvm-master-build</td>\n",
" <td>:seedling: setup</td>\n",
" <td>None</td>\n",
" <td>passed</td>\n",
" <td>0</td>\n",
" <td>f20d42d3-31cb-4e46-a3d6-699877e7b283</td>\n",
" <td>premerge-debian-77f64f444-fm624-1</td>\n",
" <td>2020-07-27 18:10:14</td>\n",
" <td>2020-07-27 18:15:25.094</td>\n",
" <td>311.094</td>\n",
" <td>2020-07-27 18:15:27.918</td>\n",
" <td>2.824</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>189</th>\n",
" <td>llvm-master-build</td>\n",
" <td>:windows: build and test windows</td>\n",
" <td>windows</td>\n",
" <td>passed</td>\n",
" <td>0</td>\n",
" <td>42f6f98d-15bd-4ad4-ac48-8626a752a154</td>\n",
" <td>w16c2-1</td>\n",
" <td>2020-07-29 18:22:31</td>\n",
" <td>2020-07-29 20:23:50.686</td>\n",
" <td>7279.686</td>\n",
" <td>2020-07-29 21:23:50.271</td>\n",
" <td>3599.585</td>\n",
" </tr>\n",
" <tr>\n",
" <th>190</th>\n",
" <td>llvm-master-build</td>\n",
" <td>:seedling: setup</td>\n",
" <td>None</td>\n",
" <td>passed</td>\n",
" <td>0</td>\n",
" <td>db5829eb-04bf-4700-9bec-423258de4a7d</td>\n",
" <td>premerge-debian-77f64f444-vxgx4-1</td>\n",
" <td>2020-07-29 18:21:47</td>\n",
" <td>2020-07-29 18:22:09.243</td>\n",
" <td>22.243</td>\n",
" <td>2020-07-29 18:22:12.321</td>\n",
" <td>3.078</td>\n",
" </tr>\n",
" <tr>\n",
" <th>191</th>\n",
" <td>llvm-master-build</td>\n",
" <td>:windows: build and test windows</td>\n",
" <td>windows</td>\n",
" <td>passed</td>\n",
" <td>0</td>\n",
" <td>42f6f98d-15bd-4ad4-ac48-8626a752a154</td>\n",
" <td>w16c2-1</td>\n",
" <td>2020-07-29 18:22:12</td>\n",
" <td>2020-07-29 19:24:00.345</td>\n",
" <td>3708.345</td>\n",
" <td>2020-07-29 20:23:45.967</td>\n",
" <td>3585.622</td>\n",
" </tr>\n",
" <tr>\n",
" <th>192</th>\n",
" <td>llvm-master-build</td>\n",
" <td>:seedling: setup</td>\n",
" <td>None</td>\n",
" <td>passed</td>\n",
" <td>0</td>\n",
" <td>db5829eb-04bf-4700-9bec-423258de4a7d</td>\n",
" <td>premerge-debian-77f64f444-vxgx4-1</td>\n",
" <td>2020-07-29 18:21:45</td>\n",
" <td>2020-07-29 18:21:49.190</td>\n",
" <td>4.190</td>\n",
" <td>2020-07-29 18:21:52.862</td>\n",
" <td>3.672</td>\n",
" </tr>\n",
" <tr>\n",
" <th>193</th>\n",
" <td>llvm-master-build</td>\n",
" <td>:windows: build and test windows</td>\n",
" <td>windows</td>\n",
" <td>passed</td>\n",
" <td>0</td>\n",
" <td>42f6f98d-15bd-4ad4-ac48-8626a752a154</td>\n",
" <td>w16c2-1</td>\n",
" <td>2020-07-29 18:21:52</td>\n",
" <td>2020-07-29 18:21:54.857</td>\n",
" <td>2.857</td>\n",
" <td>2020-07-29 19:23:58.471</td>\n",
" <td>3723.614</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>194 rows × 12 columns</p>\n",
"</div>"
],
"text/plain": [
" pipeline name step_key state \\\n",
"0 llvm-master-build :seedling: setup None passed \n",
"1 llvm-master-build :windows: build and test windows windows passed \n",
"2 llvm-master-build :seedling: setup None passed \n",
"3 llvm-master-build :windows: build and test windows windows passed \n",
"4 llvm-master-build :seedling: setup None passed \n",
".. ... ... ... ... \n",
"189 llvm-master-build :windows: build and test windows windows passed \n",
"190 llvm-master-build :seedling: setup None passed \n",
"191 llvm-master-build :windows: build and test windows windows passed \n",
"192 llvm-master-build :seedling: setup None passed \n",
"193 llvm-master-build :windows: build and test windows windows passed \n",
"\n",
" exit_status agent_id \\\n",
"0 0 f20d42d3-31cb-4e46-a3d6-699877e7b283 \n",
"1 0 c9e48cee-e909-45b2-aa23-0d7335786499 \n",
"2 0 f20d42d3-31cb-4e46-a3d6-699877e7b283 \n",
"3 0 d4d0a0a4-255b-4fdd-8aba-abb00ba0bf34 \n",
"4 0 f20d42d3-31cb-4e46-a3d6-699877e7b283 \n",
".. ... ... \n",
"189 0 42f6f98d-15bd-4ad4-ac48-8626a752a154 \n",
"190 0 db5829eb-04bf-4700-9bec-423258de4a7d \n",
"191 0 42f6f98d-15bd-4ad4-ac48-8626a752a154 \n",
"192 0 db5829eb-04bf-4700-9bec-423258de4a7d \n",
"193 0 42f6f98d-15bd-4ad4-ac48-8626a752a154 \n",
"\n",
" agent_name runnable_at \\\n",
"0 premerge-debian-77f64f444-fm624-1 2020-07-27 18:10:16 \n",
"1 we32n1b 2020-07-27 18:15:47 \n",
"2 premerge-debian-77f64f444-fm624-1 2020-07-27 18:10:15 \n",
"3 we16c2b 2020-07-27 18:15:37 \n",
"4 premerge-debian-77f64f444-fm624-1 2020-07-27 18:10:14 \n",
".. ... ... \n",
"189 w16c2-1 2020-07-29 18:22:31 \n",
"190 premerge-debian-77f64f444-vxgx4-1 2020-07-29 18:21:47 \n",
"191 w16c2-1 2020-07-29 18:22:12 \n",
"192 premerge-debian-77f64f444-vxgx4-1 2020-07-29 18:21:45 \n",
"193 w16c2-1 2020-07-29 18:21:52 \n",
"\n",
" started_at wait_duration finished_at \\\n",
"0 2020-07-27 18:15:44.928 328.928 2020-07-27 18:15:47.797 \n",
"1 2020-07-28 01:36:57.687 26470.687 2020-07-28 02:26:08.750 \n",
"2 2020-07-27 18:15:34.989 319.989 2020-07-27 18:15:37.721 \n",
"3 2020-07-28 03:13:59.996 32302.996 2020-07-28 04:14:12.521 \n",
"4 2020-07-27 18:15:25.094 311.094 2020-07-27 18:15:27.918 \n",
".. ... ... ... \n",
"189 2020-07-29 20:23:50.686 7279.686 2020-07-29 21:23:50.271 \n",
"190 2020-07-29 18:22:09.243 22.243 2020-07-29 18:22:12.321 \n",
"191 2020-07-29 19:24:00.345 3708.345 2020-07-29 20:23:45.967 \n",
"192 2020-07-29 18:21:49.190 4.190 2020-07-29 18:21:52.862 \n",
"193 2020-07-29 18:21:54.857 2.857 2020-07-29 19:23:58.471 \n",
"\n",
" run_duration \n",
"0 2.869 \n",
"1 2951.063 \n",
"2 2.732 \n",
"3 3612.525 \n",
"4 2.824 \n",
".. ... \n",
"189 3599.585 \n",
"190 3.078 \n",
"191 3585.622 \n",
"192 3.672 \n",
"193 3723.614 \n",
"\n",
"[194 rows x 12 columns]"
]
},
"execution_count": 730,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"jobs"
]
},
{
"cell_type": "code",
"execution_count": 731,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/usr/local/google/home/goncharov/etc/merge-checks/venv/lib/python3.7/site-packages/ipykernel_launcher.py:1: UserWarning: Boolean Series key will be reindexed to match DataFrame index.\n",
" \"\"\"Entry point for launching an IPython kernel.\n"
]
}
],
"source": [
"ds = jobs[jobs['pipeline'] == 'llvm-master-build'][jobs['step_key'] == 'windows'][jobs['state']=='passed'][~jobs['agent_name'].str.startswith('buildkite-')][jobs['started_at'] > np.datetime64('2020-01-22')]\n",
"ds = ds.drop_duplicates()\n",
"# remove one slowest run (repo checkout)\n",
"# t = ds.loc[ds.groupby([\"agent_name\"])[\"run_duration\"].idxmax()]\n",
"# ds = pd.concat([ds, t]).drop_duplicates(keep=False)"
]
},
{
"cell_type": "code",
"execution_count": 732,
"metadata": {
"scrolled": false
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/usr/local/google/home/goncharov/etc/merge-checks/venv/lib/python3.7/site-packages/seaborn/categorical.py:2971: UserWarning: The `split` parameter has been renamed to `dodge`.\n",
" warnings.warn(msg, UserWarning)\n"
]
},
{
"data": {
"text/plain": [
"(0.0, 5877.15505)"
]
},
"execution_count": 732,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 720x720 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"fig, ax = plt.subplots(figsize=(10,10)) # size of the plot (width, height)\n",
"\n",
"sns.swarmplot(\n",
" ax=ax,\n",
" x='run_duration',\n",
" y='agent_name',\n",
" split=True,\n",
" data=ds)\n",
"\n",
"plt.xlim(0, None)"
]
},
{
"cell_type": "code",
"execution_count": 733,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead tr th {\n",
" text-align: left;\n",
" }\n",
"\n",
" .dataframe thead tr:last-of-type th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr>\n",
" <th></th>\n",
" <th>median</th>\n",
" <th>mean</th>\n",
" <th>std</th>\n",
" <th>count_nonzero</th>\n",
" </tr>\n",
" <tr>\n",
" <th></th>\n",
" <th>run_duration</th>\n",
" <th>run_duration</th>\n",
" <th>run_duration</th>\n",
" <th>run_duration</th>\n",
" </tr>\n",
" <tr>\n",
" <th>agent_name</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>we16n1a</th>\n",
" <td>4982.7380</td>\n",
" <td>5013.848800</td>\n",
" <td>396.926050</td>\n",
" <td>5.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>we16n1b</th>\n",
" <td>4692.7930</td>\n",
" <td>4707.102222</td>\n",
" <td>121.624149</td>\n",
" <td>9.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>w16n2-1</th>\n",
" <td>3846.2090</td>\n",
" <td>3881.809600</td>\n",
" <td>81.657742</td>\n",
" <td>5.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>we16c2a</th>\n",
" <td>3779.3110</td>\n",
" <td>3858.373400</td>\n",
" <td>183.822602</td>\n",
" <td>5.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>we16c2b</th>\n",
" <td>3593.5200</td>\n",
" <td>3615.016200</td>\n",
" <td>66.460005</td>\n",
" <td>10.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>w16c2-1</th>\n",
" <td>3585.6220</td>\n",
" <td>3612.092800</td>\n",
" <td>63.120688</td>\n",
" <td>5.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>we16n1c</th>\n",
" <td>3068.6440</td>\n",
" <td>3085.927100</td>\n",
" <td>1412.888086</td>\n",
" <td>10.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>we32n1b</th>\n",
" <td>2964.4520</td>\n",
" <td>2964.178300</td>\n",
" <td>59.215712</td>\n",
" <td>10.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>we32n1a</th>\n",
" <td>2880.9180</td>\n",
" <td>3031.068800</td>\n",
" <td>428.110568</td>\n",
" <td>5.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>we16c2c</th>\n",
" <td>2366.5155</td>\n",
" <td>2377.441900</td>\n",
" <td>1005.847826</td>\n",
" <td>10.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>we32n1c</th>\n",
" <td>2289.9605</td>\n",
" <td>2275.634700</td>\n",
" <td>629.386804</td>\n",
" <td>10.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>w64</th>\n",
" <td>2282.6860</td>\n",
" <td>2282.769800</td>\n",
" <td>33.481977</td>\n",
" <td>5.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" median mean std count_nonzero\n",
" run_duration run_duration run_duration run_duration\n",
"agent_name \n",
"we16n1a 4982.7380 5013.848800 396.926050 5.0\n",
"we16n1b 4692.7930 4707.102222 121.624149 9.0\n",
"w16n2-1 3846.2090 3881.809600 81.657742 5.0\n",
"we16c2a 3779.3110 3858.373400 183.822602 5.0\n",
"we16c2b 3593.5200 3615.016200 66.460005 10.0\n",
"w16c2-1 3585.6220 3612.092800 63.120688 5.0\n",
"we16n1c 3068.6440 3085.927100 1412.888086 10.0\n",
"we32n1b 2964.4520 2964.178300 59.215712 10.0\n",
"we32n1a 2880.9180 3031.068800 428.110568 5.0\n",
"we16c2c 2366.5155 2377.441900 1005.847826 10.0\n",
"we32n1c 2289.9605 2275.634700 629.386804 10.0\n",
"w64 2282.6860 2282.769800 33.481977 5.0"
]
},
"execution_count": 733,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"t = pd.pivot_table(ds, values=['run_duration'], index=['agent_name'],\n",
" aggfunc=[np.median, np.mean, np.std, np.count_nonzero])\n",
"t = t.reindex(t.sort_values(by=('median', 'run_duration'), ascending=False).index)\n",
"t"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```\n",
"// TODO: try with w64 w/o AV (temporary disabled)\n",
"w1 - 16 - non ssd 100 + ssd\n",
"w1a - 16 - non ssd 100 + ssd - AV (temp)\n",
"w4a - 16 - non ssd 100 + ssd - AV\n",
"w16-1 - 16 - non sdd 200 + ssd\n",
"w32-1 - 32 - non ssd 100 + ssd\n",
"w32-2 - 32 - non ssd 100 + ssd - AV\n",
"w32-2d - 32 - non ssd 200 + ssd\n",
"w64 - 64 - ssd 200 + ssd \n",
"w64a - 64 - ssd 200 + ssd - AV (temp)\n",
"wh63-3 - 64 low ram - non ssd 100 + ssd - AV\n",
"\n",
"buildkite-windows-16n1-exp\n",
"gcloud beta compute instances create \"${NAME}\" \\\n",
" --project=\"${GCP_PROJECT}\" \\\n",
" --zone=\"${GCP_ZONE}\" \\\n",
" --machine-type=n1-standard-16 \\\n",
" --local-ssd=device-name=local-ssd-0 \\\n",
" --image=windows-server-2019-dc-for-containers-v20200714 \\\n",
" --image-project=windows-cloud \\\n",
" --boot-disk-size=200GB --boot-disk-type=pd-ssd\n",
"\n",
"buildkite-32-experimental-1\n",
"gcloud beta compute instances create \"${NAME}\" \\\n",
" --project=\"${GCP_PROJECT}\" \\\n",
" --zone=\"${GCP_ZONE}\" \\\n",
" --machine-type=n1-standard-32 \\\n",
" --local-ssd=device-name=local-ssd-0 \\\n",
" --image=windows-server-2019-dc-for-containers-v20200714 \\\n",
" --image-project=windows-cloud \\\n",
" --boot-disk-size=200GB --boot-disk-type=pd-ssd\n",
"\n",
" \n",
"buildkite-16c2-exp\n",
"gcloud beta compute instances create \"${NAME}\" \\\n",
" --project=\"${GCP_PROJECT}\" \\\n",
" --zone=\"${GCP_ZONE}\" \\\n",
" --machine-type=c2-standard-16 \\\n",
" --local-ssd=device-name=local-ssd-0 \\\n",
" --local-ssd=interface=SCSI \\\n",
" --image=windows-server-2019-dc-for-containers-v20200714 \\\n",
" --image-project=windows-cloud \\\n",
" --boot-disk-size=200GB --boot-disk-type=pd-ssd\n",
" \n",
"...a: as is D:/ is a workdir (ealy run with full cache build)\n",
"...b: C:/ws as a workdir, no cache\n",
"```\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.5rc1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}