alba 3.4.0 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -0
- data/README.md +7 -41
- data/lib/alba/association.rb +4 -1
- data/lib/alba/conditional_attribute.rb +11 -14
- data/lib/alba/layout.rb +8 -6
- data/lib/alba/railtie.rb +6 -5
- data/lib/alba/resource.rb +59 -15
- data/lib/alba/typed_attribute.rb +2 -0
- data/lib/alba/version.rb +1 -1
- data/lib/alba.rb +72 -38
- metadata +4 -52
- data/.codeclimate.yml +0 -12
- data/.editorconfig +0 -10
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -26
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- data/.github/dependabot.yml +0 -12
- data/.github/workflows/codeql-analysis.yml +0 -70
- data/.github/workflows/lint.yml +0 -17
- data/.github/workflows/main.yml +0 -39
- data/.gitignore +0 -11
- data/.rubocop.yml +0 -156
- data/.yardopts +0 -4
- data/CODE_OF_CONDUCT.md +0 -132
- data/CONTRIBUTING.md +0 -30
- data/Gemfile +0 -29
- data/HACKING.md +0 -42
- data/Rakefile +0 -17
- data/SECURITY.md +0 -12
- data/alba.gemspec +0 -33
- data/benchmark/Gemfile +0 -24
- data/benchmark/README.md +0 -119
- data/benchmark/collection.rb +0 -275
- data/benchmark/prep.rb +0 -56
- data/benchmark/single_resource.rb +0 -300
- data/bin/console +0 -15
- data/bin/setup +0 -8
- data/codecov.yml +0 -8
- data/docs/migrate_from_active_model_serializers.md +0 -359
- data/docs/migrate_from_jbuilder.md +0 -237
- data/docs/rails.md +0 -56
- data/gemfiles/without_active_support.gemfile +0 -19
- data/gemfiles/without_oj.gemfile +0 -19
- data/logo/alba-card.png +0 -0
- data/logo/alba-sign.png +0 -0
- data/logo/alba-typography.png +0 -0
data/HACKING.md
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
# Hacking document
|
2
|
-
|
3
|
-
This document is intended to provide detailed information about the internal design and implementation of Alba. You are recommended to read through it if you want to hack Alba.
|
4
|
-
|
5
|
-
## Design
|
6
|
-
|
7
|
-
The design of Alba is simple. `Alba::Resource` module is the only interface end users use by `include`ing it. Other classes and modules are referenced by `Alba::Resource`.
|
8
|
-
|
9
|
-
When a class `include`s `Alba::Resource` module it defines `ClassMethods` such as `attributes` and `InstanceMethods` such as `serialize`. Instance methods work with information collected by class methods.
|
10
|
-
|
11
|
-
## Methods
|
12
|
-
|
13
|
-
The main methods users directly use are listed below.
|
14
|
-
|
15
|
-
Class methods (DSL):
|
16
|
-
|
17
|
-
* `attribute` for block style attribute
|
18
|
-
* `attributes` for symbol style attribute
|
19
|
-
* `association` and its aliases such as `one` for association
|
20
|
-
* `nested` for nested attribute
|
21
|
-
|
22
|
-
Instance methods:
|
23
|
-
|
24
|
-
* `serializable_hash` and `to_h` for hash from target object
|
25
|
-
* `serialize` and `to_json` for serialized JSON string
|
26
|
-
|
27
|
-
Other methods are rather trivial. They'll be added to this list when it turned out it's important enough.
|
28
|
-
|
29
|
-
## Implementation
|
30
|
-
|
31
|
-
In `Alba::Resource` module there are some things to note.
|
32
|
-
|
33
|
-
`@object` is an object for serialization. It's either a singular object or a collection.
|
34
|
-
|
35
|
-
Attribute object can be either `Symbol`, `Proc`, `Alba::Association` or `Alba::TypedAttribute`.
|
36
|
-
|
37
|
-
* `Symbol` attributes come from `attributes` method and are sent to `__send__` as method name
|
38
|
-
* `Proc` attributes come from `attribute` method and are `instance_exec`uted
|
39
|
-
* `Alba::Association` attributes come from `association` method and `to_h` method on the object is called
|
40
|
-
* `Alba::TypedAttribute` attributes come when users specify `type` option and `value` method on the object is called
|
41
|
-
|
42
|
-
When users provide `if` option, the attribute object becomes an `Array`. It contains two element, attribute itself and condition.
|
data/Rakefile
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'bundler/gem_tasks'
|
4
|
-
require 'rake/testtask'
|
5
|
-
|
6
|
-
if ENV['BUNDLE_GEMFILE'] == File.expand_path('Gemfile') || ENV['BUNDLE_GEMFILE'].empty? || ENV['BUNDLE_GEMFILE'].nil?
|
7
|
-
ENV['BUNDLE_GEMFILE'] = File.expand_path('Gemfile')
|
8
|
-
end
|
9
|
-
|
10
|
-
Rake::TestTask.new(:test) do |t|
|
11
|
-
t.libs << 'test'
|
12
|
-
t.libs << 'lib'
|
13
|
-
file_list = ENV['BUNDLE_GEMFILE'] == File.expand_path('Gemfile') ? FileList['test/**/*_test.rb'] : FileList['test/dependencies/test_dependencies.rb']
|
14
|
-
t.test_files = file_list
|
15
|
-
end
|
16
|
-
|
17
|
-
task default: :test
|
data/SECURITY.md
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
# Security Policy
|
2
|
-
|
3
|
-
## Supported Versions
|
4
|
-
|
5
|
-
| Version | Supported |
|
6
|
-
| ------- | ------------------ |
|
7
|
-
| 1.x.y | :white_check_mark: |
|
8
|
-
| < 1.0 | :x: |
|
9
|
-
|
10
|
-
## Reporting a Vulnerability
|
11
|
-
|
12
|
-
If you find a vulnerability of Alba, please contact me (OKURA Masafumi) via [email](masafumi.o1988@gmail.com). I'll report back within a few days.
|
data/alba.gemspec
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
require_relative 'lib/alba/version'
|
2
|
-
|
3
|
-
Gem::Specification.new do |spec|
|
4
|
-
spec.name = 'alba'
|
5
|
-
spec.version = Alba::VERSION
|
6
|
-
spec.authors = ['OKURA Masafumi']
|
7
|
-
spec.email = ['masafumi.o1988@gmail.com']
|
8
|
-
|
9
|
-
spec.summary = 'Alba is the fastest JSON serializer for Ruby.'
|
10
|
-
spec.description = "Alba is the fastest JSON serializer for Ruby. It focuses on performance, flexibility and usability."
|
11
|
-
spec.homepage = 'https://github.com/okuramasafumi/alba'
|
12
|
-
spec.license = 'MIT'
|
13
|
-
spec.required_ruby_version = Gem::Requirement.new('>= 3.0.0')
|
14
|
-
|
15
|
-
spec.metadata = {
|
16
|
-
'bug_tracker_uri' => 'https://github.com/okuramasafumi/alba/issues',
|
17
|
-
'changelog_uri' => 'https://github.com/okuramasafumi/alba/blob/main/CHANGELOG.md',
|
18
|
-
'documentation_uri' => 'https://rubydoc.info/github/okuramasafumi/alba',
|
19
|
-
'source_code_uri' => 'https://github.com/okuramasafumi/alba',
|
20
|
-
'rubygems_mfa_required' => 'true'
|
21
|
-
}
|
22
|
-
|
23
|
-
# Specify which files should be added to the gem when it is released.
|
24
|
-
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
|
-
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
26
|
-
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
27
|
-
end
|
28
|
-
spec.bindir = 'exe'
|
29
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
30
|
-
spec.require_paths = ['lib']
|
31
|
-
|
32
|
-
spec.add_dependency "ostruct", "~> 0.6"
|
33
|
-
end
|
data/benchmark/Gemfile
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
source 'https://rubygems.org'
|
4
|
-
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
5
|
-
|
6
|
-
gem 'active_model_serializers'
|
7
|
-
gem 'activerecord', '~> 7.1'
|
8
|
-
gem 'alba', path: '../'
|
9
|
-
gem 'benchmark-ips'
|
10
|
-
gem 'benchmark-memory'
|
11
|
-
gem 'blueprinter'
|
12
|
-
gem 'fast_serializer_ruby'
|
13
|
-
gem 'jbuilder'
|
14
|
-
gem 'jserializer'
|
15
|
-
gem 'multi_json'
|
16
|
-
gem 'oj'
|
17
|
-
gem 'oj_serializers'
|
18
|
-
gem 'panko_serializer'
|
19
|
-
gem 'pg'
|
20
|
-
gem 'primalize'
|
21
|
-
gem 'representable'
|
22
|
-
gem 'simple_ams'
|
23
|
-
gem 'sqlite3', '~> 1.4'
|
24
|
-
gem 'turbostreamer'
|
data/benchmark/README.md
DELETED
@@ -1,119 +0,0 @@
|
|
1
|
-
## Benchmark for json serializers
|
2
|
-
|
3
|
-
This directory contains a few different benchmark scripts. They all use inline Bundler definitions so you can run them by `ruby benchmark/collection.rb` for instance.
|
4
|
-
|
5
|
-
## Result
|
6
|
-
|
7
|
-
As a reference, here's the benchmark result run in my (@okuramasafumi) machine.
|
8
|
-
|
9
|
-
Machine spec:
|
10
|
-
|
11
|
-
|Key|Value|
|
12
|
-
|---|---|
|
13
|
-
|OS|macOS 14.7|
|
14
|
-
|CPU|Apple M1 Pro|
|
15
|
-
|RAM|16GB|
|
16
|
-
|Ruby|ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]|
|
17
|
-
|
18
|
-
Library versions:
|
19
|
-
|
20
|
-
|Library|Version|
|
21
|
-
|---|---|
|
22
|
-
|alba|3.2.0|
|
23
|
-
|blueprinter|1.1.0|
|
24
|
-
|fast_serializer_ruby|0.6.9|
|
25
|
-
|jserializer|0.2.1|
|
26
|
-
|oj|3.16.6|
|
27
|
-
|simple_ams|0.2.6|
|
28
|
-
|representable|3.2.0|
|
29
|
-
|turbostreamer|1.11.0|
|
30
|
-
|jbuilder|2.13.0|
|
31
|
-
|panko_serializer|0.8.2|
|
32
|
-
|active_model_serializers|0.10.14|
|
33
|
-
|
34
|
-
`benchmark-ips` with `Oj.optimize_rails`:
|
35
|
-
|
36
|
-
```
|
37
|
-
Comparison:
|
38
|
-
panko: 447.0 i/s
|
39
|
-
jserializer: 168.9 i/s - 2.65x slower
|
40
|
-
alba_inline: 149.4 i/s - 2.99x slower
|
41
|
-
alba: 146.5 i/s - 3.05x slower
|
42
|
-
turbostreamer: 138.7 i/s - 3.22x slower
|
43
|
-
rails: 105.6 i/s - 4.23x slower
|
44
|
-
fast_serializer: 97.6 i/s - 4.58x slower
|
45
|
-
blueprinter: 66.7 i/s - 6.70x slower
|
46
|
-
representable: 50.6 i/s - 8.83x slower
|
47
|
-
simple_ams: 35.5 i/s - 12.57x slower
|
48
|
-
ams: 14.8 i/s - 30.25x slower
|
49
|
-
```
|
50
|
-
|
51
|
-
`benchmark-ips` without `Oj.optimize_rails`:
|
52
|
-
|
53
|
-
```
|
54
|
-
Comparison:
|
55
|
-
panko: 457.9 i/s
|
56
|
-
jserializer: 165.9 i/s - 2.76x slower
|
57
|
-
alba: 160.1 i/s - 2.86x slower
|
58
|
-
alba_inline: 158.5 i/s - 2.89x slower
|
59
|
-
turbostreamer: 141.7 i/s - 3.23x slower
|
60
|
-
fast_serializer: 96.2 i/s - 4.76x slower
|
61
|
-
rails: 87.2 i/s - 5.25x slower
|
62
|
-
blueprinter: 67.4 i/s - 6.80x slower
|
63
|
-
representable: 43.4 i/s - 10.55x slower
|
64
|
-
simple_ams: 34.7 i/s - 13.20x slower
|
65
|
-
ams: 14.2 i/s - 32.28x slower
|
66
|
-
```
|
67
|
-
|
68
|
-
`benchmark-ips` with `Oj.optimize_rail` and YJIT:
|
69
|
-
|
70
|
-
```
|
71
|
-
Comparison:
|
72
|
-
panko: 676.6 i/s
|
73
|
-
jserializer: 285.3 i/s - 2.37x slower
|
74
|
-
turbostreamer: 264.2 i/s - 2.56x slower
|
75
|
-
alba: 258.9 i/s - 2.61x slower
|
76
|
-
fast_serializer: 179.0 i/s - 3.78x slower
|
77
|
-
rails: 150.7 i/s - 4.49x slower
|
78
|
-
alba_inline: 131.5 i/s - 5.15x slower
|
79
|
-
blueprinter: 110.0 i/s - 6.15x slower
|
80
|
-
representable: 73.5 i/s - 9.21x slower
|
81
|
-
simple_ams: 62.8 i/s - 10.77x slower
|
82
|
-
ams: 20.4 i/s - 33.10x slower
|
83
|
-
```
|
84
|
-
|
85
|
-
`benchmark-ips` with YJIT and without `Oj.optimize_rail`:
|
86
|
-
|
87
|
-
```
|
88
|
-
Comparison:
|
89
|
-
panko: 701.9 i/s
|
90
|
-
alba: 311.1 i/s - 2.26x slower
|
91
|
-
jserializer: 281.6 i/s - 2.49x slower
|
92
|
-
turbostreamer: 240.4 i/s - 2.92x slower
|
93
|
-
fast_serializer: 180.5 i/s - 3.89x slower
|
94
|
-
alba_inline: 135.6 i/s - 5.18x slower
|
95
|
-
rails: 131.4 i/s - 5.34x slower
|
96
|
-
blueprinter: 110.7 i/s - 6.34x slower
|
97
|
-
representable: 70.5 i/s - 9.96x slower
|
98
|
-
simple_ams: 57.3 i/s - 12.24x slower
|
99
|
-
ams: 20.3 i/s - 34.51x slower
|
100
|
-
```
|
101
|
-
|
102
|
-
`benchmark-memory`:
|
103
|
-
|
104
|
-
```
|
105
|
-
Comparison:
|
106
|
-
panko: 259178 allocated
|
107
|
-
turbostreamer: 817800 allocated - 3.16x more
|
108
|
-
jserializer: 826425 allocated - 3.19x more
|
109
|
-
alba: 846465 allocated - 3.27x more
|
110
|
-
alba_inline: 867361 allocated - 3.35x more
|
111
|
-
fast_serializer: 1474345 allocated - 5.69x more
|
112
|
-
rails: 2265905 allocated - 8.74x more
|
113
|
-
blueprinter: 2469905 allocated - 9.53x more
|
114
|
-
representable: 4994281 allocated - 19.27x more
|
115
|
-
ams: 5233265 allocated - 20.19x more
|
116
|
-
simple_ams: 9506817 allocated - 36.68x more
|
117
|
-
```
|
118
|
-
|
119
|
-
Conclusion: panko is extremely fast but it's a C extension gem. As pure Ruby gems, Alba, `turbostreamer` and `jserializer` are notably faster than others, but Alba is slightly slower than other two. With `Oj.optimize_rails`, `jbuilder` and Rails standard serialization are also fast.
|
data/benchmark/collection.rb
DELETED
@@ -1,275 +0,0 @@
|
|
1
|
-
# Benchmark script to run varieties of JSON serializers
|
2
|
-
# Fetch Alba from local, otherwise fetch latest from RubyGems
|
3
|
-
|
4
|
-
require_relative 'prep'
|
5
|
-
|
6
|
-
# --- Alba serializers ---
|
7
|
-
|
8
|
-
require "alba"
|
9
|
-
|
10
|
-
class AlbaCommentResource
|
11
|
-
include ::Alba::Resource
|
12
|
-
attributes :id, :body
|
13
|
-
end
|
14
|
-
|
15
|
-
class AlbaPostResource
|
16
|
-
include ::Alba::Resource
|
17
|
-
attributes :id, :body
|
18
|
-
attribute :commenter_names do |post|
|
19
|
-
post.commenters.pluck(:name)
|
20
|
-
end
|
21
|
-
many :comments, resource: AlbaCommentResource
|
22
|
-
end
|
23
|
-
|
24
|
-
# --- ActiveModelSerializer serializers ---
|
25
|
-
|
26
|
-
require "active_model_serializers"
|
27
|
-
|
28
|
-
ActiveModelSerializers.logger = Logger.new(nil)
|
29
|
-
|
30
|
-
class AMSCommentSerializer < ActiveModel::Serializer
|
31
|
-
attributes :id, :body
|
32
|
-
end
|
33
|
-
|
34
|
-
class AMSPostSerializer < ActiveModel::Serializer
|
35
|
-
attributes :id, :body
|
36
|
-
attribute :commenter_names
|
37
|
-
has_many :comments, serializer: AMSCommentSerializer
|
38
|
-
|
39
|
-
def commenter_names
|
40
|
-
object.commenters.pluck(:name)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# --- Blueprint serializers ---
|
45
|
-
|
46
|
-
require "blueprinter"
|
47
|
-
|
48
|
-
class CommentBlueprint < Blueprinter::Base
|
49
|
-
fields :id, :body
|
50
|
-
end
|
51
|
-
|
52
|
-
class PostBlueprint < Blueprinter::Base
|
53
|
-
fields :id, :body, :commenter_names
|
54
|
-
association :comments, blueprint: CommentBlueprint
|
55
|
-
|
56
|
-
def commenter_names
|
57
|
-
commenters.pluck(:name)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
# --- Fast Serializer Ruby
|
62
|
-
|
63
|
-
require "fast_serializer"
|
64
|
-
|
65
|
-
class FastSerializerCommentResource
|
66
|
-
include ::FastSerializer::Schema::Mixin
|
67
|
-
attributes :id, :body
|
68
|
-
end
|
69
|
-
|
70
|
-
class FastSerializerPostResource
|
71
|
-
include ::FastSerializer::Schema::Mixin
|
72
|
-
|
73
|
-
attributes :id, :body
|
74
|
-
|
75
|
-
attribute :commenter_names do
|
76
|
-
object.commenters.pluck(:name)
|
77
|
-
end
|
78
|
-
|
79
|
-
has_many :comments, serializer: FastSerializerCommentResource
|
80
|
-
end
|
81
|
-
|
82
|
-
# --- Jserializer serializers ---
|
83
|
-
|
84
|
-
require 'jserializer'
|
85
|
-
|
86
|
-
class JserializerCommentSerializer < Jserializer::Base
|
87
|
-
attributes :id, :body
|
88
|
-
end
|
89
|
-
|
90
|
-
class JserializerPostSerializer < Jserializer::Base
|
91
|
-
attributes :id, :body, :commenter_names
|
92
|
-
has_many :comments, serializer: JserializerCommentSerializer
|
93
|
-
def commenter_names
|
94
|
-
object.commenters.pluck(:name)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
# --- Panko serializers ---
|
99
|
-
#
|
100
|
-
|
101
|
-
require "panko_serializer"
|
102
|
-
|
103
|
-
class PankoCommentSerializer < Panko::Serializer
|
104
|
-
attributes :id, :body
|
105
|
-
end
|
106
|
-
|
107
|
-
|
108
|
-
class PankoPostSerializer < Panko::Serializer
|
109
|
-
attributes :id, :body, :commenter_names
|
110
|
-
|
111
|
-
has_many :comments, serializer: PankoCommentSerializer
|
112
|
-
|
113
|
-
def commenter_names
|
114
|
-
object.commenters.pluck(:name)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
# --- Representable serializers ---
|
119
|
-
|
120
|
-
require "representable"
|
121
|
-
|
122
|
-
class CommentRepresenter < Representable::Decorator
|
123
|
-
include Representable::JSON
|
124
|
-
|
125
|
-
property :id
|
126
|
-
property :body
|
127
|
-
end
|
128
|
-
|
129
|
-
class PostsRepresenter < Representable::Decorator
|
130
|
-
include Representable::JSON::Collection
|
131
|
-
|
132
|
-
items class: Post do
|
133
|
-
property :id
|
134
|
-
property :body
|
135
|
-
property :commenter_names
|
136
|
-
collection :comments
|
137
|
-
end
|
138
|
-
|
139
|
-
def commenter_names
|
140
|
-
commenters.pluck(:name)
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
# --- SimpleAMS serializers ---
|
145
|
-
|
146
|
-
require "simple_ams"
|
147
|
-
|
148
|
-
class SimpleAMSCommentSerializer
|
149
|
-
include SimpleAMS::DSL
|
150
|
-
|
151
|
-
attributes :id, :body
|
152
|
-
end
|
153
|
-
|
154
|
-
class SimpleAMSPostSerializer
|
155
|
-
include SimpleAMS::DSL
|
156
|
-
|
157
|
-
attributes :id, :body
|
158
|
-
attribute :commenter_names
|
159
|
-
has_many :comments, serializer: SimpleAMSCommentSerializer
|
160
|
-
|
161
|
-
def commenter_names
|
162
|
-
object.commenters.pluck(:name)
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
require 'turbostreamer'
|
167
|
-
TurboStreamer.set_default_encoder(:json, :oj)
|
168
|
-
|
169
|
-
class TurbostreamerSerializer
|
170
|
-
def initialize(posts)
|
171
|
-
@posts = posts
|
172
|
-
end
|
173
|
-
|
174
|
-
def to_json
|
175
|
-
TurboStreamer.encode do |json|
|
176
|
-
json.array! @posts do |post|
|
177
|
-
json.object! do
|
178
|
-
json.extract! post, :id, :body, :commenter_names
|
179
|
-
|
180
|
-
json.comments post.comments do |comment|
|
181
|
-
json.object! do
|
182
|
-
json.extract! comment, :id, :body
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
# --- Test data creation ---
|
192
|
-
|
193
|
-
100.times do |i|
|
194
|
-
post = Post.create!(body: "post#{i}")
|
195
|
-
user1 = User.create!(name: "John#{i}")
|
196
|
-
user2 = User.create!(name: "Jane#{i}")
|
197
|
-
10.times do |n|
|
198
|
-
post.comments.create!(commenter: user1, body: "Comment1_#{i}_#{n}")
|
199
|
-
post.comments.create!(commenter: user2, body: "Comment2_#{i}_#{n}")
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
posts = Post.all.includes(:comments, :commenters)
|
204
|
-
|
205
|
-
# --- Store the serializers in procs ---
|
206
|
-
|
207
|
-
alba = Proc.new { AlbaPostResource.new(posts).serialize }
|
208
|
-
alba_inline = Proc.new do
|
209
|
-
Alba.serialize(posts) do
|
210
|
-
attributes :id, :body
|
211
|
-
attribute :commenter_names do |post|
|
212
|
-
post.commenters.pluck(:name)
|
213
|
-
end
|
214
|
-
many :comments do
|
215
|
-
attributes :id, :body
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
219
|
-
ams = Proc.new { ActiveModelSerializers::SerializableResource.new(posts, {each_serializer: AMSPostSerializer}).to_json }
|
220
|
-
blueprinter = Proc.new { PostBlueprint.render(posts) }
|
221
|
-
fast_serializer = Proc.new { FastSerializerPostResource.new(posts).to_json }
|
222
|
-
jserializer = Proc.new { JserializerPostSerializer.new(posts, is_collection: true).to_json }
|
223
|
-
panko = proc { Panko::ArraySerializer.new(posts, each_serializer: PankoPostSerializer).to_json }
|
224
|
-
rails = Proc.new do
|
225
|
-
ActiveSupport::JSON.encode(posts.map{ |post| post.serializable_hash(include: :comments) })
|
226
|
-
end
|
227
|
-
representable = Proc.new { PostsRepresenter.new(posts).to_json }
|
228
|
-
simple_ams = Proc.new { SimpleAMS::Renderer::Collection.new(posts, serializer: SimpleAMSPostSerializer).to_json }
|
229
|
-
turbostreamer = Proc.new { TurbostreamerSerializer.new(posts).to_json }
|
230
|
-
|
231
|
-
# --- Execute the serializers to check their output ---
|
232
|
-
GC.disable
|
233
|
-
puts "Checking outputs..."
|
234
|
-
correct = alba.call
|
235
|
-
parsed_correct = JSON.parse(correct)
|
236
|
-
{
|
237
|
-
alba_inline: alba_inline,
|
238
|
-
ams: ams,
|
239
|
-
blueprinter: blueprinter,
|
240
|
-
fast_serializer: fast_serializer,
|
241
|
-
jserializer: jserializer,
|
242
|
-
panko: panko,
|
243
|
-
rails: rails,
|
244
|
-
representable: representable,
|
245
|
-
simple_ams: simple_ams,
|
246
|
-
turbostreamer: turbostreamer
|
247
|
-
}.each do |name, serializer|
|
248
|
-
result = serializer.call
|
249
|
-
parsed_result = JSON.parse(result)
|
250
|
-
puts "#{name} yields wrong output: #{parsed_result}" unless parsed_result == parsed_correct
|
251
|
-
end
|
252
|
-
|
253
|
-
# --- Run the benchmarks ---
|
254
|
-
|
255
|
-
benchmark_body = lambda do |x|
|
256
|
-
x.report(:alba, &alba)
|
257
|
-
x.report(:alba_inline, &alba_inline)
|
258
|
-
x.report(:ams, &ams)
|
259
|
-
x.report(:blueprinter, &blueprinter)
|
260
|
-
x.report(:fast_serializer, &fast_serializer)
|
261
|
-
x.report(:jserializer, &jserializer)
|
262
|
-
x.report(:panko, &panko)
|
263
|
-
x.report(:rails, &rails)
|
264
|
-
x.report(:representable, &representable)
|
265
|
-
x.report(:simple_ams, &simple_ams)
|
266
|
-
x.report(:turbostreamer, &turbostreamer)
|
267
|
-
|
268
|
-
x.compare!
|
269
|
-
end
|
270
|
-
|
271
|
-
require 'benchmark/ips'
|
272
|
-
Benchmark.ips(&benchmark_body)
|
273
|
-
|
274
|
-
require 'benchmark/memory'
|
275
|
-
Benchmark.memory(&benchmark_body)
|
data/benchmark/prep.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
# --- Test data model setup ---
|
2
|
-
|
3
|
-
RubyVM::YJIT.enable if ENV["YJIT"]
|
4
|
-
require "csv"
|
5
|
-
require "pg"
|
6
|
-
require "active_record"
|
7
|
-
require "active_record/connection_adapters/postgresql_adapter"
|
8
|
-
require "logger"
|
9
|
-
require "oj"
|
10
|
-
require "sqlite3"
|
11
|
-
Oj.optimize_rails unless ENV['NO_OJ_OPTIMIZE_RAILS']
|
12
|
-
|
13
|
-
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
|
14
|
-
# ActiveRecord::Base.logger = Logger.new($stdout)
|
15
|
-
|
16
|
-
ActiveRecord::Schema.define do
|
17
|
-
create_table :posts, force: true do |t|
|
18
|
-
t.string :body
|
19
|
-
end
|
20
|
-
|
21
|
-
create_table :comments, force: true do |t|
|
22
|
-
t.integer :post_id
|
23
|
-
t.string :body
|
24
|
-
t.integer :commenter_id
|
25
|
-
end
|
26
|
-
|
27
|
-
create_table :users, force: true do |t|
|
28
|
-
t.string :name
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
class Post < ActiveRecord::Base
|
33
|
-
has_many :comments
|
34
|
-
has_many :commenters, through: :comments, class_name: 'User', source: :commenter
|
35
|
-
|
36
|
-
def attributes
|
37
|
-
{id: nil, body: nil, commenter_names: commenter_names}
|
38
|
-
end
|
39
|
-
|
40
|
-
def commenter_names
|
41
|
-
commenters.pluck(:name)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
class Comment < ActiveRecord::Base
|
46
|
-
belongs_to :post
|
47
|
-
belongs_to :commenter, class_name: 'User'
|
48
|
-
|
49
|
-
def attributes
|
50
|
-
{id: nil, body: nil}
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
class User < ActiveRecord::Base
|
55
|
-
has_many :comments
|
56
|
-
end
|