Problem
GET /search is the highest externally consumed endpoint in BioPortal (~138K requests/day, ~96 rpm average). It averages ~890 ms (median 848 ms, p95 1.34 s, p99 2.19 s, Apdex 0.5).
New Relic segment data shows the time is not spent in I/O: Solr answers in ~10 ms (~1% of transaction time), Redis adds ~44 ms across ~15 round trips, and the triple store is not called at all on ~98% of requests. Roughly 830 ms per request is in-process Ruby compute, previously invisible as a single opaque controller segment.
Originally flagged by @alexskr in Slack: the Solr server response is fast, but a 1-second average response should be investigated to see where the time goes.
Evidence so far
Duration segmentation over 24 h (137,960 requests):
| Band |
Count |
Avg duration |
All I/O combined |
| < 2 s |
136,186 (98.7%) |
870 ms |
~55 ms |
| 2 to 5 s |
1,761 (1.3%) |
2,377 ms |
~195 ms |
| > 5 s |
13 |
10,763 ms |
~11,400 ms (AllegroGraph query storms on SPARQL cache miss; rare, tracked separately) |
PR #243 added method tracers that decompose the opaque segment. A local verification run (staging backends) attributes ~86% of the search pipeline to restricted_ontologies (helpers/application_helper.rb): on every site-wide search it loads all ~1,200 ontologies as goo model objects with a heavyweight attribute set, filters the full set (slice, user, ACL), then keeps only the acronyms to build the Solr filter query. The output is identical between requests for anonymous no-slice traffic and changes only when ontologies or ACLs change. Production tracer data (post v7.4.3 deploy) will confirm the share at scale.
Candidate improvements (to be validated against prod tracer data)
- Slim the site-wide attribute load to
acronym + access-control attributes (the ontology-scoped branch already does this).
- Cache the computed accessible-acronym list (keyed by anonymous/slice/user, short TTL or invalidated on ontology/ACL change) instead of recomputing per request.
- Avoid enumerating ~1,200 acronyms in the Solr
fq for unrestricted traffic (e.g. exclude the small private set instead).
- Batch the ~15 sequential Redis round trips (~44 ms, second-order).
Expected impact if the restricted_ontologies share holds in prod: average response time roughly halved, with the 2 to 5 s band compressed correspondingly.
Acceptance criteria
- Production tracer data identifies the dominant segment and the fix targets it
- Measurable before/after improvement in
/search average and p95 from the same New Relic segments
- No behavior change to search results, access control, or response format
Related
Problem
GET /searchis the highest externally consumed endpoint in BioPortal (~138K requests/day, ~96 rpm average). It averages ~890 ms (median 848 ms, p95 1.34 s, p99 2.19 s, Apdex 0.5).New Relic segment data shows the time is not spent in I/O: Solr answers in ~10 ms (~1% of transaction time), Redis adds ~44 ms across ~15 round trips, and the triple store is not called at all on ~98% of requests. Roughly 830 ms per request is in-process Ruby compute, previously invisible as a single opaque controller segment.
Originally flagged by @alexskr in Slack: the Solr server response is fast, but a 1-second average response should be investigated to see where the time goes.
Evidence so far
Duration segmentation over 24 h (137,960 requests):
PR #243 added method tracers that decompose the opaque segment. A local verification run (staging backends) attributes ~86% of the search pipeline to
restricted_ontologies(helpers/application_helper.rb): on every site-wide search it loads all ~1,200 ontologies as goo model objects with a heavyweight attribute set, filters the full set (slice, user, ACL), then keeps only the acronyms to build the Solr filter query. The output is identical between requests for anonymous no-slice traffic and changes only when ontologies or ACLs change. Production tracer data (post v7.4.3 deploy) will confirm the share at scale.Candidate improvements (to be validated against prod tracer data)
acronym+ access-control attributes (the ontology-scoped branch already does this).fqfor unrestricted traffic (e.g. exclude the small private set instead).Expected impact if the
restricted_ontologiesshare holds in prod: average response time roughly halved, with the 2 to 5 s band compressed correspondingly.Acceptance criteria
/searchaverage and p95 from the same New Relic segmentsRelated