lutaml-model 0.8.48 → 0.8.49
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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2dab1dcbc2ea77cfd1c61d9ffba4717521b9e97e1f3f6c8dd6f9ce6c7014222f
|
|
4
|
+
data.tar.gz: ed16efadd94ce85b9e52a5c7de822f9c7de7e3c581203280120630e8cdb389ff
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cd6bbdebb2c812eb849774ac168fe2c194bc21113521be6b4ca8b389ab5f6ebb2743b951478077332a18a2c214f458962c0a89d54e1a26447b3b103b7c2bb153
|
|
7
|
+
data.tar.gz: fddad44bad334a640facc5f6869b91c2a12134da6c79e58b7bed1787e14c03702d5ffd0ffcece27e435fe2f9387a7d13040e45794d178424cd7e56acbf9bb36c
|
|
@@ -55,4 +55,50 @@ jobs:
|
|
|
55
55
|
run: rake vendor:compile
|
|
56
56
|
|
|
57
57
|
- name: Run performance benchmarks
|
|
58
|
-
run: bundle exec rake performance:compare
|
|
58
|
+
run: bundle exec rake performance:compare
|
|
59
|
+
# TODO.max-perf/36: YJIT moves exactly the interpretive paths the
|
|
60
|
+
# model layer still runs. Sequential off/on probes on one runner give
|
|
61
|
+
# a directly comparable pair per commit - a measurement leg, not a
|
|
62
|
+
# gate. The plan fast path shrinks the YJIT win; watch both.
|
|
63
|
+
performance-yjit:
|
|
64
|
+
runs-on: ubuntu-latest
|
|
65
|
+
timeout-minutes: 15
|
|
66
|
+
steps:
|
|
67
|
+
- uses: actions/checkout@v6
|
|
68
|
+
with:
|
|
69
|
+
submodules: "recursive"
|
|
70
|
+
|
|
71
|
+
- name: Set up Ruby
|
|
72
|
+
uses: ruby/setup-ruby@v1
|
|
73
|
+
with:
|
|
74
|
+
ruby-version: '3.4'
|
|
75
|
+
bundler-cache: false
|
|
76
|
+
|
|
77
|
+
- name: Install ragel
|
|
78
|
+
run: sudo apt-get update && sudo apt-get install -y ragel
|
|
79
|
+
|
|
80
|
+
- name: Install ruby-ll (for rake vendor:prepare)
|
|
81
|
+
run: gem install ruby-ll --no-document
|
|
82
|
+
|
|
83
|
+
- name: Generate ragel / ruby-ll outputs in vendored forks
|
|
84
|
+
run: rake vendor:prepare
|
|
85
|
+
|
|
86
|
+
- name: Configure bundler
|
|
87
|
+
run: |
|
|
88
|
+
mkdir -p .bundle
|
|
89
|
+
echo "---" > .bundle/config
|
|
90
|
+
echo 'BUNDLE_BUILD__RUBY___LL: "--with-cflags=-std=gnu17"' >> .bundle/config
|
|
91
|
+
|
|
92
|
+
- name: Install dependencies
|
|
93
|
+
run: bundle install
|
|
94
|
+
|
|
95
|
+
- name: Compile liboga / libll native extensions
|
|
96
|
+
run: rake vendor:compile
|
|
97
|
+
|
|
98
|
+
- name: Probe YJIT off
|
|
99
|
+
run: bundle exec rake performance:probe
|
|
100
|
+
|
|
101
|
+
- name: Probe YJIT on
|
|
102
|
+
env:
|
|
103
|
+
RUBY_YJIT_ENABLE: "1"
|
|
104
|
+
run: bundle exec rake performance:probe
|
|
@@ -31,6 +31,36 @@ leptris and yeptris ship prebuilt platform gems for Linux and macOS
|
|
|
31
31
|
every platform, including Windows. When a gem is absent, lutaml-model
|
|
32
32
|
automatically falls back to the standard engine for that format.
|
|
33
33
|
|
|
34
|
+
== YJIT doubles the model pipeline
|
|
35
|
+
|
|
36
|
+
The model layer's own work — mapping dispatch, casts, hydration — is
|
|
37
|
+
plain Ruby and exactly the code shape YJIT compiles well; the native
|
|
38
|
+
engines' C work is unaffected either way. On a controlled runner
|
|
39
|
+
(ubuntu-latest, Ruby 3.4, the repository's performance probe):
|
|
40
|
+
|
|
41
|
+
|===
|
|
42
|
+
| op | YJIT off | YJIT on | change
|
|
43
|
+
|
|
44
|
+
| from_yaml | 75.1 i/s | 129.7 i/s | +73%
|
|
45
|
+
| to_yaml | 67.3 i/s | 145.1 i/s | +116%
|
|
46
|
+
| from_json | 73.2 i/s | 128.4 i/s | +75%
|
|
47
|
+
| to_json | 115.4 i/s | 255.5 i/s | +121%
|
|
48
|
+
|===
|
|
49
|
+
|
|
50
|
+
Enable it like any Ruby application does — this is the application's
|
|
51
|
+
call, never a gem's:
|
|
52
|
+
|
|
53
|
+
[source,sh]
|
|
54
|
+
----
|
|
55
|
+
RUBY_YJIT_ENABLE=1 ruby app.rb
|
|
56
|
+
# or in code, before heavy work:
|
|
57
|
+
RubyVM::YJIT.enable
|
|
58
|
+
----
|
|
59
|
+
|
|
60
|
+
The opt-in XML plan fast path (see below) moves work out of Ruby and
|
|
61
|
+
into the engine, which shrinks the YJIT win — enabling both is still
|
|
62
|
+
net faster than either alone.
|
|
63
|
+
|
|
34
64
|
== Selecting adapters explicitly
|
|
35
65
|
|
|
36
66
|
The engines register as ordinary adapter types, so explicit selection and
|
data/lib/lutaml/model/version.rb
CHANGED
|
@@ -200,7 +200,14 @@ module Lutaml
|
|
|
200
200
|
|
|
201
201
|
def compilable_mapping?(mapping)
|
|
202
202
|
mapping.root_element &&
|
|
203
|
-
!(mapping.respond_to?(:root_mappings) && mapping.root_mappings)
|
|
203
|
+
!(mapping.respond_to?(:root_mappings) && mapping.root_mappings) &&
|
|
204
|
+
# lutaml-model#88: when_attribute partitions route same-name
|
|
205
|
+
# occurrences by attribute value — name-keyed plan rows would
|
|
206
|
+
# hydrate every occurrence into EVERY partition attribute
|
|
207
|
+
# (verified double-capture under the flag). The interpretive
|
|
208
|
+
# filter is the only correct path until the descriptor ABI
|
|
209
|
+
# grows row predicates.
|
|
210
|
+
mapping.mappings.none?(&:when_attribute?)
|
|
204
211
|
end
|
|
205
212
|
|
|
206
213
|
# Attribute for a rule — delegate rules resolve against their
|
|
@@ -517,6 +517,83 @@ RSpec.describe "XML plan fast path" do
|
|
|
517
517
|
expect(model.to_xml).to eq(interpretive)
|
|
518
518
|
end
|
|
519
519
|
|
|
520
|
+
# lutaml-model#88: name-keyed plan rows would hydrate every
|
|
521
|
+
# same-name occurrence into EVERY partition attribute (verified
|
|
522
|
+
# double-capture) — discriminator models must take the interpretive
|
|
523
|
+
# path, and a partitioned CHILD model must opt its parent out too.
|
|
524
|
+
it "falls back to the interpretive path for when_attribute models" do
|
|
525
|
+
component = Class.new(Lutaml::Model::Serializable) do
|
|
526
|
+
attribute :text, :string
|
|
527
|
+
|
|
528
|
+
xml do
|
|
529
|
+
element "component"
|
|
530
|
+
map_element "text", to: :text
|
|
531
|
+
end
|
|
532
|
+
end
|
|
533
|
+
stub_const("PlanFastPath::Component", component)
|
|
534
|
+
|
|
535
|
+
partitioned = Class.new(Lutaml::Model::Serializable) do
|
|
536
|
+
attribute :guidance, component, collection: true
|
|
537
|
+
attribute :purpose, component, collection: true
|
|
538
|
+
|
|
539
|
+
xml do
|
|
540
|
+
element "requirement"
|
|
541
|
+
map_element "component", when_attribute: "type",
|
|
542
|
+
to: { "guidance" => :guidance,
|
|
543
|
+
"purpose" => :purpose }
|
|
544
|
+
end
|
|
545
|
+
end
|
|
546
|
+
stub_const("PlanFastPath::Partitioned", partitioned)
|
|
547
|
+
|
|
548
|
+
req = partitioned.from_xml(<<~XML)
|
|
549
|
+
<requirement>
|
|
550
|
+
<component type="guidance"><text>g1</text></component>
|
|
551
|
+
<component type="purpose"><text>p1</text></component>
|
|
552
|
+
<component type="guidance"><text>g2</text></component>
|
|
553
|
+
</requirement>
|
|
554
|
+
XML
|
|
555
|
+
|
|
556
|
+
expect(req.guidance.map(&:text)).to eq(%w[g1 g2])
|
|
557
|
+
expect(req.purpose.map(&:text)).to eq(["p1"])
|
|
558
|
+
|
|
559
|
+
expect(Lutaml::Xml::PlanCompiler.compile(partitioned,
|
|
560
|
+
:default)).to be_nil
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
it "opts a parent out when a child model partitions with when_attribute" do
|
|
564
|
+
component = Class.new(Lutaml::Model::Serializable) do
|
|
565
|
+
attribute :text, :string
|
|
566
|
+
|
|
567
|
+
xml do
|
|
568
|
+
element "component"
|
|
569
|
+
map_element "text", to: :text
|
|
570
|
+
end
|
|
571
|
+
end
|
|
572
|
+
inner = Class.new(Lutaml::Model::Serializable) do
|
|
573
|
+
attribute :guidance, component, collection: true
|
|
574
|
+
|
|
575
|
+
xml do
|
|
576
|
+
element "req"
|
|
577
|
+
map_element "component", to: :guidance,
|
|
578
|
+
when_attribute: { "type" => "guidance" }
|
|
579
|
+
end
|
|
580
|
+
end
|
|
581
|
+
outer = Class.new(Lutaml::Model::Serializable) do
|
|
582
|
+
attribute :req, inner
|
|
583
|
+
|
|
584
|
+
xml do
|
|
585
|
+
element "holder"
|
|
586
|
+
map_element "req", to: :req
|
|
587
|
+
end
|
|
588
|
+
end
|
|
589
|
+
stub_const("PlanFastPath::Nested", outer)
|
|
590
|
+
|
|
591
|
+
doc = outer.from_xml(
|
|
592
|
+
"<holder><req><component type=\"guidance\"><text>g1</text></component></req></holder>",
|
|
593
|
+
)
|
|
594
|
+
expect(doc.req.guidance.map(&:text)).to eq(["g1"])
|
|
595
|
+
end
|
|
596
|
+
|
|
520
597
|
it "round-trips through both fast paths" do
|
|
521
598
|
item = Class.new(Lutaml::Model::Serializable) do
|
|
522
599
|
attribute :id, :integer
|