{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "classified-alcohol",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "from plotnine import *\n",
    "import plotnine\n",
    "import random\n",
    "plotnine.options.figure_size = (12, 5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "union-circle",
   "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 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>event</th>\n",
       "      <th>duration</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>a</td>\n",
       "      <td>954.462517</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>a</td>\n",
       "      <td>982.854305</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>a</td>\n",
       "      <td>1037.667967</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>a</td>\n",
       "      <td>1002.143116</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>a</td>\n",
       "      <td>1020.217687</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18328</th>\n",
       "      <td>c</td>\n",
       "      <td>3040.239624</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18329</th>\n",
       "      <td>c</td>\n",
       "      <td>2941.655774</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18330</th>\n",
       "      <td>c</td>\n",
       "      <td>3053.683405</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18331</th>\n",
       "      <td>c</td>\n",
       "      <td>2980.200817</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18332</th>\n",
       "      <td>c</td>\n",
       "      <td>3050.789074</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>18333 rows × 2 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "      event     duration\n",
       "0         a   954.462517\n",
       "1         a   982.854305\n",
       "2         a  1037.667967\n",
       "3         a  1002.143116\n",
       "4         a  1020.217687\n",
       "...     ...          ...\n",
       "18328     c  3040.239624\n",
       "18329     c  2941.655774\n",
       "18330     c  3053.683405\n",
       "18331     c  2980.200817\n",
       "18332     c  3050.789074\n",
       "\n",
       "[18333 rows x 2 columns]"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "points=10000\n",
    "mu=1000\n",
    "sigma=50\n",
    "events = pd.concat([\n",
    "    pd.DataFrame({'event': 'a', 'duration': np.random.normal(mu, sigma, points)}),\n",
    "    pd.DataFrame({'event': 'b', 'duration': np.random.normal(mu*2, sigma, int(points/2))}),\n",
    "    pd.DataFrame({'event': 'c', 'duration': np.random.normal(mu*3, sigma, int(points/3))}),\n",
    "], ignore_index=True)\n",
    "events"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "right-discovery",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 43096 characters]\n",
      "text/plain": [
       "<Figure size 1200x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<ggplot: (324948417)>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(\n",
    "ggplot(events)\n",
    "+ aes(x='duration',color='event')\n",
    "+ labs(x='event duration (ns)',title='Block events from 3 sources with different means, but the same sum(duration)')\n",
    "+ geom_histogram(binwidth=10)\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "brief-bailey",
   "metadata": {},
   "outputs": [],
   "source": [
    "# sample implements the sampling used by the go block profiler. Returning 0 is the\n",
    "# same as false in the go implementation, otherwise the actual number of cycles to\n",
    "# track is returned. This allows to adjust them for bias if the debias paramter is\n",
    "# set to True.\n",
    "#\n",
    "# \tif rate <= 0 || (rate > cycles && int64(fastrand())%rate > cycles) {\n",
    "# \t\treturn false\n",
    "# \t}\n",
    "# \treturn true\n",
    "def sample(cycles, rate, debias):\n",
    "    if cycles >= rate:\n",
    "        return cycles\n",
    "    elif cycles > 0 and random.getrandbits(64)%rate <= cycles:\n",
    "        if debias:\n",
    "            return cycles*(rate/cycles)\n",
    "        else:\n",
    "            return cycles\n",
    "    return 0\n",
    "\n",
    "def simulate_rates(rates, debias):\n",
    "    frames = []\n",
    "    for rate in rates:\n",
    "        rf = (events\n",
    "            .groupby('event')['duration']\n",
    "            .agg(lambda durations: sum(durations.apply(lambda d: sample(d, rate, debias)))).reset_index()\n",
    "        )\n",
    "        rf['rate'] = rate\n",
    "        frames.append(rf)\n",
    "    return pd.concat(frames)\n",
    "\n",
    "rates = range(0, 5000, 100)\n",
    "profiles = simulate_rates(rates, False)\n",
    "profiles_debiased = simulate_rates(rates, True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "relative-minnesota",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 62108 characters]\n",
      "text/plain": [
       "<Figure size 1200x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<ggplot: (325120862)>"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(\n",
    "ggplot(profiles)\n",
    "+ aes(x='rate', y='duration',ymin=0,color='event')\n",
    "+ labs(y='block profile duration (ns)', x='blockprofilerate (ns)',title='Simulations for different blockprofile rates')\n",
    "+ geom_point()\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "aerial-trunk",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 58392 characters]\n",
      "text/plain": [
       "<Figure size 1200x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<ggplot: (324948336)>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(\n",
    "ggplot(profiles_debiased)\n",
    "+ aes(x='rate', y='duration',ymin=0,color='event')\n",
    "+ labs(y='block profile duration (ns)', x='blockprofilerate (ns)',title='Simulations for different blockprofile rates with debias scaling applied')\n",
    "+ geom_point()\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "comparative-ordering",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "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.9.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
