• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ruby-grape / grape
97%
master: 97%

Build:
Build:
LAST BUILD BRANCH: router-compile-registered-methods
DEFAULT BRANCH: master
Repo Added 04 Apr 2013 06:08AM UTC
Files 169
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

LAST BUILD ON BRANCH perf/endpoint-helpers-prototype
branch: perf/endpoint-helpers-prototype
CHANGE BRANCH
x
Reset
  • perf/endpoint-helpers-prototype
  • DateFormat
  • Handle_json_array
  • ISSUE-2321
  • Issue-1908
  • active_support_6_1_minimal
  • add-agents-md
  • add_irb_in_gemfile_for_bundle_console_warning
  • add_numericality_validator
  • add_rack_3_2_gemfile
  • add_rails_8_1_on_ci
  • add_ruby_3_4
  • add_ruby_4_0_cli
  • api_override_singleton_methods
  • array-param-regression
  • as-explicit-kwarg
  • benchmark/results-machine-spec
  • body-metadata
  • bugfix/1577
  • bugfix/1970
  • bugfix/1986
  • bugfix/2041
  • bugfix/autoload
  • bugfix/memory-leak
  • build_with_registry
  • chore/agents-md-style-rules
  • chore/cleanup-on-compilation
  • chore/coercion-tests
  • chore/drop-middleware-globals
  • chore/guard-clause-cleanup
  • chore/json-parse-fallback
  • chore/min-ruby-3.3
  • chore/normalize-eql-aliases
  • chore/primitive-coercer-spec
  • chore/prune-requires
  • chore/raise-dependency-lower-bounds
  • chore/readability-guard-clauses
  • chore/readability-pass
  • chore/version-throughput-deltas
  • clean_up_useless_dependencies
  • cleanup-deprecated-code
  • compiled_endpoints
  • contract_scope_validator_public_schema
  • cookies_delegation
  • crush_desclared_params
  • custom-validator-namespace-lookup
  • declared-params-scope-kwarg
  • declared_params_optional_array
  • deprecate-positional-options-hash
  • deprecated_endpoint_return
  • doc
  • doc/remove_manual_toc_and_toc_danger_check
  • doc/remove_toc
  • doc/update_reload_documentation_for_current_Rails_versions
  • docs/format-removal-note
  • docs/readme-typos-and-fixnum-cleanup
  • draft/middleware-options-data
  • drop_namespace_description
  • drop_ruby_3_0_as_7_0
  • drop_support_ruby_2_7_0
  • dynamic_registration
  • empty_string_and_bool
  • enable_branch_coverage
  • enable_frozen_string_literal_ci
  • endpoint_api_kwarg
  • endpoint_app_kwarg
  • endpoint_cleanup
  • endpoint_http_methods_kwarg
  • endpoint_path_kwarg
  • entity-dsl
  • eql-hash-consistency
  • erik/remove-faulty-documentation-about-blank-values
  • exclude_ruby_3_2_rails_edge
  • explicit-required-flag
  • explicit_route_options
  • exposes-to-s
  • extract_entity_dsl_and_kwargs_with
  • extract_testing_module
  • extract_translation
  • failing_spec_for_1967
  • faster_normalize_path
  • feature/endpoint-logger
  • feature/error-formatter-kwargs-2527
  • feature/grape-api-setup-var-array
  • feature/hash-oneof-2385
  • feature/return_of_return
  • feature/warn-on-helper-overrides
  • feature_rack_lint
  • fix-636
  • fix-badges
  • fix-before-each-nil-nomethoderror
  • fix-cascade-dsl-getter
  • fix-coercer-request-time-state
  • fix-compile-instance-race
  • fix-docs
  • fix-helper-inheritance
  • fix-line-anchored-regexes
  • fix-multiple-type-values-check
  • fix-options-const-defined-object-fallback
  • fix-path-versioner-root-version
  • fix-router-cascade-routing-args
  • fix-router-cascade-sibling-routes
  • fix-top-level-entity-constant
  • fix-typo
  • fix-validator-non-hash-guard
  • fix/2748-structured-message-leak
  • fix/2763-multijson-deprecations
  • fix/auth-base-subclass-issue-2669
  • fix/avoid_multiple_mounts_pollution
  • fix/base-only-rescue-handlers
  • fix/cascade_reading_api_level
  • fix/case-insensitive-media-types
  • fix/custom-type-coercer-symbolize-collection
  • fix/entity-lookup-own-class-first
  • fix/error-rendering-failsafe
  • fix/grape-exceptions-precedence
  • fix/greedy-route-params-for
  • fix/json-load-create-additions
  • fix/json-use-parse
  • fix/multixml-deprecation
  • fix/nested-array-validation-bypass
  • fix/path-param-encoding
  • fix/recompile-after-route-added
  • fix/recompile-settings-mutation-race
  • fix/redirect-plain-text-body
  • fix/reduce_base_route_array_allocation
  • fix/rescue-from-internal-errors-2482
  • fix/route-param-named-version
  • fix/route-success-failure-readers
  • fix/router-request-time-map-mutation
  • fix/safe-default-rack-exception
  • fix/sendfile_test_fix
  • fix/stackable-copy-aliasing
  • fix/variant-collection-coercer-to-s
  • fix/warn-shadowed-rescue-from
  • fix_2566_memory_leak
  • fix_all_media_types_regression
  • fix_before_each_no_method_error
  • fix_coercer_cache
  • fix_danger_workflow
  • fix_endpoint_status_when_not_calling_error!
  • fix_gh_workflow_annotations_warnings
  • fix_grape_swagger_test
  • fix_helpers_methods_in_public_scope
  • fix_leaky_slash
  • fix_middleware_keywords
  • fix_param_scope_thread_safety
  • fix_registry_warning_message
  • fix_require_logger
  • fix_routes_memoization
  • fix_shared_params_empty_args
  • fix_style_optional_boolean_parameter
  • format_header_best_q_match
  • forward_match_kwarg
  • freeze-coercers-and-sync-caches
  • funding
  • happy_rubocop
  • head_route_on_route_class
  • hook-readme
  • inheritable-setting-auth-params-builder
  • inheritable-setting-callbacks
  • inheritable-setting-cheap-equality
  • inheritable-setting-content-negotiation
  • inheritable-setting-contract-key-map
  • inheritable-setting-finale
  • inheritable-setting-format-defaults
  • inheritable-setting-integration
  • inheritable-setting-middleware-helpers
  • inheritable-setting-params-state
  • inheritable-setting-representations
  • inheritable-setting-rescue-options
  • inheritable-setting-routing-flags
  • inheritable-setting-routing-scopes
  • inheritable-setting-versioning
  • instance-to-s-nil-fallback
  • instance_to_s_delegation
  • internalize-stackable-storage
  • issue-1775
  • issue-2385
  • layer1-thread-safety-invariants
  • layer2-concurrency-stress
  • lazy_block
  • lazy_compile
  • less_active_support_concern
  • less_parse_nested_query
  • master
  • migrate-danger-pr-comment
  • migrate-to-dry-configurable
  • mount-refresh-internal
  • mountable_apis
  • namespace_route_param_explicit_kwargs
  • optimize/parameters-extract-options-non-mutating
  • optimize_api_documentation
  • params-declare-extraction
  • patch-1
  • perf/avoid-empty-hash-merges
  • perf/build-headers-each-header
  • perf/config-param-builder
  • perf/content-type-lookup
  • perf/formatter-content-negotiation
  • perf/formatter-rack-tuple
  • perf/formatter-skip-rack-request
  • perf/instrument-only-when-subscribed
  • perf/lazy-base-inheritable-new-values
  • perf/lazy-error-backtrace
  • perf/lazy-inheritable-setting-fields
  • perf/lazy-param-scope-tracker
  • perf/lazy-response-cookies
  • perf/path-normalizer-fast-path
  • perf/precompute-middleware-caches
  • perf/request-hot-path-polish
  • perf/router-transaction-no-proc
  • perf/routing-args-in-place-merge
  • perf/routing-args-single-hash
  • perf/share-content-type-tables
  • perf/skip-capture-free-param-extraction
  • perf/skip-default-version-pattern
  • perf/skip-empty-validation-errors-alloc
  • perf/skip-redundant-routing-args-write
  • perf/skip-validation-backtrace
  • perf/stackable-empty-singleton
  • perf/versioner-path-prefix
  • perf/versioner-prefix-each
  • precompiled_json
  • private_namespace_reverse_stackable_with_hash
  • private_within_namespace
  • query-http-method
  • rack_request_error
  • real-api-integration-test
  • reduce_array_alloc_on_setup
  • refactor/api-instance-dsl-modules
  • refactor/attrs_iterator
  • refactor/auth-dsl-kwargs
  • refactor/available-media-types-attr-reader
  • refactor/base-validator-encapsulation
  • refactor/coerce-options-data
  • refactor/de-morgan-conditions
  • refactor/declared-params-handler
  • refactor/declared_availability
  • refactor/define-method-cleanup
  • refactor/drop-indifferent-and-reverse-merge-requires
  • refactor/dsl-group-validators-dry
  • refactor/encapsulate-reverse-stackable
  • refactor/endpoint-options-data
  • refactor/endpoint-options-route-enabled
  • refactor/error-response-data
  • refactor/error-response-value-object
  • refactor/extract-handler-case-when
  • refactor/extract-path-normalizer
  • refactor/guard-clauses-style
  • refactor/inline-mustermann-grape
  • refactor/lazy-base-ancestor
  • refactor/middleware-cleanups
  • refactor/mountable-marker
  • refactor/named_kwargs_params_scope
  • refactor/nest-path-in-pattern
  • refactor/params-dsl-using-except-kwargs
  • refactor/precomputed-content-types-move
  • refactor/replace-tap-usages
  • refactor/rescue-from-explicit-first-arg
  • refactor/rescue-handler-dedup
  • refactor/router-pattern-delegation
  • refactor/router-simplification
  • refactor/shared-options-data
  • refactor/stateless-attributes-iterator
  • refactor/validates-pure-helpers
  • refactor/validation-errors-drop-enumerable
  • refactor/validations-spec-self-validate
  • refactor/version-guard-clause
  • refactor_available_media_types_in_header_middleware
  • refactor_declared_params_handling
  • refactor_http_headers
  • refactor_mime_type_for
  • refactor_route_setting_internal_usage
  • refactor_setting_get_or_set
  • refs/heads/master
  • refs/tags/v1.7.1
  • refs/tags/v1.8.0
  • refs/tags/v2.0.0
  • regression/json-error-formatter-double-wrap
  • release/3.2.1
  • remove-inheritable-values
  • remove-reverse-stackable-values
  • remove-unused-constant
  • remove/http-digest-dsl
  • remove_deprecated_param_builder_extensions
  • remove_guard
  • remove_instance_variable_defined
  • remove_namespace_reverse_stackable_from_public_interface
  • remove_namespace_stackable_and_inheritable_from_public_space
  • remove_namespace_stackable_with_hash_from_public_interface
  • remove_non_supported_jsonapi
  • remove_obsolete_docker_compose_version
  • remove_path_dup
  • remove_pattern_format
  • remove_settings_unset_functions
  • remove_strict_hash_configuration
  • remove_test_prof
  • replace_try_by_respond_to
  • rescue_from
  • resolve_performace_issue_with_given
  • restore-routing-args-per-attempt
  • revert-1953-chore/micto-optimization-3
  • revert-2726-refactor/stateless-attributes-iterator
  • revert-2774-forward_match_kwarg
  • revert-wrong-commit
  • revisit_auth_middleware
  • revisit_endpoint_helpers_and_new
  • revisit_middleware_default_options
  • revisit_validators
  • robust_mounted_app_comparison
  • route-default-hash-collision
  • route-default-reads-description-key
  • route-default-response-alias
  • route-scope-accessors
  • route_attributes_kwargs
  • route_match_params_via_pattern
  • router-compile-registered-methods
  • rubocop-mutable-constant-recursive
  • ruby3_handling_argument_delegation
  • ruby_3_1_shorthand_kwargs
  • ruby_optimizations
  • ruby_style_send
  • security/mounted-rack-auth-and-html-escape
  • skip_instrumentation_no_validators
  • skip_run_filters_on_empty
  • small_refactor_versioner_middleware
  • spec-only-rack-class
  • support-open-ranges-values
  • test-adversarial-nesting-depth
  • test/grape-swagger-integration
  • try_pattern_instead_of_respond_to
  • unify-group-type-check
  • untangle_route_params
  • update-simplecov
  • update_min_ruby_version_and_rubocop
  • update_return_upgrading_notes_and_simplify_execute
  • update_rubocop
  • update_rubocop_1_71_2
  • update_rubocop_1_88
  • update_rubocop_and_autocorrect
  • upgrade-mustermann
  • upgrade-rubocop
  • upgrading-array-unknown-element-type
  • upgrading-description
  • use_forwardable
  • use_require_relative_in_gemspec
  • v0.19.2
  • v1.0.0
  • v1.0.1
  • v1.0.2
  • v1.0.3
  • v1.1.0
  • v1.2.0
  • v1.2.1
  • v1.2.2
  • v1.2.3
  • v1.2.4
  • v1.2.5
  • v1.3.0
  • v1.3.1
  • v1.3.2
  • v1.3.3
  • v1.4.0
  • v1.5.0
  • v1.5.1
  • v2.1.0
  • v2.1.1
  • v2.1.2
  • v2.1.3
  • v2.2.0
  • v2.3.0
  • v2.4.0
  • v3.0.0
  • v3.0.1
  • v3.1.0
  • v3.1.1
  • v3.2.0
  • v3.2.1
  • v3.3.0
  • v3.3.1
  • v3.3.1_release
  • v3.3.2
  • v3.3.2_release
  • v3.3.3
  • v3.3.3_release
  • v3.3.4
  • v3.3.4_release
  • v3.3.5
  • v3.3.5_release
  • valid_encoding_before_scrubing
  • validators_bad_encoding

02 Sep 2026 06:46AM UTC coverage: 96.973% (+0.02%) from 96.95%
33600352030

Pull #2872

github

ericproulx
Include endpoint helpers once instead of on every request

Helpers are instance methods on the endpoint, because the route block is bound
to the endpoint and runs against it. They are also per-endpoint — including
them into Grape::Endpoint itself would leak one API's helpers into every
endpoint in the process — so they went onto the per-request copy:

    def call(env)
      dup.call!(env)
    end

    def call!(env)
      ...
      singleton_class.include(@helpers) if @helpers

That had to happen per request rather than once: Object#dup deliberately does
not carry a singleton class over, so including the helpers on the shared
endpoint would never reach the copies that actually serve requests.

The cost is not the include. `dup` plus `include` measures ~510 ns against
~110 ns for `dup` alone, which would be under 2% of a request. The expense is
that `singleton_class` on a fresh copy *creates a class*, and a class nothing
has called through yet has no method cache. Counting allocations: the dup, its
singleton class and the iclasses are 4 objects, and the first call to each
distinct method through that class costs 3 more — paid again on the next
request, for every helper, for the route block, and for every DSL method the
endpoint answers.

Include them once, at compile! time, into a subclass owned by this endpoint,
and copy the endpoint's state onto an instance of it. Each request then copies
an object whose class has been warm since boot, and request handling no longer
mutates a class at all.

On a small API with helpers, params and validations (median of 9 runs, Ruby
4.0.5, single-threaded Benchmark.ips):

                          YJIT                   no-YJIT          objects/req
    GET    40,853 -> 51,605  (+26%)   19,574 -> 21,368  (+9%)      154 -> 121
    POST   40,045 -> 51,009  (+27%)   19,657 -> 21,711  (+10%)     157 -> 123

An endpoint that declares no helpers is its own prototype: throughput and
allocation counts there are unchanged.

On... (continued)
Pull Request #2872: Include endpoint helpers once instead of on every request

1237 of 1330 branches covered (93.01%)

Branch coverage included in aggregate %.

10 of 10 new or added lines in 1 file covered. (100.0%)

3921 of 3989 relevant lines covered (98.3%)

27245.97 hits per line

Relevant lines Covered
Build:
Build:
3989 RELEVANT LINES 3921 COVERED LINES
27245.97 HITS PER LINE
Source Files on perf/endpoint-helpers-prototype
  • Tree
  • List 169
  • Changed 2
  • Source Changed 1
  • Coverage Changed 2
Coverage ∆ File Lines Relevant Covered Missed Hits/Line Branch Hits Branch Misses

Recent builds

Builds Branch Commit Type Ran Committer Via Coverage
33600352030 perf/endpoint-helpers-prototype Include endpoint helpers once instead of on every request Helpers are instance methods on the endpoint, because the route block is bound to the endpoint and runs against it. They are also per-endpoint — including them into Grape::Endpoint itself ... Pull #2872 02 Sep 2026 06:46AM UTC ericproulx github
96.97
33553892511 perf/endpoint-helpers-prototype Include endpoint helpers once instead of on every request Helpers are instance methods on the endpoint, because the route block is bound to the endpoint and runs against it. They are also per-endpoint — including them into Grape::Endpoint itself ... Pull #2872 01 Sep 2026 08:12PM UTC ericproulx github
96.97
33415163133 perf/endpoint-helpers-prototype Merge branch 'master' into perf/endpoint-helpers-prototype Pull #2872 31 Aug 2026 04:38PM UTC web-flow github
96.97
33380104055 perf/endpoint-helpers-prototype Include endpoint helpers once instead of on every request Helpers are instance methods on the endpoint, because the route block is bound to the endpoint and runs against it. They are also per-endpoint — including them into Grape::Endpoint itself ... Pull #2872 31 Aug 2026 09:56AM UTC ericproulx github
97.0
33379659757 perf/endpoint-helpers-prototype Include endpoint helpers once instead of on every request Helpers are instance methods on the endpoint, because the route block is bound to the endpoint and runs against it. They are also per-endpoint — including them into Grape::Endpoint itself ... Pull #2872 31 Aug 2026 09:50AM UTC ericproulx github
97.0
33379390620 perf/endpoint-helpers-prototype Include endpoint helpers once instead of on every request Helpers are instance methods on the endpoint, because the route block is bound to the endpoint and runs against it. They are also per-endpoint — including them into Grape::Endpoint itself ... Pull #2872 31 Aug 2026 09:47AM UTC ericproulx github
97.0
33378892198 perf/endpoint-helpers-prototype Include endpoint helpers once instead of on every request Helpers are instance methods on the endpoint, because the route block is bound to the endpoint and runs against it. They are also per-endpoint — including them into Grape::Endpoint itself ... Pull #2872 31 Aug 2026 09:41AM UTC ericproulx github
97.0
33378858587 perf/endpoint-helpers-prototype Merge 84c885578 into 4b32ecce3 Pull #2872 31 Aug 2026 09:40AM UTC web-flow github
97.0
33378832180 perf/endpoint-helpers-prototype Include endpoint helpers once instead of on every request Helpers are instance methods on the endpoint, because the route block is bound to the endpoint and runs against it. They are also per-endpoint — including them into Grape::Endpoint itself ... push 31 Aug 2026 09:40AM UTC ericproulx github
97.0
See All Builds (3635)
  • Repo on GitHub
  • CI Project
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc