23 releases
Uses new Rust 2024
| new 0.1.26 | Nov 7, 2025 |
|---|---|
| 0.1.25 | Oct 19, 2025 |
| 0.1.16 | Sep 11, 2025 |
| 0.1.12 | Aug 27, 2025 |
#168 in Debugging
1,340 downloads per month
Used in helios-sof
36MB
91K
SLoC
helios-fhirpath
This is an implementation of HL7's FHIRPath Specification - 3.0.0-ballot written in Rust.
This implementation is available for testing in Brian Postlethwaite's FHIRPath Lab.
Table of Contents
About FHIRPath
FHIRPath is a path-based navigation and extraction language for healthcare data that is used in many different contexts within healthcare IT systems. Here are the main places where FHIRPath is implemented and used:
FHIR Specification and Resource Validation
FHIRPath is used to define and express constraints and co-occurrence rules in FHIR resources within the FHIR specification.
Example (Validation Invariant):
reference.startsWith('#').not() or
($context.reference.substring(1) in $resource.contained.id)
This invariant ensures that a local reference in a resource actually points to a contained resource that exists, checking that the reference (if it starts with "#") points to a valid contained resource ID.
Relevant Specification Link:
FHIR Search Parameter Definitions
FHIRPath defines what contents a search parameter refers to in FHIR resources.
Example (Search Parameter Path):
Patient.name.given
This path is used in a search parameter definition to specify that the search parameter applies to a patient's given names.
More Complex Example:
Patient.extension('http://example.org/myExtension').value
This path is used to create a search parameter that indexes values from a specific extension.
Relevant Specification Link:
FHIR Implementation Guides
FHIRPath is used to express constraints in implementation guides, particularly for profile definitions.
Example (Profile Constraint):
telecom.where(system='phone').exists() or telecom.where(system='email').exists()
This constraint requires that a resource has at least one telecom with either a phone or email system.
Example (Slicing Discriminator):
Observation.category
This path is used as a discriminator for slicing, meaning the category element will define uniqueness in sliced arrays.
Relevant Specification Link:
Clinical Decision Support
FHIRPath is used in clinical decision support systems, particularly within CDS Hooks and smart apps.
Example (CDS Hook Prefetch Template):
"prefetch": {
"patient": "Patient/{{context.patientId}}",
"medications": "MedicationRequest?patient={{context.patientId}}&status=active",
"conditions": "Condition?patient={{context.patientId}}&clinicalStatus=active&_fhirpath=code.memberOf('http://example.org/ValueSet/ChronicConditions')"
}
This prefetch template uses FHIRPath to filter conditions to only those with codes in a specific value set.
Example (Clinical Rule):
Observation.where(code.coding.system='http://loinc.org' and code.coding.code='8480-6')
.value.quantity > 140
This expression identifies systolic blood pressure observations with values above 140.
Relevant Specification Link:
Terminology Service Integration
FHIRPath provides access to terminology services through a %terminologies object. This implementation supports all standard terminology operations.
⚠️ IMPORTANT: Default Terminology Servers By default, this implementation uses test terminology servers:
- R4/R4B:
https://tx.fhir.org/r4/ - R5:
https://tx.fhir.org/r5/
DO NOT USE THESE DEFAULT SERVERS IN PRODUCTION! They are test servers with limited resources and no SLA.
Configuring a Terminology Server:
# Via environment variable
export FHIRPATH_TERMINOLOGY_SERVER=https://your-terminology-server.com/fhir
# Via CLI option
fhirpath-cli --terminology-server https://your-terminology-server.com/fhir ...
# Via server option
fhirpath-server --terminology-server https://your-terminology-server.com/fhir
Supported %terminologies Functions:
# Expand a ValueSet
%terminologies.expand('http://hl7.org/fhir/ValueSet/administrative-gender')
# Lookup code details
%terminologies.lookup(Observation.code.coding.first())
# Validate against ValueSet
%terminologies.validateVS('http://hl7.org/fhir/ValueSet/observation-vitalsignresult', Observation.code.coding.first())
# Validate against CodeSystem
%terminologies.validateCS('http://loinc.org', Observation.code.coding.first())
# Check code subsumption
%terminologies.subsumes('http://snomed.info/sct', '73211009', '5935008')
# Translate using ConceptMap
%terminologies.translate('http://hl7.org/fhir/ConceptMap/cm-address-use-v2', Patient.address.use)
memberOf Function:
# Check if a coding is member of a ValueSet
Observation.code.coding.where(memberOf('http://hl7.org/fhir/ValueSet/observation-vitalsignresult'))
Example with Parameters:
# Expand with count limit
%terminologies.expand('http://hl7.org/fhir/ValueSet/languages', {'count': '10'})
# Validate with language parameter
%terminologies.validateVS('http://hl7.org/fhir/ValueSet/condition-clinical',
Condition.clinicalStatus.coding.first(),
{'language': 'es'})
Relevant Specification Link:
FHIR Resource Mapping and Transformation
FHIRPath is used to map between different FHIR versions or between FHIR and other formats.
Example (Mapping Rule):
source.telecom.where(system='phone').value
This expression might be used in a mapping language to extract phone numbers from a source resource.
Relevant Specification Link:
SQL on FHIR
The SQL on FHIR specification leverages FHIRPath to define flattened tabular views of FHIR data that can be queried using standard SQL.
Example ViewDefinition:
{
"resourceType": "ViewDefinition",
"id": "patient-demographics",
"name": "PatientDemographics",
"title": "Basic Patient Demographics",
"description": "A flattened view of key patient demographic information",
"from": {
"resourceType": "Patient"
},
"select": [
{
"column": [
{"name": "id", "path": "getResourceKey()"},
{"name": "birth_date", "path": "birthDate"},
{"name": "gender", "path": "gender"},
{"name": "first_name", "path": "name.where(use='official').given.first()"},
{"name": "last_name", "path": "name.where(use='official').family"},
{"name": "ssn", "path": "identifier.where(system='http://hl7.org/fhir/sid/us-ssn').value"},
{"name": "email", "path": "telecom.where(system='email').value"},
{"name": "phone", "path": "telecom.where(system='phone' and use='mobile').value"},
{"name": "address_line", "path": "address.where(use='home').line.join(', ')"},
{"name": "city", "path": "address.where(use='home').city"},
{"name": "state", "path": "address.where(use='home').state"},
{"name": "postal_code", "path": "address.where(use='home').postalCode"}
]
}
]
}
Relevant Specification Link:
Features Implemented
Legend:
- ✅ Implemented
- 🟡 Partially Implemented (Basic functionality, known limitations)
- ❌ Not Implemented
- 🚧 In Progress
- (STU) - Standard for Trial Use in the specification
Expressions
- Literals
- Boolean: ✅
- String: ✅
- Integer: ✅
- Long (STU): 🟡 (Parser support, runtime implementation gaps)
- Decimal: ✅
- Date: ✅ (Full parsing and arithmetic support)
- Time: ✅ (Full parsing and comparison support)
- DateTime: ✅ (Full parsing, timezone and arithmetic support)
- Quantity: 🟡 (Basic value/unit storage, limited unit conversion)
- Time-valued Quantities: 🟡 (Keywords parsed, conversion implementation needed)
Functions
- Existence
- empty(): ✅
- exists(): ✅
- all(): ✅
- allTrue(): ✅
- anyTrue(): ✅
- allFalse(): ✅
- anyFalse(): ✅
- subsetOf(): ✅
- supersetOf(): ✅
- count(): ✅
- distinct(): ✅
- isDistinct(): ✅
- Filtering and Projection
- Subsetting
- Indexer
[]: ✅ - single(): ✅
- first(): ✅
- last(): ✅
- tail(): ✅
- skip(): ✅
- take(): ✅
- intersect(): ✅
- exclude(): ✅
- Indexer
- Combining
- Conversion
- Implicit Conversions: ✅ (Integer/Decimal)
- iif(): ✅
- toBoolean(): ✅
- convertsToBoolean(): ✅
- toInteger(): ✅
- convertsToInteger(): ✅
- toLong() (STU): ✅
- convertsToLong() (STU): ✅
- toDate(): ✅
- convertsToDate(): ✅
- toDateTime(): ✅
- convertsToDateTime(): ✅
- toDecimal(): ✅
- convertsToDecimal(): ✅
- toQuantity(): 🟡 (Basic types, no unit conversion)
- convertsToQuantity(): 🟡 (Basic types, no unit conversion)
- toString(): ✅
- convertsToString(): ✅
- toTime(): ✅
- convertsToTime(): ✅
- String Manipulation
- indexOf(): ✅
- lastIndexOf() (STU): ✅
- substring(): ✅
- startsWith(): ✅
- endsWith(): ✅
- contains(): ✅
- upper(): ✅
- lower(): ✅
- replace(): ✅
- matches(): ✅
- matchesFull() (STU): ✅
- replaceMatches(): ✅
- length(): ✅
- toChars(): ✅
- encode(): ✅
- decode(): ✅
- Additional String Functions (STU): ✅
- escape(): ✅ (html, json targets)
- unescape(): ✅ (html, json targets)
- split(): ✅
- trim(): ✅
- Math (STU): ✅
- Tree Navigation
- children(): ✅
- descendants(): ✅
- extension(): ✅ (Full support for object and primitive extensions with variable resolution)
- Utility Functions
- trace(): ✅ (With projection support)
- now(): ✅
- timeOfDay(): ✅
- today(): ✅
- defineVariable() (STU): ✅
- lowBoundary() (STU): ✅ (Full support for Decimal, Date, DateTime, and Time)
- highBoundary() (STU): ✅ (Full support for Decimal, Date, DateTime, and Time)
- precision() (STU): ✅ (See limitation for decimal trailing zeros)
- Date/DateTime/Time Component Extraction (STU): ✅ (All component functions implemented: yearOf, monthOf, dayOf, hourOf, minuteOf, secondOf, millisecondOf)
Operations
- Equality
=(Equals): ✅ (Full support for all types including dates and quantities)~(Equivalent): ✅ (Full equivalence checking)!=(Not Equals): ✅!~(Not Equivalent): ✅
- Comparison
>(Greater Than): ✅ (Full support including dates and numeric types)<(Less Than): ✅ (Full support including dates and numeric types)<=(Less or Equal): ✅ (Full support including dates and numeric types)>=(Greater or Equal): ✅ (Full support including dates and numeric types)
- Types
- Collections
|(Union): ✅in(Membership): ✅contains(Containership): ✅- Collection Navigation: ✅ (Full polymorphic access and choice element support)
- Boolean Logic
- Math
*(Multiplication): ✅/(Division): ✅+(Addition): ✅ (Numeric, String)-(Subtraction): ✅div(Integer Division): ✅ (Numeric)mod(Modulo): ✅ (Numeric)&(String Concatenation): ✅
- Date/Time Arithmetic: ✅ (Full arithmetic support with timezone and precision handling)
- Operator Precedence: ✅
Aggregates
- aggregate() (STU): ✅ (Full accumulator support)
Lexical Elements
- Lexical Elements: ✅ (Handled by parser)
- Comments: ✅ (Both single-line
//and multi-line/* */comments)
Environment Variables
%variable: ✅ (Full variable resolution including built-in constants)%context: ✅ (Full context support with $this, $index, $total)
Types and Reflection
- Models: ✅ (Full namespace qualification and FHIR type hierarchy support)
- Reflection (
type()) (STU): ✅ (Enhanced with namespace support and type hierarchy)
Type Safety and Strict Evaluation
- Type Safety / Strict Evaluation: ✅ (Configurable strict mode with proper error handling)
Architecture
Overview
This FHIRPath implementation is built using a modular architecture with clear separation of concerns:
- Parser (
parser.rs): Converts FHIRPath expressions into an Abstract Syntax Tree (AST) - Evaluator (
evaluator.rs): Evaluates AST nodes against FHIR resources with context management - Type System (
fhir_type_hierarchy.rs): Manages FHIR and System type hierarchies with version-aware resource type checking - Function Modules: Specialized modules for individual FHIRPath functions and operations
FHIR Version Support
The implementation supports multiple FHIR versions (R4, R4B, R5, R6) through:
- Feature flags: Each FHIR version is enabled via Cargo features
- Version-aware type checking: Resource type validation uses the appropriate FHIR version's Resource enum
- Dynamic resource type discovery: The
FhirResourceTypeProvidertrait automatically extracts resource types from generated Resource enums
Evaluation Context
The EvaluationContext provides the runtime environment for FHIRPath evaluation:
use helios_fhirpath::evaluator::EvaluationContext;
use helios_fhir::FhirVersion;
// Create context with explicit FHIR version
let context = EvaluationContext::new_empty(FhirVersion::R4);
// Create context with resources (version auto-detected)
let context = EvaluationContext::new(fhir_resources);
// Create context with specific version and resources
let context = EvaluationContext::new_with_version(fhir_resources, FhirVersion::R5);
The context includes:
- FHIR Version: Used for version-specific type checking and resource validation
- Resources: Available FHIR resources for evaluation
- Variables: Environment variables (including
$this,$index,$total) - Configuration: Strict mode, ordered function checking, etc.
- Variable Scoping: Parent context support for proper variable scoping in functions like
select()andwhere()
Type System and Namespace Resolution
The type system handles both FHIR and System namespaces:
FHIR Namespace
- Primitive types:
boolean,string,integer,decimal,date,dateTime,time, etc. - Complex types:
Quantity,HumanName,CodeableConcept,Reference, etc. - Resource types: Version-specific types like
Patient,Observation,Condition, etc.
System Namespace
- Primitive types:
Boolean,String,Integer,Decimal,Date,DateTime,Time,Quantity
Version-Aware Resource Type Checking
The implementation uses the FhirResourceTypeProvider trait to automatically detect resource types for each FHIR version:
use helios_fhir::FhirVersion;
use helios_fhirpath::evaluator::EvaluationContext;
// Context automatically detects FHIR version from resources
let context = EvaluationContext::new(resources);
// Or specify version explicitly
let context = EvaluationContext::new_with_version(resources, FhirVersion::R4);
Code Generation Integration
The implementation leverages procedural macros to automatically generate type information:
- FhirPath Macro: Automatically generates
IntoEvaluationResultimplementations for all FHIR types - Resource Type Provider: Automatically generates
FhirResourceTypeProvidertrait implementations for Resource enums - Dynamic Resource Discovery: Resource type information is extracted at compile time from the actual FHIR specification
This approach ensures that:
- Resource type lists are never hardcoded
- Each FHIR version gets accurate resource type information
- Type information stays in sync with the generated FHIR models
Function Module Architecture
Each FHIRPath function category is implemented in its own module:
aggregate_function.rs: Implementation ofaggregate()with accumulator supportboolean_functions.rs: Boolean logic functions (allTrue,anyFalse, etc.)collection_functions.rs: Collection manipulation (where,select,count, etc.)collection_navigation.rs: Navigation functions (children,descendants)conversion_functions.rs: Type conversion functions (toInteger,toString, etc.)date_operation.rs: Date/time operations and arithmeticextension_function.rs: FHIR extension access functionspolymorphic_access.rs: Choice element and polymorphic type operationsrepeat_function.rs: Implementation ofrepeat()with cycle detectionresource_type.rs: Type checking operations (is,as,ofType)trace_function.rs: Implementation oftrace()with projection supporttype_function.rs: Type reflection andtype()function
This modular approach enables:
- Clear separation of concerns by function category
- Independent testing of each function group
- Easy addition of new functions
- Maintainable and organized code structure
Executables
This crate provides two executable targets for FHIRPath expression evaluation:
fhirpath-cli - Command Line Interface
A feature-rich command-line tool for evaluating FHIRPath expressions against FHIR resources.
Installation
# Install from the workspace root
cargo install --path crates/helios-fhirpath --bin fhirpath-cli
# Or build directly
cargo build --release --bin fhirpath-cli
Features
- Expression Evaluation: Execute FHIRPath expressions against FHIR resources
- Context Support: Evaluate expressions with context for scoped evaluation
- Variables: Define variables via command line or JSON file
- Parse Debug: Generate AST visualizations for expression analysis
- FHIR Version Support: Handle resources from any supported FHIR version
- JSON Output: Results formatted as JSON for easy processing
Command Line Options
-e, --expression <EXPRESSION> FHIRPath expression to evaluate
-c, --context <CONTEXT> Context expression to evaluate first
-r, --resource <RESOURCE> Path to FHIR resource JSON file (use '-' for stdin)
-v, --variables <VARIABLES> Path to variables JSON file
--var <KEY=VALUE> Set a variable directly
-o, --output <OUTPUT> Output file path (defaults to stdout)
--parse-debug-tree Output parse debug tree as JSON
--parse-debug Output parse debug info
--trace Enable trace output
--fhir-version <VERSION> FHIR version [default: R4]
--validate Validate expression before execution
--terminology-server <URL> Terminology server URL
-h, --help Print help
Usage Examples
Basic Expression Evaluation
# Evaluate expression against a resource
fhirpath-cli -e "Patient.name.family" -r patient.json
# Get first given name
fhirpath-cli -e "Patient.name.given.first()" -r patient.json
# Filter telecom by system
fhirpath-cli -e "Patient.telecom.where(system = 'email')" -r patient.json
Using Context Expressions
# Evaluate with context
fhirpath-cli -c "Patient.name" -e "given.join(' ')" -r patient.json
# Context with filtering
fhirpath-cli -c "Patient.telecom.where(system = 'phone')" -e "value" -r patient.json
Working with Variables
# Variable from command line
fhirpath-cli -e "value > %threshold" -r observation.json --var threshold=5.0
# Multiple variables
fhirpath-cli -e "%system = 'phone' and use = %use" -r patient.json \
--var system=phone --var use=mobile
# Variables from JSON file
cat > vars.json << EOF
{
"threshold": 140,
"unit": "mm[Hg]"
}
EOF
fhirpath-cli -e "value.value > %threshold and value.unit = %unit" \
-r observation.json -v vars.json
Parse Debug Features
# Generate parse debug tree (JSON format)
fhirpath-cli -e "Patient.name.where(use = 'official').given.first()" \
--parse-debug-tree
# Generate parse debug text
fhirpath-cli -e "Patient.name.given.first() | Patient.name.family" \
--parse-debug
Using stdin
# Resource from stdin
cat patient.json | fhirpath-cli -e "Patient.name.family" -r -
# Pipe from other commands
curl -s https://example.com/fhir/Patient/123 | \
fhirpath-cli -e "name.family" -r -
Output Options
# Output to file
fhirpath-cli -e "Patient.name" -r patient.json -o names.json
# Pretty printed JSON output (default)
fhirpath-cli -e "Patient.identifier" -r patient.json
fhirpath-server - HTTP Server
An HTTP server providing FHIRPath expression evaluation via a REST API, compatible with fhirpath-lab.
Installation
# Install from the workspace root
cargo install --path crates/helios-fhirpath --bin fhirpath-server
# Or build directly
cargo build --release --bin fhirpath-server
Features
- FHIRPath Evaluation API: POST endpoint accepting FHIR Parameters resources
- Parse Debug Tree: Generate and return AST visualizations
- Variable Support: Pass variables to expressions via Parameters
- Context Expressions: Support for context-based evaluation
- CORS Configuration: Flexible cross-origin resource sharing
- Health Check: Simple health status endpoint
- fhirpath-lab Compatible: Full compatibility with the fhirpath-lab tool
Configuration
The server can be configured via command-line arguments or environment variables:
| Environment Variable | CLI Argument | Description | Default |
|---|---|---|---|
FHIRPATH_SERVER_PORT |
--port |
Server port | 3000 |
FHIRPATH_SERVER_HOST |
--host |
Server host | 127.0.0.1 |
FHIRPATH_LOG_LEVEL |
--log-level |
Log level (error/warn/info/debug/trace) | info |
FHIRPATH_ENABLE_CORS |
--enable-cors |
Enable CORS | true |
FHIRPATH_CORS_ORIGINS |
--cors-origins |
Allowed origins (comma-separated) | * |
FHIRPATH_CORS_METHODS |
--cors-methods |
Allowed methods | GET,POST,OPTIONS |
FHIRPATH_CORS_HEADERS |
--cors-headers |
Allowed headers | Common headers |
Starting the Server
# Start with defaults
fhirpath-server
# Custom port and host
fhirpath-server --port 8080 --host 0.0.0.0
# With environment variables
FHIRPATH_SERVER_PORT=8080 FHIRPATH_LOG_LEVEL=debug fhirpath-server
# Production configuration
fhirpath-server \
--host 0.0.0.0 \
--port 8080 \
--log-level warn \
--cors-origins "https://fhirpath-lab.com,https://dev.fhirpath-lab.com,https://fhirpath-lab.azurewebsites.net,https://fhirpath-lab-dev.azurewebsites.net/,http://localhost:3000"
API Endpoints
POST / - Evaluate FHIRPath Expression
Accepts a FHIR Parameters resource and returns evaluation results. Auto-detects the FHIR version from the resource.
POST /r4, /r4b, /r5, /r6 - Version-Specific Evaluation
Forces evaluation with a specific FHIR version (if compiled with the corresponding feature). Useful when you want to ensure your resource is processed with a specific FHIR version, overriding auto-detection.
Request Body (FHIR Parameters):
{
"resourceType": "Parameters",
"parameter": [
{
"name": "expression",
"valueString": "Patient.name.given.first()"
},
{
"name": "resource",
"resource": {
"resourceType": "Patient",
"name": [{
"given": ["John", "James"],
"family": "Doe"
}]
}
}
]
}
Response (FHIR Parameters):
{
"resourceType": "Parameters",
"id": "fhirpath",
"parameter": [
{
"name": "parameters",
"part": [
{
"name": "evaluator",
"valueString": "Helios FHIRPath-0.1.0"
},
{
"name": "expression",
"valueString": "Patient.name.given.first()"
},
{
"name": "resource",
"resource": { "...": "..." }
}
]
},
{
"name": "result",
"valueString": "Resource",
"part": [
{
"name": "string",
"valueString": "John"
}
]
}
]
}
Supported Input Parameters:
expression(required): FHIRPath expression to evaluatecontext(optional): Context expression to evaluate firstresource(required): FHIR resource to evaluate againstvalidate(optional): Whether to validate the expressionvariables(optional): Variables to pass to the expressionterminologyServer(optional): Terminology server URL
Additional Output Parameters (when validate is true):
parseDebugTree: JSON representation of the expression ASTparseDebug: Text representation of the parse treeexpectedReturnType: Expected return type of the expression
GET /health - Health Check
Returns server health status.
curl http://localhost:3000/health
Response:
{
"status": "ok",
"service": "fhirpath-server"
}
Usage Examples
Basic Evaluation
# Auto-detect FHIR version
curl -X POST http://localhost:3000 \
-H "Content-Type: application/json" \
-d '{
"resourceType": "Parameters",
"parameter": [
{
"name": "expression",
"valueString": "Patient.birthDate"
},
{
"name": "resource",
"resource": {
"resourceType": "Patient",
"birthDate": "1974-12-25"
}
}
]
}'
# Force R4 processing
curl -X POST http://localhost:3000/r4 \
-H "Content-Type: application/json" \
-d '{
"resourceType": "Parameters",
"parameter": [
{
"name": "expression",
"valueString": "Patient.birthDate"
},
{
"name": "resource",
"resource": {
"resourceType": "Patient",
"birthDate": "1974-12-25"
}
}
]
}'
With Context and Variables
curl -X POST http://localhost:3000 \
-H "Content-Type: application/json" \
-d '{
"resourceType": "Parameters",
"parameter": [
{
"name": "context",
"valueString": "Observation.component"
},
{
"name": "expression",
"valueString": "value > %threshold"
},
{
"name": "variables",
"part": [
{
"name": "threshold",
"valueString": "140"
}
]
},
{
"name": "resource",
"resource": {
"resourceType": "Observation",
"component": [
{"valueQuantity": {"value": 150}},
{"valueQuantity": {"value": 130}}
]
}
}
]
}'
With Parse Debug
curl -X POST http://localhost:3000 \
-H "Content-Type: application/json" \
-d '{
"resourceType": "Parameters",
"parameter": [
{
"name": "expression",
"valueString": "Patient.name.given.first() | Patient.name.family"
},
{
"name": "validate",
"valueBoolean": true
},
{
"name": "resource",
"resource": {
"resourceType": "Patient",
"name": [{"given": ["John"], "family": "Doe"}]
}
}
]
}'
Integration with fhirpath-lab
The server is compatible with fhirpath-lab. To use your local server with fhirpath-lab:
-
Start the server with CORS enabled for fhirpath-lab domains:
fhirpath-server --cors-origins "https://fhirpath-lab.com,http://localhost:3000" -
In fhirpath-lab, configure the custom server URL to point to your local instance
-
The server will properly handle all fhirpath-lab requests including parse debug tree generation
Performance
This implementation is designed for high performance FHIRPath expression evaluation. We use Criterion.rs for comprehensive performance benchmarking across all major components.
Running Benchmarks
To run all benchmarks:
cargo bench
To run specific benchmark suites:
# Parser benchmarks only
cargo bench --bench parser_benches
# Evaluator benchmarks only
cargo bench --bench evaluator_benches
# CLI benchmarks only
cargo bench --bench cli_benches
# Server benchmarks only
cargo bench --bench server_benches
Benchmark results are saved in target/criterion/ with HTML reports for detailed analysis.
Benchmark Categories
Parser Benchmarks (parser_benches)
- Simple expressions: Basic paths, literals, and indexed access
- Function calls: Single functions, chained functions, nested calls
- Operators: Arithmetic, comparison, boolean logic, unions
- Complex expressions: Filters, type checking, extensions, aggregates
- Large expressions: Many conditions, deep nesting, multiple functions
Evaluator Benchmarks (evaluator_benches)
- Navigation: Simple and nested field access, indexing
- Collections: where(), select(), exists(), count(), distinct()
- String operations: Concatenation, upper/lower, substring, regex
- Type operations: is(), ofType(), as(), type reflection
- Date/time: Comparisons, today(), now(), arithmetic
- Extensions: URL-based access, typed values
- Complex expressions: Multi-step filters, unions, quantity comparisons
CLI Benchmarks (cli_benches)
- Simple expressions: Basic navigation with and without functions
- Context expressions: Simple and complex context evaluation
- Variables: Inline variables and file-based variables
- Bundle operations: Filtering and aggregation on bundles
- Debug features: Parse tree generation and validation
Server Benchmarks (server_benches)
- Simple requests: Basic expressions and health checks
- Complex requests: Filters, context, and variables
- Validation: Parse debug tree generation
- Large resources: Bundle processing with many entries
- Concurrent requests: Parallel request handling
Performance Results
The following results are from a typical development machine (results will vary based on hardware):
| Operation | Time (avg) | Description |
|---|---|---|
| Parser | ||
| Simple path | ~500 ns | Patient.name |
| Nested path | ~800 ns | Patient.name.family |
| Function call | ~1.2 μs | Patient.name.first() |
| Complex filter | ~3.5 μs | Patient.telecom.where(system = 'phone') |
| Evaluator | ||
| Field access | ~1.5 μs | Navigate to single field |
| Collection filter | ~4.2 μs | Filter telecom by system |
| String operation | ~2.8 μs | Upper case conversion |
| Type check | ~1.8 μs | Check resource type |
| CLI | ||
| Simple expression | ~150 μs | Full CLI execution |
| With variables | ~180 μs | Variable resolution |
| Bundle processing | ~450 μs | Process 10 resources |
| Server | ||
| Simple request | ~350 μs | Basic expression evaluation |
| Complex request | ~500 μs | With filtering and context |
| Large bundle | ~2.5 ms | Process 50 resources |
Performance Optimization Tips
-
Expression Optimization
- Use specific paths instead of wildcards when possible
- Filter early in the expression chain
- Avoid redundant type checks
-
Resource Optimization
- Keep resource sizes reasonable
- Use appropriate FHIR version features
- Consider using context expressions for repeated navigation
-
Server Optimization
- Enable connection pooling for high load
- Use appropriate log levels in production
- Configure CORS for specific origins only
-
Memory Usage
- The evaluator uses streaming where possible
- Large collections are processed lazily
- Recursive expressions have cycle detection
Benchmark Methodology
Our benchmarks follow these principles:
- Use realistic FHIR resources and expressions
- Cover both simple and complex scenarios
- Measure end-to-end performance for CLI/server
- Include memory allocation patterns
- Test with various resource sizes
- Verify correctness alongside performance
The benchmark suite is continuously expanded to cover new features and edge cases.
Dependencies
~22–40MB
~574K SLoC