{ "cells": [ { "cell_type": "markdown", "id": "59428441", "metadata": {}, "source": [ "## Tasks" ] }, { "cell_type": "code", "execution_count": 1, "id": "8c84b475", "metadata": {}, "outputs": [], "source": [ "from dataclasses import dataclass, fields\n", "\n", "@dataclass\n", "class Task:\n", " is_project_private: int\n", " is_user_approved: int\n", " load_packit_yaml: int\n", " set_status: int\n", " \n", " @property\n", " def total(self):\n", " return sum(getattr(self, field.name) for field in fields(self.__class__))\n", " \n", " def __mul__(self, num):\n", " if not isinstance(num, int):\n", " raise TypeError(f\"unsupported operand type(s) for *: {type(self)!r} and {type(num)!r}\")\n", " return Task(*[num * getattr(self, field.name) for field in fields(self.__class__)])\n", " \n", " __rmul__ = __mul__\n", " \n", " def __add__(self, obj):\n", " if not isinstance(obj, Task) and not isinstance(obj, int):\n", " raise TypeError(f\"unsupported operand type(s) for +: {type(self)!r} and {type(obj)!r}\")\n", " if isinstance(obj, int) and obj != 0:\n", " raise TypeError(f\"adding {obj!r} to an {type(self)!r} is not supported\")\n", " if isinstance(obj, int) and obj == 0:\n", " obj = Task(*[0] * len(fields(self.__class__)))\n", " return Task(*[(getattr(self, field.name) + getattr(obj, field.name)) for field in fields(self.__class__)])\n", " \n", " __radd__ = __add__" ] }, { "cell_type": "markdown", "id": "464ee1d0", "metadata": {}, "source": [ "## Estimating the number of API calls" ] }, { "cell_type": "code", "execution_count": 2, "id": "bd8ae47b", "metadata": {}, "outputs": [], "source": [ "from collections import namedtuple\n", "\n", "metrics = [\n", " \"prs_per_hour_per_org\", \n", " \"total_is_project_private\", \n", " \"total_is_user_approved\", \n", " \"total_load_packit_yaml\", \n", " \"total_set_status\",\n", " \"grand_total\",\n", "]\n", "\n", "class APICallMetrics(namedtuple(\"APICallMetrics\", metrics)):\n", " def __repr__(self):\n", " return \"\\n\".join(f\"{field} = {getattr(self, field)}\" for field in self._fields)\n", " \n", "def github_api_calls(\n", " # The number of chroots configured to be built in Copr\n", " chroots=3, \n", " # GitHub server-to-server rate limit per hour\n", " rate_limit=5000,\n", " # Calls to load .packit.yaml.\n", " # The current implementation cycles through a list of 7 files.\n", " # If the config file is .packit.yaml, this is loaded from 2 calls.\n", " # If the config file is packit.yaml, it's loaded from 5 calls.\n", " # The +1 call is to try to find the specfile path.\n", " load_packit_yaml=2+1,\n", " # Whether builds are enabled\n", " builds_enabled=True, \n", " # Whether tests are enabled\n", " tests_enabled=True, \n", " # Load packit.yaml once during the pipeline run\n", " load_packit_yaml_once=False, \n", " # Set all flags (including test ones) when the build status changes\n", " all_flags=True,\n", " # Check if the repo is private only in the beginning\n", " is_private_once=False,\n", "):\n", " build_status_flag = int(builds_enabled)\n", " test_status_flag = int(tests_enabled)\n", " tasks = {\n", " \"PR is updated\": Task(\n", " # https://github.com/packit/packit-service/blob/bc1f66bb82aa7c013bde8b8e670ce7e02f55de41/packit_service/worker/jobs.py#L156\n", " is_project_private=1,\n", " # https://github.com/packit/packit-service/blob/bc1f66bb82aa7c013bde8b8e670ce7e02f55de41/packit_service/worker/allowlist.py#L275\n", " is_user_approved=2,\n", " # https://github.com/packit/packit-service/blob/bc1f66bb82aa7c013bde8b8e670ce7e02f55de41/packit_service/worker/events/event.py#L415\n", " load_packit_yaml=load_packit_yaml,\n", " set_status=chroots * (build_status_flag + test_status_flag)\n", " ),\n", " \"Submit Copr build\": Task(\n", " is_project_private=0,\n", " is_user_approved=0,\n", " load_packit_yaml=0,\n", " set_status=chroots * (build_status_flag + test_status_flag),\n", " ),\n", " }\n", " load_packit_yaml = load_packit_yaml if not load_packit_yaml_once else 0\n", " flags_to_set = (build_status_flag + test_status_flag) if all_flags else build_status_flag\n", " is_private = 0 if is_private_once else 1\n", " task = Task(is_private, 0, load_packit_yaml, flags_to_set)\n", " tasks.update({\n", " \"SRPM build started\": chroots * task,\n", " \"SRPM build finished\": chroots * task,\n", " \"RPM build started\": chroots * task,\n", " \"RPM build finished\": chroots * task,\n", " })\n", " if tests_enabled:\n", " task = Task(is_private, 0, load_packit_yaml, test_status_flag)\n", " tasks.update({\n", " \"Tests started\": chroots * task,\n", " \"Tests finished\": chroots * task,\n", " })\n", " total_is_project_private = sum(task.is_project_private for task in tasks.values())\n", " total_is_user_approved = sum(task.is_user_approved for task in tasks.values())\n", " total_load_packit_yaml = sum(task.load_packit_yaml for task in tasks.values())\n", " total_set_status = sum(task.set_status for task in tasks.values())\n", " grand_total = sum(tasks.values()).total\n", " prs_per_hour_per_org = int(rate_limit / grand_total)\n", " \n", " return APICallMetrics(\n", " prs_per_hour_per_org, \n", " total_is_project_private, \n", " total_is_user_approved, \n", " total_load_packit_yaml, \n", " total_set_status,\n", " grand_total,\n", " )" ] }, { "cell_type": "code", "execution_count": 3, "id": "cc02ce48", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "prs_per_hour_per_org = 41\n", "total_is_project_private = 19\n", "total_is_user_approved = 2\n", "total_load_packit_yaml = 57\n", "total_set_status = 42\n", "grand_total = 120" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "github_api_calls(\n", " chroots=3, \n", " rate_limit=5000, \n", " load_packit_yaml=2+1, \n", " builds_enabled=True, \n", " tests_enabled=True\n", ")" ] }, { "cell_type": "code", "execution_count": 4, "id": "453ac2c3", "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as pp\n", "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 5, "id": "dd6e3f87", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "labels = [\"Project is private\", \"User is approved\", \"load packit.yaml\", \"set status\"]\n", "sizes = github_api_calls(\n", " chroots=3, \n", " rate_limit=5000, \n", " load_packit_yaml=2+1, \n", " builds_enabled=True, \n", " tests_enabled=True\n", ")[1:-1]\n", "fig1, ax1 = pp.subplots()\n", "ax1.pie(sizes, labels=labels, autopct='%1.1f%%')\n", "ax1.axis('equal')\n", "\n", "pp.show()" ] }, { "cell_type": "markdown", "id": "82c80b3e", "metadata": {}, "source": [ "## A few common scenarios" ] }, { "cell_type": "code", "execution_count": 6, "id": "a0fa3ac4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3 chroots, config is called '.packit.yaml'\n" ] }, { "data": { "text/plain": [ "prs_per_hour_per_org = 41\n", "total_is_project_private = 19\n", "total_is_user_approved = 2\n", "total_load_packit_yaml = 57\n", "total_set_status = 42\n", "grand_total = 120" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(\"3 chroots, config is called '.packit.yaml'\")\n", "github_api_calls(\n", " chroots=3, \n", " rate_limit=5000, \n", " load_packit_yaml=2+1, \n", " builds_enabled=True, \n", " tests_enabled=True\n", ")" ] }, { "cell_type": "code", "execution_count": 7, "id": "8035045b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "6 chroots, config is called '.packit.yaml'\n" ] }, { "data": { "text/plain": [ "prs_per_hour_per_org = 21\n", "total_is_project_private = 37\n", "total_is_user_approved = 2\n", "total_load_packit_yaml = 111\n", "total_set_status = 84\n", "grand_total = 234" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(\"6 chroots, config is called '.packit.yaml'\")\n", "github_api_calls(\n", " chroots=6, \n", " rate_limit=5000, \n", " load_packit_yaml=2+1, \n", " builds_enabled=True, \n", " tests_enabled=True\n", ")" ] }, { "cell_type": "code", "execution_count": 8, "id": "a8e19023", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3 chroots, config is called 'packit.yaml'\n" ] }, { "data": { "text/plain": [ "prs_per_hour_per_org = 28\n", "total_is_project_private = 19\n", "total_is_user_approved = 2\n", "total_load_packit_yaml = 114\n", "total_set_status = 42\n", "grand_total = 177" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(\"3 chroots, config is called 'packit.yaml'\")\n", "github_api_calls(\n", " chroots=3, \n", " rate_limit=5000, \n", " load_packit_yaml=5+1, \n", " builds_enabled=True, \n", " tests_enabled=True\n", ")" ] }, { "cell_type": "code", "execution_count": 9, "id": "a7159baf", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "6 chroots, config is called 'packit.yaml'\n" ] }, { "data": { "text/plain": [ "prs_per_hour_per_org = 14\n", "total_is_project_private = 37\n", "total_is_user_approved = 2\n", "total_load_packit_yaml = 222\n", "total_set_status = 84\n", "grand_total = 345" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(\"6 chroots, config is called 'packit.yaml'\")\n", "github_api_calls(\n", " chroots=6, \n", " rate_limit=5000, \n", " load_packit_yaml=5+1, \n", " builds_enabled=True, \n", " tests_enabled=True\n", ")" ] }, { "cell_type": "code", "execution_count": 10, "id": "a748a141", "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "6 chroots, config is called '.packit.yaml', no tests\n" ] }, { "data": { "text/plain": [ "prs_per_hour_per_org = 36\n", "total_is_project_private = 25\n", "total_is_user_approved = 2\n", "total_load_packit_yaml = 75\n", "total_set_status = 36\n", "grand_total = 138" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(\"6 chroots, config is called '.packit.yaml', no tests\")\n", "github_api_calls(\n", " chroots=6, \n", " rate_limit=5000, \n", " load_packit_yaml=2+1, \n", " builds_enabled=True, \n", " tests_enabled=False\n", ")" ] }, { "cell_type": "markdown", "id": "42af2a1a", "metadata": {}, "source": [ "## Ways to improve things" ] }, { "cell_type": "markdown", "id": "0c05d101", "metadata": {}, "source": [ "The main issue seems to be that `task.steve_jobs.process_message` re-creates the context of the pipeline by getting information from GitHub: checks if the project is private, if the user is approved to run the pipeline, and load the package config (`.packit.yaml`).\n", "\n", "All this could be avoided by looking up the pipeline when an event arrives (Copr events, testing farm events - when these are received there already needs to be a pipeline created, otherwise they are invalid), and getting this information from the pipeline.\n", "\n", "The only time it makes sense to load this from GitHub is when the pipeline is started, for example when the PR event is received." ] }, { "cell_type": "markdown", "id": "616bb63c", "metadata": {}, "source": [ "Let's pick the worst case from the list above (*6 chroots, config is called 'packit.yaml'*) as a reference, and check how the number of API calls change if we apply the above.\n", "\n", "**Load the package config only once per pipeline run** to increase the number of possible runs from 14 to 38 (~171% increase). This is achived by reducing the number of API calls to get the package config from 222 to 6." ] }, { "cell_type": "code", "execution_count": 11, "id": "c1b001e5", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "prs_per_hour_per_org = 38\n", "total_is_project_private = 37\n", "total_is_user_approved = 2\n", "total_load_packit_yaml = 6\n", "total_set_status = 84\n", "grand_total = 129" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "github_api_calls(\n", " chroots=6, \n", " rate_limit=5000,\n", " load_packit_yaml=5+1,\n", " builds_enabled=True,\n", " tests_enabled=True,\n", " load_packit_yaml_once=True)" ] }, { "cell_type": "markdown", "id": "2284d964", "metadata": {}, "source": [ "**Don't update the test flags while the build is in progress**, to get to 47 PRs/hour/org (a 235% increase in total), thanks to shaving of 24 API calls to update the status flags." ] }, { "cell_type": "code", "execution_count": 12, "id": "1cc97054", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "prs_per_hour_per_org = 47\n", "total_is_project_private = 37\n", "total_is_user_approved = 2\n", "total_load_packit_yaml = 6\n", "total_set_status = 60\n", "grand_total = 105" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "github_api_calls(\n", " chroots=6, \n", " rate_limit=5000, \n", " load_packit_yaml=5+1, \n", " builds_enabled=True, \n", " tests_enabled=True, \n", " load_packit_yaml_once=True,\n", " all_flags=False)" ] }, { "cell_type": "markdown", "id": "21c94f9b", "metadata": {}, "source": [ "**Reduce the number of calls to get the package config**, and don't search for the specfile path ([packit/packit#1799](https://github.com/packit/packit/issues/1799)). This is an increase in the possible PRs handled per hour per org of ~250%.\n", "\n", "Reducing the number of calls to get the package config has probably a greater impact when Packit is enabled for all repositories in the org, but only a few of those repositories have a package config present. In this case events from repositories which don't have a package config will consume only 2 API calls (1 to check if the repo is private, and 1 to find out that there is no package config), instead of 9 API calls." ] }, { "cell_type": "code", "execution_count": 13, "id": "5eab470d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "prs_per_hour_per_org = 49\n", "total_is_project_private = 37\n", "total_is_user_approved = 2\n", "total_load_packit_yaml = 2\n", "total_set_status = 60\n", "grand_total = 101" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "github_api_calls(\n", " chroots=6, \n", " rate_limit=5000, \n", " load_packit_yaml=2, \n", " builds_enabled=True, \n", " tests_enabled=True, \n", " load_packit_yaml_once=True, \n", " all_flags=False)" ] }, { "cell_type": "markdown", "id": "be6760ff", "metadata": {}, "source": [ "By **checking if the repo is private only once**, when the event that the PR was updated is received and the pipeline created, a further 55% increase can be achieved, which brings us to a **442% increase compared to the current state**.\n", "\n", "The number of API calls drops from 345 to 65." ] }, { "cell_type": "code", "execution_count": 14, "id": "eba2722a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "prs_per_hour_per_org = 76\n", "total_is_project_private = 1\n", "total_is_user_approved = 2\n", "total_load_packit_yaml = 2\n", "total_set_status = 60\n", "grand_total = 65" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "github_api_calls(\n", " chroots=6, \n", " rate_limit=5000, \n", " load_packit_yaml=2, \n", " builds_enabled=True, \n", " tests_enabled=True, \n", " load_packit_yaml_once=True, \n", " all_flags=False, \n", " is_private_once=True)" ] }, { "cell_type": "markdown", "id": "cea66f97", "metadata": {}, "source": [ "The above is a 246% improvement even for the best case scenario, by dropping the number of API calls per pipeline from 120 to 35." ] }, { "cell_type": "code", "execution_count": 15, "id": "d4094d47", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "prs_per_hour_per_org = 142\n", "total_is_project_private = 1\n", "total_is_user_approved = 2\n", "total_load_packit_yaml = 2\n", "total_set_status = 30\n", "grand_total = 35" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "github_api_calls(\n", " chroots=3,\n", " rate_limit=5000,\n", " load_packit_yaml=2,\n", " builds_enabled=True,\n", " tests_enabled=True,\n", " load_packit_yaml_once=True,\n", " all_flags=False,\n", " is_private_once=True)" ] }, { "cell_type": "markdown", "id": "7fed3b7e", "metadata": {}, "source": [ "From this point on, the number of API calls could be further reduced only by having fewer status flags (merging flags for different chroots) or making fewer updates to these flags. Both of these could make the user experiance worse." ] }, { "cell_type": "markdown", "id": "8745cba8", "metadata": {}, "source": [ "Note, that the above assumes that pipelines are never running in parallel, which is probably not the case, for example, when PRs are updated while a previous pipeline is still in progress. In these situations old pipeline runs could still consume from the GitHub API rate limit (and maybe override statuses?). This could be solved by canceling Copr builds and test runs belonging to pipelines which become irrelevant ([packit/packit-service#5](https://github.com/packit/packit-service/issues/5))." ] }, { "cell_type": "code", "execution_count": null, "id": "42a23da2", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.11.1" } }, "nbformat": 4, "nbformat_minor": 5 }