panko_serializer 0.3.4 → 0.3.5
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/.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);
|