panko_serializer 0.3.4 → 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.clang-format +16 -2
- data/.travis.yml +1 -2
- data/Gemfile +5 -3
- data/Rakefile +31 -5
- data/benchmarks/bm_ams_0_10.rb +56 -0
- data/benchmarks/bm_fastjsonapi.rb +56 -0
- data/benchmarks/bm_panko_json.rb +4 -4
- data/benchmarks/bm_panko_object.rb +4 -22
- data/benchmarks/bm_plain_object.rb +102 -0
- data/benchmarks/type_casts/bm_panko.rb +0 -3
- data/docs/README.md +1 -1
- data/ext/panko_serializer/{attributes_iterator.c → attributes_writer/active_record.c} +8 -12
- data/ext/panko_serializer/attributes_writer/active_record.h +15 -0
- data/ext/panko_serializer/attributes_writer/common.c +10 -0
- data/ext/panko_serializer/attributes_writer/common.h +8 -0
- data/ext/panko_serializer/attributes_writer/plain.c +17 -0
- data/ext/panko_serializer/attributes_writer/plain.h +9 -0
- data/ext/panko_serializer/{time_conversion.c → attributes_writer/type_cast/time_conversion.c} +0 -0
- data/ext/panko_serializer/{time_conversion.h → attributes_writer/type_cast/time_conversion.h} +2 -0
- data/ext/panko_serializer/{type_cast.c → attributes_writer/type_cast/type_cast.c} +2 -1
- data/ext/panko_serializer/{type_cast.h → attributes_writer/type_cast/type_cast.h} +2 -5
- data/ext/panko_serializer/attributes_writer/writer.c +50 -0
- data/ext/panko_serializer/attributes_writer/writer.h +31 -0
- data/ext/panko_serializer/extconf.rb +20 -0
- data/ext/panko_serializer/panko_serializer.c +7 -5
- data/ext/panko_serializer/panko_serializer.h +4 -5
- data/ext/panko_serializer/{association.c → serialization_descriptor/association.c} +0 -0
- data/ext/panko_serializer/{association.h → serialization_descriptor/association.h} +0 -0
- data/ext/panko_serializer/{attribute.c → serialization_descriptor/attribute.c} +0 -0
- data/ext/panko_serializer/{attribute.h → serialization_descriptor/attribute.h} +0 -0
- data/ext/panko_serializer/{serialization_descriptor.c → serialization_descriptor/serialization_descriptor.c} +12 -0
- data/ext/panko_serializer/{serialization_descriptor.h → serialization_descriptor/serialization_descriptor.h} +7 -4
- data/lib/panko/serialization_descriptor.rb +4 -0
- data/lib/panko/version.rb +1 -1
- metadata +24 -17
- data/benchmarks/bm_active_model_serializers.rb +0 -45
- data/benchmarks/bm_controller.rb +0 -81
- data/ext/panko_serializer/attributes_iterator.h +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4504cdc0e66927014ebd2843a52e8cef9aa5d4443b2a2cc6c31342468ebdeb08
|
4
|
+
data.tar.gz: 83a6d226222bd9910addcaaf61f2c77ea131da5d0b33bcdf0ecda150d82df878
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8bd4eab5358c889a895dc4ab48623eb5659572312879c5c64fccc5785e62f1cf2a9d576430cae4109937b8e61574a26273d3e9e3399dd92a03e7d60673593fce
|
7
|
+
data.tar.gz: f3c1994beb8627937db1827f5d5f07ba17d99809f40e752c8a3157bd38c66aa040d2db94722a14cd0643241405512be87ed6696ef5c3037283b3c930215e7709
|
data/.clang-format
CHANGED
@@ -29,10 +29,13 @@ BraceWrapping:
|
|
29
29
|
AfterObjCDeclaration: false
|
30
30
|
AfterStruct: false
|
31
31
|
AfterUnion: false
|
32
|
+
AfterExternBlock: false
|
32
33
|
BeforeCatch: false
|
33
34
|
BeforeElse: false
|
34
35
|
IndentBraces: false
|
35
|
-
|
36
|
+
SplitEmptyFunction: true
|
37
|
+
SplitEmptyRecord: true
|
38
|
+
SplitEmptyNamespace: true
|
36
39
|
BreakBeforeBinaryOperators: None
|
37
40
|
BreakBeforeBraces: Attach
|
38
41
|
BreakBeforeInheritanceComma: false
|
@@ -52,8 +55,13 @@ DerivePointerAlignment: false
|
|
52
55
|
DisableFormat: false
|
53
56
|
ExperimentalAutoDetectBinPacking: false
|
54
57
|
FixNamespaceComments: true
|
55
|
-
ForEachMacros:
|
58
|
+
ForEachMacros:
|
59
|
+
- foreach
|
60
|
+
- Q_FOREACH
|
61
|
+
- BOOST_FOREACH
|
56
62
|
IncludeCategories:
|
63
|
+
- Regex: '^<ext/.*\.h>'
|
64
|
+
Priority: 2
|
57
65
|
- Regex: '^<.*\.h>'
|
58
66
|
Priority: 1
|
59
67
|
- Regex: '^<.*'
|
@@ -62,6 +70,7 @@ IncludeCategories:
|
|
62
70
|
Priority: 3
|
63
71
|
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
64
72
|
IndentCaseLabels: true
|
73
|
+
IndentPPDirectives: None
|
65
74
|
IndentWidth: 2
|
66
75
|
IndentWrappedFunctionNames: false
|
67
76
|
JavaScriptQuotes: Leave
|
@@ -82,8 +91,13 @@ PenaltyBreakString: 1000
|
|
82
91
|
PenaltyExcessCharacter: 1000000
|
83
92
|
PenaltyReturnTypeOnItsOwnLine: 200
|
84
93
|
PointerAlignment: Left
|
94
|
+
RawStringFormats:
|
95
|
+
- Delimiter: pb
|
96
|
+
Language: TextProto
|
97
|
+
BasedOnStyle: google
|
85
98
|
ReflowComments: true
|
86
99
|
SortIncludes: true
|
100
|
+
SortUsingDeclarations: true
|
87
101
|
SpaceAfterCStyleCast: false
|
88
102
|
SpaceAfterTemplateKeyword: true
|
89
103
|
SpaceBeforeAssignmentOperators: true
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -3,7 +3,8 @@ source "https://rubygems.org"
|
|
3
3
|
|
4
4
|
gemspec
|
5
5
|
|
6
|
-
|
6
|
+
raw_rails_version = ENV.fetch("RAILS_VERSION", "4.2")
|
7
|
+
rails_version = "~> #{raw_rails_version}"
|
7
8
|
|
8
9
|
gem "rails", rails_version
|
9
10
|
gem "railties", rails_version
|
@@ -14,14 +15,15 @@ gem "activerecord", rails_version, group: :test
|
|
14
15
|
|
15
16
|
group :benchmarks do
|
16
17
|
gem "sqlite3"
|
17
|
-
gem "pg"
|
18
|
+
gem "pg", "0.21"
|
18
19
|
|
19
20
|
gem "memory_profiler"
|
20
21
|
gem "ruby-prof"
|
21
22
|
gem "ruby-prof-flamegraph"
|
22
23
|
|
23
24
|
gem "benchmark-ips"
|
24
|
-
gem "active_model_serializers"
|
25
|
+
gem "active_model_serializers"
|
26
|
+
gem "fast_jsonapi" if raw_rails_version.start_with? "5"
|
25
27
|
|
26
28
|
gem "terminal-table"
|
27
29
|
end
|
data/Rakefile
CHANGED
@@ -4,6 +4,7 @@ require "rspec/core/rake_task"
|
|
4
4
|
require "json"
|
5
5
|
require "terminal-table"
|
6
6
|
require "rake/extensiontask"
|
7
|
+
require "pty"
|
7
8
|
|
8
9
|
gem = Gem::Specification.load( File.dirname(__FILE__) + "/panko_serializer.gemspec" )
|
9
10
|
|
@@ -21,15 +22,40 @@ Rake::Task[:spec].prerequisites << :compile
|
|
21
22
|
|
22
23
|
task default: :spec
|
23
24
|
|
25
|
+
def print_and_flush(str)
|
26
|
+
print str
|
27
|
+
$stdout.flush
|
28
|
+
end
|
29
|
+
|
30
|
+
def run_process(cmd)
|
31
|
+
puts "> Running #{cmd}"
|
32
|
+
lines = []
|
33
|
+
PTY.spawn(cmd) do |stdout, stdin, pid|
|
34
|
+
begin
|
35
|
+
stdout.each do |line|
|
36
|
+
print_and_flush '.'
|
37
|
+
lines << line
|
38
|
+
end
|
39
|
+
rescue Errno::EIO
|
40
|
+
puts "Errno:EIO error, but this probably just means " +
|
41
|
+
"that the process has finished giving output - #{cmd}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
lines
|
46
|
+
rescue PTY::ChildExited
|
47
|
+
puts "The child process exited! - #{cmd}"
|
48
|
+
[]
|
49
|
+
end
|
24
50
|
|
25
|
-
def run_benchmarks(files, items_count:
|
51
|
+
def run_benchmarks(files, items_count: 7_000)
|
26
52
|
headings = ["Benchmark", "ip/s", "allocs/retained"]
|
27
53
|
files.each do |benchmark_file|
|
28
|
-
output = `ITEMS_COUNT=#{items_count} RAILS_ENV=production ruby #{benchmark_file}`
|
29
54
|
|
30
|
-
|
31
|
-
|
32
|
-
|
55
|
+
lines = run_process "ITEMS_COUNT=#{items_count} RAILS_ENV=production ruby #{benchmark_file}"
|
56
|
+
rows = lines.map do |line|
|
57
|
+
row = JSON.parse(line)
|
58
|
+
row.values
|
33
59
|
end
|
34
60
|
|
35
61
|
puts "\n\n"
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative "./benchmarking_support"
|
3
|
+
require_relative "./app"
|
4
|
+
require_relative "./setup"
|
5
|
+
|
6
|
+
# disable logging for benchmarks
|
7
|
+
ActiveModelSerializers.logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new('/dev/null'))
|
8
|
+
|
9
|
+
|
10
|
+
class AmsAuthorFastSerializer < ActiveModel::Serializer
|
11
|
+
attributes :id, :name
|
12
|
+
end
|
13
|
+
|
14
|
+
class AmsPostFastSerializer < ActiveModel::Serializer
|
15
|
+
attributes :id, :body, :title, :author_id, :created_at
|
16
|
+
end
|
17
|
+
|
18
|
+
class AmsPostWithHasOneFastSerializer < ActiveModel::Serializer
|
19
|
+
attributes :id, :body, :title, :author_id
|
20
|
+
|
21
|
+
has_one :author, serializer: AmsAuthorFastSerializer
|
22
|
+
end
|
23
|
+
|
24
|
+
def benchmark_ams(prefix, serializer, options = {})
|
25
|
+
merged_options = options.merge(each_serializer: serializer)
|
26
|
+
|
27
|
+
data = Benchmark.data
|
28
|
+
posts = data[:all]
|
29
|
+
posts_50 = data[:small]
|
30
|
+
|
31
|
+
|
32
|
+
Benchmark.run("AMS_#{prefix}_Posts_#{posts.count}") do
|
33
|
+
ActiveModelSerializers::SerializableResource.new(posts, merged_options).to_json
|
34
|
+
end
|
35
|
+
|
36
|
+
data = Benchmark.data
|
37
|
+
posts = data[:all]
|
38
|
+
posts_50 = data[:small]
|
39
|
+
|
40
|
+
Benchmark.run("AMS_#{prefix}_Posts_50") do
|
41
|
+
ActiveModelSerializers::SerializableResource.new(posts_50, merged_options).to_json
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
benchmark_ams "Attributes_Simple", AmsPostFastSerializer
|
47
|
+
benchmark_ams "Attributes_HasOne", AmsPostWithHasOneFastSerializer
|
48
|
+
benchmark_ams "Attributes_Except", AmsPostWithHasOneFastSerializer, except: [:title]
|
49
|
+
benchmark_ams "Attributes_Only", AmsPostWithHasOneFastSerializer, only: [:id, :body, :author_id, :author]
|
50
|
+
|
51
|
+
ActiveModel::Serializer.config.adapter = :json_api
|
52
|
+
|
53
|
+
benchmark_ams "JsonAPI_Simple", AmsPostFastSerializer
|
54
|
+
benchmark_ams "JsonAPI_HasOne", AmsPostWithHasOneFastSerializer
|
55
|
+
benchmark_ams "JsonAPI_Except", AmsPostWithHasOneFastSerializer, except: [:title]
|
56
|
+
benchmark_ams "JsonAPI_Only", AmsPostWithHasOneFastSerializer, only: [:id, :body, :author_id, :author]
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
exit unless ENV.fetch("RAILS_VERSION", "4.2").start_with? "5"
|
3
|
+
|
4
|
+
require_relative "./benchmarking_support"
|
5
|
+
require_relative "./app"
|
6
|
+
require_relative "./setup"
|
7
|
+
require 'fast_jsonapi'
|
8
|
+
|
9
|
+
class AuthorSerializer
|
10
|
+
include FastJsonapi::ObjectSerializer
|
11
|
+
attributes :id, :name
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
class PostFastSerializer
|
16
|
+
include FastJsonapi::ObjectSerializer
|
17
|
+
attributes :id, :body, :title, :author_id, :created_at
|
18
|
+
end
|
19
|
+
|
20
|
+
class PostWithHasOneFastSerializer
|
21
|
+
include FastJsonapi::ObjectSerializer
|
22
|
+
attributes :id, :body, :title, :author_id
|
23
|
+
|
24
|
+
has_one :author
|
25
|
+
end
|
26
|
+
|
27
|
+
class AuthorWithHasManyFastSerializer
|
28
|
+
include FastJsonapi::ObjectSerializer
|
29
|
+
attributes :id, :name
|
30
|
+
|
31
|
+
has_many :posts, serializer: :post_fast
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
def benchmark(prefix, serializer, options = {})
|
36
|
+
data = Benchmark.data
|
37
|
+
posts = data[:all]
|
38
|
+
posts_50 = data[:small]
|
39
|
+
|
40
|
+
merged_options = options.merge(each_serializer: serializer)
|
41
|
+
|
42
|
+
Benchmark.run("FastJSONAPI_#{prefix}_Posts_#{posts.count}") do
|
43
|
+
serializer.new(posts, merged_options).serialized_json
|
44
|
+
end
|
45
|
+
|
46
|
+
data = Benchmark.data
|
47
|
+
posts = data[:all]
|
48
|
+
posts_50 = data[:small]
|
49
|
+
|
50
|
+
Benchmark.run("FastJSONAPI_#{prefix}_Posts_50") do
|
51
|
+
serializer.new(posts_50, merged_options).serialized_json
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
benchmark "Simple", PostFastSerializer
|
56
|
+
benchmark "HasOne", PostWithHasOneFastSerializer, include: [:author]
|
data/benchmarks/bm_panko_json.rb
CHANGED
@@ -40,7 +40,7 @@ def benchmark(prefix, serializer, options = {})
|
|
40
40
|
|
41
41
|
merged_options = options.merge(each_serializer: serializer)
|
42
42
|
|
43
|
-
Benchmark.run("
|
43
|
+
Benchmark.run("Panko_ActiveRecord_#{prefix}_Posts_#{posts.count}") do
|
44
44
|
Panko::ArraySerializer.new(posts, merged_options).to_json
|
45
45
|
end
|
46
46
|
|
@@ -48,13 +48,13 @@ def benchmark(prefix, serializer, options = {})
|
|
48
48
|
posts = data[:all]
|
49
49
|
posts_50 = data[:small]
|
50
50
|
|
51
|
-
Benchmark.run("
|
51
|
+
Benchmark.run("Panko_ActiveRecord_#{prefix}_Posts_50") do
|
52
52
|
Panko::ArraySerializer.new(posts_50, merged_options).to_json
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
benchmark "HasOne", PostWithHasOneFastSerializer
|
57
56
|
benchmark "Simple", PostFastSerializer
|
57
|
+
benchmark "HasOne", PostWithHasOneFastSerializer
|
58
58
|
benchmark "SimpleWithMethodCall", PostFastWithMethodCallSerializer
|
59
59
|
benchmark "Except", PostWithHasOneFastSerializer, except: [:title]
|
60
|
-
benchmark "
|
60
|
+
benchmark "Only", PostWithHasOneFastSerializer, only: [:id, :body, :author_id, :author]
|
@@ -32,7 +32,7 @@ def benchmark(prefix, serializer, options = {})
|
|
32
32
|
|
33
33
|
merged_options = options.merge(each_serializer: serializer)
|
34
34
|
|
35
|
-
Benchmark.run("
|
35
|
+
Benchmark.run("Panko_ActiveRecord_#{prefix}_Posts_#{posts.count}") do
|
36
36
|
Panko::ArraySerializer.new(posts, merged_options).to_a
|
37
37
|
end
|
38
38
|
|
@@ -40,30 +40,12 @@ def benchmark(prefix, serializer, options = {})
|
|
40
40
|
posts = data[:all]
|
41
41
|
posts_50 = data[:small]
|
42
42
|
|
43
|
-
Benchmark.run("
|
43
|
+
Benchmark.run("Panko_ActiveRecord_#{prefix}_Posts_50") do
|
44
44
|
Panko::ArraySerializer.new(posts_50, merged_options).to_a
|
45
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.run("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.run("Panko_Reused_#{prefix}_Posts_50") do
|
62
|
-
posts_array_serializer.serialize posts_50
|
63
|
-
end
|
64
46
|
end
|
65
47
|
|
66
|
-
benchmark "HasOne", PostWithHasOneFastSerializer
|
67
48
|
benchmark "Simple", PostFastSerializer
|
49
|
+
benchmark "HasOne", PostWithHasOneFastSerializer
|
68
50
|
benchmark "Except", PostWithHasOneFastSerializer, except: [:title]
|
69
|
-
benchmark "
|
51
|
+
benchmark "Only", PostWithHasOneFastSerializer, only: [:id, :body, :author_id, :author]
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative "./benchmarking_support"
|
3
|
+
require_relative "./app"
|
4
|
+
|
5
|
+
class AuthorFastSerializer < Panko::Serializer
|
6
|
+
attributes :id, :name
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
class PostFastSerializer < Panko::Serializer
|
11
|
+
attributes :id, :body, :title, :author_id, :created_at
|
12
|
+
end
|
13
|
+
|
14
|
+
class PostFastWithMethodCallSerializer < Panko::Serializer
|
15
|
+
attributes :id, :body, :title, :author_id, :method_call
|
16
|
+
|
17
|
+
def method_call
|
18
|
+
object.id * 2
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class PostWithHasOneFastSerializer < Panko::Serializer
|
23
|
+
attributes :id, :body, :title, :author_id
|
24
|
+
|
25
|
+
has_one :author, serializer: AuthorFastSerializer
|
26
|
+
end
|
27
|
+
|
28
|
+
class AuthorWithHasManyFastSerializer < Panko::Serializer
|
29
|
+
attributes :id, :name
|
30
|
+
|
31
|
+
has_many :posts, serializer: PostFastSerializer
|
32
|
+
end
|
33
|
+
|
34
|
+
class Post
|
35
|
+
attr_accessor :id, :body, :title, :created_at, :author, :author_id
|
36
|
+
|
37
|
+
def self.create(attrs)
|
38
|
+
p = Post.new
|
39
|
+
attrs.each do |k,v|
|
40
|
+
p.send :"#{k}=", v
|
41
|
+
end
|
42
|
+
p
|
43
|
+
end
|
44
|
+
|
45
|
+
def author=(author)
|
46
|
+
@author = author
|
47
|
+
@author_id = author_id
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class Author
|
52
|
+
attr_accessor :id, :name
|
53
|
+
|
54
|
+
def self.create(attrs)
|
55
|
+
a = Author.new
|
56
|
+
attrs.each do |k,v|
|
57
|
+
a.send :"#{k}=", v
|
58
|
+
end
|
59
|
+
a
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def benchmark_data
|
64
|
+
posts = []
|
65
|
+
ENV.fetch("ITEMS_COUNT", "2300").to_i.times do |i|
|
66
|
+
posts << Post.create(
|
67
|
+
id: i,
|
68
|
+
body: "something about how password restrictions are evil, and less secure, and with the math to prove it.",
|
69
|
+
title: "Your bank is does not know how to do security",
|
70
|
+
author: Author.create(id: i, name: "Preston Sego")
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
{ all: posts, small: posts.first(50) }
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
def benchmark(prefix, serializer, options = {})
|
79
|
+
data = benchmark_data
|
80
|
+
posts = data[:all]
|
81
|
+
posts_50 = data[:small]
|
82
|
+
|
83
|
+
merged_options = options.merge(each_serializer: serializer)
|
84
|
+
|
85
|
+
Benchmark.run("Panko_Plain_#{prefix}_Posts_#{posts.count}") do
|
86
|
+
Panko::ArraySerializer.new(posts, merged_options).to_json
|
87
|
+
end
|
88
|
+
|
89
|
+
data = benchmark_data
|
90
|
+
posts = data[:all]
|
91
|
+
posts_50 = data[:small]
|
92
|
+
|
93
|
+
Benchmark.run("Panko_Plain_#{prefix}_Posts_50") do
|
94
|
+
Panko::ArraySerializer.new(posts_50, merged_options).to_json
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
benchmark "Simple", PostFastSerializer
|
99
|
+
benchmark "HasOne", PostWithHasOneFastSerializer
|
100
|
+
benchmark "SimpleWithMethodCall", PostFastWithMethodCallSerializer
|
101
|
+
benchmark "Except", PostWithHasOneFastSerializer, except: [:title]
|
102
|
+
benchmark "Only", PostWithHasOneFastSerializer, only: [:id, :body, :author_id, :author]
|
@@ -46,9 +46,6 @@ def db_panko_time
|
|
46
46
|
end
|
47
47
|
|
48
48
|
panko_type_convert ActiveRecord::Type::String, 1, "1"
|
49
|
-
panko_type_convert ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Json, '{"a":1}', {a:1}
|
50
|
-
exit
|
51
|
-
|
52
49
|
panko_type_convert ActiveRecord::Type::Text, 1, "1"
|
53
50
|
panko_type_convert ActiveRecord::Type::Integer, "1", 1
|
54
51
|
panko_type_convert ActiveRecord::Type::Float, "1.23", 1.23
|
data/docs/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#include "
|
1
|
+
#include "active_record.h"
|
2
2
|
|
3
3
|
static ID attributes_id;
|
4
4
|
static ID types_id;
|
@@ -139,10 +139,10 @@ VALUE read_attribute(struct attributes attributes_ctx, Attribute attribute) {
|
|
139
139
|
return value;
|
140
140
|
}
|
141
141
|
|
142
|
-
VALUE
|
143
|
-
|
144
|
-
|
145
|
-
|
142
|
+
VALUE active_record_attributes_writer(VALUE obj,
|
143
|
+
VALUE attributes,
|
144
|
+
EachAttributeFunc func,
|
145
|
+
VALUE writer) {
|
146
146
|
long i;
|
147
147
|
struct attributes attributes_ctx = init_context(obj);
|
148
148
|
volatile VALUE record_class = CLASS_OF(obj);
|
@@ -152,19 +152,15 @@ VALUE panko_each_attribute(VALUE obj,
|
|
152
152
|
Attribute attribute = attribute_read(raw_attribute);
|
153
153
|
attribute_try_invalidate(attribute, record_class);
|
154
154
|
|
155
|
-
volatile VALUE name_str = attribute->name_str;
|
156
|
-
if (attribute->alias_name != Qnil) {
|
157
|
-
name_str = attribute->alias_name;
|
158
|
-
}
|
159
|
-
|
160
155
|
volatile VALUE value = read_attribute(attributes_ctx, attribute);
|
161
|
-
|
156
|
+
|
157
|
+
func(writer, attr_name_for_serialization(attribute), value);
|
162
158
|
}
|
163
159
|
|
164
160
|
return Qnil;
|
165
161
|
}
|
166
162
|
|
167
|
-
void
|
163
|
+
void init_active_record_attributes_writer(VALUE mPanko) {
|
168
164
|
attributes_id = rb_intern("@attributes");
|
169
165
|
delegate_hash_id = rb_intern("@delegate_hash");
|
170
166
|
values_id = rb_intern("@values");
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include <ruby.h>
|
4
|
+
#include <stdbool.h>
|
5
|
+
|
6
|
+
#include "serialization_descriptor/attribute.h"
|
7
|
+
#include "type_cast/type_cast.h"
|
8
|
+
#include "common.h"
|
9
|
+
|
10
|
+
extern VALUE active_record_attributes_writer(VALUE object,
|
11
|
+
VALUE attributes,
|
12
|
+
EachAttributeFunc func,
|
13
|
+
VALUE context);
|
14
|
+
|
15
|
+
void init_active_record_attributes_writer(VALUE mPanko);
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#include "plain.h"
|
2
|
+
|
3
|
+
VALUE plain_attributes_writer(VALUE obj,
|
4
|
+
VALUE attributes,
|
5
|
+
EachAttributeFunc func,
|
6
|
+
VALUE writer) {
|
7
|
+
long i;
|
8
|
+
for (i = 0; i < RARRAY_LEN(attributes); i++) {
|
9
|
+
volatile VALUE raw_attribute = RARRAY_AREF(attributes, i);
|
10
|
+
Attribute attribute = attribute_read(raw_attribute);
|
11
|
+
volatile VALUE value = rb_funcall(obj, attribute->name_id, 0);
|
12
|
+
|
13
|
+
func(writer, attr_name_for_serialization(attribute), value);
|
14
|
+
}
|
15
|
+
|
16
|
+
return Qnil;
|
17
|
+
}
|
data/ext/panko_serializer/{time_conversion.c → attributes_writer/type_cast/time_conversion.c}
RENAMED
File without changes
|
@@ -112,7 +112,8 @@ void cache_type_lookup() {
|
|
112
112
|
ar_date_time_type = rb_const_get_at(ar_type, rb_intern("DateTime"));
|
113
113
|
|
114
114
|
ar_type_methods = rb_class_instance_methods(0, NULL, ar_string_type);
|
115
|
-
if(rb_ary_includes(ar_type_methods,
|
115
|
+
if (rb_ary_includes(ar_type_methods,
|
116
|
+
rb_to_symbol(rb_str_new_cstr("deserialize")))) {
|
116
117
|
deserialize_from_db_id = rb_intern("deserialize");
|
117
118
|
} else {
|
118
119
|
deserialize_from_db_id = rb_intern("type_cast_from_database");
|
@@ -1,9 +1,8 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
1
3
|
#include <ruby.h>
|
2
4
|
#include <stdbool.h>
|
3
5
|
|
4
|
-
#ifndef __PANKO_TYPE_CAST_H__
|
5
|
-
#define __PANKO_TYPE_CAST_H__
|
6
|
-
|
7
6
|
/*
|
8
7
|
* Type Casting
|
9
8
|
*
|
@@ -75,5 +74,3 @@ static struct _TypeCast type_casts[] = {
|
|
75
74
|
|
76
75
|
extern VALUE type_cast(VALUE type_metadata, VALUE value);
|
77
76
|
void panko_init_type_cast(VALUE mPanko);
|
78
|
-
|
79
|
-
#endif
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#include "writer.h"
|
2
|
+
|
3
|
+
static bool types_initialized = false;
|
4
|
+
static VALUE ar_base_type = Qundef;
|
5
|
+
|
6
|
+
void init_types(VALUE v) {
|
7
|
+
if (types_initialized == true) {
|
8
|
+
return;
|
9
|
+
}
|
10
|
+
|
11
|
+
types_initialized = true;
|
12
|
+
|
13
|
+
volatile VALUE ar_type =
|
14
|
+
rb_const_get_at(rb_cObject, rb_intern("ActiveRecord"));
|
15
|
+
ar_base_type = rb_const_get_at(ar_type, rb_intern("Base"));
|
16
|
+
}
|
17
|
+
|
18
|
+
AttributesWriter create_attributes_writer(VALUE subject) {
|
19
|
+
// If ActiveRecord::Base can't be found it will throw error
|
20
|
+
int isErrored;
|
21
|
+
rb_protect(init_types, Qnil, &isErrored);
|
22
|
+
|
23
|
+
if (ar_base_type != Qundef &&
|
24
|
+
rb_obj_is_kind_of(subject, ar_base_type) == Qtrue) {
|
25
|
+
return (AttributesWriter){
|
26
|
+
.object_type = ActiveRecord,
|
27
|
+
.write_attributes = active_record_attributes_writer};
|
28
|
+
} else {
|
29
|
+
return (AttributesWriter){.object_type = Plain,
|
30
|
+
.write_attributes = plain_attributes_writer};
|
31
|
+
}
|
32
|
+
|
33
|
+
return create_empty_attributes_writer();
|
34
|
+
}
|
35
|
+
|
36
|
+
VALUE empty_write_attributes(VALUE obj,
|
37
|
+
VALUE attributes,
|
38
|
+
EachAttributeFunc func,
|
39
|
+
VALUE writer) {
|
40
|
+
return Qnil;
|
41
|
+
}
|
42
|
+
|
43
|
+
AttributesWriter create_empty_attributes_writer() {
|
44
|
+
return (AttributesWriter){.object_type = Unknown,
|
45
|
+
.write_attributes = empty_write_attributes};
|
46
|
+
}
|
47
|
+
|
48
|
+
void init_attributes_writer(VALUE mPanko) {
|
49
|
+
init_active_record_attributes_writer(mPanko);
|
50
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include <ruby.h>
|
4
|
+
|
5
|
+
#include "common.h"
|
6
|
+
#include "active_record.h"
|
7
|
+
#include "plain.h"
|
8
|
+
|
9
|
+
enum ObjectType { Unknown = 0, ActiveRecord = 1, Plain = 2 };
|
10
|
+
|
11
|
+
typedef struct _AttributesWriter {
|
12
|
+
enum ObjectType object_type;
|
13
|
+
|
14
|
+
int (*write_attributes)(VALUE object,
|
15
|
+
VALUE attributes,
|
16
|
+
EachAttributeFunc func,
|
17
|
+
VALUE context);
|
18
|
+
} AttributesWriter;
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Infers the attributes writer from the subject type
|
22
|
+
*/
|
23
|
+
AttributesWriter create_attributes_writer(VALUE subject);
|
24
|
+
|
25
|
+
/**
|
26
|
+
* Creates empty writer
|
27
|
+
* Useful when the writer is not known, and you need init something
|
28
|
+
*/
|
29
|
+
AttributesWriter create_empty_attributes_writer();
|
30
|
+
|
31
|
+
void init_attributes_writer(VALUE mPanko);
|
@@ -1,8 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "mkmf"
|
3
|
+
require "pathname"
|
3
4
|
|
4
5
|
$CPPFLAGS += " -Wall"
|
5
6
|
|
6
7
|
extension_name = "panko_serializer"
|
7
8
|
dir_config(extension_name)
|
9
|
+
|
10
|
+
RbConfig.expand(srcdir = "$(srcdir)".dup)
|
11
|
+
|
12
|
+
# enum all source files
|
13
|
+
$srcs = Dir[File.join(srcdir, "**/*.c")]
|
14
|
+
|
15
|
+
|
16
|
+
# Get all source directories recursivley
|
17
|
+
directories = Dir[File.join(srcdir, "**/*")].select { |f| File.directory?(f) }
|
18
|
+
directories = directories.map { |d| Pathname.new(d).relative_path_from(Pathname.new(srcdir)) }
|
19
|
+
directories.each do |dir|
|
20
|
+
# add include path to the internal folder
|
21
|
+
# $(srcdir) is a root folder, where "extconf.rb" is stored
|
22
|
+
$INCFLAGS << " -I$(srcdir)/#{dir}"
|
23
|
+
|
24
|
+
# add folder, where compiler can search source files
|
25
|
+
$VPATH << "$(srcdir)/#{dir}"
|
26
|
+
end
|
27
|
+
|
8
28
|
create_makefile("panko/panko_serializer")
|
@@ -41,8 +41,8 @@ void serialize_fields(VALUE subject,
|
|
41
41
|
VALUE str_writer,
|
42
42
|
SerializationDescriptor descriptor,
|
43
43
|
VALUE context) {
|
44
|
-
|
45
|
-
|
44
|
+
descriptor->attributes_writer.write_attributes(
|
45
|
+
subject, descriptor->attributes, write_value, str_writer);
|
46
46
|
|
47
47
|
serialize_method_fields(subject, str_writer, descriptor, context);
|
48
48
|
}
|
@@ -94,6 +94,8 @@ VALUE serialize_subject(VALUE key,
|
|
94
94
|
VALUE str_writer,
|
95
95
|
SerializationDescriptor descriptor,
|
96
96
|
VALUE context) {
|
97
|
+
sd_set_writer(descriptor, subject);
|
98
|
+
|
97
99
|
rb_funcall(str_writer, push_object_id, 1, key);
|
98
100
|
|
99
101
|
serialize_fields(subject, str_writer, descriptor, context);
|
@@ -141,8 +143,8 @@ VALUE serialize_subject_api(VALUE klass,
|
|
141
143
|
VALUE str_writer,
|
142
144
|
VALUE descriptor,
|
143
145
|
VALUE context) {
|
144
|
-
|
145
|
-
|
146
|
+
SerializationDescriptor sd = sd_read(descriptor);
|
147
|
+
return serialize_subject(Qnil, subject, str_writer, sd, context);
|
146
148
|
}
|
147
149
|
|
148
150
|
VALUE serialize_subjects_api(VALUE klass,
|
@@ -171,7 +173,7 @@ void Init_panko_serializer() {
|
|
171
173
|
serialize_subjects_api, 4);
|
172
174
|
|
173
175
|
panko_init_serialization_descriptor(mPanko);
|
174
|
-
|
176
|
+
init_attributes_writer(mPanko);
|
175
177
|
panko_init_type_cast(mPanko);
|
176
178
|
panko_init_attribute(mPanko);
|
177
179
|
panko_init_association(mPanko);
|
@@ -1,10 +1,9 @@
|
|
1
1
|
#include <ruby.h>
|
2
2
|
|
3
|
-
#include "
|
4
|
-
#include "
|
5
|
-
#include "
|
6
|
-
#include "serialization_descriptor.h"
|
7
|
-
#include "type_cast.h"
|
3
|
+
#include "attributes_writer/writer.h"
|
4
|
+
#include "serialization_descriptor/serialization_descriptor.h"
|
5
|
+
#include "serialization_descriptor/association.h"
|
6
|
+
#include "serialization_descriptor/attribute.h"
|
8
7
|
|
9
8
|
VALUE serialize_subject(VALUE key,
|
10
9
|
VALUE subject,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -5,6 +5,7 @@ VALUE cSerializationDescriptor;
|
|
5
5
|
static ID context_id;
|
6
6
|
static ID object_id;
|
7
7
|
|
8
|
+
|
8
9
|
static void sd_free(SerializationDescriptor sd) {
|
9
10
|
if (!sd) {
|
10
11
|
return;
|
@@ -42,6 +43,8 @@ static VALUE sd_new(int argc, VALUE* argv, VALUE self) {
|
|
42
43
|
sd->has_many_associations = Qnil;
|
43
44
|
sd->aliases = Qnil;
|
44
45
|
|
46
|
+
sd->attributes_writer = create_empty_attributes_writer();
|
47
|
+
|
45
48
|
return Data_Wrap_Struct(cSerializationDescriptor, sd_mark, sd_free, sd);
|
46
49
|
}
|
47
50
|
|
@@ -49,6 +52,15 @@ SerializationDescriptor sd_read(VALUE descriptor) {
|
|
49
52
|
return (SerializationDescriptor)DATA_PTR(descriptor);
|
50
53
|
}
|
51
54
|
|
55
|
+
|
56
|
+
void sd_set_writer(SerializationDescriptor sd, VALUE subject) {
|
57
|
+
if (sd->attributes_writer.object_type != Unknown) {
|
58
|
+
return;
|
59
|
+
}
|
60
|
+
|
61
|
+
sd->attributes_writer = create_attributes_writer(subject);
|
62
|
+
}
|
63
|
+
|
52
64
|
VALUE sd_build_serializer(SerializationDescriptor sd) {
|
53
65
|
if (sd->serializer == Qnil) {
|
54
66
|
VALUE args[0];
|
@@ -1,7 +1,9 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
1
3
|
#include <ruby.h>
|
4
|
+
#include <stdbool.h>
|
2
5
|
|
3
|
-
#
|
4
|
-
#define __SD_H__
|
6
|
+
#include "attributes_writer/writer.h"
|
5
7
|
|
6
8
|
typedef struct _SerializationDescriptor {
|
7
9
|
// type of the serializer, so we can create it later
|
@@ -15,6 +17,8 @@ typedef struct _SerializationDescriptor {
|
|
15
17
|
VALUE method_fields;
|
16
18
|
VALUE has_one_associations;
|
17
19
|
VALUE has_many_associations;
|
20
|
+
|
21
|
+
AttributesWriter attributes_writer;
|
18
22
|
} * SerializationDescriptor;
|
19
23
|
|
20
24
|
SerializationDescriptor sd_read(VALUE descriptor);
|
@@ -23,7 +27,6 @@ void sd_mark(SerializationDescriptor data);
|
|
23
27
|
|
24
28
|
VALUE sd_build_serializer(SerializationDescriptor descriptor);
|
25
29
|
void sd_apply_serializer_config(VALUE serializer, VALUE object, VALUE context);
|
30
|
+
void sd_set_writer(SerializationDescriptor sd, VALUE subject);
|
26
31
|
|
27
32
|
void panko_init_serialization_descriptor(VALUE mPanko);
|
28
|
-
|
29
|
-
#endif
|
@@ -7,6 +7,10 @@ module Panko
|
|
7
7
|
#
|
8
8
|
def self.build(serializer, options={})
|
9
9
|
backend = Panko::SerializationDescriptor.duplicate(serializer._descriptor)
|
10
|
+
|
11
|
+
if serializer.respond_to? :filters_for
|
12
|
+
options.merge! serializer.filters_for(options[:context])
|
13
|
+
end
|
10
14
|
backend.apply_filters(options)
|
11
15
|
backend
|
12
16
|
end
|
data/lib/panko/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: panko_serializer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yosi Attias
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-02-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -101,10 +101,11 @@ files:
|
|
101
101
|
- benchmarks/allocs.rb
|
102
102
|
- benchmarks/app.rb
|
103
103
|
- benchmarks/benchmarking_support.rb
|
104
|
-
- benchmarks/
|
105
|
-
- benchmarks/
|
104
|
+
- benchmarks/bm_ams_0_10.rb
|
105
|
+
- benchmarks/bm_fastjsonapi.rb
|
106
106
|
- benchmarks/bm_panko_json.rb
|
107
107
|
- benchmarks/bm_panko_object.rb
|
108
|
+
- benchmarks/bm_plain_object.rb
|
108
109
|
- benchmarks/bm_serialization_descriptor.rb
|
109
110
|
- benchmarks/bm_serializer_resolver.rb
|
110
111
|
- benchmarks/profile.rb
|
@@ -121,21 +122,27 @@ files:
|
|
121
122
|
- docs/getting-started.md
|
122
123
|
- docs/performance.md
|
123
124
|
- docs/response-bag.md
|
124
|
-
- ext/panko_serializer/
|
125
|
-
- ext/panko_serializer/
|
126
|
-
- ext/panko_serializer/
|
127
|
-
- ext/panko_serializer/
|
128
|
-
- ext/panko_serializer/
|
129
|
-
- ext/panko_serializer/
|
125
|
+
- ext/panko_serializer/attributes_writer/active_record.c
|
126
|
+
- ext/panko_serializer/attributes_writer/active_record.h
|
127
|
+
- ext/panko_serializer/attributes_writer/common.c
|
128
|
+
- ext/panko_serializer/attributes_writer/common.h
|
129
|
+
- ext/panko_serializer/attributes_writer/plain.c
|
130
|
+
- ext/panko_serializer/attributes_writer/plain.h
|
131
|
+
- ext/panko_serializer/attributes_writer/type_cast/time_conversion.c
|
132
|
+
- ext/panko_serializer/attributes_writer/type_cast/time_conversion.h
|
133
|
+
- ext/panko_serializer/attributes_writer/type_cast/type_cast.c
|
134
|
+
- ext/panko_serializer/attributes_writer/type_cast/type_cast.h
|
135
|
+
- ext/panko_serializer/attributes_writer/writer.c
|
136
|
+
- ext/panko_serializer/attributes_writer/writer.h
|
130
137
|
- ext/panko_serializer/extconf.rb
|
131
138
|
- ext/panko_serializer/panko_serializer.c
|
132
139
|
- ext/panko_serializer/panko_serializer.h
|
133
|
-
- ext/panko_serializer/serialization_descriptor.c
|
134
|
-
- ext/panko_serializer/serialization_descriptor.h
|
135
|
-
- ext/panko_serializer/
|
136
|
-
- ext/panko_serializer/
|
137
|
-
- ext/panko_serializer/
|
138
|
-
- ext/panko_serializer/
|
140
|
+
- ext/panko_serializer/serialization_descriptor/association.c
|
141
|
+
- ext/panko_serializer/serialization_descriptor/association.h
|
142
|
+
- ext/panko_serializer/serialization_descriptor/attribute.c
|
143
|
+
- ext/panko_serializer/serialization_descriptor/attribute.h
|
144
|
+
- ext/panko_serializer/serialization_descriptor/serialization_descriptor.c
|
145
|
+
- ext/panko_serializer/serialization_descriptor/serialization_descriptor.h
|
139
146
|
- lib/panko/array_serializer.rb
|
140
147
|
- lib/panko/attribute.rb
|
141
148
|
- lib/panko/response.rb
|
@@ -165,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
165
172
|
version: '0'
|
166
173
|
requirements: []
|
167
174
|
rubyforge_project:
|
168
|
-
rubygems_version: 2.7.
|
175
|
+
rubygems_version: 2.7.5
|
169
176
|
signing_key:
|
170
177
|
specification_version: 4
|
171
178
|
summary: Fast serialization for ActiveModel
|
@@ -1,45 +0,0 @@
|
|
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, :created_at
|
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.run("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.run("AMS_#{prefix}_Posts_50") do
|
37
|
-
ActiveModel::ArraySerializer.new(posts_50, merged_options).serializable_object
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
|
42
|
-
benchmark_ams "Simple", AmsPostFastSerializer
|
43
|
-
benchmark_ams "HasOne", AmsPostWithHasOneFastSerializer
|
44
|
-
benchmark_ams "Except", AmsPostWithHasOneFastSerializer, except: [:title]
|
45
|
-
benchmark_ams "Include", AmsPostWithHasOneFastSerializer, include: [:id, :body, :author_id, :author]
|
data/benchmarks/bm_controller.rb
DELETED
@@ -1,81 +0,0 @@
|
|
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.run("text") { request(:get, "/text") }
|
79
|
-
Benchmark.run("simple") { request(:get, "/simple") }
|
80
|
-
|
81
|
-
Benchmark.run("serialize_to_string") { request(:get, "/serialize_to_string") }
|
@@ -1,15 +0,0 @@
|
|
1
|
-
#include <ruby.h>
|
2
|
-
#include <stdbool.h>
|
3
|
-
|
4
|
-
#include "attribute.h"
|
5
|
-
#include "serialization_descriptor.h"
|
6
|
-
#include "type_cast.h"
|
7
|
-
|
8
|
-
typedef void (*EachAttributeFunc)(VALUE writer, VALUE name, VALUE value);
|
9
|
-
|
10
|
-
extern VALUE panko_each_attribute(VALUE object,
|
11
|
-
VALUE attributes,
|
12
|
-
EachAttributeFunc func,
|
13
|
-
VALUE context);
|
14
|
-
|
15
|
-
void panko_init_attributes_iterator(VALUE mPanko);
|