serialbench 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/benchmark.yml +9 -0
- data/config/benchmarks/full-xml.yml +1 -0
- data/lib/serialbench/benchmark_runner.rb +35 -1
- data/lib/serialbench/models/benchmark_config.rb +1 -1
- data/lib/serialbench/models/benchmark_result.rb +2 -0
- data/lib/serialbench/serializers/xml/base_xml_serializer.rb +4 -0
- data/lib/serialbench/serializers/xml/leptris_serializer.rb +1 -1
- data/lib/serialbench/serializers/xml/saxon_serializer.rb +72 -0
- data/lib/serialbench/serializers.rb +3 -1
- data/lib/serialbench/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b2f980d28503e644be4c2f0807637b531c91640ad50af4eeb72c5cf41b26f3eb
|
|
4
|
+
data.tar.gz: 2e45051b18ab56d9a4fe2d569d3abc3206f151398dca094aa0a28fecd3ceb07f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 35d305480351a282cf7cccc5c18874d1d5f053f2ee914452082c0abed7f1b92e66a63ba582a90ed898320d55c499a43b5207c3e4f12c529111223f7841e5d89b
|
|
7
|
+
data.tar.gz: 7441471432ba4b498ac91d7a4bdf4b21338c36789a231014f3f0bc49bb3858952f3627eeb2209442b9c266d4664e91515e677dda472003bb20614c25648c5010
|
|
@@ -116,6 +116,15 @@ jobs:
|
|
|
116
116
|
- name: Install gems
|
|
117
117
|
run: bundle install
|
|
118
118
|
|
|
119
|
+
- name: Fetch Saxon-HE (XSLT 2.0/3.0 comparison)
|
|
120
|
+
run: |
|
|
121
|
+
mkdir -p vendor
|
|
122
|
+
curl -sL -o vendor/saxonhe.jar "https://repo1.maven.org/maven2/net/sf/saxon/Saxon-HE/12.10/Saxon-HE-12.10.jar"
|
|
123
|
+
curl -sL -o vendor/xmlresolver.jar "https://repo1.maven.org/maven2/org/xmlresolver/xmlresolver/5.2.2/xmlresolver-5.2.2.jar"
|
|
124
|
+
echo "SAXON_JAR=$PWD/vendor/saxonhe.jar" >> "$GITHUB_ENV"
|
|
125
|
+
echo "XMLRESOLVER_JAR=$PWD/vendor/xmlresolver.jar" >> "$GITHUB_ENV"
|
|
126
|
+
shell: bash
|
|
127
|
+
|
|
119
128
|
- name: Load canonical fixtures
|
|
120
129
|
run: |
|
|
121
130
|
git clone --depth 1 https://github.com/serialbench/fixtures.git test_data
|
|
@@ -142,10 +142,39 @@ _DEFAULT_XSLT_STYLESHEET = <<'XSL'.freeze
|
|
|
142
142
|
</xsl:stylesheet>
|
|
143
143
|
XSL
|
|
144
144
|
|
|
145
|
+
_DEFAULT_XSLT30_STYLESHEET = <<'XSL30'.freeze
|
|
146
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
147
|
+
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
|
148
|
+
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
|
149
|
+
exclude-result-prefixes="xs"
|
|
150
|
+
version="3.0">
|
|
151
|
+
<xsl:output method="xml" indent="yes"/>
|
|
152
|
+
<xsl:template match="/">
|
|
153
|
+
<report30>
|
|
154
|
+
<xsl:iterate select="//user | //record | //database | //cache">
|
|
155
|
+
<xsl:param name="labels" as="xs:string*" select="()"/>
|
|
156
|
+
<xsl:on-completion>
|
|
157
|
+
<joined><xsl:value-of select="string-join($labels, ', ')"/></joined>
|
|
158
|
+
<count><xsl:value-of select="count($labels)"/></count>
|
|
159
|
+
</xsl:on-completion>
|
|
160
|
+
<xsl:variable name="label" select="string((name, data/field1, ttl)[1])"/>
|
|
161
|
+
<xsl:if test="$label != ''">
|
|
162
|
+
<row kind="{local-name()}" label="{upper-case($label)}"/>
|
|
163
|
+
</xsl:if>
|
|
164
|
+
<xsl:next-iteration>
|
|
165
|
+
<xsl:with-param name="labels" select="if ($label != '') then ($labels, $label) else $labels"/>
|
|
166
|
+
</xsl:next-iteration>
|
|
167
|
+
</xsl:iterate>
|
|
168
|
+
</report30>
|
|
169
|
+
</xsl:template>
|
|
170
|
+
</xsl:stylesheet>
|
|
171
|
+
XSL30
|
|
172
|
+
|
|
145
173
|
XPATH_QUERIES = ['//book', "//book[@id='101']", '//book[price > 30]/title'].freeze
|
|
146
174
|
XQUERY_EXPRESSIONS = ['count(//user | //record)', "//record[@id='101']/data/field1", '//user[profile/age > 40]/name'].freeze
|
|
147
175
|
RNG_SCHEMA = File.expand_path('test_data/schema.rng', Dir.pwd).then { |p| File.exist?(p) ? File.read(p) : _DEFAULT_RNG_SCHEMA }
|
|
148
176
|
XSLT_STYLESHEET = File.expand_path('test_data/transform.xsl', Dir.pwd).then { |p| File.exist?(p) ? File.read(p) : _DEFAULT_XSLT_STYLESHEET }
|
|
177
|
+
XSLT30_STYLESHEET = File.expand_path('test_data/transform30.xsl', Dir.pwd).then { |p| File.exist?(p) ? File.read(p) : _DEFAULT_XSLT30_STYLESHEET }
|
|
149
178
|
|
|
150
179
|
OPERATIONS = {
|
|
151
180
|
'parsing' => ->(s, data) { s.parse(data) },
|
|
@@ -158,7 +187,8 @@ XSL
|
|
|
158
187
|
doc = s.parse(data)
|
|
159
188
|
XQUERY_EXPRESSIONS.each { |x| s.xquery_eval(doc, x) }
|
|
160
189
|
},
|
|
161
|
-
'xslt' => ->(s, data) { s.
|
|
190
|
+
'xslt' => ->(s, data) { s.xslt_apply(data, XSLT_STYLESHEET) },
|
|
191
|
+
'xslt30' => ->(s, data) { s.xslt_apply(data, XSLT30_STYLESHEET) },
|
|
162
192
|
'validation' => ->(s, data) { s.validate(s.parse(data), RNG_SCHEMA) },
|
|
163
193
|
'streaming' => ->(s, data) { s.stream_parse(data) { |_event, _data| } },
|
|
164
194
|
}.freeze
|
|
@@ -280,6 +310,8 @@ XSL
|
|
|
280
310
|
serializers = Serializers.for_format(format)
|
|
281
311
|
|
|
282
312
|
case type_name
|
|
313
|
+
when 'parsing', 'memory'
|
|
314
|
+
serializers.select { |s| s.supports?(:parse) }
|
|
283
315
|
when 'generation'
|
|
284
316
|
serializers.select { |s| s.supports?(:generate) }
|
|
285
317
|
when 'streaming'
|
|
@@ -292,6 +324,8 @@ XSL
|
|
|
292
324
|
serializers.select { |s| s.supports?(:xslt) }
|
|
293
325
|
when 'validation'
|
|
294
326
|
serializers.select { |s| s.supports?(:validation) }
|
|
327
|
+
when 'xslt30'
|
|
328
|
+
serializers.select { |s| s.supports?(:xslt30) }
|
|
295
329
|
else
|
|
296
330
|
serializers
|
|
297
331
|
end
|
|
@@ -51,7 +51,7 @@ module Serialbench
|
|
|
51
51
|
attribute :formats, :string, collection: true, values: %w[xml html json yaml toml]
|
|
52
52
|
attribute :iterations, BenchmarkIteration
|
|
53
53
|
attribute :warmup, :integer, default: -> { 1 }
|
|
54
|
-
attribute :operations, :string, collection: true, values: %w[parsing generation xpath xquery xslt validation streaming memory]
|
|
54
|
+
attribute :operations, :string, collection: true, values: %w[parsing generation xpath xquery xslt xslt30 validation streaming memory]
|
|
55
55
|
|
|
56
56
|
key_value do
|
|
57
57
|
map 'name', to: :name
|
|
@@ -73,6 +73,7 @@ module Serialbench
|
|
|
73
73
|
attribute :xpath, IterationPerformance, collection: true
|
|
74
74
|
attribute :xquery, IterationPerformance, collection: true
|
|
75
75
|
attribute :xslt, IterationPerformance, collection: true
|
|
76
|
+
attribute :xslt30, IterationPerformance, collection: true
|
|
76
77
|
attribute :validation, IterationPerformance, collection: true
|
|
77
78
|
|
|
78
79
|
key_value do
|
|
@@ -84,6 +85,7 @@ module Serialbench
|
|
|
84
85
|
map 'xpath', to: :xpath
|
|
85
86
|
map 'xquery', to: :xquery
|
|
86
87
|
map 'xslt', to: :xslt
|
|
88
|
+
map 'xslt30', to: :xslt30
|
|
87
89
|
map 'validation', to: :validation
|
|
88
90
|
end
|
|
89
91
|
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_xml_serializer'
|
|
4
|
+
require 'open3'
|
|
5
|
+
require 'tmpdir'
|
|
6
|
+
|
|
7
|
+
module Serialbench
|
|
8
|
+
module Serializers
|
|
9
|
+
module Xml
|
|
10
|
+
# Saxon-HE via its Java CLI: the reference XSLT 2.0/3.0 engine.
|
|
11
|
+
# Cold-process semantics: every iteration is a full JVM + compile +
|
|
12
|
+
# transform, so ips is comparable to leptris only end-to-end, never
|
|
13
|
+
# per-transform — features record cold_process: true.
|
|
14
|
+
class SaxonSerializer < BaseXmlSerializer
|
|
15
|
+
def name
|
|
16
|
+
'saxon-he'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def capabilities
|
|
20
|
+
Set.new(%i[xslt xslt30])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def features
|
|
24
|
+
{ 'xslt_version' => '3.0', 'cold_process' => true }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def classpath
|
|
28
|
+
jars = [ENV['SAXON_JAR'], ENV['XMLRESOLVER_JAR']].compact
|
|
29
|
+
jars.empty? ? nil : jars.join(File::PATH_SEPARATOR)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def xslt_apply(source_xml, stylesheet)
|
|
33
|
+
Dir.mktmpdir('saxonbench') do |dir|
|
|
34
|
+
src = File.join(dir, 's.xml')
|
|
35
|
+
xsl = File.join(dir, 's.xsl')
|
|
36
|
+
File.write(src, source_xml)
|
|
37
|
+
File.write(xsl, stylesheet)
|
|
38
|
+
out, _err, _st = Open3.capture3('java', '-cp', classpath, 'net.sf.saxon.Transform',
|
|
39
|
+
"-xsl:#{xsl}", "-s:#{src}")
|
|
40
|
+
raise Error, "saxon transform failed: #{out}#{_err}"[0, 200] unless _st.success?
|
|
41
|
+
|
|
42
|
+
out
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def available?
|
|
47
|
+
return @available if defined?(@available)
|
|
48
|
+
|
|
49
|
+
@available = begin
|
|
50
|
+
cp = classpath
|
|
51
|
+
raise LoadError, 'SAXON_JAR / XMLRESOLVER_JAR not set' unless cp
|
|
52
|
+
|
|
53
|
+
out, _err, st = Open3.capture3('java', '-cp', cp, 'net.sf.saxon.Version')
|
|
54
|
+
raise LoadError, 'java failed' unless st.success?
|
|
55
|
+
|
|
56
|
+
true
|
|
57
|
+
rescue StandardError, LoadError => e
|
|
58
|
+
warn "#{name} unavailable: #{e.class}: #{e.message}"
|
|
59
|
+
false
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def version
|
|
64
|
+
return 'unknown' unless available?
|
|
65
|
+
|
|
66
|
+
out, = Open3.capture3('java', '-cp', classpath, 'net.sf.saxon.Version')
|
|
67
|
+
out[/Saxon-HE (\S+)/, 1] || out.strip[0, 40]
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -11,6 +11,7 @@ require_relative 'serializers/xml/nokogiri_serializer'
|
|
|
11
11
|
require_relative 'serializers/xml/oga_serializer'
|
|
12
12
|
require_relative 'serializers/xml/libxml_serializer'
|
|
13
13
|
require_relative 'serializers/xml/leptris_serializer'
|
|
14
|
+
require_relative 'serializers/xml/saxon_serializer'
|
|
14
15
|
|
|
15
16
|
# HTML Serializers
|
|
16
17
|
require_relative 'serializers/html/base_html_serializer'
|
|
@@ -49,7 +50,8 @@ module Serialbench
|
|
|
49
50
|
Xml::NokogiriSerializer,
|
|
50
51
|
Xml::OgaSerializer,
|
|
51
52
|
Xml::LibxmlSerializer,
|
|
52
|
-
Xml::LeptrisSerializer
|
|
53
|
+
Xml::LeptrisSerializer,
|
|
54
|
+
Xml::SaxonSerializer
|
|
53
55
|
],
|
|
54
56
|
json: [
|
|
55
57
|
Json::JsonSerializer,
|
data/lib/serialbench/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: serialbench
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.11.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose
|
|
@@ -346,6 +346,7 @@ files:
|
|
|
346
346
|
- lib/serialbench/serializers/xml/oga_serializer.rb
|
|
347
347
|
- lib/serialbench/serializers/xml/ox_serializer.rb
|
|
348
348
|
- lib/serialbench/serializers/xml/rexml_serializer.rb
|
|
349
|
+
- lib/serialbench/serializers/xml/saxon_serializer.rb
|
|
349
350
|
- lib/serialbench/serializers/yaml/base_yaml_serializer.rb
|
|
350
351
|
- lib/serialbench/serializers/yaml/psych_serializer.rb
|
|
351
352
|
- lib/serialbench/serializers/yaml/syck_serializer.rb
|