panko_serializer 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.clang-format +102 -0
  3. data/.gitignore +12 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +22 -0
  6. data/.travis.yml +8 -0
  7. data/Gemfile +36 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +8 -0
  10. data/Rakefile +62 -0
  11. data/benchmarks/BENCHMARKS.md +48 -0
  12. data/benchmarks/allocs.rb +23 -0
  13. data/benchmarks/app.rb +13 -0
  14. data/benchmarks/benchmarking_support.rb +43 -0
  15. data/benchmarks/bm_active_model_serializers.rb +45 -0
  16. data/benchmarks/bm_controller.rb +81 -0
  17. data/benchmarks/bm_panko_json.rb +60 -0
  18. data/benchmarks/bm_panko_object.rb +69 -0
  19. data/benchmarks/profile.rb +88 -0
  20. data/benchmarks/sanity.rb +67 -0
  21. data/benchmarks/setup.rb +62 -0
  22. data/benchmarks/type_casts/bm_active_record.rb +57 -0
  23. data/benchmarks/type_casts/bm_panko.rb +67 -0
  24. data/benchmarks/type_casts/bm_pg.rb +35 -0
  25. data/benchmarks/type_casts/support.rb +16 -0
  26. data/ext/panko_serializer/attributes_iterator.c +62 -0
  27. data/ext/panko_serializer/attributes_iterator.h +17 -0
  28. data/ext/panko_serializer/extconf.rb +8 -0
  29. data/ext/panko_serializer/panko_serializer.c +189 -0
  30. data/ext/panko_serializer/panko_serializer.h +17 -0
  31. data/ext/panko_serializer/serialization_descriptor.c +166 -0
  32. data/ext/panko_serializer/serialization_descriptor.h +30 -0
  33. data/ext/panko_serializer/time_conversion.c +94 -0
  34. data/ext/panko_serializer/time_conversion.h +6 -0
  35. data/ext/panko_serializer/type_cast.c +271 -0
  36. data/ext/panko_serializer/type_cast.h +74 -0
  37. data/lib/panko/array_serializer.rb +40 -0
  38. data/lib/panko/cache.rb +35 -0
  39. data/lib/panko/serialization_descriptor.rb +119 -0
  40. data/lib/panko/serializer.rb +57 -0
  41. data/lib/panko/version.rb +4 -0
  42. data/lib/panko.rb +8 -0
  43. data/panko_serializer.gemspec +31 -0
  44. metadata +171 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 30e3e534552c9c7592b512b679460e53de9eae33
4
+ data.tar.gz: a0a70502582161816691ba9aaa327ed17695bf8c
5
+ SHA512:
6
+ metadata.gz: 26d0cf119bad48ec684ce49fc8c6413d3a35e976ca135c96d37d7d6e738f19f00f23225195873289bfa5aff3f6059c27bb8bf54fd3f881d75c3e57b4b3da6847
7
+ data.tar.gz: d55cb3c5e156c2f4d64ac67ac9429328d3476944876cdfe4a41ef0b149bd78a636b229061d9648d5a0a9eb3eca79ea68000ab0a6f7ca9d0b472be9163b546903
data/.clang-format ADDED
@@ -0,0 +1,102 @@
1
+ ---
2
+ Language: Cpp
3
+ # BasedOnStyle: Chromium
4
+ AccessModifierOffset: -1
5
+ AlignAfterOpenBracket: Align
6
+ AlignConsecutiveAssignments: false
7
+ AlignConsecutiveDeclarations: false
8
+ AlignEscapedNewlines: Left
9
+ AlignOperands: true
10
+ AlignTrailingComments: true
11
+ AllowAllParametersOfDeclarationOnNextLine: false
12
+ AllowShortBlocksOnASingleLine: false
13
+ AllowShortCaseLabelsOnASingleLine: false
14
+ AllowShortFunctionsOnASingleLine: Inline
15
+ AllowShortIfStatementsOnASingleLine: false
16
+ AllowShortLoopsOnASingleLine: false
17
+ AlwaysBreakAfterDefinitionReturnType: None
18
+ AlwaysBreakAfterReturnType: None
19
+ AlwaysBreakBeforeMultilineStrings: true
20
+ AlwaysBreakTemplateDeclarations: true
21
+ BinPackArguments: true
22
+ BinPackParameters: false
23
+ BraceWrapping:
24
+ AfterClass: false
25
+ AfterControlStatement: false
26
+ AfterEnum: false
27
+ AfterFunction: false
28
+ AfterNamespace: false
29
+ AfterObjCDeclaration: false
30
+ AfterStruct: false
31
+ AfterUnion: false
32
+ BeforeCatch: false
33
+ BeforeElse: false
34
+ IndentBraces: false
35
+ SplitEmptyFunctionBody: true
36
+ BreakBeforeBinaryOperators: None
37
+ BreakBeforeBraces: Attach
38
+ BreakBeforeInheritanceComma: false
39
+ BreakBeforeTernaryOperators: true
40
+ BreakConstructorInitializersBeforeComma: false
41
+ BreakConstructorInitializers: BeforeColon
42
+ BreakAfterJavaFieldAnnotations: false
43
+ BreakStringLiterals: true
44
+ ColumnLimit: 80
45
+ CommentPragmas: '^ IWYU pragma:'
46
+ CompactNamespaces: false
47
+ ConstructorInitializerAllOnOneLineOrOnePerLine: true
48
+ ConstructorInitializerIndentWidth: 4
49
+ ContinuationIndentWidth: 4
50
+ Cpp11BracedListStyle: true
51
+ DerivePointerAlignment: false
52
+ DisableFormat: false
53
+ ExperimentalAutoDetectBinPacking: false
54
+ FixNamespaceComments: true
55
+ ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
56
+ IncludeCategories:
57
+ - Regex: '^<.*\.h>'
58
+ Priority: 1
59
+ - Regex: '^<.*'
60
+ Priority: 2
61
+ - Regex: '.*'
62
+ Priority: 3
63
+ IncludeIsMainRegex: '([-_](test|unittest))?$'
64
+ IndentCaseLabels: true
65
+ IndentWidth: 2
66
+ IndentWrappedFunctionNames: false
67
+ JavaScriptQuotes: Leave
68
+ JavaScriptWrapImports: true
69
+ KeepEmptyLinesAtTheStartOfBlocks: false
70
+ MacroBlockBegin: ''
71
+ MacroBlockEnd: ''
72
+ MaxEmptyLinesToKeep: 1
73
+ NamespaceIndentation: None
74
+ ObjCBlockIndentWidth: 2
75
+ ObjCSpaceAfterProperty: false
76
+ ObjCSpaceBeforeProtocolList: false
77
+ PenaltyBreakAssignment: 2
78
+ PenaltyBreakBeforeFirstCallParameter: 1
79
+ PenaltyBreakComment: 300
80
+ PenaltyBreakFirstLessLess: 120
81
+ PenaltyBreakString: 1000
82
+ PenaltyExcessCharacter: 1000000
83
+ PenaltyReturnTypeOnItsOwnLine: 200
84
+ PointerAlignment: Left
85
+ ReflowComments: true
86
+ SortIncludes: true
87
+ SpaceAfterCStyleCast: false
88
+ SpaceAfterTemplateKeyword: true
89
+ SpaceBeforeAssignmentOperators: true
90
+ SpaceBeforeParens: ControlStatements
91
+ SpaceInEmptyParentheses: false
92
+ SpacesBeforeTrailingComments: 2
93
+ SpacesInAngles: false
94
+ SpacesInContainerLiterals: true
95
+ SpacesInCStyleCastParentheses: false
96
+ SpacesInParentheses: false
97
+ SpacesInSquareBrackets: false
98
+ Standard: Auto
99
+ TabWidth: 8
100
+ UseTab: Never
101
+ ...
102
+
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,22 @@
1
+ AllCops:
2
+ DisabledByDefault: true
3
+ TargetRubyVersion: 2.4.1
4
+ DisplayCopNames: true
5
+ StyleGuideCopsOnly: false
6
+
7
+ Metrics/LineLength:
8
+ Max: 120
9
+
10
+ Style/StringLiterals:
11
+ EnforcedStyle: double_quotes
12
+
13
+ Style/FrozenStringLiteralComment:
14
+ Enabled: true
15
+ EnforcedStyle: always
16
+
17
+ Layout/TrailingBlankLines:
18
+ Enabled: true
19
+
20
+ Layout/TrailingWhitespace:
21
+ Enabled: true
22
+
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ sudo: false
2
+ cache: bundler
3
+ language: ruby
4
+ rvm:
5
+ - 2.4.1
6
+ - ruby-head
7
+ before_install: gem install bundler
8
+ after_success: bundle exec rake benchmarks
data/Gemfile ADDED
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+ source "https://rubygems.org"
3
+
4
+ gemspec
5
+
6
+ version = "4.2"
7
+ gem_version = "~> #{version}.9"
8
+
9
+ gem "rails", gem_version
10
+ gem "railties", gem_version
11
+ gem "activesupport", gem_version
12
+ gem "activemodel", gem_version
13
+ gem "actionpack", gem_version
14
+ gem "activerecord", gem_version, group: :test
15
+
16
+ group :benchmarks do
17
+ gem "sqlite3"
18
+ gem "pg"
19
+
20
+ gem "memory_profiler"
21
+ gem "ruby-prof"
22
+ gem "ruby-prof-flamegraph"
23
+
24
+ gem "benchmark-ips"
25
+ gem "active_model_serializers", "0.9.7"
26
+
27
+ gem "terminal-table"
28
+ end
29
+
30
+ group :test do
31
+ gem "faker"
32
+ end
33
+
34
+ group :development do
35
+ gem "byebug"
36
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Yosi Attias
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,8 @@
1
+ # Panko
2
+
3
+ [![Build Status](https://travis-ci.org/yosiat/panko.svg?branch=master)](https://travis-ci.org/yosiat/panko)
4
+
5
+
6
+ ## License
7
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
8
+
data/Rakefile ADDED
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
+ require "json"
5
+ require "terminal-table"
6
+ require "rake/extensiontask"
7
+
8
+ gem = Gem::Specification.load( File.dirname(__FILE__) + "/panko_serializer.gemspec" )
9
+
10
+
11
+ Rake::ExtensionTask.new("panko_serializer", gem) do |ext|
12
+ ext.lib_dir = "lib/panko"
13
+ end
14
+
15
+ Gem::PackageTask.new(gem) do |pkg|
16
+ pkg.need_zip = pkg.need_tar = false
17
+ end
18
+
19
+ RSpec::Core::RakeTask.new(:spec)
20
+ Rake::Task[:spec].prerequisites << :compile
21
+
22
+ task default: :spec
23
+
24
+
25
+ def run_benchmarks(files, items_count: 14_000)
26
+ headings = ["Benchmark", "ip/s", "allocs/retained"]
27
+ files.each do |benchmark_file|
28
+ output = `ITEMS_COUNT=#{items_count} RAILS_ENV=production ruby #{benchmark_file}`
29
+
30
+ rows = output.each_line.map do |line|
31
+ result = JSON.parse(line)
32
+ result.values
33
+ end
34
+
35
+ puts "\n\n"
36
+ title = File.basename(benchmark_file, ".rb")
37
+ table = Terminal::Table.new title: title, headings: headings, rows: rows
38
+ puts table
39
+ end
40
+ end
41
+
42
+ desc "Run all benchmarks"
43
+ task :benchmarks do
44
+ run_benchmarks Dir[File.join(__dir__, "benchmarks", "**", "bm_*")]
45
+ end
46
+
47
+ desc "Type Casts - Benchmarks"
48
+ task :bm_type_casts do
49
+ run_benchmarks Dir[File.join(__dir__, "benchmarks", "type_casts", "bm_*")]
50
+ end
51
+
52
+ desc "Sanity Benchmarks"
53
+ task :sanity do
54
+ puts Time.now.strftime("%d/%m %H:%M:%S")
55
+ puts "=========================="
56
+
57
+ run_benchmarks [
58
+ File.join(__dir__, "benchmarks", "sanity.rb")
59
+ ], items_count: 2300
60
+
61
+ puts "\n\n"
62
+ end
@@ -0,0 +1,48 @@
1
+ ## Initial state
2
+ ```
3
+ Native_Posts_2300 57 ip/s 13802 allocs/op
4
+ Native_Posts_50 2956 ip/s 302 allocs/op
5
+
6
+ AMS_Simple_Posts_2300 21 ip/s 94309 allocs/op
7
+ AMS_Simple_Posts_50 1008 ip/s 2059 allocs/op
8
+ AMS_HasOne_Posts_2300 9 ip/s 147209 allocs/op
9
+ AMS_HasOne_Posts_50 451 ip/s 3209 allocs/op
10
+
11
+ Panko_HasOne_Posts_2300 164 ip/s 2372 allocs/op
12
+ Panko_HasOne_Posts_50 6118 ip/s 122 allocs/op
13
+ Panko_Reused_HasOne_Posts_2300 178 ip/s 2303 allocs/op
14
+ Panko_Reused_HasOne_Posts_50 8203 ip/s 53 allocs/op
15
+
16
+ Panko_Simple_Posts_2300 150 ip/s 2372 allocs/op
17
+ Panko_Simple_Posts_50 5639 ip/s 122 allocs/op
18
+ Panko_Reused_Simple_Posts_2300 180 ip/s 2303 allocs/op
19
+ Panko_Reused_Simple_Posts_50 8388 ip/s 53 allocs/op
20
+ ```
21
+
22
+ ## Refactorings, method call support, combining
23
+
24
+ ### class eval
25
+ ```
26
+ Panko_HasOne_Posts_2300 64 ip/s 9477 allocs/op
27
+ Panko_HasOne_Posts_50 2397 ip/s 477 allocs/op
28
+ Panko_Reused_HasOne_Posts_2300 70 ip/s 9423 allocs/op
29
+ Panko_Reused_HasOne_Posts_50 2596 ip/s 423 allocs/op
30
+
31
+ Panko_Simple_Posts_2300 191 ip/s 2472 allocs/op
32
+ Panko_Simple_Posts_50 5128 ip/s 222 allocs/op
33
+ Panko_Reused_Simple_Posts_2300 180 ip/s 2418 allocs/op
34
+ Panko_Reused_Simple_Posts_50 5534 ip/s 168 allocs/op
35
+ ```
36
+
37
+ ### instance eval
38
+ ```
39
+ Panko_HasOne_Posts_2300 60 ip/s 9473 allocs/op
40
+ Panko_HasOne_Posts_50 2399 ip/s 473 allocs/op
41
+ Panko_Reused_HasOne_Posts_2300 66 ip/s 9419 allocs/op
42
+ Panko_Reused_HasOne_Posts_50 2582 ip/s 419 allocs/op
43
+
44
+ Panko_Simple_Posts_2300 195 ip/s 2470 allocs/op
45
+ Panko_Simple_Posts_50 4838 ip/s 220 allocs/op
46
+ Panko_Reused_Simple_Posts_2300 196 ip/s 2416 allocs/op
47
+ Panko_Reused_Simple_Posts_50 6241 ip/s 166 allocs/op
48
+ ```
@@ -0,0 +1,23 @@
1
+
2
+ # frozen_string_literal: true
3
+ require_relative "./benchmarking_support"
4
+ require_relative "./app"
5
+ require_relative "./setup"
6
+
7
+ require "memory_profiler"
8
+
9
+ class PostFastSerializer < Panko::Serializer
10
+ attributes :id, :body, :title, :author_id
11
+ end
12
+
13
+ def count_allocs(&block)
14
+ memory_report = MemoryProfiler.report(&block)
15
+ puts memory_report.pretty_print
16
+ end
17
+
18
+ posts = Post.all.to_a
19
+ merged_options = {}.merge(each_serializer: PostFastSerializer)
20
+ posts_array_serializer = Panko::ArraySerializer.new([], merged_options)
21
+
22
+ # prints out 18402
23
+ count_allocs { posts_array_serializer.serialize_to_json posts }
data/benchmarks/app.rb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ require "bundler/setup"
3
+
4
+
5
+ require "rails"
6
+ require "active_model"
7
+ require "active_support"
8
+ require "active_support/json"
9
+ require "action_controller"
10
+ require "action_controller/railtie"
11
+
12
+ require "active_model_serializers"
13
+ require "panko"
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+ require "benchmark/ips"
3
+ require "json"
4
+ require "memory_profiler"
5
+
6
+ module Benchmark
7
+ module ActiveModelSerializers
8
+ def data
9
+ posts = Post.all.includes(:author).to_a
10
+ posts_50 = posts.first(50).to_a
11
+ { all: posts, small: posts_50 }
12
+ end
13
+
14
+ def ams(label = nil, time: 10, disable_gc: true, warmup: 3, &block)
15
+ fail ArgumentError.new, "block should be passed" unless block_given?
16
+
17
+ GC.start
18
+
19
+ if disable_gc
20
+ GC.disable
21
+ else
22
+ GC.enable
23
+ end
24
+
25
+ memory_report = MemoryProfiler.report(&block)
26
+
27
+ report = Benchmark.ips(time, warmup, true) do |x|
28
+ x.report(label) { yield }
29
+ end
30
+
31
+ results = {
32
+ label: label,
33
+ ips: ActiveSupport::NumberHelper.number_to_delimited(report.entries.first.ips.round(2)),
34
+ allocs: "#{memory_report.total_allocated}/#{memory_report.total_retained}"
35
+ }.to_json
36
+
37
+ puts results
38
+
39
+ end
40
+ end
41
+
42
+ extend Benchmark::ActiveModelSerializers
43
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+ require_relative "./benchmarking_support"
3
+ require_relative "./app"
4
+ require_relative "./setup"
5
+
6
+ class AmsAuthorFastSerializer < ActiveModel::Serializer
7
+ attributes :id, :name
8
+ end
9
+
10
+ class AmsPostFastSerializer < ActiveModel::Serializer
11
+ attributes :id, :body, :title, :author_id
12
+ end
13
+
14
+ class AmsPostWithHasOneFastSerializer < ActiveModel::Serializer
15
+ attributes :id, :body, :title, :author_id
16
+
17
+ has_one :author, serializer: AmsAuthorFastSerializer
18
+ end
19
+
20
+ def benchmark_ams(prefix, serializer, options = {})
21
+ merged_options = options.merge(each_serializer: serializer)
22
+
23
+ data = Benchmark.data
24
+ posts = data[:all]
25
+ posts_50 = data[:small]
26
+
27
+
28
+ Benchmark.ams("AMS_#{prefix}_Posts_#{posts.count}") do
29
+ ActiveModel::ArraySerializer.new(posts, merged_options).serializable_object
30
+ end
31
+
32
+ data = Benchmark.data
33
+ posts = data[:all]
34
+ posts_50 = data[:small]
35
+
36
+ Benchmark.ams("AMS_#{prefix}_Posts_50") do
37
+ ActiveModel::ArraySerializer.new(posts_50, merged_options).serializable_object
38
+ end
39
+ end
40
+
41
+
42
+ benchmark_ams "HasOne", AmsPostWithHasOneFastSerializer
43
+ benchmark_ams "Simple", AmsPostFastSerializer
44
+ benchmark_ams "Except", AmsPostWithHasOneFastSerializer, except: [:title]
45
+ benchmark_ams "Include", AmsPostWithHasOneFastSerializer, include: [:id, :body, :author_id, :author]
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+ require_relative "./benchmarking_support"
3
+ require_relative "./app"
4
+ require_relative "./setup"
5
+
6
+ class NullLogger < Logger
7
+ def initialize(*args)
8
+ end
9
+
10
+ def add(*args, &block)
11
+ end
12
+ end
13
+
14
+ class BenchmarkApp < Rails::Application
15
+ routes.append do
16
+ get "/simple" => "main#simple"
17
+ get "/text" => "main#text"
18
+
19
+ get "/serialize_to_string" => "main#serialize_to_string"
20
+ end
21
+
22
+ config.secret_token = "s"*30
23
+ config.secret_key_base = "foo"
24
+ config.consider_all_requests_local = false
25
+
26
+ # simulate production
27
+ config.cache_classes = true
28
+ config.eager_load = true
29
+ config.action_controller.perform_caching = true
30
+
31
+ # otherwise deadlock occured
32
+ config.middleware.delete "Rack::Lock"
33
+
34
+ # to disable log files
35
+ config.logger = NullLogger.new
36
+ config.active_support.deprecation = :log
37
+ end
38
+
39
+ BenchmarkApp.initialize!
40
+
41
+ class AuthorFastSerializer < Panko::Serializer
42
+ attributes :id, :name
43
+ end
44
+
45
+ class PostWithHasOneFastSerializer < Panko::Serializer
46
+ attributes :id, :body, :title, :author_id
47
+
48
+ has_one :author, serializer: AuthorFastSerializer
49
+ end
50
+
51
+ class MainController < ActionController::Base
52
+ def text
53
+ render text: '{"ok":true}'.freeze, content_type: "application/json".freeze
54
+ end
55
+
56
+ def simple
57
+ render json: { ok: true }
58
+ end
59
+
60
+ def serialize_to_string
61
+ data = Benchmark.data[:all]
62
+ render text: Panko::ArraySerializer.new(data, each_serializer: PostWithHasOneFastSerializer).to_json, content_type: "application/json".freeze
63
+ end
64
+ end
65
+
66
+ class RouteNotFoundError < StandardError;end
67
+
68
+
69
+ def request(method, path)
70
+ response = Rack::MockRequest.new(BenchmarkApp).send(method, path)
71
+ if response.status.in?([404, 500])
72
+ raise RouteNotFoundError.new, 'not found #{method.to_s.upcase} #{path}'
73
+ end
74
+ response
75
+ end
76
+
77
+
78
+ Benchmark.ams("text") { request(:get, "/text") }
79
+ Benchmark.ams("simple") { request(:get, "/simple") }
80
+
81
+ Benchmark.ams("serialize_to_string") { request(:get, "/serialize_to_string") }
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+ require_relative "./benchmarking_support"
3
+ require_relative "./app"
4
+ require_relative "./setup"
5
+
6
+ class AuthorFastSerializer < Panko::Serializer
7
+ attributes :id, :name
8
+ end
9
+
10
+
11
+ class PostFastSerializer < Panko::Serializer
12
+ attributes :id, :body, :title, :author_id
13
+ end
14
+
15
+ class PostFastWithMethodCallSerializer < Panko::Serializer
16
+ attributes :id, :body, :title, :author_id, :method_call
17
+
18
+ def method_call
19
+ object.id * 2
20
+ end
21
+ end
22
+
23
+ class PostWithHasOneFastSerializer < Panko::Serializer
24
+ attributes :id, :body, :title, :author_id
25
+
26
+ has_one :author, serializer: AuthorFastSerializer
27
+ end
28
+
29
+ class AuthorWithHasManyFastSerializer < Panko::Serializer
30
+ attributes :id, :name
31
+
32
+ has_many :posts, serializer: PostFastSerializer
33
+ end
34
+
35
+
36
+ def benchmark(prefix, serializer, options = {})
37
+ data = Benchmark.data
38
+ posts = data[:all]
39
+ posts_50 = data[:small]
40
+
41
+ merged_options = options.merge(each_serializer: serializer)
42
+
43
+ Benchmark.ams("Panko_#{prefix}_Posts_#{posts.count}") do
44
+ Panko::ArraySerializer.new(posts, merged_options).to_json
45
+ end
46
+
47
+ data = Benchmark.data
48
+ posts = data[:all]
49
+ posts_50 = data[:small]
50
+
51
+ Benchmark.ams("Panko_#{prefix}_Posts_50") do
52
+ Panko::ArraySerializer.new(posts_50, merged_options).to_json
53
+ end
54
+ end
55
+
56
+ benchmark "HasOne", PostWithHasOneFastSerializer
57
+ benchmark "Simple", PostFastSerializer
58
+ benchmark "SimpleWithMethodCall", PostFastWithMethodCallSerializer
59
+ benchmark "Except", PostWithHasOneFastSerializer, except: [:title]
60
+ benchmark "Include", PostWithHasOneFastSerializer, include: [:id, :body, :author_id, :author]
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+ require_relative "./benchmarking_support"
3
+ require_relative "./app"
4
+ require_relative "./setup"
5
+
6
+ class AuthorFastSerializer < Panko::Serializer
7
+ attributes :id, :name
8
+ end
9
+
10
+
11
+ class PostFastSerializer < Panko::Serializer
12
+ attributes :id, :body, :title, :author_id
13
+ end
14
+
15
+ class PostWithHasOneFastSerializer < Panko::Serializer
16
+ attributes :id, :body, :title, :author_id
17
+
18
+ has_one :author, serializer: AuthorFastSerializer
19
+ end
20
+
21
+ class AuthorWithHasManyFastSerializer < Panko::Serializer
22
+ attributes :id, :name
23
+
24
+ has_many :posts, serializer: PostFastSerializer
25
+ end
26
+
27
+
28
+ def benchmark(prefix, serializer, options = {})
29
+ data = Benchmark.data
30
+ posts = data[:all]
31
+ posts_50 = data[:small]
32
+
33
+ merged_options = options.merge(each_serializer: serializer)
34
+
35
+ Benchmark.ams("Panko_#{prefix}_Posts_#{posts.count}") do
36
+ Panko::ArraySerializer.new(posts, merged_options).to_a
37
+ end
38
+
39
+ data = Benchmark.data
40
+ posts = data[:all]
41
+ posts_50 = data[:small]
42
+
43
+ Benchmark.ams("Panko_#{prefix}_Posts_50") do
44
+ Panko::ArraySerializer.new(posts_50, merged_options).to_a
45
+ end
46
+
47
+ posts_array_serializer = Panko::ArraySerializer.new([], merged_options)
48
+
49
+ data = Benchmark.data
50
+ posts = data[:all]
51
+ posts_50 = data[:small]
52
+
53
+ Benchmark.ams("Panko_Reused_#{prefix}_Posts_#{posts.count}") do
54
+ posts_array_serializer.serialize posts
55
+ end
56
+
57
+ data = Benchmark.data
58
+ posts = data[:all]
59
+ posts_50 = data[:small]
60
+
61
+ Benchmark.ams("Panko_Reused_#{prefix}_Posts_50") do
62
+ posts_array_serializer.serialize posts_50
63
+ end
64
+ end
65
+
66
+ benchmark "HasOne", PostWithHasOneFastSerializer
67
+ benchmark "Simple", PostFastSerializer
68
+ benchmark "Except", PostWithHasOneFastSerializer, except: [:title]
69
+ benchmark "Include", PostWithHasOneFastSerializer, include: [:id, :body, :author_id, :author]