{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       ":sns"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "require 'matplotlib/iruby'\n",
    "Matplotlib::IRuby.activate\n",
    "\n",
    "require 'pycall/import'\n",
    "include PyCall::Import\n",
    "\n",
    "pyimport :pandas, as: :pd\n",
    "pyimport :seaborn, as: :sns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "require 'benchmark'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "n = 100_000\n",
    "trials = 100\n",
    "array = Array.new(n) { rand }\n",
    "enum = array.each\n",
    "method = []\n",
    "runtime = []"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "100"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Array#sum\n",
    "trials.times do\n",
    "  method << 'array.sum'\n",
    "  runtime << Benchmark.realtime { array.sum }\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "100"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Array#sum\n",
    "trials.times do\n",
    "  method << 'enum.sum'\n",
    "  runtime << Benchmark.realtime { enum.sum }\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "100"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Array#inject\n",
    "trials.times do\n",
    "  method << 'array.inject'\n",
    "  runtime << Benchmark.realtime { array.inject :+ }\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "100"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Enumerable#inject\n",
    "trials.times do\n",
    "  method << 'enum.inject'\n",
    "  runtime << Benchmark.realtime { enum.inject :+ }\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "100"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# while\n",
    "def while_sum(array)\n",
    "  sum, i, cnt = 0, 0, array.length\n",
    "  while i < cnt\n",
    "    sum += array[i]\n",
    "    i += 1\n",
    "  end\n",
    "  sum\n",
    "end\n",
    "\n",
    "trials.times do\n",
    "  method << 'while'\n",
    "  runtime << Benchmark.realtime { while_sum(array) }\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th colspan=\"8\" halign=\"left\">runtime</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>std</th>\n",
       "      <th>min</th>\n",
       "      <th>25%</th>\n",
       "      <th>50%</th>\n",
       "      <th>75%</th>\n",
       "      <th>max</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>method</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>array.inject</th>\n",
       "      <td>100.0</td>\n",
       "      <td>0.013103</td>\n",
       "      <td>0.001518</td>\n",
       "      <td>0.012029</td>\n",
       "      <td>0.012350</td>\n",
       "      <td>0.012590</td>\n",
       "      <td>0.013337</td>\n",
       "      <td>0.022215</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>array.sum</th>\n",
       "      <td>100.0</td>\n",
       "      <td>0.001882</td>\n",
       "      <td>0.000372</td>\n",
       "      <td>0.001498</td>\n",
       "      <td>0.001587</td>\n",
       "      <td>0.001804</td>\n",
       "      <td>0.002008</td>\n",
       "      <td>0.003009</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>enum.inject</th>\n",
       "      <td>100.0</td>\n",
       "      <td>0.023528</td>\n",
       "      <td>0.002267</td>\n",
       "      <td>0.021078</td>\n",
       "      <td>0.021782</td>\n",
       "      <td>0.023041</td>\n",
       "      <td>0.024574</td>\n",
       "      <td>0.033859</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>enum.sum</th>\n",
       "      <td>100.0</td>\n",
       "      <td>0.010069</td>\n",
       "      <td>0.001304</td>\n",
       "      <td>0.009078</td>\n",
       "      <td>0.009221</td>\n",
       "      <td>0.009463</td>\n",
       "      <td>0.010708</td>\n",
       "      <td>0.018378</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>while</th>\n",
       "      <td>100.0</td>\n",
       "      <td>0.011932</td>\n",
       "      <td>0.001089</td>\n",
       "      <td>0.011079</td>\n",
       "      <td>0.011357</td>\n",
       "      <td>0.011491</td>\n",
       "      <td>0.012085</td>\n",
       "      <td>0.018309</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "#<Object:0x007fd93f0727e8 @__pyptr__=#<PyCall::PyPtr:0x007fd93f0727c0 type=DataFrame addr=0x00000117195c50>>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pd.DataFrame.new(data: {method: method, runtime: runtime})\n",
    "df.groupby('method').describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 35156 characters]",
      "text/plain": [
       "#<Matplotlib::Figure:0x007fd93f02a650 @__pyptr__=#<PyCall::PyPtr:0x007fd93f02a6a0 type=Figure addr=0x00000117192358>>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "#<Object:0x007fd93f020088 @__pyptr__=#<PyCall::PyPtr:0x007fd93f020010 type=Text addr=0x000001176abe10>>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sns.barplot(x: 'method', y: 'runtime', data: df, errwidth: 2.5, capsize: 0.04)\n",
    "plt = Matplotlib::Pyplot\n",
    "plt.title(\"Array and Enumerable summation benchmark (#{trials} trials)\")\n",
    "plt.xlabel(\"Summation method\")\n",
    "plt.ylabel(\"Average runtime [sec]\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Ruby 2.4.1",
   "language": "ruby",
   "name": "ruby"
  },
  "language_info": {
   "file_extension": ".rb",
   "mimetype": "application/x-ruby",
   "name": "ruby",
   "version": "2.4.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
