Skip to content

Instantly share code, notes, and snippets.

@rabernat
Created December 8, 2022 00:08
Show Gist options
  • Save rabernat/c7ca31ffac475ca84e470ddaa3014f59 to your computer and use it in GitHub Desktop.
Save rabernat/c7ca31ffac475ca84e470ddaa3014f59 to your computer and use it in GitHub Desktop.
S3 Listing Benchmarks
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"from glob import glob\n",
"from matplotlib import pyplot as plt"
]
},
{
"cell_type": "code",
"execution_count": 2,
"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>function</th>\n",
" <th>time</th>\n",
" <th>depth</th>\n",
" <th>leaves</th>\n",
" <th>root</th>\n",
" <th>size</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>create_tree</td>\n",
" <td>4.769455</td>\n",
" <td>10</td>\n",
" <td>2</td>\n",
" <td>tree/6dbe63b4cda84d95864c98181480acf5</td>\n",
" <td>1024</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>list_flat</td>\n",
" <td>0.317860</td>\n",
" <td>10</td>\n",
" <td>2</td>\n",
" <td>tree/6dbe63b4cda84d95864c98181480acf5</td>\n",
" <td>1024</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>list_recursive</td>\n",
" <td>3.941669</td>\n",
" <td>10</td>\n",
" <td>2</td>\n",
" <td>tree/6dbe63b4cda84d95864c98181480acf5</td>\n",
" <td>1024</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>list_flat</td>\n",
" <td>0.259197</td>\n",
" <td>10</td>\n",
" <td>2</td>\n",
" <td>tree/6dbe63b4cda84d95864c98181480acf5</td>\n",
" <td>1024</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>list_recursive</td>\n",
" <td>4.204455</td>\n",
" <td>10</td>\n",
" <td>2</td>\n",
" <td>tree/6dbe63b4cda84d95864c98181480acf5</td>\n",
" <td>1024</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",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>list_flat</td>\n",
" <td>10.345440</td>\n",
" <td>1</td>\n",
" <td>65536</td>\n",
" <td>tree/141ec6681fb0417a9a0a6ec088ad31f6</td>\n",
" <td>65536</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>list_recursive</td>\n",
" <td>9.836301</td>\n",
" <td>1</td>\n",
" <td>65536</td>\n",
" <td>tree/141ec6681fb0417a9a0a6ec088ad31f6</td>\n",
" <td>65536</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>list_flat</td>\n",
" <td>12.053110</td>\n",
" <td>1</td>\n",
" <td>65536</td>\n",
" <td>tree/141ec6681fb0417a9a0a6ec088ad31f6</td>\n",
" <td>65536</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>list_recursive</td>\n",
" <td>10.210790</td>\n",
" <td>1</td>\n",
" <td>65536</td>\n",
" <td>tree/141ec6681fb0417a9a0a6ec088ad31f6</td>\n",
" <td>65536</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>delete_tree</td>\n",
" <td>236.942297</td>\n",
" <td>1</td>\n",
" <td>65536</td>\n",
" <td>tree/141ec6681fb0417a9a0a6ec088ad31f6</td>\n",
" <td>65536</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>230 rows × 6 columns</p>\n",
"</div>"
],
"text/plain": [
" function time depth leaves \\\n",
"0 create_tree 4.769455 10 2 \n",
"1 list_flat 0.317860 10 2 \n",
"2 list_recursive 3.941669 10 2 \n",
"3 list_flat 0.259197 10 2 \n",
"4 list_recursive 4.204455 10 2 \n",
".. ... ... ... ... \n",
"5 list_flat 10.345440 1 65536 \n",
"6 list_recursive 9.836301 1 65536 \n",
"7 list_flat 12.053110 1 65536 \n",
"8 list_recursive 10.210790 1 65536 \n",
"9 delete_tree 236.942297 1 65536 \n",
"\n",
" root size \n",
"0 tree/6dbe63b4cda84d95864c98181480acf5 1024 \n",
"1 tree/6dbe63b4cda84d95864c98181480acf5 1024 \n",
"2 tree/6dbe63b4cda84d95864c98181480acf5 1024 \n",
"3 tree/6dbe63b4cda84d95864c98181480acf5 1024 \n",
"4 tree/6dbe63b4cda84d95864c98181480acf5 1024 \n",
".. ... ... \n",
"5 tree/141ec6681fb0417a9a0a6ec088ad31f6 65536 \n",
"6 tree/141ec6681fb0417a9a0a6ec088ad31f6 65536 \n",
"7 tree/141ec6681fb0417a9a0a6ec088ad31f6 65536 \n",
"8 tree/141ec6681fb0417a9a0a6ec088ad31f6 65536 \n",
"9 tree/141ec6681fb0417a9a0a6ec088ad31f6 65536 \n",
"\n",
"[230 rows x 6 columns]"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dfs = []\n",
"for fname in glob(\"s3_listing_results/*.json\"):\n",
" dfs.append(pd.read_json(fname))\n",
"\n",
"df = pd.concat(dfs)\n",
"df['size'] = df.leaves**df.depth\n",
"df"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<AxesSubplot:xlabel='size'>"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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PP3rX//S1q1btXfvXs2fP18BAQGKjY2VdOHOnq+++kqHDh3S8ePHb8gxb775Zi1dulQbN27Upk2b1LdvX1mtVrs2zjguAACSB505ud6J0VwlNDRUL7zwgpKTk1VUVKQGDRrok08+UcWKFSVJzz77rP72t7+pZs2aysvLk2EY133MV199VYMGDVKrVq1UqVIljRo1Sjk5OXZtnHFcAAAkNwonKSkpSklJKbOXEv4438gfL6H06tVLvXr1uux2t912mzZt2lTi44SGhl4SJAYOHKiBAwfaXlevXl1ffvmlXZukpKTrOi4AACXlNuHEU28lBoDiVB+9wuFt9vk7oRDACRhzUsYkJiaqfPnyxX49//zzri4PAICrcpszJyiZOXPm6Ny5c8WuCwsLK+VqAABwHOGkjKlataqrSwAA4LpwWQcAAJgK4QQAAJgK4QQAAJiK24STlJQU1atXTwkJCa4uBQAAOJHbhJOkpCRt27ZNGRkZri4FAAA4kduEk7Kuffv2GjFihKQLM7TOmDHDpfWYwb59+2SxWLRx40ZXlwIAKEUecyvx9jp1S+1YdXdsv67tMzIyFBQUVKK21atX14gRI2zBpiyJiYlRdna2KlWq5OpSAAClyGPCiTupXLlyqR2rqKhIFotFXl6lfxKtoKBAPj4+l13v7e2tiIiIUqwITjHRgcdNePlLjd52Xi0A3AKXdUzoz5d1Jk6cqGrVqsnPz09RUVEaPny4pAuXgvbv36/HH39cFotFFovlqvueN2+eQkND9emnn6pevXry8/PT/v37lZ+fr5EjR6pq1aoKCgpSixYt7B5GKEnr1q1Tu3btFBgYqJtuukldu3bV77//XmzNktS4cWNNnDjR9tpiseitt95Sz549FRQUpMmTJ+v3339Xv379VLlyZQUEBKhWrVqaO3euJPvLOlarVdHR0XrrrbfsjvHDDz/IYrFo7969kqRTp05p6NChqlKlikJCQtSxY0ceUAgAboZwYnKLFy/Wq6++qtmzZ2v37t1avny5GjRoIElaunSpoqOj9eyzzyo7O1vZ2dkl2ufZs2c1depUzZkzRz/99JOqVKmihx9+WOvWrdPChQu1efNm3XPPPbrzzju1e/duSdLGjRvVqVMn1a9fX998842+/vpr3X333Q4/JXrChAnq2bOntmzZokGDBmn8+PHatm2b/ve//2n79u168803i72M4+Xlpfvvv1///e9/7ZYvWLBALVu2VFxcnAzDUPfu3XXkyBGlpqYqMzNTTZs2VadOnfTbb785VCcAwHW4rGNyBw4cUEREhO644w75+PioWrVqat68uaQLz8rx9vZWcHCwQ5c/CgoKNGvWLDVq1EiStGfPHr3//vv65ZdfFBUVJUl68skn9dlnn2nu3Ll6/vnn9dJLLyk+Pl6zZs2y7ad+/foOv5++fftq0KBBdu+vSZMmio+Pl3ThDMzl9OvXT9OnT9f+/fsVGxsrq9WqhQsX6umnn5YkrV69Wlu2bNHRo0fl5+cnSXrllVe0fPlyLV68WEOHDnW4XgBA6ePMicndc889OnfunOLi4jRkyBAtW7ZMhYWF17VPX19fNWzY0Pb6hx9+kGEYql27tt1TjNesWaM9e/ZI+v9nTq7XxRBy0d///nctXLhQjRs31siRI7V+/frLbtukSRPVqVNH77//viRpzZo1Onr0qO69915JUmZmpnJzc1WxYkW795GVlWV7HwAA8+PMicnFxMRo586dSktL0+eff65hw4bp5Zdf1po1a644mPRKAgIC7ManWK1WeXt7KzMzU97e3nZty5cvb9vmSry8vGQYht2ygoKCS9r9+S6kxMRE7d+/XytWrNDnn3+uTp06KSkpSa+88kqxx+nXr58WLFig0aNHa8GCBeratavtMpDValVkZOQlY2UkKTQ09Ir1AwDMw23OnHjyDLEBAQHq0aOHXn/9daWnp+ubb77Rli1bJF04C+LouI8/a9KkiYqKinT06FHdfPPNdl8XLxc1bNhQX3zxxWX3UblyZbsxLzk5OcrKyirR8StXrqyBAwfqP//5j2bMmKG337783Rp9+/bVli1blJmZqcWLF6tfv362dU2bNtWRI0dUrly5S94HtyMDgPtwm3DiqTPEzps3T//617+0detW7d27V/Pnz1dAQIBiY2MlXRij8dVXX+nQoUM6fvz4NR2jdu3a6tevn/r376+lS5cqKytLGRkZevHFF5WamipJGjNmjDIyMjRs2DBt3rxZO3bs0Jtvvmk7ZseOHTV//nytXbtWW7du1YABAy45C1OcZ555Rh999JF+/vln/fTTT/r0009Vt+7l56SpUaOGWrVqpcGDB6uwsFA9e/a0rbvjjjvUsmVL9erVSytXrtS+ffu0fv16jRs3Ths2bLim7w0A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rVxYoWeIjIw0vvnmG8MwDOPEiROGxWIxPv/8c9v6L7/80oiLi3NVeaWGMyelxGKxSLowAvvP/zKvUaOGsrOzXVGWx1m+fLlmz56tv/71r3rkkUeUmZmp48eP6+6771ZeXp6k/99XcC4/Pz+777WXl5eKiopUWFgo6cLl0H379rmoOs+zZcsWPf744ypfvrxGjBihI0eO6JFHHrGtHzp0qH766ScXVugZfv/9d9sl/rCwMAUGBtrNv1SzZk2P+LwgnJSSgQMHqk+fPiooKND+/fvt1mVnZys0NNQ1hXmY48eP2/2iV6xYUWlpaTp9+rS6deums2fPurA6z3L77bfrmWee0ZkzZ1RQUKCnn35acXFxttmSjx07pptuusnFVXoOX19fnT9/XtKFO3WsVqvttSSdO3fOIwZiulqVKlXswsdjjz1mN4P477//7hE3UBBOSsGAAQNUpUoVVahQQT179lRubq7d+iVLlqhx48auKc7DxMTEXPKk2+DgYK1atUrnzp1T7969XVSZ53nllVe0ceNGhYaGKigoSPPmzdObb75pW799+3YNHDjQdQV6mNatW2v06NFat26dHn/8cTVt2lSTJ0/WmTNndPbsWT333HOKj493dZllXuPGje2eUv/CCy/YhZOvv/7aIx5Myt06JnDmzBl5e3vL39/f1aWUecOHD1d2dnaxT/Q8ffq0OnfurIyMDB5uVkrOnj2rr7/+Wvn5+brttttUqVIlV5fksXbv3q1u3bppz549qlevnlatWqW///3vtrtEbrrpJn322Wdq2rSpiyv1bBkZGQoICNCtt97q6lKcinACj/L777/r8OHDql+/frHrc3NzlZmZqXbt2pVyZYA5nDhxQhUrVrS9/uKLL3Tu3Dm1bNnSbjngTISTUnLu3DllZmYqLCzskmmgz58/rw8//FD9+/d3UXWAa5w5c0YLFizQ+vXrdeTIEVksFoWHh6t169Z64IEHPOLaOnA1GzdutE3a2bp1a48YtE84KQW7du1Sly5ddODAAVksFrVp00bvv/++bRKdX3/9VVFRUVxKKCV8IJrDtm3b1LlzZ509e1bt2rVTeHi4DMPQ0aNHtWbNGgUFBWnVqlU806UUGYahffv2KSYmRuXKlVN+fr6WLVumvLw8devWjctupaBv376aPXu2goODlZubq7/85S9KS0uTj4+PCgoK1KxZM6WlpZX5mygIJ6Wgd+/eKiws1Ny5c3Xy5EklJydr69atSk9PV7Vq1QgnpYgPRPPo0KGDIiIi9N5778nX19duXX5+vgYOHKjs7GytXr3aRRV6lp07d6pr1646ePCg4uLitGrVKt1zzz3asWOHDMNQYGCg1q9fz2MFnMzb21vZ2dmqUqWKnnrqKS1ZskSLFy9W06ZNtXXrVt1777268847NX36dFeX6lSEk1IQHh6uzz//3G7q56SkJH366adavXq1goKCCCelhA9E8wgMDNSGDRsuGwS3bt2q5s2bc3t3KenVq5cMw9DkyZP17rvvatWqVapVq5YWLVokwzB07733Kjg4WPPnz3d1qWWal5eXjhw5oipVqujWW2/VM888o3vvvde2PjU1VSNGjNCuXbtcWKXzlXN1AZ7g3LlzKlfO/ludkpIiLy8vtWvXTgsWLHBRZZ7nu+++04YNGy4JJtKFeR6efvppNW/e3AWVeZ6bbrpJu3fvvmw4+fnnn5nnpBStX79eq1atUoMGDTR58mS99tprmj17tm1uk1GjRun+++93cZWe4eKYkl9//fWSu3Lq16+vgwcPuqKsUkU4KQV16tTRhg0bVLduXbvlb7zxhgzDUI8ePVxUmefhA9E8hgwZogEDBmjcuHHq3LmzwsPDZbFYdOTIEaWlpen555/XiBEjXF2mx8jNzbXNpxEUFKSgoCC7h8tFR0fr119/dVV5HmX8+PEKDAy0nUX549+r48ePq3z58i6srnQQTkpB79699f777+uhhx66ZN3MmTNltVr11ltvuaAyz8MHonlMnDhRAQEBmj59ukaOHGn716JhGIqIiNDo0aM1cuRIF1fpOaKionTgwAHbE7lfeuklValSxbaeGXtLR9u2bbVz505JUr169ZSVlWW3PjU19bJTIZQljDmBx3nxxRf12muv2e7Ukf7/B+KIESP4QHSBrKwsHTlyRNKFMVpxcXEursjzPProo4qPj7d7ns4fvfDCC1q7dq1WrFhRypXhj/bu3StfX19FR0e7uhSnIpzAY/3xAzEiIuKSBzLCNXx9fbVp06ZLLoPCtbKysuTv7293qQdwFsIJ8AcHDx7UhAkT9O6777q6lDIvOTm52OWvvfaaHnzwQdtspGX9lkngSgoKCrRixQrbJGy9e/f2iLmYCCfAH2zatElNmzbltu5S4OXlpUaNGl0ymdSaNWsUHx+voKAgWSwWffnll64p0MP88ssv8vf3t020tnbtWr311ls6cOCAYmNjlZSUpJYtW7q4yrKvVatWSk1NVWhoqI4dO6ZOnTpp586dio2N1cGDB1WlShWtX79eVatWdXWpTkU4gUf5+OOPr7h+7969euKJJwgnpWDq1Kl65513NGfOHHXs2NG23MfHR5s2bWIivFLWqlUrjR8/XomJifroo4/Up08f3XXXXapbt6527dqlTz/9VEuXLtVdd93l6lLLtD/OczJ06FBlZGTof//7nyIiInTixAn16NFDderU0b/+9S9Xl+pUhBN4FC8vL1ksFl3px95isRBOSklGRoYefPBB3X333Zo6dap8fHwIJy4SEhKizZs3q3r16rrtttvUu3dvjRo1yrZ+5syZevfdd/XDDz+4sMqy74/h5JZbbtH06dPVvXt32/r09HQ9/PDDl9zFU9Z4uboAoDRFRkZqyZIlslqtxX7xh7d0JSQkKDMzU8eOHVN8fLy2bNniEQ81MyMvLy/l5ORIujD4NTEx0W59YmKi7RZXONfF34GTJ09eMlC/Ro0ays7OdkVZpYpwAo/SrFmzKwaQq51VwY1Xvnx5vffeexozZow6d+7MWSsXadeund5//31JUpMmTZSenm63fvXq1WV+nINZDBw4UH369FFBQYH2799vty47O7vMP/RPYhI2eJinnnpKZ86cuez6m2++mefquMj999+v22+/XZmZmYqNjXV1OR7nhRdeUJs2bXT48GHdfvvtGjt2rDIyMlS3bl3t3LlTH3zwAZNFloIBAwbY/r9nz57Kzc21W79kyRI1bty4lKsqfYw5AQBIkvbs2aNx48ZpxYoVtg/FcuXKKSEhQU899ZR69erl2gKhM2fOyNvbW/7+/q4uxakIJwAAO4Zh6OjRo7JarapUqZLt4X9AaWHMCQDAjsViUXh4uCIjI23B5ODBgxo0aJCLKyv7fvzxR7s7cf7zn/+odevWiomJ0e23366FCxe6sLrSQzgBAFzVb7/9pvfee8/VZZR5gwcP1r59+yRJc+bM0dChQxUfH6+xY8cqISFBQ4YM8YgZrBkQCwAo0QSFcL6dO3eqZs2akqRZs2ZpxowZGjp0qG19QkKCpkyZUubPYhFOAADq1atXiSYohHMFBATo2LFjqlatmg4dOqQWLVrYrW/RokWZn4BN4rIOAEBMUGgWiYmJevPNNyVdmHtm8eLFdus//PBD3Xzzza4orVRx5gQAYJug8HK3CzNBYel48cUX1bp1a7Vr107x8fGaNm2a0tPTbfPNfPvtt1q2bJmry3Q6wgkAgAkKTSIqKko//vijXnjhBX3yyScyDEPff/+9Dh48qNatW2vdunWKj493dZlOxzwnAADAVBhzAgAATIVwAgAATIVwAgAATIVwAsAlBg4cyIPkABSLAbEAXOLUqVMyDEOhoaGuLgWAyRBOAACAqXBZB4BTLV68WA0aNFBAQIAqVqyoO+64Q2fOnLG7rLNv3z5ZLJZLvtq3b2/bz/r169W2bVsFBAQoJiZGw4cPv+K8HADcF+EEgNNkZ2frgQce0KBBg7R9+3alp6erT58+l8w0GhMTo+zsbNvXjz/+qIoVK6pt27aSpC1btqhr167q06ePNm/erA8++EBff/21HnvsMVe8LQBOxmUdAE7zww8/qFmzZtq3b59iY2Pt1g0cOFAnT57U8uXL7ZafP39e7du3V+XKlfXRRx/Jy8tL/fv3V0BAgGbPnm1r9/XXX6tdu3Y6c+aM/P39S+PtACglTF8PwGkaNWqkTp06qUGDBuratau6dOmiv/71r7rpppsuu83gwYN1+vRppaWlycvrwsndzMxM/fzzz/rvf/9ra2cYhqxWq7KyslS3bl2nvxcApYdwAsBpvL29lZaWpvXr12vVqlV64403NHbsWH333XfFtp88ebI+++wzff/99woODrYtt1qt+tvf/qbhw4dfsk21atWcVj8A1+CyDoBSU1RUpNjYWCUnJ2vz5s12l3WWLFmiBx54QP/73//UqVMnu+369eunI0eO6IsvvnBB1QBKGwNiATjNd999p+eff14bNmzQgQMHtHTpUh07duySyzBbt25V//79NWrUKNWvX19HjhzRkSNH9Ntvv0mSRo0apW+++UZJSUnauHGjdu/erY8//lj/+Mc/XPG2ADgZ4QSA04SEhOirr75St27dVLt2bY0bN07Tpk1TYmKiXbsNGzbo7Nmzmjx5siIjI21fffr0kSQ1bNhQa9as0e7du9WmTRs1adJE48ePV2RkpCveFgAn47IOAAAwFc6cAAAAUyGcAAAAUyGcAAAAUyGcAAAAUyGcAAAAUyGcAAAAUyGcAAAAUyGcAAAAUyGcAAAAUyGcAAAAUyGcAAAAUyGcAAAAU/l/8HBqqYh9IX4AAAAASUVORK5CYII=",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"df.groupby(['size', 'function']).time.median().unstack().plot(kind='bar', grid=True, logy=True)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<AxesSubplot:xlabel='size'>"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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rfBaIpFAKpUCeHUGxN3dHVu2bCm1XskZjsrQ0NAote+ioiKlalHmzE15Smoo6315c9rrtZTMK+v9IyKiusczLiK3ePFi/P7774iPj5dPa9OmDU6ePKmwXHx8PFq1agVNTc1KbbdDhw64efMmLCws0KJFC4WvBg0aVLq+xo0bIzc3F3l5efJpb962/DYtW7aEvr6+/NLRm0qeePz62aQ3tWjRAjo6OgrvS1FRERITE+HkpDrXbomIqGIMLiLn4uKC4cOHY9WqVfJpX375JY4cOYL58+fjxo0b2Lx5M1avXo2pU6dWervDhw9Ho0aN8NFHH+HEiRNITU3F8ePHMXny5DI7BJfn3XffhYGBAb7++mvcunULkZGRSo+toqenh+nTp2PatGn4+eefkZKSgtOnT8v7plhYWEBfXx+HDh3CP//8g6dPn5bahqGhIT7//HN89dVXOHToEJKTkzFu3Djk5+djzJgxStVDRETCYXBRA/Pnz1e4lNGhQwfs2LED27Ztg7OzM2bPno158+YpXE56GwMDA8TFxcHOzg4DBgyAk5MTRo8ejefPn8PExATA/90+XN4t0gBgbm6OX3/9FVFRUXBxccHWrVsRFham9DHOmjULX375JWbPng0nJycMGTJE3gdGS0sLK1euxLp162BjY4OPPvqozG0sXrwYAwcORGBgIDp06IBbt24hOjoaZmZmStdDRETCkMjU7OJ9Tk4OGjRogKdPn8o/YEu8ePECqampaNasGfT09ASqsHKkUilycnJgYmKisk/2jYiIwLfffovk5ORSfVTUiRja4m3E9LNfkaKiIkRFRcHPz0+tf+bEgG2hOqraFsre4ux07erbF6qGij6/XyfOv8KkEg4dOoSFCxfyjxYREdUZ3lVEVbZt2zahSyAionqGZ1yIiIhINBhciIiISDQYXIiIiEg0GFyIiIhINBhciIiISDQYXIiIiEg0GFyIiIhINDiOCwCHGQfqdH9piz9Uep3s7Gw4OTnhzJkzcHBwqPK+vb290b59eyxfvrzK23hTREQEpkyZgidPngAAwsLCsG/fPqUfplhZ9+/fR2BgIOLj46GtrY0nT55AIpFg79696N+/f5W3W1BQgJYtW2Lv3r1wd3evuYKJiKjG8IyLSCxatAj+/v7VCi0AsGfPHsyfP79miirH1KlTy32S85vCwsLQvn17pbb/ww8/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tQkuHDmXiIhI/alNcCEiIiL1x+BCREREosHgQkRERKLB4EJERESiweBCREREosHgQkRERKLB4EJERESiweBCREREosHgQkRERKLB4EJERESiweBCREREoqE2wYUPWSQiIlJ/ahNc+JBFIiIi9ac2wYWIiIjUn5bQBVDFOkd2RgEKKrXsjlquhYiISGg840JERESiweBCREREosHgQkRERKLB4EJERESiweBCREREosG7iqj+CWug3PIaekC79bVTCxERKYVnXIiIiEg0GFyIiIhINBhciIiISDQYXIiIiEg0GFyIiIhINBhciIiISDQYXIiIiEg0OI4LiZ7DjANKLZ+mV0uFEBFRreMZFyIiIhINtQku4eHhaNOmDTp27Ch0KURERFRL1Ca4BAUFITk5GQkJCUKXQkRERLVEbYILERERqT8GFyIiIhINBhciIiISDQYXIiIiEg0GFyIiIhINBhciIiISDQYXIiIiEg0GFyIiIhINBhciIiISDQYXIiIiEg0GFyIiIhINBhciIiISDQYXIiIiEg0GFyIiIhINBhciIiISDQYXIiIiEg0GFyIiIhINLaELqDfCGii3vIYe0G597dRCREQkUjzjQkRERKLB4EJERESiweBCREREosHgQkRERKLBzrlV5DDjgFLLp+nVUiFERET1iEqecQkICICZmRkGDRokdClERESkQlQyuAQHB+Pnn38WugwiIiJSMSoZXHr06AFjY2OhyyAiIiIVo3RwiYuLg7+/P2xsbCCRSLBv375Sy6xZswbNmjWDnp4e3N3dceLEiZqolYiIiOo5pYNLXl4e2rVrh9WrV5c5f/v27ZgyZQpmzpyJ8+fPo2vXrvD19UV6erp8GXd3dzg7O5f6unfvXtWPhIiIiNSe0ncV+fr6wtfXt9z5y5Ytw5gxYzB27FgAwPLlyxEdHY21a9di0aJFAICzZ89WsdzSCgoKUFBQIH+dk5MDACgqKkJRUVGN7edNupoypZYv0lDutqKS5XWgU+l1inU1ldtHLb4/dUkd2gJQj/ZQti0A5dqDbVF5qtgWAP9OVVZ9bIvKbl8ik8mU/+kuWVkiwd69e9G/f38AQGFhIQwMDLBz504EBATIl5s8eTKSkpJw/PjxSm87NjYWq1evxq5duypcLiwsDHPnzi01PTIyEgYGBpXeHxEREQknPz8fw4YNw9OnT2Fi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evr0KWQyGUxNTYUuhYhUCIMLERERiQYvFRGRoHbt2gUXFxfo6+ujYcOGeP/995GXl6dwqSgtLQ0SiaTUl7e3t3w78fHx6NatG/T19WFra4vg4OAKxx0hInFicCEiwWRmZmLo0KEYPXo0rl69itjYWAwYMKDUCKy2trbIzMyUf50/fx4NGzZEt27dAACXLl2Cj48PBgwYgIsXL2L79u04efIkvvjiCyEOi4hqES8VEZFgzp07B3d3d6SlpcHe3l5h3qhRo/DkyRPs27dPYfqLFy/g7e2Nxo0b43//+x80NDQwYsQI6OvrY926dfLlTp48ie7duyMvLw96enp1cThEVAc45D8RCaZdu3bo1asXXFxc4OPjgz59+mDQoEEwMzMrd50xY8YgNzcXMTEx0NB4ddL47NmzuHXrFrZs2SJfTiaTQSqVIjU1FU5OTrV+LERUNxhciEgwmpqaiImJQXx8PA4fPoxVq1Zh5syZ+Ouvv8pcfsGCBTh06BDOnDkDY2Nj+XSpVIrPPvsMwcHBpdaxs7OrtfqJqO7xUhERqYzi4mLY29sjJCQEFy9eVLhUtHv3bgwdOhQHDx5Er169FNYbPnw47t+/jyNHjghQNRHVJXbOJSLB/PXXX1i4cCESExORnp6OPXv24MGDB6Uu7Vy+fBkjRozA9OnT0bZtW9y/fx/379/Ho0ePAADTp0/HqVOnEBQUhKSkJNy8eRO//fYbJk2aJMRhEVEtYnAhIsGYmJggLi4Ofn5+aNWqFb755hssXboUvr6+CsslJiYiPz8fCxYsgLW1tfxrwIABAABXV1ccP34cN2/eRNeuXeHm5oZZs2bB2tpaiMMiolrES0VEREQkGjzjQkRERKLB4EJERESiweBCREREosHgQkRERKLB4EJERESiweBCREREosHgQkRERKLB4EJERESiweBCREREosHgQkRERKLB4EJERESiweBCREREovH/ANez9LBbPriLAAAAAElFTkSuQmCC",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"df_list = df[(df.function == 'list_flat') | (df.function == 'list_recursive')]\n",
"df_list.groupby(['size', 'function']).time.aggregate([\"min\", \"max\"]).unstack().plot(kind='bar', grid=True, logy=True)\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1104"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_list.size"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Text(0, 0.5, 'Time (s)')"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAjoAAAHICAYAAABH+kBPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA0FElEQVR4nO3deVhV1f7H8c8GmQVxQkRRHFLDi0M5JJVZiQOaQ6PK72dqT1lR6rWy7GagNtpk17DhWtqt1LpOmdchNS21QdScoqwUlRTjWiKKoMDZvz/8eW6EAweBg+u8X8/D83j2Xnuv7z4bPR/XXmdvy7ZtWwAAAAbycncBAAAAFYWgAwAAjEXQAQAAxiLoAAAAYxF0AACAsQg6AADAWAQdAABgLIIOAAAwFkEHAAAYi6ADQJJ07NgxjRs3Tj169FDdunVlWZaSk5PP2b6goEAvv/yyYmJiFBAQoNDQUMXGxurLL790tsnNzdWgQYPUsmVLBQcHKygoSK1bt9ZTTz2l3NzcEvtcs2aN4uLiFBYWpurVq6tNmzb6+9//rqKionPWkZeXpxYtWsiyLL344osX9R6Ut+TkZFmW5e4yAI9Wzd0FAKgafvvtN7311ltq27atBgwYoBkzZpyzbVFRkQYOHKj169dr3Lhxio2NVW5urjZv3lwswBQUFMi2bY0dO1ZNmjSRl5eXvvjiC02aNElr167VqlWrnG1XrVqlnj17qmvXrvrHP/6hoKAgLV68WKNHj9bu3bv16quvnrWWCRMmnDU0AYBE0AHw/xo3bqwjR47IsiwdPnz4vEFn2rRpWrZsmTZs2KCrrrrKubxPnz7F2oWGhurDDz8stqx79+46efKkpkyZoj179qhp06aSpFmzZsnHx0dLlixRUFCQs+2uXbs0a9asswadjRs3atq0afrggw902223lfnYAZiLS1cAJEmWZZX6Msurr76qrl27Fgs5rqhbt64kqVq1//5fy8fHR76+vgoICCjWNjQ0VP7+/iX2cerUKY0YMUKJiYnq0KFDqfveu3ev8zLXyy+/rCZNmqh69erq0qWLvv766xLtFy9erC5duigwMFDBwcGKi4vTV199VaLdv//9b7Vr105+fn5q0qTJOS+j2bat6dOnq127dgoICFDNmjV16623as+ePcXaffvtt+rbt6/CwsLk5+eniIgI9enTR7/88kupjxUAQQeAizIyMrR3717FxMTo8ccfV7169VStWjW1bt1a77777lm3sW1bhYWFysnJ0fLly/XSSy9p8ODBatSokbPNvffeq1OnTmnUqFE6ePCgsrOz9d5772nhwoUaN25ciX1OmjRJubm5mjx5cpmOIyUlRStXrtTUqVP1wQcfKDc3V/Hx8Tp69KizzezZs9W/f3+FhIRozpw5evvtt3XkyBF169ZN69evd7ZbvXq1+vfvr+DgYM2dO1cvvPCCPvroI82cObNEvyNHjtSYMWPUvXt3LVq0SNOnT9d3332n2NhY/frrr5JOz22Ki4vTr7/+WqzORo0a6dixY2U6XsBj2QDwJ//5z39sSXZSUlKJdV999ZUtyQ4JCbGjo6Ptjz76yF6xYoV966232pLst956q8Q2c+bMsSU5f4YPH24XFBSUaLdhwwY7IiLC2c7b29ueMmVKiXbffvut7ePjYy9fvty2bdtOT0+3JdkvvPDCBY/tTNuYmBi7sLDQuXzjxo22JHvOnDm2bdt2UVGRHRERYcfExNhFRUXOdseOHbPDwsLs2NhY57LOnTvbERERdl5ennNZTk6OXatWLfuP/8yeee9eeumlYjVlZGTYAQEB9rhx42zbtu1NmzbZkuxFixZd8HgAnB9zdAC4xOFwSJLy8/O1dOlSNW7cWJIUFxenDh06aNKkSbr77ruLbdOzZ0+lpqbq2LFj+uqrr/T888/rt99+08KFC+XldXpgefPmzRo4cKA6d+6sN998U0FBQfrss8/0xBNPKD8/XxMmTJAkFRYWasSIEbrjjjvUs2fPMh9Hnz595O3t7Xzdpk0bSdK+ffskSbt27dLBgwc1ZswYZ42SVL16dd1yyy168803deLECdm2rdTUVN1///3FLrEFBwfrpptuKjbKtWTJElmWpf/5n/9RYWGhc3l4eLjatm2rtWvXSpKaN2+umjVr6tFHH1VmZqa6du2q6OjoMh8r4MkIOgBcUrt2bUlSq1atnCFHOj3Hp2fPnnr22WeVlZWlsLAw57qaNWs659Fcf/31atasmQYNGqSPP/5YAwcOlCQlJiaqXr16WrhwoTOAXH/99fLy8lJycrISEhLUtGlTTZ06VXv27NFHH32k7OxsSVJOTo6k0+ErOztbwcHBxULM+Y7jDD8/P0mnv64unf4WmiTVr1+/xLYRERFyOBw6cuSIbNuWw+FQeHh4iXZ/Xvbrr7/Ktm3Vq1fvrDWdmZhdo0YNff7553r66af1+OOP68iRI6pfv77uvvtuPfHEE/Lx8TnvsQH4L4IOAJc0a9ZMgYGBZ11n27YkFRsBOZtOnTpJkn788Ufnsq1bt2rw4MElAkrHjh3lcDj0/fffq2nTptq5c6eOHj2qyy67rMR+J0yYoAkTJujbb79Vu3btXDmsEs4EoczMzBLrDh48KC8vL9WsWVO2bcuyLB06dKhEuz8vq1OnjizL0rp165zB6o/+uCwmJkZz586Vbdvavn27Zs2apUmTJikgIECPPfbYRR0b4EmYjAzAJdWqVVP//v31/fffa+/evc7ltm1r+fLlatasmerUqXPefaxZs0bS6Us0Z0RERGjTpk0lbg545htODRs2lCQ99thjWrNmTbGfOXPmSDo9oXnNmjXF9ltWLVu2VIMGDTR79mxngJNOTxSeP3++85tYQUFB6tSpkxYsWKD8/Hxnu2PHjumTTz4pts++ffvKtm0dOHBAHTp0KPETExNTog7LstS2bVu98sorCg0N1ZYtWy762ABPwogOAKdly5YpNzfX+c2etLQ0zZs3T5IUHx/vHMmZPHmyli1bpl69eik5OVkhISGaMWOGtm3bpo8++si5vzfffFPr1q1Tjx49FBkZqdzcXK1bt07Tpk1TbGys+vfv72z717/+VaNGjdJNN92kkSNHKjAwUKtXr9ZLL72k7t27q23btpJOXzJr1apVsbrPBK5mzZqpW7du5fJeeHl5acqUKUpISFDfvn01cuRInTx5Ui+88IKys7P13HPPOdtOnjxZvXr1UlxcnB566CEVFRXp+eefV1BQkH7//Xdnu6uvvlr33HOPhg8frk2bNqlr164KCgpSZmam1q9fr5iYGN13331asmSJpk+frgEDBqhp06aybVsLFixQdna24uLiyuX4AI/hrlnQAKqexo0bF/t21B9/0tPTi7XdsWOH3adPHzs4ONj29/e3r7rqKvuTTz4p1mbDhg1237597YiICNvX19cODAy027Zta0+ePNnOzc0t0f/8+fPta665xq5Tp44dFBRkt27d2p48ebJ9/Pjx89Zdlm9dna2tzvJNs0WLFtmdO3e2/f397aCgIPvGG2+0N2zYUGLbxYsX223atLF9fX3tRo0a2c8995ydlJRkn+2f2Xfeecfu3LmzHRQUZAcE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nuzWrZvatWunqVOnKioqSmPGjNGYMWMqprZLxN69e9WkSRN9++23ateunbvLAQBUEo8MOp4kNTVVQUFBpWprciiKjIxUZmam6tSp4+5SAACViKBjuLp161ZaX0VFRbIsyy3PzyooKDjvc328vb0VHh5eiRUBAKoCj5yj40mioqI0depU5+vk5GRFRUWpXr16atiwoUaNGiXp9OWuffv26a9//assy5JlWRfc96xZsxQaGqolS5YoOjpafn5+2rdvn06dOqVx48apQYMGCgoKUufOnbV27dpi227YsEHXXXedAgMDVbNmTfXs2VNHjhw5a82S1K5dOyUnJztfW5alN954Q/3791dQUJCeeuopHTlyRAkJCapbt64CAgJ02WWXaebMmZJOX7qyLEtbt26Vw+FQw4YN9cYbbxTrY8uWLbIsS3v27JEkHT16VPfcc4/CwsIUEhKiG264Qdu2bSvN2w4AqCIIOh5k3rx5euWVV/T6669r06ZNWrBggWJiYiRJCxYsUMOGDTVp0iRlZmYqMzOzVPs8ceKEnn32Wc2YMUPfffedwsLCNHz4cG3YsEFz587V9u3bddttt6lXr1766aefJElbt27VjTfeqNatW+urr77S+vXrddNNN6moqMil40lKSlL//v21Y8cOjRgxQhMmTFBaWpqWLVum77//Xq+//vpZL1V5eXlp0KBB+uCDD4otnz17trp06aKmTZvKtm316dNHhw4d0tKlS7V582ZdccUVuvHGG/X777+7VCcAwH24dOVB9u/fr/DwcHXv3l15eXkKCQnRVVddJen0s6u8vb0VHBzs0iWegoICTZ8+XW3btpUk7d69W3PmzNEvv/yiiIgISdLDDz+s5cuXa+bMmXrmmWc0ZcoUdejQQdOnT3fup3Xr1i4fz5AhQzRixIhix9e+fXt16NBB0umRoXNJSEjQyy+/rH379qlx48ZyOByaO3euHn/8cUnSmjVrtGPHDmVlZcnPz0+S9OKLL2rRokWaN2+e7rnnHpfrBQBUPkZ0PMhtt92mvLw8NW/eXKNHj9bChQtVWFh4Ufv09fVVmzZtnK+3bNki27bVokWLYk87//zzz7V7925J/x3RuVhnAs0Z9913n+bOnat27dpp3Lhx+vLLL8+5bfv27dWqVSvNmTNHkvT5558rKytLt99+uyRp8+bNOn78uGrXrl3sONLT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Lj8/X//85z/dUBUqwoMPPqh169a5uwxUAU2bNtVPP/3k7jKqJG4YCG3btk1XXHGFioqK3F0KLtKPP/6oHj16aP/+/bIsS9dee63mzJmj+vXrS5J+/fVXRUREcK4N4eXlJcuy1KxZM91111268847FR4e7u6yUIH+/ve/n3X52LFjNW7cOOf5HzVqVGWWVaURdDzA4sWLz7t+z549euihh/jwM8DAgQNVWFiomTNnKjs7W2PHjtXOnTu1du1aNWrUiKBjGC8vL61cuVKffPKJPvjgAx09elS9e/fW3Xffrfj4eHl5MWhvGi8vLzVo0EDVqlUrtnzfvn2KiIiQj4+PLMvSnj173FRh1UPQ8QBn/td3vlNtWRYffgaoV6+eVq1apZiYGOeyxMRELVmyRGvWrFFQUBBBxyBeXl46dOiQwsLCVFBQoIULF+qdd97RqlWrVK9ePQ0bNkzDhw9X8+bN3V0qysnIkSO1ceNGzZ49W5dffrlzuY+Pj7Zt26bo6Gg3Vlc1Efc9QP369TV//nw5HI6z/mzZssXdJaKc5OXllfifXkpKivr166frrrtOP/74o5sqQ0Xz8fHR7bffruXLl2vPnj26++679cEHH6hly5buLg3l6M0331RSUpJ69uyp1157zd3lXBIIOh7gyiuvPG+YudBoDy4drVq10qZNm0osnzZtmvr3769+/fq5oSpUtkaNGik5OVnp6elavny5u8tBORswYIC++uorLVy4UL1799ahQ4fcXVKVRtDxAI888ohiY2PPub558+Zas2ZNJVaEijJw4EDNmTPnrOtee+01DR48mFBrkMaNG8vb2/uc6y3LUlxcXCVWhMrSoEEDrVq1Sl27dlX79u35e30ezNEBAOAStnnzZq1fv15Dhw5VzZo13V1OlUPQAQDAEBkZGUpKStI777zj7lKqDIIOAACG4L5oJVW7cBMAAFAVlOa+aCiOER0AAC4R3BfNdXzrCgCASwT3RXMdQQcAgEsE90VzHXN0AAC4RDzyyCPKzc0953rui1YSc3QAAICxuHQFAACMRdABAADGIugAAABjEXQAAICxCDoALgndunXTmDFjKrwfy7K0aNGiCu8HQOUg6ADwSMnJyWrXrp27ywBQwQg6AADAWAQdAFVObm6uhg4dqurVq6t+/fp66aWXiq0/deqUxo0bpwYNGigoKEidO3fW2rVrnetnzZql0NBQLVq0SC1atJC/v7/i4uKUkZHhXD9x4kRt27ZNlmXJsizNmjXLuf3hw4c1cOBABQYG6rLLLrvggxQBVF0EHQBVziOPPKI1a9Zo4cKF+vTTT7V27Vpt3rzZuX748OHasGGD5s6dq+3bt+u2225Tr1699NNPPznbnDhxQk8//bTeffddbdiwQTk5ORo0aJAk6Y477tBDDz2k1q1bKzMzU5mZmbrjjjuc206cOFG33367tm/frvj4eCUkJOj333+vvDcAQPmxAaAKOXbsmO3r62vPnTvXuey3336zAwIC7NGjR9s///yzbVmWfeDAgWLb3Xjjjfb48eNt27btmTNn2pLsr7/+2rn++++/tyXZ33zzjW3btp2UlGS3bdu2RP+S7CeeeML5+vjx47ZlWfayZcvK8zABVBKedQWgStm9e7dOnTqlLl26OJfVqlVLLVu2lCRt2bJFtm2rRYsWxbY7efKkateu7XxdrVo1dejQwfm6VatWCg0N1ffff69OnTqdt4Y2bdo4/xwUFKTg4GBlZWVd1HEBcA+CDoAqxb7A4/ccDoe8vb21efNmeXt7F1tXvXr1Yq8tyyqx/dmW/ZmPj0+JbRwOxwW3A1D1MEcHQJXSvHlz+fj46Ouvv3YuO3LkiH788UdJUvv27VVUVKSsrCw1b9682E94eLhzm8LCQm3atMn5eteuXcrOzlarVq0kSb6+vioqKqqkowLgLgQdAFVK9erVddddd+mRRx7R6tWrtXPnTg0bNkxeXqf/uWrRooUSEhI0dOhQLViwQOnp6UpNTdXzzz+vpUuXOvfj4+OjBx98UN988422bNmi4cOH66qrrnJetoqKilJ6erq2bt2qw4cP6+TJk245XgAVi6ADoMp54YUX1LVrV/Xr10/du3fXNddcoyuvvNK5fubMmRo6dKgeeughtWzZUv369dM333yjyMhIZ5vAwEA9+uijGjJkiLp06aKAgADNnTvXuf6WW25Rr169dP3116tu3bqaM2dOpR4jgMph2Re6IA4Al5hZs2ZpzJgxys7OdncpANyMER0AAGAsgg4AADAWl64AAICxGNEBAADGIugAAABjEXQAAICxCDoAAMBYBB0AAGAsgg4AADAWQQcAABiLoAMAAIz1f1eOYbxmZ8zhAAAAAElFTkSuQmCC",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"res = df_list[df_list[\"size\"] == 16384].groupby(['depth', 'function']).time.aggregate(['median', 'std']).unstack()\n",
"ax = plt.subplot()\n",
"res.plot(kind='bar', y='median', yerr='std', grid=True, logy=True, ax=ax)\n",
"ax.set_title(\"16384 nodes\")\n",
"ax.set_ylabel(\"Time (s)\")"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Text(0, 0.5, 'Time (s)')"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAjoAAAHICAYAAABH+kBPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA5p0lEQVR4nO3dd3wVVf7/8fckpJPQIYQuVdgEkCa9VyniKrqwIsIuKrEgKmV1DUUFRTHf1QDrooD8BNwvIrKYlSZNbAm9iUiNEMxSQ24IhNzz+4Mvd42BkITc3DD39Xw88nhwZ87MfG5OkvvmzJkZyxhjBAAAYEM+ni4AAADAXQg6AADAtgg6AADAtgg6AADAtgg6AADAtgg6AADAtgg6AADAtgg6AADAtgg6AADAtgg6ALL56quv1KdPH5UpU0ZBQUGqW7eupkyZkq3NsGHDZFlWjq8GDRrk2N/12lmWpWnTpmVrt2bNGnXv3l0REREKCAhQxYoV1aVLF8XHx1+3TofDoZdffln16tVTQECAypUrp86dO+vAgQOF9824RRMnTpRlWZ4uA/BqJTxdAIDiY+HChXr44Yc1aNAgffjhhypZsqQOHjyoEydO5GgbFBSkL7/8Msey67n//vv13HPPZVtWvXr1bK9Pnz6tRo0a6U9/+pPCw8N15swZzZ49W/fcc48WLFigP/7xj662aWlp6ty5s06cOKHx48crKipK58+f19dff6309PSCvn0ANkTQASBJOn78uEaOHKnHHntMM2fOdC3v3Lnzddv7+Pjo7rvvztO+K1WqdNO2Dz74oB588MFsy/r27atatWrpvffeyxZ0XnrpJe3bt087d+7UHXfc4Vrev3//PNUDwHtw6gqAJGnOnDlyOBwaN26cp0tx8fPzU+nSpVWixH//T5aenq45c+bogQceyBZy8urIkSOyLEtvvvmmZsyYoVq1aqlkyZJq3bq1vv322xztly9frtatWys4OFihoaHq3r27vvnmmxztPv/8czVp0kQBAQGqVauW3nzzzese3xijmTNnqkmTJgoKClKZMmV0//3369ChQ9nabdu2TX379lXFihUVEBCgiIgI3XPPPfr555/z/Z4Bb0bQASBJ2rhxo8qWLasffvhBTZo0UYkSJVSxYkU9/vjjSk1NzdH+4sWLCg8Pl6+vr6pWraonn3xSZ86cue6+Fy5cqKCgIAUEBKhZs2aaO3fuDetwOp26cuWKTpw4oZiYGP3444/ZTntt2bJFDodDdevW1RNPPKEyZcrI399fzZs31+eff57n9xsXF6fVq1crNjZWH330kRwOh/r06aPz589nq3vAgAEKCwvTokWL9P777+vs2bPq1KmTvvrqK1e7tWvXasCAAQoNDdXixYs1ffp0/fOf/7zu+3zsscc0evRodevWTcuWLdPMmTO1Z88etWnTRr/88oukq/OPunfvrl9++SVbndWrV9eFCxfy/B4BSDIAYIypX7++CQwMNKGhoea1114z69atM2+88YYJCgoybdu2NU6n09V2xowZZsaMGWbVqlVm1apV5sUXXzTBwcGmQYMG5sKFC9n2O3jwYPPRRx+ZjRs3miVLlpjevXsbSeall166bh09e/Y0kowkExYWZpYuXZpt/aJFi1zr2rZta5YvX25WrFhhOnfubCzLMl988UWu7/Pw4cNGkomMjDRXrlxxLf/++++NJLNo0SJjjDFZWVkmIiLCREZGmqysLFe7CxcumIoVK5o2bdq4lrVq1cpERESYixcvupalpqaasmXLml//mf3mm2+MJPPWW29lqykpKckEBQWZsWPHGmOMSUxMNJLMsmXLcn0vAG6OoAPAGGNM3bp1jSQzderUbMtjY2ONJLN69epct1+yZImRZGbMmHHTY/Xt29eUKFHCpKSk5Fj3448/mu+//9589tln5oEHHjB+fn5m4cKFrvUfffSRkWTKly9vUlNTXcsdDoeJiIgwbdu2zfXY14LO+PHjsy3PyMgwksy0adOMMcbs3bvXSDJvvPFGjn088cQTxsfHxzgcDpOWlmZ8fHzMk08+maPdI488ki3ovPjii8ayLPPLL7+YzMzMbF933323admypTHGmHPnzpkyZcqY+vXrm1mzZpk9e/bk+p4A3BinrgBIksqVKydJ6tmzZ7blvXv3liRt3bo11+0HDhyokJCQ685z+a0//vGPunLlihITE3Osq1u3rlq0aKH+/fvrn//8p7p27aro6Gg5nc5sdbZp00ahoaGu7YKDg9WxY8eb1nnNtf1cExAQIOnqKTnp6lVgklS5cuUc20ZERMjpdOrs2bM6e/asnE6nwsPDc7T77bJffvlFxhhVqlRJfn5+2b6+/fZbnTp1SpJUqlQpbdiwQU2aNNFf/vIXNWrUSBEREYqJiVFm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6lv7xgAAvBqnrmyiVKlSCg0NLdBpo2HDhukPf/iDJOm1117TO++8o++//169evVSXFycSpUqpcWLF7vu9FuvXj3XtkFBQbp06VKux5w5c6aqVaumd999V5ZlqUGDBjpx4oTGjRunl19+2XU356ioKMXExEiS6tatq3fffVdr165V9+7d8/V+AAC4hhEdKCoqyvXvkJAQhYaGKiUlRZK0fft2tW/f/pYeZ7Bv3z61bt06280X27Ztq7S0NP3888/XrUOSKleu7KoDAICCYETHxnx8fHLcoffaoy1+7bchxrIsOZ1OSVdHbG6VMSbHHaav1fXr5bnVAQAoZFOrSs6M3Ntc/tVnyKuVJf98PC1g4vmC1VXIGNGxsQoVKig5Odn1OjU1VYcPH87XPqKiorRp06brBiRJ8vf3V1ZWVq77aNiwob7++utsoevrr79WaGioqlSpkq96AADID4KOjXXp0kULFizQpk2btHv3bj3yyCPy9fXN1z6efPJJpaam6qGHHlJiYqIOHDigBQsWaP/+/ZKkmjVraufOndq/f79OnTp13UA0atQoJSUl6amnntIPP/ygzz77TDExMRozZgxPWwcAuBWfMjY2YcIEdejQQX379lWfPn107733qnbt2vnaR7ly5fTll18qLS1NHTt2VLNmzfSPf/zDdZrpz3/+s+rXr6/mzZurQoUK2rx5c459VKlSRfHx8fr+++/VuHFjPf744xoxYoReeumlQnmfAADciGW8+DHLqampKlWqlM6fP6+wsLBs6zIyMnT48GHVqlVLgYGBHqowb5xOp1JTUxUWFsYIiYelp6dr3759qlevnkJDQz1djlfLzMxUfHy8+vTpc0uT6VE46I/iw9UXO0bK72ZzdG6FG+fo5Pb5/Vt8KgIAANsi6AAAANsi6AAAANsi6AAAANsi6AAAANsi6AAAANsi6AAAANsi6AAAANsi6AAAANvi6eUFUHP850V6vCPT7slX+06dOqlJkyaKjY1VzZo1NXr0aI0ePdottS1btkzPP/+8Dh8+rKeeekpNmjTR6NGjde7cObccDwCA/GBEx+YSEhI0cuTIPLWtWbOmYmNj87X/xx57TPfff7+SkpI0ZcqUAlRYsOMCAJAXjOjYXIUKFdy277S0NKWkpKhnz56KiIhw23EAACgoRnRs7rejJRMnTlT16tUVEBCgiIgIPf30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CAAAUFAFCjrp6ekKDQ2VJK1atUr33XeffHx8dPfdd+vo0aOFWiAAAEBBFSjo1KlTR8uWLVNSUpJWrlypHj16SJJSUlIUFhZWqAUCAAAUVIGCzssvv6znn39eNWvWVKtWrdS6dWtJV0d3mjZtWqgFAgAAFFSBHgFx//33q127dkpOTlbjxo1dy7t27aqBAwcWWnEAAAC3osDPugoPD1d4eHi2ZS1btrzlggAAAApLnk9dPf7440pKSspT248//lgfffRRgYsCAAAoDHke0alQoYJ+97vfqU2bNurfv7+aN2+uiIgIBQYG6uzZs9q7d6+++uorLV68WFWqVNF7773nzroBAABuKs9BZ8qUKXrqqaf0/vvva/bs2dq9e3e29aGhoerWrZvmzJnjugoLAADAk/I1R6dixYqaMGGCJkyYoHPnzuno0aO6ePGiypcvr9q1a8uyLHfVCQAAkG8FnoxcunRplS5duhBLAQAAKFwFuo8OAADA7YCgAwAAbIugAwAAbIugAwAAbKvAQefKlStas2aN/v73v+vChQuSpBMnTigtLa3QigMAALgVBbrq6ujRo+rVq5eOHTumS5cuqXv37goNDdUbb7yhjIwMzZ49u7DrBAAAyLcCjeg888wzat68uc6ePaugoCDX8oEDB2rt2rWFVhwAAMCtKNCIzldffaXNmzfL398/2/IaNWro+PHjhVIYAADArSrQiI7T6VRWVlaO5T///LNCQ0NvuSgAAIDCUKCg0717d8XGxrpeW5altLQ0xcTEqE+fPoVVGwAAwC0p0Kmrt99+W507d1bDhg2VkZGhwYMH68CBAypfvrwWLVpU2DUCAAAUSIGCTkREhLZv365FixZp69atcjqdGjFihIYMGZJtcjIAAIAnFfihnkFBQRo+fLiGDx9emPUUibi4OMXFxV13nhEAALCPAged48ePa/PmzUpJSZHT6cy27umnn77lwtwpOjpa0dHRSk1NValSpTxdDgAAcJMCBZ25c+fq8ccfl7+/v8qVKyfLslzrLMsq9kEHAAB4hwIFnZdfflkvv/yyJkyYIB8fHpcFAACKpwKllPT0dD300EOEHAAAUKwVKKmMGDFC//u//1vYtQAAABSqAp26mjp1qvr27asvvvhCkZGR8vPzy7Z+xowZhVIcAADArShQ0Hnttde0cuVK1a9fX5JyTEYGAAAoDgoUdGbMmKEPPvhAw4YNK+RyAAAACk+B5ugEBASobdu2hV0LAABAoSpQ0HnmmWf0zjvvFHYtAAAAhapAp66+//57ffnll1qxYoUaNWqUYzLy0qVLC6U4AACAW1GgoFO6dGndd999hV0LAABAoSrwIyAAAACKO25tDAAAbCvPIzp33XWX1q5dqzJlyqhp06a53i9n69athVIcAADArchz0BkwYIACAgIkSffee6+76gEAACg0eQ46MTExGj58uP7nf/5HMTEx7qwJAACgUORrjs78+fN18eJFd9UCAABQqPIVdIwx7qoDAACg0OX7qise2gkAAG4X+b6PTr169W4ads6cOVPgggAAAApLvoPOpEmTVKpUKXfUAgAAUKjyHXQeeughVaxY0R21AAAAFKp8zdFhfg4AALidcNUVAACwrXydunI6ne6qAwAAoNDxUE8AAGBbBB0AAGBbBB0AAGBbBB0AAGBbBB0AAGBbBB0AAGBbBB0AAGBbBB0AAGBbBB0AAGBbBB0AAGBbBB0AAGBbXhl04uLi1LBhQ7Vo0cLTpQAAADfyyqATHR2tvXv3KiEhwdOlAAAAN/LKoAMAALwDQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAANgWQQcAJDkcDlmWJcuy5HA4PF0OgEJC0AEAALZF0AEAALZF0AEAALZF0AEAALZF0AEAALZF0AEAALZF0AEAALZF0AEAALZF0AEAALZF0AEAALZF0AEAALZF0AEAALZVwtMFAIBbTa0qOTNu3u6y+e+/X60s+Vt52//E8wWrC0CRYEQHAADYFkEHAADYFkEHAADYFkEHAADYFkEHAADYFkEHAADYFkEHAADYFkEHAADYFkEHAADYFkEHAADYFkEHAADYFkEHAADYFkEHAADYFkGnmHE4HLIsS5ZlyeFweLocAABuayU8XQAAFAch/pZMTJinywBQyBjRAQAAtkXQAQAAtkXQAQAAtkXQAQAAtkXQAQAAtmWLq64GDhyo9evXq2vXrlqyZImny8mh5vjP89zWeTnD9e87//qF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BAQoJiZGAQEBni7F69EXxQd9UbzQH8WHt/WFV09GBgAA9saIDgAAsC2CDgAAsC2CDgAAsC2CDgAAsC2CDgAAsC2CDgDb4qJSAAQdALYVEBCgffv2eboMAB7k1c+6sqOkpCTFxMTogw8+8HQpXuHixYvasmWLypYtq4YNG2Zbl5GRoX/+858aOnSoh6rzHmPGjLnu8qysLE2bNk3lypWTJM2YMaMoy/Jq77zzjhITE3XPPfdo0KBBWrBggaZOnSqn06n77rtPkydPVokSfAS5288//6zAwECVL19ekrRp0ybNnj1bx44dU40aNRQdHa3WrVt7uEr3YkTHZs6cOaP58+d7ugyv8OOPP+rOO+9Uhw4dFBkZqU6dOik5Odm1/vz583r00Uc9WKH3iI2N1bp167Rt27ZsX8YY7du3T9u2bdP27ds9XabXmDJlil588UU5HA4988wzev311/Xss89qyJAheuSRRzRnzhxNmTLF02V6hUGDBikhIUGS9Nlnn6lTp05KS0tT27ZtlZ6ero4dO2rFihUertK9uDPybWb58uW5rj906JCee+45ZWVlFVFF3mvgwIG6cuWK5s6dq3PnzmnMmDHavXu31q9fr+rVq+uXX35RREQEfVEEpk6dqn/84x+aM2eOunTp4lru5+enHTt25Bhtg3vVrl1b06dP13333acdO3aoWbNmmj9/voYMGSJJ+vTTTzV27FgdOHDAw5XaX1hYmHbu3KmaNWvq7rvv1sCBAzVu3DjX+nfffVcffPCBtm7d6sEq3Yugc5vx8fGRZVm5TrK0LIsP1yJQqVIlrVmzRpGRka5l0dHRWrFihdatW6eQkBCCThFKSEjQH//4R/Xr109Tp06Vn58fQcdDgoOD9cMPP6h69eqSJH9/f23btk2NGjWSJB09elQNGzaUw+HwZJleoXTp0tq4caOioqJUqVIlrV69WlFRUa71Bw8eVFRUlK37glNXt5nKlSvrk08+kdPpvO6XnVN5cXPx4sUccwzi4uLUv39/dezYUT/++KOHKvNOLVq00JYtW/Sf//xHzZs3165du2RZlqfL8krh4eHau3evJOnAgQPKyspyvZakPXv2qGLFip4qz6t07NhRixYtkiQ1bdpU69evz7Z+3bp1qlKligcqKzrMBLvNNGvWTFu3btW999573fU3G+1B4WnQoIESExN15513Zlv+zjvvyBij/v37e6gy71WyZEnNnz9fixcvVvfu3RlN85DBgwdr6NChGjBggNauXatx48bp+eef1+nTp2VZll599VXdf//9ni7TK0ybNk3t27fXiRMn1K5dO7344otKSEjQnXfeqf379+vjjz/W7NmzPV2mW3Hq6jazadMmORwO9erV67rrHQ6HEhMT1bFjxyKuzPtMnTpVmzZtUnx8/HXXjxo1SrNnz5bT6SziyiBdvdpky5Yt6tatm0JCQjxdjle5drXbt99+q3bt2mncuHFavHixxo4dq/T0dPXr10/vvvsu/VJEDh48qJdeekmff/650tLSJEklSpRQixYt9MILL9zwP852QdABAMALGGOUkpIip9Op8uXLy8/Pz9MlFQnm6AAA4AUsy1KlSpVUuXJlV8hJSkrS8OHDPVyZezGiAwCAl9qxY4fuuusuW89nYzIyAAA2lZd7r9kdIzoAANgU915jjg4AALbFvdcIOgAA2Na1e6/diDfce405OgAA2NQLL7yQ6+Md6tSpo3Xr1hVhRUWPOToAAMC2OHUFAABsi6ADAABsi6ADAABsi6ADAABsi6AD4LbQqVMnjR492u3HsSxLy5Ytc/txABQNgg4ArzRx4kQ1adLE02UAcDOCDgAAsC2CDoBix+FwaOjQoSpZsqQqV66st956K9v6y5cva+zYsapSpYpCQkLUqlUrrV+/3rV+3rx5Kl26tJYtW6Z69eopMDBQ3bt3V1JSkmv9pEmTtGPHDlmWJcuyNG/ePNf2p06d0sCBAxUcHKy6deve9MGIAIovgg6AYueFF17QunXr9Omnn2rVqlVav369tmzZ4lr/6KOPavPmzVq8eLF27typBx54QL169dKBAwdcbdLT0/Xqq69q/vz52rx5s1JTU/XQQw9Jkh588EE999xzatSokZKTk5WcnKwHH3zQte2kSZM0aNAg7dy5U3369NGQIUN05syZovsGACg8BgCKkQsXLhh/f3+zePFi17LTp0+boKAg88wzz5iffvrJWJZljh8/nm27rl27mgkTJhhjjJk7d66RZL799lvX+n379hlJ5rvvvjPGGBMTE2MaN26c4/iSzEsvveR6nZaWZizLMv/+978L820CKCI86wpAsXLw4EFdvnxZrVu3di0rW7as6tevL0naunWrjDGqV69etu0uXbqkcuXKuV6XKFFCzZs3d71u0KCBSpcurX379qlly5a51hAVFeX6d0hIiEJDQ5WSknJL7wuAZxB0ABQr5iaP33M6nfL19dWWLVvk6+ubbV3JkiWzvbYsK8f211v2W35+fjm2cTqdN90OQPHDHB0AxUqdOnXk5+enb7/91rXs7Nmz+vHHHyVJTZs2VVZWllJSUlSnTp1sX+Hh4a5trly5osTERNfr/fv369y5c2rQoIEkyd/fX1lZWUX0rgB4CkEHQLFSsmRJjRgxQi+88ILWrl2r3bt3a9iwYfLxufrnql69ehoyZIiGDh2qpUuX6vDhw0pISNDrr7+u+Ph41378/Pz01FNP6bvvvtPWrVv16KOP6u6773adtqpZs6YOHz6s7du369SpU7p06ZJH3i8A9yLoACh2pk+frg4dOqh///7q1q2b2rVrp2bNmrnWz507V0OHDtVzzz2n+vXrq3///vruu+9UrVo1V5vg4GCNGzdOgwcPVuvWrRUUFKTFixe71v/+979Xr1691LlzZ1WoUEGLFi0q0vcIoGhY5mYnxAHgNjNv3jyNHj1a586d83QpADyMER0AAGBbBB0AAGBbnLoCAAC2xYgOAACwLYIOAACwLYIOAACwLYIOAACwLYIOAACwLYIOAACwLYIOAACwLYIOAACwrf8PJD/2BWBdxfgAAAAASUVORK5CYII=",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"res = df_list[df_list[\"size\"] == 65536].groupby(['depth', 'function']).time.aggregate(['median', 'std']).unstack()\n",
"ax = plt.subplot()\n",
"res.plot(kind='bar', y='median', yerr='std', grid=True, logy=True, ax=ax)\n",
"ax.set_title(\"65536 nodes\")\n",
"ax.set_ylabel(\"Time (s)\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.9.13 ('pangeo-forge-recipes')",
"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.9.13"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "803e3ac3a659d66b93cf53f7a1d909055f69c6ef647a5a5677b69ba9dd66edb3"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
import asyncio
from time import perf_counter
import functools
from rich import print
from math import log
import json
import uuid
import modal
import modal.aio
s3_image = modal.Image.debian_slim().pip_install(["aiobotocore", "numpy"])
stub = modal.aio.AioStub("s3-test", image=s3_image)
def execution_timer(func):
@functools.wraps(func)
async def wrapper(*args, **kwargs):
tic = perf_counter()
result = await func(*args, **kwargs)
toc = perf_counter()
return {"function": func.__name__, "time": (toc - tic), **kwargs}
return wrapper
def generate_tree(depth=1, leaves=2, root: str = "root"):
if depth == 0:
return
if depth == 1:
for n in range(leaves):
yield "/".join((root, f"{n}.leaf"))
else:
for n in range(leaves):
new_root = "/".join((root, str(n)))
yield from generate_tree(depth=depth - 1, leaves=leaves, root=new_root)
def tree_size(depth, leaves):
return leaves**depth
# size = leaves**depth
# depth = log(size, leaves)
@stub.function(secret=modal.Secret.from_name("ryan-earthmover-aws-keys"))
@execution_timer
async def create_tree(*, depth: int, leaves: int, root: str):
from aiobotocore.session import get_session
bucket = "arraylake-test"
session = get_session()
async with session.create_client("s3", region_name="us-east-1") as client:
await asyncio.gather(
*(
client.put_object(Bucket=bucket, Key=key, Body=b"x01")
for key in generate_tree(depth, leaves, root)
),
return_exceptions=True,
)
async def list_objects_and_directories(client, bucket, root, include_subdirs=True):
if not root.endswith("/"):
root += "/"
is_finished = False
continuation_token = None
objects = []
directories = []
while not is_finished:
kwargs = {} if include_subdirs else {"Delimiter": "/"}
if continuation_token:
kwargs["ContinuationToken"] = continuation_token
result = await client.list_objects_v2(Bucket=bucket, Prefix=root, **kwargs)
objects += result.get("Contents", [])
directories += result.get("CommonPrefixes", [])
is_finished = not result["IsTruncated"]
continuation_token = result.get("NextContinuationToken")
return objects, [item["Prefix"] for item in directories]
async def count_objects_recursive(client, bucket, root) -> int:
objects, directories = await list_objects_and_directories(
client, bucket, root, include_subdirs=False
)
count = len(objects)
subdir_counts = await asyncio.gather(
*(count_objects_recursive(client, bucket, dir) for dir in directories)
)
return count + sum(subdir_counts)
@stub.function(secret=modal.Secret.from_name("ryan-earthmover-aws-keys"))
@execution_timer
async def list_flat(*, depth: int, leaves: int, root: str):
from aiobotocore.session import get_session
bucket = "arraylake-test"
session = get_session()
async with session.create_client("s3", region_name="us-east-1") as client:
objects, directories = await list_objects_and_directories(
client, bucket, root, include_subdirs=True
)
count = len(objects)
expected = tree_size(depth, leaves)
if count / expected < 0.9:
raise ValueError(f"Expected {expected} objects, got {count} objects")
@stub.function(secret=modal.Secret.from_name("ryan-earthmover-aws-keys"))
@execution_timer
async def list_recursive(*, depth: int, leaves: int, root: str):
from aiobotocore.session import get_session
bucket = "arraylake-test"
session = get_session()
async with session.create_client("s3", region_name="us-east-1") as client:
count = await count_objects_recursive(client, bucket, root)
expected = tree_size(depth, leaves)
if count / expected < 0.9:
raise ValueError(f"Expected {expected} objects, got {count} objects")
@stub.function(secret=modal.Secret.from_name("ryan-earthmover-aws-keys"))
@execution_timer
async def delete_tree(*, depth: int, leaves: int, root: str):
from aiobotocore.session import get_session
bucket = "arraylake-test"
session = get_session()
async with session.create_client("s3", region_name="us-east-1") as client:
await asyncio.gather(
*(
client.delete_object(Bucket=bucket, Key=key)
for key in generate_tree(depth, leaves, root)
),
return_exceptions=True,
)
@stub.function(secret=modal.Secret.from_name("ryan-earthmover-aws-keys"))
async def clear_all(*, root: str):
from aiobotocore.session import get_session
bucket = "arraylake-test"
session = get_session()
async with session.create_client("s3", region_name="us-east-1") as client:
objects, _ = await list_objects_and_directories(
client, bucket, root, include_subdirs=True
)
print("Deleting", len(objects), "objects")
await asyncio.gather(
*(
client.delete_object(Bucket=bucket, Key=obj["Key"])
for obj in objects
),
return_exceptions=True,
)
async def benchmark_run(*, depth: int, leaves: int, nruns=4):
root = "tree/" + uuid.uuid4().hex
print("Total Nodes:", tree_size(depth, leaves), "Depth:", depth, "Leaves:", leaves, "Root:", root)
create_time = await create_tree(depth=depth, leaves=leaves, root=root)
results = [create_time]
print(create_time)
await asyncio.sleep(1) # give s3 some time to catch up
for run in range(nruns):
list_time_flat = await list_flat(depth=depth, leaves=leaves, root=root)
print(list_time_flat)
results.append(list_time_flat)
list_time_recursive = await list_recursive(depth=depth, leaves=leaves, root=root)
print(list_time_recursive)
results.append(list_time_recursive)
delete_time = await delete_tree(depth=depth, leaves=leaves, root=root)
print(delete_time)
results.append(delete_time)
return results
async def main():
async with stub.run():
await clear_all(root="root")
coros =[]
for max_depth in range(14, 17, 2):
size = 2**max_depth
for depth in range(1, max_depth + 1):
if not max_depth % depth == 0:
continue
f = max_depth // depth
leaves = 2**f
assert leaves**depth == size
coros.append(benchmark_run(depth=depth, leaves=leaves))
for task in asyncio.as_completed(coros):
result = await task
fname = f"s3_listing_results/depth-{result[0]['depth']}_leaves-{result[0]['leaves']}.json"
print("Writing", fname)
with open(fname, mode="w") as fp:
json.dump(result, fp)
if __name__ == "__main__":
asyncio.run(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment