Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/adampetro/bluejay-rb
A fast GraphQL engine for Ruby.
https://github.com/adampetro/bluejay-rb
graphql ruby
Last synced: about 2 months ago
JSON representation
A fast GraphQL engine for Ruby.
- Host: GitHub
- URL: https://github.com/adampetro/bluejay-rb
- Owner: adampetro
- License: mit
- Created: 2023-01-27T00:00:57.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2023-09-06T18:35:58.000Z (over 1 year ago)
- Last Synced: 2024-04-24T10:16:08.583Z (9 months ago)
- Topics: graphql, ruby
- Language: Rust
- Homepage:
- Size: 2.76 MB
- Stars: 30
- Watchers: 4
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# `bluejay-rb`
> **Warning**
> This project is still very early in its development and should be considered highly unstable and experimental. It is incomplete and not ready for production use.> **Note**
> In an effort to get a working proof-of-concept, documentation and test coverage has been sacrificied. This will be corrected prior to a stable release.`bluejay-rb` is a GraphQL engine for Ruby written primarily in Rust through the use of [`magnus`](https://github.com/matsadler/magnus).
## Goal
`bluejay-rb`'s goal is to provide a lightning fast GraphQL engine with first-class integration with [Sorbet](https://sorbet.org/). If you do not care deeply about one or both of these goals, then you should seriously consider using the excellent [`graphql-ruby`](https://graphql-ruby.org) gem, which has many more features than `bluejay-rb` in addition to being production-ready and much more customizable.
## Benchmarks
Some benchmarks comparing the performance of `bluejay-rb` against `graphql-ruby` (with C parser) are located at [`/bench`](/bench). The results of some of these benchmarks are included below.
Parse + Execute (Ruby 3.2, YJIT enabled)
```
Profiling IPS:
Warming up --------------------------------------
graphql 158.000 i/100ms
bluejay 1.764k i/100ms
Calculating -------------------------------------
graphql 1.928k (± 2.7%) i/s - 9.638k in 5.003328s
bluejay 17.899k (± 2.7%) i/s - 89.964k in 5.029921sComparison:
bluejay: 17899.5 i/s
graphql: 1927.9 i/s - 9.28x slowerProfiling Ruby memory allocations:
Calculating -------------------------------------
graphql 45.944k memsize ( 2.736k retained)
421.000 objects ( 41.000 retained)
12.000 strings ( 11.000 retained)
bluejay 5.256k memsize ( 208.000 retained)
40.000 objects ( 2.000 retained)
0.000 strings ( 0.000 retained)Comparison:
bluejay: 5256 allocated
graphql: 45944 allocated - 8.74x more
```Parse + Execute (Ruby 3.2, YJIT disabled)
```
Profiling IPS:
Warming up --------------------------------------
graphql 79.000 i/100ms
bluejay 1.804k i/100ms
Calculating -------------------------------------
graphql 781.860 (± 2.2%) i/s - 3.950k in 5.054411s
bluejay 18.017k (± 1.6%) i/s - 90.200k in 5.007842sComparison:
bluejay: 18016.7 i/s
graphql: 781.9 i/s - 23.04x slowerProfiling Ruby memory allocations:
Calculating -------------------------------------
graphql 45.944k memsize ( 21.752k retained)
421.000 objects ( 197.000 retained)
12.000 strings ( 12.000 retained)
bluejay 5.256k memsize ( 5.056k retained)
40.000 objects ( 35.000 retained)
0.000 strings ( 0.000 retained)Comparison:
bluejay: 5256 allocated
graphql: 45944 allocated - 8.74x more
```Parse + Execute with large variables (Ruby 3.2, YJIT enabled)
```
Profiling IPS:
Warming up --------------------------------------
graphql 166.000 i/100ms
bluejay 1.101k i/100ms
Calculating -------------------------------------
graphql 1.642k (± 2.1%) i/s - 8.300k in 5.055691s
bluejay 10.876k (± 1.8%) i/s - 55.050k in 5.063054sComparison:
bluejay: 10876.3 i/s
graphql: 1642.4 i/s - 6.62x slowerProfiling Ruby memory allocations:
Calculating -------------------------------------
graphql 97.728k memsize ( 40.000 retained)
885.000 objects ( 1.000 retained)
6.000 strings ( 0.000 retained)
bluejay 15.640k memsize ( 80.000 retained)
228.000 objects ( 2.000 retained)
15.000 strings ( 1.000 retained)Comparison:
bluejay: 15640 allocated
graphql: 97728 allocated - 6.25x more
```Parse + Execute with large variables (Ruby 3.2, YJIT disabled)
```
Profiling IPS:
Warming up --------------------------------------
graphql 79.000 i/100ms
bluejay 1.009k i/100ms
Calculating -------------------------------------
graphql 841.882 (± 1.5%) i/s - 4.266k in 5.068484s
bluejay 10.163k (± 2.1%) i/s - 51.459k in 5.065688sComparison:
bluejay: 10163.2 i/s
graphql: 841.9 i/s - 12.07x slowerProfiling Ruby memory allocations:
Calculating -------------------------------------
graphql 97.688k memsize ( 30.736k retained)
884.000 objects ( 319.000 retained)
6.000 strings ( 5.000 retained)
bluejay 12.600k memsize ( 536.000 retained)
152.000 objects ( 6.000 retained)
8.000 strings ( 1.000 retained)Comparison:
bluejay: 12600 allocated
graphql: 97688 allocated - 7.75x more
```Parse small (Ruby 3.2, YJIT enabled)
```
Profiling IPS:
Warming up --------------------------------------
bluejay 39.288k i/100ms
graphql 6.906k i/100ms
Calculating -------------------------------------
bluejay 397.916k (± 1.4%) i/s - 2.004M in 5.036417s
graphql 67.671k (± 4.9%) i/s - 338.394k in 5.015897sComparison:
bluejay: 397915.9 i/s
graphql: 67671.2 i/s - 5.88x slowerProfiling Ruby memory allocations:
Calculating -------------------------------------
bluejay 0.000 memsize ( 0.000 retained)
0.000 objects ( 0.000 retained)
0.000 strings ( 0.000 retained)
graphql 6.192k memsize ( 2.816k retained)
70.000 objects ( 37.000 retained)
6.000 strings ( 6.000 retained)Comparison:
bluejay: 0 allocated
graphql: 6192 allocated - Infx more
```Parse small (Ruby 3.2, YJIT disabled)
```
Profiling IPS:
Warming up --------------------------------------
bluejay 37.618k i/100ms
graphql 6.034k i/100ms
Calculating -------------------------------------
bluejay 403.347k (± 2.1%) i/s - 2.031M in 5.038540s
graphql 59.928k (± 2.0%) i/s - 301.700k in 5.036461sComparison:
bluejay: 403347.5 i/s
graphql: 59928.3 i/s - 6.73x slowerProfiling Ruby memory allocations:
Calculating -------------------------------------
bluejay 0.000 memsize ( 0.000 retained)
0.000 objects ( 0.000 retained)
0.000 strings ( 0.000 retained)
graphql 6.192k memsize ( 0.000 retained)
70.000 objects ( 0.000 retained)
6.000 strings ( 0.000 retained)Comparison:
bluejay: 0 allocated
graphql: 6192 allocated - Infx more
```Parse large (Ruby 3.2, YJIT enabled)
```
Profiling IPS:
Warming up --------------------------------------
bluejay 203.000 i/100ms
graphql 30.000 i/100ms
Calculating -------------------------------------
bluejay 2.106k (± 1.4%) i/s - 10.556k in 5.014156s
graphql 308.161 (± 1.9%) i/s - 1.560k in 5.064324sComparison:
bluejay: 2105.7 i/s
graphql: 308.2 i/s - 6.83x slowerProfiling Ruby memory allocations:
Calculating -------------------------------------
bluejay 0.000 memsize ( 0.000 retained)
0.000 objects ( 0.000 retained)
0.000 strings ( 0.000 retained)
graphql 1.425M memsize ( 556.448k retained)
16.001k objects ( 7.541k retained)
50.000 strings ( 50.000 retained)Comparison:
bluejay: 0 allocated
graphql: 1425400 allocated - Infx more
```Parse large (Ruby 3.2, YJIT disabled)
```
Profiling IPS:
Warming up --------------------------------------
bluejay 208.000 i/100ms
graphql 27.000 i/100ms
Calculating -------------------------------------
bluejay 2.098k (± 1.6%) i/s - 10.608k in 5.057106s
graphql 274.835 (± 1.8%) i/s - 1.377k in 5.011880sComparison:
bluejay: 2098.2 i/s
graphql: 274.8 i/s - 7.63x slowerProfiling Ruby memory allocations:
Calculating -------------------------------------
bluejay 0.000 memsize ( 0.000 retained)
0.000 objects ( 0.000 retained)
0.000 strings ( 0.000 retained)
graphql 1.425M memsize ( 0.000 retained)
16.001k objects ( 0.000 retained)
50.000 strings ( 0.000 retained)Comparison:
bluejay: 0 allocated
graphql: 1425400 allocated - Infx more
```Parse + Validate (Ruby 3.2, YJIT enabled)
```
Profiling IPS:
Warming up --------------------------------------
graphql 504.000 i/100ms
bluejay 5.370k i/100ms
Calculating -------------------------------------
graphql 4.991k (± 6.2%) i/s - 25.200k in 5.073307s
bluejay 45.612k (±11.5%) i/s - 225.540k in 5.057627sComparison:
bluejay: 45612.5 i/s
graphql: 4991.1 i/s - 9.14x slowerProfiling Ruby memory allocations:
Calculating -------------------------------------
graphql 33.392k memsize ( 12.200k retained)
383.000 objects ( 152.000 retained)
17.000 strings ( 13.000 retained)
bluejay 40.000 memsize ( 40.000 retained)
1.000 objects ( 1.000 retained)
0.000 strings ( 0.000 retained)Comparison:
bluejay: 40 allocated
graphql: 33392 allocated - 834.80x more
```Parse + Validate (Ruby 3.2, YJIT disabled)
```
Profiling IPS:
Warming up --------------------------------------
graphql 299.000 i/100ms
bluejay 4.726k i/100ms
Calculating -------------------------------------
graphql 2.953k (± 5.0%) i/s - 14.950k in 5.075697s
bluejay 51.904k (± 4.0%) i/s - 259.930k in 5.016499sComparison:
bluejay: 51904.0 i/s
graphql: 2953.1 i/s - 17.58x slowerProfiling Ruby memory allocations:
Calculating -------------------------------------
graphql 33.304k memsize ( 12.320k retained)
381.000 objects ( 155.000 retained)
15.000 strings ( 13.000 retained)
bluejay 40.000 memsize ( 40.000 retained)
1.000 objects ( 1.000 retained)
0.000 strings ( 0.000 retained)Comparison:
bluejay: 40 allocated
graphql: 33304 allocated - 832.60x more
```Schema dump (Ruby 3.2, YJIT enabled)
```
Profiling IPS:
Warming up --------------------------------------
graphql 189.000 i/100ms
bluejay 4.228k i/100ms
Calculating -------------------------------------
graphql 1.929k (± 7.3%) i/s - 9.639k in 5.026688s
bluejay 43.632k (± 4.6%) i/s - 219.856k in 5.050598sComparison:
bluejay: 43631.9 i/s
graphql: 1929.2 i/s - 22.62x slowerProfiling Ruby memory allocations:
Calculating -------------------------------------
graphql 77.788k memsize ( 0.000 retained)
755.000 objects ( 0.000 retained)
50.000 strings ( 0.000 retained)
bluejay 699.000 memsize ( 0.000 retained)
1.000 objects ( 0.000 retained)
1.000 strings ( 0.000 retained)Comparison:
bluejay: 699 allocated
graphql: 77788 allocated - 111.28x more
```Schema dump (Ruby 3.2, YJIT disabled)
```
Profiling IPS:
Warming up --------------------------------------
graphql 157.000 i/100ms
bluejay 4.662k i/100ms
Calculating -------------------------------------
graphql 1.562k (± 1.7%) i/s - 7.850k in 5.027157s
bluejay 45.335k (± 3.3%) i/s - 228.438k in 5.044407sComparison:
bluejay: 45335.1 i/s
graphql: 1561.9 i/s - 29.02x slowerProfiling Ruby memory allocations:
Calculating -------------------------------------
graphql 77.884k memsize ( 675.000 retained)
755.000 objects ( 10.000 retained)
50.000 strings ( 7.000 retained)
bluejay 699.000 memsize ( 0.000 retained)
1.000 objects ( 0.000 retained)
1.000 strings ( 0.000 retained)Comparison:
bluejay: 699 allocated
graphql: 77884 allocated - 111.42x more
```To update the benchmark report above, run `rake bench:doc`.
## Installation
Install the gem and add to the application's Gemfile by executing:
$ bundle add bluejay
If bundler is not being used to manage dependencies, install the gem by executing:
$ gem install bluejay
## Usage
See an example in the [`/example`](/example) directory. Note the usage of [Tapioca](https://github.com/Shopify/tapioca) RBI generation for the DSL at [`/example/sorbet/rbi/dsl/graph`](/example/sorbet/rbi/dsl/graph)
## Development
After checking out the repo, run `bin/setup` to install dependencies and `rake compile` to compile the Rust extension. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run `bundle exec rake install`.
To release a new version, update the version number in `version.rb`, and push that to `main`. Then, [create a new release in the GitHub UI](https://github.com/adampetro/bluejay-rb/releases/new) with a new tag equal to the version number in `version.rb` prefixed with `v`. This will trigger the [release workflow](.github/workflows/release.yml) which will publish the new version with pre-built binaries.