diff --git a/learner.ipynb b/learner.ipynb
index 7461a5a0ff7e10f04ad02aaa167d71ed81d750cf..dad946c1d76c48ddf28110bfcbfed7a4f81b1962 100644
--- a/learner.ipynb
+++ b/learner.ipynb
@@ -656,6 +656,61 @@
     "learner.plot().opts(style=dict(size=6)) * reconstructed_learner.plot()"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Timing functions"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "To time the runner you **cannot** simply use \n",
+    "```python\n",
+    "now = datetime.now()\n",
+    "runner = adaptive.Runner(...)\n",
+    "print(datetime.now() - now)\n",
+    "```\n",
+    "because this will be done immediately. Also blocking the kernel with `while not runner.task.done()` will not work because the runner will not do anything when the kernel is blocked.\n",
+    "\n",
+    "Therefore you need to create an `async` function and hook it into the `ioloop` like so:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import asyncio\n",
+    "\n",
+    "async def time(runner):\n",
+    "    from datetime import datetime\n",
+    "    now = datetime.now()\n",
+    "    await runner.task\n",
+    "    return datetime.now() - now\n",
+    "\n",
+    "ioloop = asyncio.get_event_loop()\n",
+    "\n",
+    "learner = adaptive.learner.IntegratorLearner(f24, bounds=(0, 3), tol=1e-3)\n",
+    "runner = adaptive.Runner(learner, executor=adaptive.runner.SequentialExecutor(),\n",
+    "                         goal=lambda l: l.done())\n",
+    "\n",
+    "timer = ioloop.create_task(time(runner))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# The result will only be set when the runner is done.\n",
+    "timer.result()"
+   ]
+  },
   {
    "cell_type": "markdown",
    "metadata": {},