leptris 1.9.32 → 1.9.33

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: b6c303e18e7a4d19b69b163dfaf0e9200bbc552e5638f9653e3d062140b02062
4
- data.tar.gz: 6d4ed3e7928354aea683f4bcf3f10da38b69c85668a629383acaa73ed7240a05
3
+ metadata.gz: '01791cd8ecc5e2c7b472ac0333ae89ab338d6fa8872a55f724cafe708f866f2b'
4
+ data.tar.gz: 00d0115424789446417bce8b22d35a8b1f23883c17dd135f4a4e8d0d8ba19aa1
5
5
  SHA512:
6
- metadata.gz: 4f685962dff8a718b0af38822b84ca736f109448fd14381dabfd11c8021cde290233cc24aaae6f98fb4d812db235b448d9920cb6190f6e1c27a5f9aa86e3db15
7
- data.tar.gz: dc4bd35eb15ceb1a558750e4e06d103d0045770aa694c4b131fdcfc050d41808339febcac55327336d4138ed37dfc5c1f0391582c8501f6dda02258a7388f086
6
+ metadata.gz: a8d17f3f61f0317d9165a57e6ecf134cb22751c23f5fd39a669e9df7f6fa414e780a52ab55f7bd549c1ea10ae8cfa6d0fad6fe44f9b092ac581974d391cfa521
7
+ data.tar.gz: 2842e82675cba9aad3bc4bb859e1a85a78043b3b81b4eebf2d7c0afab4df3abacb01ddc56144d0bec96bd3473d5ad31bff9dc4beef31c2639282c9f7c55b84f1
data/CHANGELOG.md CHANGED
@@ -5,6 +5,23 @@ All notable changes to Leptris will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.9.33] - 2026-08-28
9
+
10
+ ### Changed
11
+
12
+ - **Cached namespace binding sets**: every namespaced query
13
+ previously built its binding set from scratch (flatten the hash,
14
+ allocate the CStringArray wire format, `ns_set_new_from_pairs`,
15
+ eval, free) — ~6.7 µs of construction, 2.6× the same query
16
+ without namespaces on a small document. The XPath VM reads the
17
+ set as a const map during evaluation (vm.c) and never mutates
18
+ it, so sets are now cached per distinct prefix/URI vocabulary and
19
+ shared across queries and threads. Measured: namespaced
20
+ `//x:rect` 10.9 -> **6.9 µs per query (-38%)**; `at_xpath` -26%.
21
+ Single-pair key fast path; failed builds raise before caching;
22
+ symbol- and string-keyed hashes share one entry. The remaining
23
+ gap vs no-namespace queries is the VM's prefix resolution.
24
+
8
25
  ## [1.9.32] - 2026-08-28
9
26
 
10
27
  ### Fixed
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Leptris
4
- VERSION = "1.9.32"
4
+ VERSION = "1.9.33"
5
5
  end
@@ -800,21 +800,37 @@ module Leptris
800
800
 
801
801
  # Namespace-binding lifecycle, written once: flatten the
802
802
  # prefix/URI hash into the alternating CStringArray wire
803
- # format, build the caller-owned set, yield it, free it under
804
- # all outcomes. Every eval variant uses this; none of them
805
- # knows how a set is born or dies.
803
+ # format and build the C set. Sets are cached per distinct
804
+ # vocabulary: the XPath VM reads the set as a const map
805
+ # during evaluation (vm.c) and never mutates it, so one set
806
+ # serves the process across queries and threads — building
807
+ # the wire format plus a C set per query cost ~6.7 µs, 2.6×
808
+ # a no-namespace query on a small document. Cached sets are
809
+ # never freed (bounded by the process's distinct namespace
810
+ # vocabularies — the same trade the CSS translation cache
811
+ # makes). Failed builds raise before caching.
812
+ NS_SET_CACHE = {}
813
+
806
814
  def self.with_ns_set(hash)
807
- flat = hash.flat_map { |prefix, uri| [prefix.to_s, uri.to_s] }
808
- buffer, _anchors = Leptris::XML::CStringArray.to_c(flat)
809
- set = leptris_xpath_ns_set_new_from_pairs(buffer, flat.length / 2)
810
- if set.null?
811
- raise Leptris::XML::Error,
812
- "leptris_xpath_ns_set_new_from_pairs failed"
813
- end
814
- begin
815
- yield set
816
- ensure
817
- leptris_xpath_ns_set_free(set)
815
+ yield ns_set_for(hash)
816
+ end
817
+
818
+ def self.ns_set_for(hash)
819
+ pairs = hash.map { |prefix, uri| [prefix.to_s, uri.to_s] }
820
+ key = if pairs.size == 1
821
+ "#{pairs[0][0]}\x00#{pairs[0][1]}"
822
+ else
823
+ pairs.sort.join("\x00")
824
+ end
825
+ NS_SET_CACHE.fetch(key) do
826
+ flat = pairs.flatten
827
+ buffer, _anchors = Leptris::XML::CStringArray.to_c(flat)
828
+ set = leptris_xpath_ns_set_new_from_pairs(buffer, flat.length / 2)
829
+ if set.null?
830
+ raise Leptris::XML::Error,
831
+ "leptris_xpath_ns_set_new_from_pairs failed"
832
+ end
833
+ NS_SET_CACHE[key] = set
818
834
  end
819
835
  end
820
836
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leptris
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.32
4
+ version: 1.9.33
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.