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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fb37afdfb65ed1d7226788c226fad30d1779b39578ad762bf097783fea638b08
4
- data.tar.gz: 8d7a5f9ae73d6b2cd74b84d9861e4fbc9934c371960cc578d3bd0cef2798bc44
3
+ metadata.gz: b2f980d28503e644be4c2f0807637b531c91640ad50af4eeb72c5cf41b26f3eb
4
+ data.tar.gz: 2e45051b18ab56d9a4fe2d569d3abc3206f151398dca094aa0a28fecd3ceb07f
5
5
  SHA512:
6
- metadata.gz: 4a426f90212feb0b50c4a5b488f82bac91bbdfe30208cefc66390baa864ff217b92d551c38504d666dee1aa6f96b389cbdda65a35b91fac0cb34909ae5a280b9
7
- data.tar.gz: 1202d30b4bfc472ea3a30f7b66f5eb0ac2874933411031b0add26ceb3f69dd1fd0d469df71a39665cfc8a53fb84dabf29c7f51811a6e121247d486ea2e235be8
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
@@ -23,6 +23,7 @@ operations:
23
23
  - xpath
24
24
  - xquery
25
25
  - xslt
26
+ - xslt30
26
27
  - validation
27
28
  - memory
28
29
 
@@ -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.xslt_transform(s.parse(data), XSLT_STYLESHEET) },
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
@@ -27,6 +27,10 @@ module Serialbench
27
27
  super | Set.new(%i[namespaces])
28
28
  end
29
29
 
30
+ def xslt_apply(source_xml, stylesheet)
31
+ xslt_transform(parse(source_xml), stylesheet)
32
+ end
33
+
30
34
  # XML-specific features derive from the capability set
31
35
  def features
32
36
  {
@@ -37,7 +37,7 @@ module Serialbench
37
37
  end
38
38
 
39
39
  def capabilities
40
- super | Set.new(%i[xpath xquery xslt validation sax stax])
40
+ super | Set.new(%i[xpath xquery xslt xslt30 validation sax stax])
41
41
  end
42
42
 
43
43
  def xquery_eval(document, expression)
@@ -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,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Serialbench
4
- VERSION = '0.10.0'
4
+ VERSION = '0.11.0'
5
5
  end
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.10.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