From 163405ff1cc1dc0f4a865769518e13b23f1e90dd Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sat, 16 Nov 2024 16:08:27 +0100 Subject: [PATCH] [PR #9925/69756b49 backport][3.11] Add benchmarks for github url resolving emulation (#9927) **This is a backport of PR #9925 as merged into master (69756b495d8fe0e1bf47056582d63cb6b0cb2913).** I think github API is a representative example for possible route table. Co-authored-by: Andrew Svetlov --- tests/github-urls.json | 653 +++++++++++++++++++++ tests/test_benchmarks_web_urldispatcher.py | 136 ++++- 2 files changed, 783 insertions(+), 6 deletions(-) create mode 100644 tests/github-urls.json diff --git a/tests/github-urls.json b/tests/github-urls.json new file mode 100644 index 00000000000..02e37554615 --- /dev/null +++ b/tests/github-urls.json @@ -0,0 +1,653 @@ +[ + "/", + "/advisories", + "/advisories/{ghsa_id}", + "/app", + "/app-manifests/{code}/conversions", + "/app/hook/config", + "/app/hook/deliveries", + "/app/hook/deliveries/{delivery_id}", + "/app/hook/deliveries/{delivery_id}/attempts", + "/app/installation-requests", + "/app/installations", + "/app/installations/{installation_id}", + "/app/installations/{installation_id}/access_tokens", + "/app/installations/{installation_id}/suspended", + "/applications/{client_id}/grant", + "/applications/{client_id}/token", + "/applications/{client_id}/token/scoped", + "/apps/{app_slug}", + "/assignments/{assignment_id}", + "/assignments/{assignment_id}/accepted_assignments", + "/assignments/{assignment_id}/grades", + "/classrooms", + "/classrooms/{classroom_id}", + "/classrooms/{classroom_id}/assignments", + "/codes_of_conduct", + "/codes_of_conduct/{key}", + "/emojis", + "/enterprises/{enterprise}/copilot/billing/seats", + "/enterprises/{enterprise}/copilot/metrics", + "/enterprises/{enterprise}/copilot/usage", + "/enterprises/{enterprise}/dependabot/alerts", + "/enterprises/{enterprise}/secret-scanning/alerts", + "/enterprises/{enterprise}/team/{team_slug}/copilot/metrics", + "/enterprises/{enterprise}/team/{team_slug}/copilot/usage", + "/events", + "/feeds", + "/gists", + "/gists/public", + "/gists/starred", + "/gists/{gist_id}", + "/gists/{gist_id}/comments", + "/gists/{gist_id}/comments/{comment_id}", + "/gists/{gist_id}/commits", + "/gists/{gist_id}/forks", + "/gists/{gist_id}/star", + "/gists/{gist_id}/{sha}", + "/gitignore/templates", + "/gitignore/templates/{name}", + "/installation/repositories", + "/installation/token", + "/issues", + "/licenses", + "/licenses/{license}", + "/markdown", + "/markdown/raw", + "/marketplace_listing/accounts/{account_id}", + "/marketplace_listing/plans", + "/marketplace_listing/plans/{plan_id}/accounts", + "/marketplace_listing/stubbed/accounts/{account_id}", + "/marketplace_listing/stubbed/plans", + "/marketplace_listing/stubbed/plans/{plan_id}/accounts", + "/meta", + "/networks/{owner}/{repo}/events", + "/notifications", + "/notifications/threads/{thread_id}", + "/notifications/threads/{thread_id}/subscription", + "/octocat", + "/organizations", + "/orgs/{org}", + "/orgs/{org}/actions/cache/usage", + "/orgs/{org}/actions/cache/usage-by-repository", + "/orgs/{org}/actions/oidc/customization/sub", + "/orgs/{org}/actions/permissions", + "/orgs/{org}/actions/permissions/repositories", + "/orgs/{org}/actions/permissions/repositories/{repository_id}", + "/orgs/{org}/actions/permissions/selected-actions", + "/orgs/{org}/actions/permissions/workflow", + "/orgs/{org}/actions/runner-groups", + "/orgs/{org}/actions/runner-groups/{runner_group_id}", + "/orgs/{org}/actions/runner-groups/{runner_group_id}/repositories", + "/orgs/{org}/actions/runner-groups/{runner_group_id}/repositories/{repository_id}", + "/orgs/{org}/actions/runner-groups/{runner_group_id}/runners", + "/orgs/{org}/actions/runner-groups/{runner_group_id}/runners/{runner_id}", + "/orgs/{org}/actions/runners", + "/orgs/{org}/actions/runners/downloads", + "/orgs/{org}/actions/runners/generate-jitconfig", + "/orgs/{org}/actions/runners/registration-token", + "/orgs/{org}/actions/runners/remove-token", + "/orgs/{org}/actions/runners/{runner_id}", + "/orgs/{org}/actions/runners/{runner_id}/labels", + "/orgs/{org}/actions/runners/{runner_id}/labels/{name}", + "/orgs/{org}/actions/secrets", + "/orgs/{org}/actions/secrets/public-key", + "/orgs/{org}/actions/secrets/{secret_name}", + "/orgs/{org}/actions/secrets/{secret_name}/repositories", + "/orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id}", + "/orgs/{org}/actions/variables", + "/orgs/{org}/actions/variables/{name}", + "/orgs/{org}/actions/variables/{name}/repositories", + "/orgs/{org}/actions/variables/{name}/repositories/{repository_id}", + "/orgs/{org}/attestations/{subject_digest}", + "/orgs/{org}/blocks", + "/orgs/{org}/blocks/{username}", + "/orgs/{org}/code-scanning/alerts", + "/orgs/{org}/code-security/configurations", + "/orgs/{org}/code-security/configurations/defaults", + "/orgs/{org}/code-security/configurations/detach", + "/orgs/{org}/code-security/configurations/{configuration_id}", + "/orgs/{org}/code-security/configurations/{configuration_id}/attach", + "/orgs/{org}/code-security/configurations/{configuration_id}/defaults", + "/orgs/{org}/code-security/configurations/{configuration_id}/repositories", + "/orgs/{org}/codespaces", + "/orgs/{org}/codespaces/access", + "/orgs/{org}/codespaces/access/selected_users", + "/orgs/{org}/codespaces/secrets", + "/orgs/{org}/codespaces/secrets/public-key", + "/orgs/{org}/codespaces/secrets/{secret_name}", + "/orgs/{org}/codespaces/secrets/{secret_name}/repositories", + "/orgs/{org}/codespaces/secrets/{secret_name}/repositories/{repository_id}", + "/orgs/{org}/copilot/billing", + "/orgs/{org}/copilot/billing/seats", + "/orgs/{org}/copilot/billing/selected_teams", + "/orgs/{org}/copilot/billing/selected_users", + "/orgs/{org}/copilot/metrics", + "/orgs/{org}/copilot/usage", + "/orgs/{org}/dependabot/alerts", + "/orgs/{org}/dependabot/secrets", + "/orgs/{org}/dependabot/secrets/public-key", + "/orgs/{org}/dependabot/secrets/{secret_name}", + "/orgs/{org}/dependabot/secrets/{secret_name}/repositories", + "/orgs/{org}/dependabot/secrets/{secret_name}/repositories/{repository_id}", + "/orgs/{org}/docker/conflicts", + "/orgs/{org}/events", + "/orgs/{org}/failed_invitations", + "/orgs/{org}/hooks", + "/orgs/{org}/hooks/{hook_id}", + "/orgs/{org}/hooks/{hook_id}/config", + "/orgs/{org}/hooks/{hook_id}/deliveries", + "/orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id}", + "/orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id}/attempts", + "/orgs/{org}/hooks/{hook_id}/pings", + "/orgs/{org}/insights/api/route-stats/{actor_type}/{actor_id}", + "/orgs/{org}/insights/api/subject-stats", + "/orgs/{org}/insights/api/summary-stats", + "/orgs/{org}/insights/api/summary-stats/users/{user_id}", + "/orgs/{org}/insights/api/summary-stats/{actor_type}/{actor_id}", + "/orgs/{org}/insights/api/time-stats", + "/orgs/{org}/insights/api/time-stats/users/{user_id}", + "/orgs/{org}/insights/api/time-stats/{actor_type}/{actor_id}", + "/orgs/{org}/insights/api/user-stats/{user_id}", + "/orgs/{org}/installation", + "/orgs/{org}/installations", + "/orgs/{org}/interaction-limits", + "/orgs/{org}/invitations", + "/orgs/{org}/invitations/{invitation_id}", + "/orgs/{org}/invitations/{invitation_id}/teams", + "/orgs/{org}/issues", + "/orgs/{org}/members", + "/orgs/{org}/members/{username}", + "/orgs/{org}/members/{username}/codespaces", + "/orgs/{org}/members/{username}/codespaces/{codespace_name}", + "/orgs/{org}/members/{username}/codespaces/{codespace_name}/stop", + "/orgs/{org}/members/{username}/copilot", + "/orgs/{org}/memberships/{username}", + "/orgs/{org}/migrations", + "/orgs/{org}/migrations/{migration_id}", + "/orgs/{org}/migrations/{migration_id}/archive", + "/orgs/{org}/migrations/{migration_id}/repos/{repo_name}/lock", + "/orgs/{org}/migrations/{migration_id}/repositories", + "/orgs/{org}/organization-roles", + "/orgs/{org}/organization-roles/teams/{team_slug}", + "/orgs/{org}/organization-roles/teams/{team_slug}/{role_id}", + "/orgs/{org}/organization-roles/users/{username}", + "/orgs/{org}/organization-roles/users/{username}/{role_id}", + "/orgs/{org}/organization-roles/{role_id}", + "/orgs/{org}/organization-roles/{role_id}/teams", + "/orgs/{org}/organization-roles/{role_id}/users", + "/orgs/{org}/outside_collaborators", + "/orgs/{org}/outside_collaborators/{username}", + "/orgs/{org}/packages", + "/orgs/{org}/packages/{package_type}/{package_name}", + "/orgs/{org}/packages/{package_type}/{package_name}/restore", + "/orgs/{org}/packages/{package_type}/{package_name}/versions", + "/orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}", + "/orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore", + "/orgs/{org}/personal-access-token-requests", + "/orgs/{org}/personal-access-token-requests/{pat_request_id}", + "/orgs/{org}/personal-access-token-requests/{pat_request_id}/repositories", + "/orgs/{org}/personal-access-tokens", + "/orgs/{org}/personal-access-tokens/{pat_id}", + "/orgs/{org}/personal-access-tokens/{pat_id}/repositories", + "/orgs/{org}/projects", + "/orgs/{org}/properties/schema", + "/orgs/{org}/properties/schema/{custom_property_name}", + "/orgs/{org}/properties/values", + "/orgs/{org}/public_members", + "/orgs/{org}/public_members/{username}", + "/orgs/{org}/repos", + "/orgs/{org}/rulesets", + "/orgs/{org}/rulesets/rule-suites", + "/orgs/{org}/rulesets/rule-suites/{rule_suite_id}", + "/orgs/{org}/rulesets/{ruleset_id}", + "/orgs/{org}/secret-scanning/alerts", + "/orgs/{org}/security-advisories", + "/orgs/{org}/security-managers", + "/orgs/{org}/security-managers/teams/{team_slug}", + "/orgs/{org}/settings/billing/actions", + "/orgs/{org}/settings/billing/packages", + "/orgs/{org}/settings/billing/shared-storage", + "/orgs/{org}/team/{team_slug}/copilot/metrics", + "/orgs/{org}/team/{team_slug}/copilot/usage", + "/orgs/{org}/teams", + "/orgs/{org}/teams/{team_slug}", + "/orgs/{org}/teams/{team_slug}/discussions", + "/orgs/{org}/teams/{team_slug}/discussions/{discussion_number}", + "/orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments", + "/orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}", + "/orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions", + "/orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions/{reaction_id}", + "/orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions", + "/orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions/{reaction_id}", + "/orgs/{org}/teams/{team_slug}/invitations", + "/orgs/{org}/teams/{team_slug}/members", + "/orgs/{org}/teams/{team_slug}/memberships/{username}", + "/orgs/{org}/teams/{team_slug}/projects", + "/orgs/{org}/teams/{team_slug}/projects/{project_id}", + "/orgs/{org}/teams/{team_slug}/repos", + "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}", + "/orgs/{org}/teams/{team_slug}/teams", + "/orgs/{org}/{security_product}/{enablement}", + "/projects/columns/cards/{card_id}", + "/projects/columns/cards/{card_id}/moves", + "/projects/columns/{column_id}", + "/projects/columns/{column_id}/cards", + "/projects/columns/{column_id}/moves", + "/projects/{project_id}", + "/projects/{project_id}/collaborators", + "/projects/{project_id}/collaborators/{username}", + "/projects/{project_id}/collaborators/{username}/permission", + "/projects/{project_id}/columns", + "/rate_limit", + "/repos/{owner}/{repo}", + "/repos/{owner}/{repo}/actions/artifacts", + "/repos/{owner}/{repo}/actions/artifacts/{artifact_id}", + "/repos/{owner}/{repo}/actions/artifacts/{artifact_id}/{archive_format}", + "/repos/{owner}/{repo}/actions/cache/usage", + "/repos/{owner}/{repo}/actions/caches", + "/repos/{owner}/{repo}/actions/caches/{cache_id}", + "/repos/{owner}/{repo}/actions/jobs/{job_id}", + "/repos/{owner}/{repo}/actions/jobs/{job_id}/logs", + "/repos/{owner}/{repo}/actions/jobs/{job_id}/rerun", + "/repos/{owner}/{repo}/actions/oidc/customization/sub", + "/repos/{owner}/{repo}/actions/organization-secrets", + "/repos/{owner}/{repo}/actions/organization-variables", + "/repos/{owner}/{repo}/actions/permissions", + "/repos/{owner}/{repo}/actions/permissions/access", + "/repos/{owner}/{repo}/actions/permissions/selected-actions", + "/repos/{owner}/{repo}/actions/permissions/workflow", + "/repos/{owner}/{repo}/actions/runners", + "/repos/{owner}/{repo}/actions/runners/downloads", + "/repos/{owner}/{repo}/actions/runners/generate-jitconfig", + "/repos/{owner}/{repo}/actions/runners/registration-token", + "/repos/{owner}/{repo}/actions/runners/remove-token", + "/repos/{owner}/{repo}/actions/runners/{runner_id}", + "/repos/{owner}/{repo}/actions/runners/{runner_id}/labels", + "/repos/{owner}/{repo}/actions/runners/{runner_id}/labels/{name}", + "/repos/{owner}/{repo}/actions/runs", + "/repos/{owner}/{repo}/actions/runs/{run_id}", + "/repos/{owner}/{repo}/actions/runs/{run_id}/approvals", + "/repos/{owner}/{repo}/actions/runs/{run_id}/approve", + "/repos/{owner}/{repo}/actions/runs/{run_id}/artifacts", + "/repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}", + "/repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs", + "/repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/logs", + "/repos/{owner}/{repo}/actions/runs/{run_id}/cancel", + "/repos/{owner}/{repo}/actions/runs/{run_id}/deployment_protection_rule", + "/repos/{owner}/{repo}/actions/runs/{run_id}/force-cancel", + "/repos/{owner}/{repo}/actions/runs/{run_id}/jobs", + "/repos/{owner}/{repo}/actions/runs/{run_id}/logs", + "/repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments", + "/repos/{owner}/{repo}/actions/runs/{run_id}/rerun", + "/repos/{owner}/{repo}/actions/runs/{run_id}/rerun-failed-jobs", + "/repos/{owner}/{repo}/actions/runs/{run_id}/timing", + "/repos/{owner}/{repo}/actions/secrets", + "/repos/{owner}/{repo}/actions/secrets/public-key", + "/repos/{owner}/{repo}/actions/secrets/{secret_name}", + "/repos/{owner}/{repo}/actions/variables", + "/repos/{owner}/{repo}/actions/variables/{name}", + "/repos/{owner}/{repo}/actions/workflows", + "/repos/{owner}/{repo}/actions/workflows/{workflow_id}", + "/repos/{owner}/{repo}/actions/workflows/{workflow_id}/disable", + "/repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches", + "/repos/{owner}/{repo}/actions/workflows/{workflow_id}/enable", + "/repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs", + "/repos/{owner}/{repo}/actions/workflows/{workflow_id}/timing", + "/repos/{owner}/{repo}/activity", + "/repos/{owner}/{repo}/assignees", + "/repos/{owner}/{repo}/assignees/{assignee}", + "/repos/{owner}/{repo}/attestations", + "/repos/{owner}/{repo}/attestations/{subject_digest}", + "/repos/{owner}/{repo}/autolinks", + "/repos/{owner}/{repo}/autolinks/{autolink_id}", + "/repos/{owner}/{repo}/automated-security-fixes", + "/repos/{owner}/{repo}/branches", + "/repos/{owner}/{repo}/branches/{branch}", + "/repos/{owner}/{repo}/branches/{branch}/protection", + "/repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins", + "/repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews", + "/repos/{owner}/{repo}/branches/{branch}/protection/required_signatures", + "/repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks", + "/repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", + "/repos/{owner}/{repo}/branches/{branch}/protection/restrictions", + "/repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", + "/repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", + "/repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", + "/repos/{owner}/{repo}/branches/{branch}/rename", + "/repos/{owner}/{repo}/check-runs", + "/repos/{owner}/{repo}/check-runs/{check_run_id}", + "/repos/{owner}/{repo}/check-runs/{check_run_id}/annotations", + "/repos/{owner}/{repo}/check-runs/{check_run_id}/rerequest", + "/repos/{owner}/{repo}/check-suites", + "/repos/{owner}/{repo}/check-suites/preferences", + "/repos/{owner}/{repo}/check-suites/{check_suite_id}", + "/repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs", + "/repos/{owner}/{repo}/check-suites/{check_suite_id}/rerequest", + "/repos/{owner}/{repo}/code-scanning/alerts", + "/repos/{owner}/{repo}/code-scanning/alerts/{alert_number}", + "/repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances", + "/repos/{owner}/{repo}/code-scanning/analyses", + "/repos/{owner}/{repo}/code-scanning/analyses/{analysis_id}", + "/repos/{owner}/{repo}/code-scanning/codeql/databases", + "/repos/{owner}/{repo}/code-scanning/codeql/databases/{language}", + "/repos/{owner}/{repo}/code-scanning/codeql/variant-analyses", + "/repos/{owner}/{repo}/code-scanning/codeql/variant-analyses/{codeql_variant_analysis_id}", + "/repos/{owner}/{repo}/code-scanning/codeql/variant-analyses/{codeql_variant_analysis_id}/repos/{repo_owner}/{repo_name}", + "/repos/{owner}/{repo}/code-scanning/default-setup", + "/repos/{owner}/{repo}/code-scanning/sarifs", + "/repos/{owner}/{repo}/code-scanning/sarifs/{sarif_id}", + "/repos/{owner}/{repo}/code-security-configuration", + "/repos/{owner}/{repo}/codeowners/errors", + "/repos/{owner}/{repo}/codespaces", + "/repos/{owner}/{repo}/codespaces/devcontainers", + "/repos/{owner}/{repo}/codespaces/machines", + "/repos/{owner}/{repo}/codespaces/new", + "/repos/{owner}/{repo}/codespaces/permissions_check", + "/repos/{owner}/{repo}/codespaces/secrets", + "/repos/{owner}/{repo}/codespaces/secrets/public-key", + "/repos/{owner}/{repo}/codespaces/secrets/{secret_name}", + "/repos/{owner}/{repo}/collaborators", + "/repos/{owner}/{repo}/collaborators/{username}", + "/repos/{owner}/{repo}/collaborators/{username}/permission", + "/repos/{owner}/{repo}/comments", + "/repos/{owner}/{repo}/comments/{comment_id}", + "/repos/{owner}/{repo}/comments/{comment_id}/reactions", + "/repos/{owner}/{repo}/comments/{comment_id}/reactions/{reaction_id}", + "/repos/{owner}/{repo}/commits", + "/repos/{owner}/{repo}/commits/{commit_sha}/branches-where-head", + "/repos/{owner}/{repo}/commits/{commit_sha}/comments", + "/repos/{owner}/{repo}/commits/{commit_sha}/pulls", + "/repos/{owner}/{repo}/commits/{ref}", + "/repos/{owner}/{repo}/commits/{ref}/check-runs", + "/repos/{owner}/{repo}/commits/{ref}/check-suites", + "/repos/{owner}/{repo}/commits/{ref}/status", + "/repos/{owner}/{repo}/commits/{ref}/statuses", + "/repos/{owner}/{repo}/community/profile", + "/repos/{owner}/{repo}/compare/{basehead}", + "/repos/{owner}/{repo}/contents/{path}", + "/repos/{owner}/{repo}/contributors", + "/repos/{owner}/{repo}/dependabot/alerts", + "/repos/{owner}/{repo}/dependabot/alerts/{alert_number}", + "/repos/{owner}/{repo}/dependabot/secrets", + "/repos/{owner}/{repo}/dependabot/secrets/public-key", + "/repos/{owner}/{repo}/dependabot/secrets/{secret_name}", + "/repos/{owner}/{repo}/dependency-graph/compare/{basehead}", + "/repos/{owner}/{repo}/dependency-graph/sbom", + "/repos/{owner}/{repo}/dependency-graph/snapshots", + "/repos/{owner}/{repo}/deployments", + "/repos/{owner}/{repo}/deployments/{deployment_id}", + "/repos/{owner}/{repo}/deployments/{deployment_id}/statuses", + "/repos/{owner}/{repo}/deployments/{deployment_id}/statuses/{status_id}", + "/repos/{owner}/{repo}/dispatches", + "/repos/{owner}/{repo}/environments", + "/repos/{owner}/{repo}/environments/{environment_name}", + "/repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies", + "/repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id}", + "/repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules", + "/repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/apps", + "/repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/{protection_rule_id}", + "/repos/{owner}/{repo}/environments/{environment_name}/secrets", + "/repos/{owner}/{repo}/environments/{environment_name}/secrets/public-key", + "/repos/{owner}/{repo}/environments/{environment_name}/secrets/{secret_name}", + "/repos/{owner}/{repo}/environments/{environment_name}/variables", + "/repos/{owner}/{repo}/environments/{environment_name}/variables/{name}", + "/repos/{owner}/{repo}/events", + "/repos/{owner}/{repo}/forks", + "/repos/{owner}/{repo}/git/blobs", + "/repos/{owner}/{repo}/git/blobs/{file_sha}", + "/repos/{owner}/{repo}/git/commits", + "/repos/{owner}/{repo}/git/commits/{commit_sha}", + "/repos/{owner}/{repo}/git/matching-refs/{ref}", + "/repos/{owner}/{repo}/git/ref/{ref}", + "/repos/{owner}/{repo}/git/refs", + "/repos/{owner}/{repo}/git/refs/{ref}", + "/repos/{owner}/{repo}/git/tags", + "/repos/{owner}/{repo}/git/tags/{tag_sha}", + "/repos/{owner}/{repo}/git/trees", + "/repos/{owner}/{repo}/git/trees/{tree_sha}", + "/repos/{owner}/{repo}/hooks", + "/repos/{owner}/{repo}/hooks/{hook_id}", + "/repos/{owner}/{repo}/hooks/{hook_id}/config", + "/repos/{owner}/{repo}/hooks/{hook_id}/deliveries", + "/repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id}", + "/repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id}/attempts", + "/repos/{owner}/{repo}/hooks/{hook_id}/pings", + "/repos/{owner}/{repo}/hooks/{hook_id}/tests", + "/repos/{owner}/{repo}/import", + "/repos/{owner}/{repo}/import/authors", + "/repos/{owner}/{repo}/import/authors/{author_id}", + "/repos/{owner}/{repo}/import/large_files", + "/repos/{owner}/{repo}/import/lfs", + "/repos/{owner}/{repo}/installation", + "/repos/{owner}/{repo}/interaction-limits", + "/repos/{owner}/{repo}/invitations", + "/repos/{owner}/{repo}/invitations/{invitation_id}", + "/repos/{owner}/{repo}/issues", + "/repos/{owner}/{repo}/issues/comments", + "/repos/{owner}/{repo}/issues/comments/{comment_id}", + "/repos/{owner}/{repo}/issues/comments/{comment_id}/reactions", + "/repos/{owner}/{repo}/issues/comments/{comment_id}/reactions/{reaction_id}", + "/repos/{owner}/{repo}/issues/events", + "/repos/{owner}/{repo}/issues/events/{event_id}", + "/repos/{owner}/{repo}/issues/{issue_number}", + "/repos/{owner}/{repo}/issues/{issue_number}/assignees", + "/repos/{owner}/{repo}/issues/{issue_number}/assignees/{assignee}", + "/repos/{owner}/{repo}/issues/{issue_number}/comments", + "/repos/{owner}/{repo}/issues/{issue_number}/events", + "/repos/{owner}/{repo}/issues/{issue_number}/labels", + "/repos/{owner}/{repo}/issues/{issue_number}/labels/{name}", + "/repos/{owner}/{repo}/issues/{issue_number}/lock", + "/repos/{owner}/{repo}/issues/{issue_number}/reactions", + "/repos/{owner}/{repo}/issues/{issue_number}/reactions/{reaction_id}", + "/repos/{owner}/{repo}/issues/{issue_number}/timeline", + "/repos/{owner}/{repo}/keys", + "/repos/{owner}/{repo}/keys/{key_id}", + "/repos/{owner}/{repo}/labels", + "/repos/{owner}/{repo}/labels/{name}", + "/repos/{owner}/{repo}/languages", + "/repos/{owner}/{repo}/license", + "/repos/{owner}/{repo}/merge-upstream", + "/repos/{owner}/{repo}/merges", + "/repos/{owner}/{repo}/milestones", + "/repos/{owner}/{repo}/milestones/{milestone_number}", + "/repos/{owner}/{repo}/milestones/{milestone_number}/labels", + "/repos/{owner}/{repo}/notifications", + "/repos/{owner}/{repo}/pages", + "/repos/{owner}/{repo}/pages/builds", + "/repos/{owner}/{repo}/pages/builds/latest", + "/repos/{owner}/{repo}/pages/builds/{build_id}", + "/repos/{owner}/{repo}/pages/deployments", + "/repos/{owner}/{repo}/pages/deployments/{pages_deployment_id}", + "/repos/{owner}/{repo}/pages/deployments/{pages_deployment_id}/cancel", + "/repos/{owner}/{repo}/pages/health", + "/repos/{owner}/{repo}/private-vulnerability-reporting", + "/repos/{owner}/{repo}/projects", + "/repos/{owner}/{repo}/properties/values", + "/repos/{owner}/{repo}/pulls", + "/repos/{owner}/{repo}/pulls/comments", + "/repos/{owner}/{repo}/pulls/comments/{comment_id}", + "/repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions", + "/repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions/{reaction_id}", + "/repos/{owner}/{repo}/pulls/{pull_number}", + "/repos/{owner}/{repo}/pulls/{pull_number}/codespaces", + "/repos/{owner}/{repo}/pulls/{pull_number}/comments", + "/repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies", + "/repos/{owner}/{repo}/pulls/{pull_number}/commits", + "/repos/{owner}/{repo}/pulls/{pull_number}/files", + "/repos/{owner}/{repo}/pulls/{pull_number}/merge", + "/repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers", + "/repos/{owner}/{repo}/pulls/{pull_number}/reviews", + "/repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}", + "/repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments", + "/repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/dismissals", + "/repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/events", + "/repos/{owner}/{repo}/pulls/{pull_number}/update-branch", + "/repos/{owner}/{repo}/readme", + "/repos/{owner}/{repo}/readme/{dir}", + "/repos/{owner}/{repo}/releases", + "/repos/{owner}/{repo}/releases/assets/{asset_id}", + "/repos/{owner}/{repo}/releases/generate-notes", + "/repos/{owner}/{repo}/releases/latest", + "/repos/{owner}/{repo}/releases/tags/{tag}", + "/repos/{owner}/{repo}/releases/{release_id}", + "/repos/{owner}/{repo}/releases/{release_id}/assets", + "/repos/{owner}/{repo}/releases/{release_id}/reactions", + "/repos/{owner}/{repo}/releases/{release_id}/reactions/{reaction_id}", + "/repos/{owner}/{repo}/rules/branches/{branch}", + "/repos/{owner}/{repo}/rulesets", + "/repos/{owner}/{repo}/rulesets/rule-suites", + "/repos/{owner}/{repo}/rulesets/rule-suites/{rule_suite_id}", + "/repos/{owner}/{repo}/rulesets/{ruleset_id}", + "/repos/{owner}/{repo}/secret-scanning/alerts", + "/repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}", + "/repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations", + "/repos/{owner}/{repo}/secret-scanning/push-protection-bypasses", + "/repos/{owner}/{repo}/security-advisories", + "/repos/{owner}/{repo}/security-advisories/reports", + "/repos/{owner}/{repo}/security-advisories/{ghsa_id}", + "/repos/{owner}/{repo}/security-advisories/{ghsa_id}/cve", + "/repos/{owner}/{repo}/security-advisories/{ghsa_id}/forks", + "/repos/{owner}/{repo}/stargazers", + "/repos/{owner}/{repo}/stats/code_frequency", + "/repos/{owner}/{repo}/stats/commit_activity", + "/repos/{owner}/{repo}/stats/contributors", + "/repos/{owner}/{repo}/stats/participation", + "/repos/{owner}/{repo}/stats/punch_card", + "/repos/{owner}/{repo}/statuses/{sha}", + "/repos/{owner}/{repo}/subscribers", + "/repos/{owner}/{repo}/subscription", + "/repos/{owner}/{repo}/tags", + "/repos/{owner}/{repo}/tags/protection", + "/repos/{owner}/{repo}/tags/protection/{tag_protection_id}", + "/repos/{owner}/{repo}/tarball/{ref}", + "/repos/{owner}/{repo}/teams", + "/repos/{owner}/{repo}/topics", + "/repos/{owner}/{repo}/traffic/clones", + "/repos/{owner}/{repo}/traffic/popular/paths", + "/repos/{owner}/{repo}/traffic/popular/referrers", + "/repos/{owner}/{repo}/traffic/views", + "/repos/{owner}/{repo}/transfer", + "/repos/{owner}/{repo}/vulnerability-alerts", + "/repos/{owner}/{repo}/zipball/{ref}", + "/repos/{template_owner}/{template_repo}/generate", + "/repositories", + "/search/code", + "/search/commits", + "/search/issues", + "/search/labels", + "/search/repositories", + "/search/topics", + "/search/users", + "/teams/{team_id}", + "/teams/{team_id}/discussions", + "/teams/{team_id}/discussions/{discussion_number}", + "/teams/{team_id}/discussions/{discussion_number}/comments", + "/teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}", + "/teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}/reactions", + "/teams/{team_id}/discussions/{discussion_number}/reactions", + "/teams/{team_id}/invitations", + "/teams/{team_id}/members", + "/teams/{team_id}/members/{username}", + "/teams/{team_id}/memberships/{username}", + "/teams/{team_id}/projects", + "/teams/{team_id}/projects/{project_id}", + "/teams/{team_id}/repos", + "/teams/{team_id}/repos/{owner}/{repo}", + "/teams/{team_id}/teams", + "/user", + "/user/blocks", + "/user/blocks/{username}", + "/user/codespaces", + "/user/codespaces/secrets", + "/user/codespaces/secrets/public-key", + "/user/codespaces/secrets/{secret_name}", + "/user/codespaces/secrets/{secret_name}/repositories", + "/user/codespaces/secrets/{secret_name}/repositories/{repository_id}", + "/user/codespaces/{codespace_name}", + "/user/codespaces/{codespace_name}/exports", + "/user/codespaces/{codespace_name}/exports/{export_id}", + "/user/codespaces/{codespace_name}/machines", + "/user/codespaces/{codespace_name}/publish", + "/user/codespaces/{codespace_name}/start", + "/user/codespaces/{codespace_name}/stop", + "/user/docker/conflicts", + "/user/email/visibility", + "/user/emails", + "/user/followers", + "/user/following", + "/user/following/{username}", + "/user/gpg_keys", + "/user/gpg_keys/{gpg_key_id}", + "/user/installations", + "/user/installations/{installation_id}/repositories", + "/user/installations/{installation_id}/repositories/{repository_id}", + "/user/interaction-limits", + "/user/issues", + "/user/keys", + "/user/keys/{key_id}", + "/user/marketplace_purchases", + "/user/marketplace_purchases/stubbed", + "/user/memberships/orgs", + "/user/memberships/orgs/{org}", + "/user/migrations", + "/user/migrations/{migration_id}", + "/user/migrations/{migration_id}/archive", + "/user/migrations/{migration_id}/repos/{repo_name}/lock", + "/user/migrations/{migration_id}/repositories", + "/user/orgs", + "/user/packages", + "/user/packages/{package_type}/{package_name}", + "/user/packages/{package_type}/{package_name}/restore", + "/user/packages/{package_type}/{package_name}/versions", + "/user/packages/{package_type}/{package_name}/versions/{package_version_id}", + "/user/packages/{package_type}/{package_name}/versions/{package_version_id}/restore", + "/user/projects", + "/user/public_emails", + "/user/repos", + "/user/repository_invitations", + "/user/repository_invitations/{invitation_id}", + "/user/social_accounts", + "/user/ssh_signing_keys", + "/user/ssh_signing_keys/{ssh_signing_key_id}", + "/user/starred", + "/user/starred/{owner}/{repo}", + "/user/subscriptions", + "/user/teams", + "/user/{account_id}", + "/users", + "/users/{username}", + "/users/{username}/attestations/{subject_digest}", + "/users/{username}/docker/conflicts", + "/users/{username}/events", + "/users/{username}/events/orgs/{org}", + "/users/{username}/events/public", + "/users/{username}/followers", + "/users/{username}/following", + "/users/{username}/following/{target_user}", + "/users/{username}/gists", + "/users/{username}/gpg_keys", + "/users/{username}/hovercard", + "/users/{username}/installation", + "/users/{username}/keys", + "/users/{username}/orgs", + "/users/{username}/packages", + "/users/{username}/packages/{package_type}/{package_name}", + "/users/{username}/packages/{package_type}/{package_name}/restore", + "/users/{username}/packages/{package_type}/{package_name}/versions", + "/users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}", + "/users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore", + "/users/{username}/projects", + "/users/{username}/received_events", + "/users/{username}/received_events/public", + "/users/{username}/repos", + "/users/{username}/settings/billing/actions", + "/users/{username}/settings/billing/packages", + "/users/{username}/settings/billing/shared-storage", + "/users/{username}/social_accounts", + "/users/{username}/ssh_signing_keys", + "/users/{username}/starred", + "/users/{username}/subscriptions", + "/versions", + "/zen" +] diff --git a/tests/test_benchmarks_web_urldispatcher.py b/tests/test_benchmarks_web_urldispatcher.py index cca3be0c826..452f4afa7b3 100644 --- a/tests/test_benchmarks_web_urldispatcher.py +++ b/tests/test_benchmarks_web_urldispatcher.py @@ -1,7 +1,11 @@ """codspeed benchmarks for the URL dispatcher.""" import asyncio +import json import pathlib +import random +import string +from pathlib import Path from typing import NoReturn from unittest import mock @@ -46,11 +50,12 @@ async def handler(request: web.Request) -> NoReturn: app = web.Application() app.router.add_route("GET", "/", handler) app.freeze() + router = app.router request = _mock_request(method="GET", path="/") async def run_url_dispatcher_benchmark() -> None: for _ in range(resolve_count): - await app._router.resolve(request) + await router.resolve(request) @benchmark def _run() -> None: @@ -67,11 +72,12 @@ def test_resolve_static_root_route( app = web.Application() app.router.add_static("/", pathlib.Path(aiohttp.__file__).parent) app.freeze() + router = app.router request = _mock_request(method="GET", path="/") async def run_url_dispatcher_benchmark() -> None: for _ in range(resolve_count): - await app._router.resolve(request) + await router.resolve(request) @benchmark def _run() -> None: @@ -92,11 +98,12 @@ async def handler(request: web.Request) -> NoReturn: for count in range(250): app.router.add_route("GET", f"/api/server/dispatch/{count}/update", handler) app.freeze() + router = app.router request = _mock_request(method="GET", path="/api/server/dispatch/1/update") async def run_url_dispatcher_benchmark() -> None: for _ in range(resolve_count): - await app._router.resolve(request) + await router.resolve(request) @benchmark def _run() -> None: @@ -116,6 +123,7 @@ async def handler(request: web.Request) -> NoReturn: for count in range(250): app.router.add_route("GET", f"/api/server/dispatch/{count}/update", handler) app.freeze() + router = app.router requests = [ _mock_request(method="GET", path=f"/api/server/dispatch/{count}/update") @@ -124,7 +132,7 @@ async def handler(request: web.Request) -> NoReturn: async def run_url_dispatcher_benchmark() -> None: for request in requests: - await app._router.resolve(request) + await router.resolve(request) @benchmark def _run() -> None: @@ -152,12 +160,13 @@ async def handler(request: web.Request) -> NoReturn: for url in urls: app.router.add_route("GET", url, handler) app.freeze() + router = app.router requests = [_mock_request(method="GET", path=url) for url in urls] async def run_url_dispatcher_benchmark() -> None: for request in requests: - await app._router.resolve(request) + await router.resolve(request) @benchmark def _run() -> None: @@ -178,6 +187,7 @@ async def handler(request: web.Request) -> NoReturn: app.router.add_route("GET", f"/api/server/other/{count}/update", handler) app.router.add_route("GET", "/api/server/dispatch/{customer}/update", handler) app.freeze() + router = app.router requests = [ _mock_request(method="GET", path=f"/api/server/dispatch/{customer}/update") @@ -186,7 +196,121 @@ async def handler(request: web.Request) -> NoReturn: async def run_url_dispatcher_benchmark() -> None: for request in requests: - await app._router.resolve(request) + await router.resolve(request) + + @benchmark + def _run() -> None: + loop.run_until_complete(run_url_dispatcher_benchmark()) + + +def test_resolve_gitapi( + loop: asyncio.AbstractEventLoop, + benchmark: BenchmarkFixture, +) -> None: + """Resolve DynamicResource for simulated github API. + + The benchmark uses OpenAPI generated info for github. + To update the local data file please run the following command: + $ curl https://raw.githubusercontent.com/github/rest-api-description/refs/heads/main/descriptions/api.github.com/api.github.com.json | jq ".paths | keys" > github-urls.json + """ + + async def handler(request: web.Request) -> NoReturn: + assert False + + here = Path(__file__).parent + with (here / "github-urls.json").open() as f: + urls = json.load(f) + + app = web.Application() + for url in urls: + app.router.add_get(url, handler) + app.freeze() + router = app.router + + # PR reviews API was selected absolutely voluntary. + # It is not any special but sits somewhere in the middle of the urls list. + # If anybody has better idea please suggest. + + alnums = string.ascii_letters + string.digits + + requests = [] + for i in range(250): + owner = "".join(random.sample(alnums, 10)) + repo = "".join(random.sample(alnums, 10)) + pull_number = random.randint(0, 250) + requests.append( + _mock_request( + method="GET", path=f"/repos/{owner}/{repo}/pulls/{pull_number}/reviews" + ) + ) + + async def run_url_dispatcher_benchmark() -> None: + for request in requests: + await router.resolve(request) + + @benchmark + def _run() -> None: + loop.run_until_complete(run_url_dispatcher_benchmark()) + + +def test_resolve_gitapi_subapps( + loop: asyncio.AbstractEventLoop, + benchmark: BenchmarkFixture, +) -> None: + """Resolve DynamicResource for simulated github API, grouped in subapps. + + The benchmark uses OpenAPI generated info for github. + To update the local data file please run the following command: + $ curl https://raw.githubusercontent.com/github/rest-api-description/refs/heads/main/descriptions/api.github.com/api.github.com.json | jq ".paths | keys" > github-urls.json + """ + + async def handler(request: web.Request) -> NoReturn: + assert False + + here = Path(__file__).parent + with (here / "github-urls.json").open() as f: + urls = json.load(f) + + subapps = { + "gists": web.Application(), + "orgs": web.Application(), + "projects": web.Application(), + "repos": web.Application(), + "teams": web.Application(), + "user": web.Application(), + "users": web.Application(), + } + + app = web.Application() + for url in urls: + parts = url.split("/") + subapp = subapps.get(parts[1], app) + subapp.router.add_get(url, handler) + for key, subapp in subapps.items(): + app.add_subapp("/" + key, subapp) + app.freeze() + router = app.router + + # PR reviews API was selected absolutely voluntary. + # It is not any special but sits somewhere in the middle of the urls list. + # If anybody has better idea please suggest. + + alnums = string.ascii_letters + string.digits + + requests = [] + for i in range(250): + owner = "".join(random.sample(alnums, 10)) + repo = "".join(random.sample(alnums, 10)) + pull_number = random.randint(0, 250) + requests.append( + _mock_request( + method="GET", path=f"/repos/{owner}/{repo}/pulls/{pull_number}/reviews" + ) + ) + + async def run_url_dispatcher_benchmark() -> None: + for request in requests: + await router.resolve(request) @benchmark def _run() -> None: