rabbit-slide-naitoh-rubykaigi-2025 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: eb549e49916b6fc135fdb13bc40f040086225b7ed9bdbda16ac85848cc47e2c0
4
+ data.tar.gz: b5f837ed07fa0b4cb15c0bcb8019d078de882eeb05357015025c450a4d7243ac
5
+ SHA512:
6
+ metadata.gz: 33c93f39fce4fd0bcffd13582e2833af9bae3044c23fc22dab873243405576b9a393dea919a3eb68bab327ea93da1e72449df1903b60b32cbb04a4198b74d924
7
+ data.tar.gz: d36f027b063d6445485e153f9ff10701be83029a093f716a88af4ebb377e37aede7626e5b3bad5522c9842085d212424f99dc01f25545c7611146ecc0bbd2678
data/.rabbit ADDED
@@ -0,0 +1,2 @@
1
+ --size 1440,900 rubykaigi-2025.rab
2
+
Binary file
data/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # Improvement of REXML and speed up using StringScanner
2
+
3
+ https://rubykaigi.org/2025/
4
+
5
+ ## 作者向け
6
+
7
+ ### 表示
8
+
9
+ rake
10
+
11
+ ### 公開
12
+
13
+ rake publish
14
+
15
+ ## 閲覧者向け
16
+
17
+ ### インストール
18
+
19
+ gem install rabbit-slide-naitoh-rubykaigi-2025
20
+
21
+ ### 表示
22
+
23
+ rabbit rabbit-slide-naitoh-rubykaigi-2025.gem
24
+
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require "rabbit/task/slide"
2
+
3
+ # Edit ./config.yaml to customize meta data
4
+
5
+ spec = nil
6
+ Rabbit::Task::Slide.new do |task|
7
+ spec = task.spec
8
+ # spec.files += Dir.glob("doc/**/*.*")
9
+ # spec.files -= Dir.glob("private/**/*.*")
10
+ # spec.add_runtime_dependency("rabbit-theme-YOUR-THEME")
11
+ end
12
+
13
+ desc "Tag #{spec.version}"
14
+ task :tag do
15
+ sh("git", "tag", "-a", spec.version.to_s, "-m", "Publish #{spec.version}")
16
+ sh("git", "push", "--tags")
17
+ end
data/config.yaml ADDED
@@ -0,0 +1,25 @@
1
+ ---
2
+ id: rubykaigi-2025
3
+ base_name: rubykaigi-2025
4
+ tags:
5
+ - ruby
6
+ - rexml
7
+ presentation_date: 2025-04-17
8
+ presentation_start_time:
9
+ presentation_end_time:
10
+ version: 1.0.0
11
+ licenses: []
12
+ slideshare_id:
13
+ speaker_deck_id:
14
+ vimeo_id:
15
+ youtube_id:
16
+ width: 1440
17
+ height: 900
18
+ source_code_uri:
19
+ author:
20
+ markup_language: :rd
21
+ name: NAITOH Jun
22
+ email: naitoh@gmail.com
23
+ rubygems_user: naitoh
24
+ slideshare_user:
25
+ speaker_deck_user:
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,18 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="800" height="400">
2
+ <style>
3
+ .line { fill: none; stroke-width: 2; }
4
+ .dashed { stroke-dasharray: 5, 5; }
5
+ .label { font-size: 18px; text-anchor: middle; }
6
+ .axis { stroke: #000; stroke-width: 1; }
7
+ .grid { stroke: #ccc; stroke-width: 0.5; }
8
+ .point { fill-opacity: 0.8; }
9
+ .title { font-size: 22px; font-weight: bold; text-anchor: middle; }
10
+ </style>
11
+ <!-- 軸 -->
12
+ <line x1="50" y1="350" x2="750" y2="350" class="axis" />
13
+ <line x1="50" y1="50" x2="50" y2="350" class="axis" />
14
+ <!-- タイトル -->
15
+ <text x="400" y="25" class="title">REXML Performance benchmarks</text>
16
+ <text x="400" y="388" class="label">rexml version</text>
17
+ <text x="12" y="200" class="label" transform="rotate(-90, 12, 200)">i/s</text>
18
+ <line x1="50" y1="350.0" x2="750" y2="350.0" class="grid" /><text x="30" y="355.0" class="label" text-anchor="end">16.0</text><line x1="50" y1="288.8888888888889" x2="750" y2="288.8888888888889" class="grid" /><text x="30" y="293.8888888888889" class="label" text-anchor="end">27.0</text><line x1="50" y1="227.77777777777777" x2="750" y2="227.77777777777777" class="grid" /><text x="30" y="232.77777777777777" class="label" text-anchor="end">38.0</text><line x1="50" y1="166.66666666666666" x2="750" y2="166.66666666666666" class="grid" /><text x="30" y="171.66666666666666" class="label" text-anchor="end">49.0</text><line x1="50" y1="105.55555555555557" x2="750" y2="105.55555555555557" class="grid" /><text x="30" y="110.55555555555557" class="label" text-anchor="end">60.0</text><line x1="50" y1="50" x2="50" y2="350" class="grid" /><text x="50" y="370" class="label">3.2.6</text><line x1="190" y1="50" x2="190" y2="350" class="grid" /><text x="190" y="370" class="label">RubyKaigi2024LT</text><line x1="330" y1="50" x2="330" y2="350" class="grid" /><text x="330" y="370" class="label">3.2.7</text><line x1="470" y1="50" x2="470" y2="350" class="grid" /><text x="470" y="370" class="label">3.2.9</text><line x1="610" y1="50" x2="610" y2="350" class="grid" /><text x="610" y="370" class="label">3.4.0</text><line x1="750" y1="50" x2="750" y2="350" class="grid" /><text x="750" y="370" class="label">3.4.1</text><polyline points="50,201.60555555555555 190,50.93888888888887 330,184.33888888888887 470,111.03888888888889 610,106.21666666666667 750,72.82222222222225" class="line dashed" stroke="#4CAF50" /><circle cx="50" cy="201.60555555555555" r="4" fill="#4CAF50" class="point" /><circle cx="190" cy="50.93888888888887" r="4" fill="#4CAF50" class="point" /><circle cx="330" cy="184.33888888888887" r="4" fill="#4CAF50" class="point" /><circle cx="470" cy="111.03888888888889" r="4" fill="#4CAF50" class="point" /><circle cx="610" cy="106.21666666666667" r="4" fill="#4CAF50" class="point" /><circle cx="750" cy="72.82222222222225" r="4" fill="#4CAF50" class="point" /><polyline points="50,222.08888888888887 190,94.91111111111113 330,207.19444444444446 470,146.93333333333334 610,120.83333333333334 750,95.17222222222222" class="line dashed" stroke="#2196F3" /><circle cx="50" cy="222.08888888888887" r="4" fill="#2196F3" class="point" /><circle cx="190" cy="94.91111111111113" r="4" fill="#2196F3" class="point" /><circle cx="330" cy="207.19444444444446" r="4" fill="#2196F3" class="point" /><circle cx="470" cy="146.93333333333334" r="4" fill="#2196F3" class="point" /><circle cx="610" cy="120.83333333333334" r="4" fill="#2196F3" class="point" /><circle cx="750" cy="95.17222222222222" r="4" fill="#2196F3" class="point" /><polyline points="50,235.72777777777776 190,129.8888888888889 330,229.7111111111111 470,184.7444444444444 610,157.43333333333334 750,143.47222222222223" class="line dashed" stroke="#FFC107" /><circle cx="50" cy="235.72777777777776" r="4" fill="#FFC107" class="point" /><circle cx="190" cy="129.8888888888889" r="4" fill="#FFC107" class="point" /><circle cx="330" cy="229.7111111111111" r="4" fill="#FFC107" class="point" /><circle cx="470" cy="184.7444444444444" r="4" fill="#FFC107" class="point" /><circle cx="610" cy="157.43333333333334" r="4" fill="#FFC107" class="point" /><circle cx="750" cy="143.47222222222223" r="4" fill="#FFC107" class="point" /><polyline points="50,295.02222222222224 190,245.47222222222223 330,290.01666666666665 470,264.3611111111111 610,263.45 750,250.4" class="line dashed" stroke="#FF5722" /><circle cx="50" cy="295.02222222222224" r="4" fill="#FF5722" class="point" /><circle cx="190" cy="245.47222222222223" r="4" fill="#FF5722" class="point" /><circle cx="330" cy="290.01666666666665" r="4" fill="#FF5722" class="point" /><circle cx="470" cy="264.3611111111111" r="4" fill="#FF5722" class="point" /><circle cx="610" cy="263.45" r="4" fill="#FF5722" class="point" /><circle cx="750" cy="250.4" r="4" fill="#FF5722" class="point" /><polyline points="50,272.55 190,245.02777777777777 330,291.7888888888889 470,276.78333333333336 610,255.09444444444443 750,247.96666666666667" class="line" stroke="#4CAF50" /><circle cx="50" cy="272.55" r="4" fill="#4CAF50" class="point" /><circle cx="190" cy="245.02777777777777" r="4" fill="#4CAF50" class="point" /><circle cx="330" cy="291.7888888888889" r="4" fill="#4CAF50" class="point" /><circle cx="470" cy="276.78333333333336" r="4" fill="#4CAF50" class="point" /><circle cx="610" cy="255.09444444444443" r="4" fill="#4CAF50" class="point" /><circle cx="750" cy="247.96666666666667" r="4" fill="#4CAF50" class="point" /><polyline points="50,282.71666666666664 190,247.68888888888893 330,295.72777777777776 470,279.3611111111111 610,257.6333333333333 750,248.61111111111111" class="line" stroke="#2196F3" /><circle cx="50" cy="282.71666666666664" r="4" fill="#2196F3" class="point" /><circle cx="190" cy="247.68888888888893" r="4" fill="#2196F3" class="point" /><circle cx="330" cy="295.72777777777776" r="4" fill="#2196F3" class="point" /><circle cx="470" cy="279.3611111111111" r="4" fill="#2196F3" class="point" /><circle cx="610" cy="257.6333333333333" r="4" fill="#2196F3" class="point" /><circle cx="750" cy="248.61111111111111" r="4" fill="#2196F3" class="point" /><polyline points="50,295.43888888888887 190,271.50555555555553 330,309.7833333333333 470,300.01666666666665 610,280.0333333333333 750,271.06111111111113" class="line" stroke="#FFC107" /><circle cx="50" cy="295.43888888888887" r="4" fill="#FFC107" class="point" /><circle cx="190" cy="271.50555555555553" r="4" fill="#FFC107" class="point" /><circle cx="330" cy="309.7833333333333" r="4" fill="#FFC107" class="point" /><circle cx="470" cy="300.01666666666665" r="4" fill="#FFC107" class="point" /><circle cx="610" cy="280.0333333333333" r="4" fill="#FFC107" class="point" /><circle cx="750" cy="271.06111111111113" r="4" fill="#FFC107" class="point" /><polyline points="50,337.86111111111114 190,324.1611111111111 330,346.6722222222222 470,340.9111111111111 610,334.2055555555556 750,330.7388888888889" class="line" stroke="#FF5722" /><circle cx="50" cy="337.86111111111114" r="4" fill="#FF5722" class="point" /><circle cx="190" cy="324.1611111111111" r="4" fill="#FF5722" class="point" /><circle cx="330" cy="346.6722222222222" r="4" fill="#FF5722" class="point" /><circle cx="470" cy="340.9111111111111" r="4" fill="#FF5722" class="point" /><circle cx="610" cy="334.2055555555556" r="4" fill="#FF5722" class="point" /><circle cx="750" cy="330.7388888888889" r="4" fill="#FF5722" class="point" /><line x1="55" y1="50" x2="75" y2="50" class="line dashed" stroke="#4CAF50" /><text x="115" y="54" class="label" text-anchor="start">pull(JIT)</text><line x1="55" y1="70" x2="75" y2="70" class="line dashed" stroke="#2196F3" /><text x="115" y="74" class="label" text-anchor="start">stream(JIT)</text><line x1="55" y1="90" x2="75" y2="90" class="line dashed" stroke="#FFC107" /><text x="115" y="94" class="label" text-anchor="start">sax2(JIT)</text><line x1="55" y1="110" x2="75" y2="110" class="line dashed" stroke="#FF5722" /><text x="115" y="114" class="label" text-anchor="start">dom(JIT)</text><line x1="55" y1="130" x2="75" y2="130" class="line" stroke="#4CAF50" /><text x="115" y="134" class="label" text-anchor="start">pull</text><line x1="55" y1="150" x2="75" y2="150" class="line" stroke="#2196F3" /><text x="115" y="154" class="label" text-anchor="start">stream</text><line x1="55" y1="170" x2="75" y2="170" class="line" stroke="#FFC107" /><text x="115" y="174" class="label" text-anchor="start">sax2</text><line x1="55" y1="190" x2="75" y2="190" class="line" stroke="#FF5722" /><text x="115" y="194" class="label" text-anchor="start">dom</text></svg>
@@ -0,0 +1,18 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="800" height="400">
2
+ <style>
3
+ .line { fill: none; stroke-width: 2; }
4
+ .dashed { stroke-dasharray: 5, 5; }
5
+ .label { font-size: 18px; text-anchor: middle; }
6
+ .axis { stroke: #000; stroke-width: 1; }
7
+ .grid { stroke: #ccc; stroke-width: 0.5; }
8
+ .point { fill-opacity: 0.8; }
9
+ .title { font-size: 22px; font-weight: bold; text-anchor: middle; }
10
+ </style>
11
+ <!-- 軸 -->
12
+ <line x1="50" y1="350" x2="750" y2="350" class="axis" />
13
+ <line x1="50" y1="50" x2="50" y2="350" class="axis" />
14
+ <!-- タイトル -->
15
+ <text x="400" y="25" class="title">REXML Performance benchmarks</text>
16
+ <text x="400" y="388" class="label">rexml version</text>
17
+ <text x="12" y="200" class="label" transform="rotate(-90, 12, 200)">i/s</text>
18
+ <line x1="50" y1="350.0" x2="750" y2="350.0" class="grid" /><text x="30" y="355.0" class="label" text-anchor="end">18.0</text><line x1="50" y1="275.0" x2="750" y2="275.0" class="grid" /><text x="30" y="280.0" class="label" text-anchor="end">22.0</text><line x1="50" y1="200.0" x2="750" y2="200.0" class="grid" /><text x="30" y="205.0" class="label" text-anchor="end">26.0</text><line x1="50" y1="125.0" x2="750" y2="125.0" class="grid" /><text x="30" y="130.0" class="label" text-anchor="end">30.0</text><line x1="50" y1="50.0" x2="750" y2="50.0" class="grid" /><text x="30" y="55.0" class="label" text-anchor="end">34.0</text><line x1="50" y1="50" x2="50" y2="350" class="grid" /><text x="50" y="370" class="label">3.2.6</text><line x1="750" y1="50" x2="750" y2="350" class="grid" /><text x="750" y="370" class="label">3.4.0</text><polyline points="50,126.10625000000002 750,67.19375000000002" class="line" stroke="#4CAF50" /><circle cx="50" cy="126.10625000000002" r="4" fill="#4CAF50" class="point" /><circle cx="750" cy="67.19375000000002" r="4" fill="#4CAF50" class="point" /><polyline points="50,160.41875 750,75.76250000000005" class="line" stroke="#2196F3" /><circle cx="50" cy="160.41875" r="4" fill="#2196F3" class="point" /><circle cx="750" cy="75.76250000000005" r="4" fill="#2196F3" class="point" /><polyline points="50,203.35624999999996 750,151.36249999999998" class="line" stroke="#FFC107" /><circle cx="50" cy="203.35624999999996" r="4" fill="#FFC107" class="point" /><circle cx="750" cy="151.36249999999998" r="4" fill="#FFC107" class="point" /><polyline points="50,346.53125 750,334.19375" class="line" stroke="#FF5722" /><circle cx="50" cy="346.53125" r="4" fill="#FF5722" class="point" /><circle cx="750" cy="334.19375" r="4" fill="#FF5722" class="point" /><line x1="55" y1="50" x2="75" y2="50" class="line" stroke="#4CAF50" /><text x="115" y="54" class="label" text-anchor="start">pull</text><line x1="55" y1="70" x2="75" y2="70" class="line" stroke="#2196F3" /><text x="115" y="74" class="label" text-anchor="start">stream</text><line x1="55" y1="90" x2="75" y2="90" class="line" stroke="#FFC107" /><text x="115" y="94" class="label" text-anchor="start">sax2</text><line x1="55" y1="110" x2="75" y2="110" class="line" stroke="#FF5722" /><text x="115" y="114" class="label" text-anchor="start">dom</text></svg>
@@ -0,0 +1,18 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="800" height="400">
2
+ <style>
3
+ .line { fill: none; stroke-width: 2; }
4
+ .dashed { stroke-dasharray: 5, 5; }
5
+ .label { font-size: 18px; text-anchor: middle; }
6
+ .axis { stroke: #000; stroke-width: 1; }
7
+ .grid { stroke: #ccc; stroke-width: 0.5; }
8
+ .point { fill-opacity: 0.8; }
9
+ .title { font-size: 22px; font-weight: bold; text-anchor: middle; }
10
+ </style>
11
+ <!-- 軸 -->
12
+ <line x1="50" y1="350" x2="750" y2="350" class="axis" />
13
+ <line x1="50" y1="50" x2="50" y2="350" class="axis" />
14
+ <!-- タイトル -->
15
+ <text x="400" y="25" class="title">REXML Performance benchmarks</text>
16
+ <text x="400" y="388" class="label">rexml version</text>
17
+ <text x="12" y="200" class="label" transform="rotate(-90, 12, 200)">i/s</text>
18
+ <line x1="50" y1="350.0" x2="750" y2="350.0" class="grid" /><text x="30" y="355.0" class="label" text-anchor="end">25.0</text><line x1="50" y1="290.0" x2="750" y2="290.0" class="grid" /><text x="30" y="295.0" class="label" text-anchor="end">32.0</text><line x1="50" y1="230.0" x2="750" y2="230.0" class="grid" /><text x="30" y="235.0" class="label" text-anchor="end">39.0</text><line x1="50" y1="170.0" x2="750" y2="170.0" class="grid" /><text x="30" y="175.0" class="label" text-anchor="end">46.0</text><line x1="50" y1="110.0" x2="750" y2="110.0" class="grid" /><text x="30" y="115.0" class="label" text-anchor="end">53.0</text><line x1="50" y1="50.0" x2="750" y2="50.0" class="grid" /><text x="30" y="55.0" class="label" text-anchor="end">60.0</text><line x1="50" y1="50" x2="50" y2="350" class="grid" /><text x="50" y="370" class="label">3.2.6</text><line x1="750" y1="50" x2="750" y2="350" class="grid" /><text x="750" y="370" class="label">3.4.0</text><polyline points="50,198.1914285714286 750,51.01999999999998" class="line dashed" stroke="#4CAF50" /><circle cx="50" cy="198.1914285714286" r="4" fill="#4CAF50" class="point" /><circle cx="750" cy="51.01999999999998" r="4" fill="#4CAF50" class="point" /><polyline points="50,229.7942857142857 750,73.57142857142861" class="line dashed" stroke="#2196F3" /><circle cx="50" cy="229.7942857142857" r="4" fill="#2196F3" class="point" /><circle cx="750" cy="73.57142857142861" r="4" fill="#2196F3" class="point" /><polyline points="50,250.83714285714285 750,130.04000000000002" class="line dashed" stroke="#FFC107" /><circle cx="50" cy="250.83714285714285" r="4" fill="#FFC107" class="point" /><circle cx="750" cy="130.04000000000002" r="4" fill="#FFC107" class="point" /><polyline points="50,342.32 750,293.6085714285714" class="line dashed" stroke="#FF5722" /><circle cx="50" cy="342.32" r="4" fill="#FF5722" class="point" /><circle cx="750" cy="293.6085714285714" r="4" fill="#FF5722" class="point" /><line x1="55" y1="50" x2="75" y2="50" class="line dashed" stroke="#4CAF50" /><text x="115" y="54" class="label" text-anchor="start">pull(JIT)</text><line x1="55" y1="70" x2="75" y2="70" class="line dashed" stroke="#2196F3" /><text x="115" y="74" class="label" text-anchor="start">stream(JIT)</text><line x1="55" y1="90" x2="75" y2="90" class="line dashed" stroke="#FFC107" /><text x="115" y="94" class="label" text-anchor="start">sax2(JIT)</text><line x1="55" y1="110" x2="75" y2="110" class="line dashed" stroke="#FF5722" /><text x="115" y="114" class="label" text-anchor="start">dom(JIT)</text></svg>
@@ -0,0 +1,18 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="800" height="400">
2
+ <style>
3
+ .line { fill: none; stroke-width: 2; }
4
+ .dashed { stroke-dasharray: 5, 5; }
5
+ .label { font-size: 18px; text-anchor: middle; }
6
+ .axis { stroke: #000; stroke-width: 1; }
7
+ .grid { stroke: #ccc; stroke-width: 0.5; }
8
+ .point { fill-opacity: 0.8; }
9
+ .title { font-size: 22px; font-weight: bold; text-anchor: middle; }
10
+ </style>
11
+ <!-- 軸 -->
12
+ <line x1="50" y1="350" x2="750" y2="350" class="axis" />
13
+ <line x1="50" y1="50" x2="50" y2="350" class="axis" />
14
+ <!-- タイトル -->
15
+ <text x="400" y="25" class="title">REXML Performance benchmarks</text>
16
+ <text x="400" y="388" class="label">rexml version</text>
17
+ <text x="12" y="200" class="label" transform="rotate(-90, 12, 200)">i/s</text>
18
+ <line x1="50" y1="350.0" x2="750" y2="350.0" class="grid" /><text x="30" y="355.0" class="label" text-anchor="end">18.0</text><line x1="50" y1="287.5" x2="750" y2="287.5" class="grid" /><text x="30" y="292.5" class="label" text-anchor="end">28.0</text><line x1="50" y1="225.0" x2="750" y2="225.0" class="grid" /><text x="30" y="230.0" class="label" text-anchor="end">38.0</text><line x1="50" y1="162.5" x2="750" y2="162.5" class="grid" /><text x="30" y="167.5" class="label" text-anchor="end">48.0</text><line x1="50" y1="100.0" x2="750" y2="100.0" class="grid" /><text x="30" y="105.0" class="label" text-anchor="end">58.0</text><line x1="50" y1="50" x2="50" y2="350" class="grid" /><text x="50" y="370" class="label">3.2.6</text><line x1="400" y1="50" x2="400" y2="350" class="grid" /><text x="400" y="370" class="label">3.4.0</text><line x1="750" y1="50" x2="750" y2="350" class="grid" /><text x="750" y="370" class="label">3.4.1</text><polyline points="50,195.55625 400,88.24375000000003 750,50.67500000000001" class="line dashed" stroke="#4CAF50" /><circle cx="50" cy="195.55625" r="4" fill="#4CAF50" class="point" /><circle cx="400" cy="88.24375000000003" r="4" fill="#4CAF50" class="point" /><circle cx="750" cy="50.67500000000001" r="4" fill="#4CAF50" class="point" /><polyline points="50,218.6 400,104.6875 750,75.81875000000002" class="line dashed" stroke="#2196F3" /><circle cx="50" cy="218.6" r="4" fill="#2196F3" class="point" /><circle cx="400" cy="104.6875" r="4" fill="#2196F3" class="point" /><circle cx="750" cy="75.81875000000002" r="4" fill="#2196F3" class="point" /><polyline points="50,233.94374999999997 400,145.8625 750,130.15625" class="line dashed" stroke="#FFC107" /><circle cx="50" cy="233.94374999999997" r="4" fill="#FFC107" class="point" /><circle cx="400" cy="145.8625" r="4" fill="#FFC107" class="point" /><circle cx="750" cy="130.15625" r="4" fill="#FFC107" class="point" /><polyline points="50,300.65 400,265.13125 750,250.45000000000002" class="line dashed" stroke="#FF5722" /><circle cx="50" cy="300.65" r="4" fill="#FF5722" class="point" /><circle cx="400" cy="265.13125" r="4" fill="#FF5722" class="point" /><circle cx="750" cy="250.45000000000002" r="4" fill="#FF5722" class="point" /><polyline points="50,275.36875 400,255.73125000000002 750,247.7125" class="line" stroke="#4CAF50" /><circle cx="50" cy="275.36875" r="4" fill="#4CAF50" class="point" /><circle cx="400" cy="255.73125000000002" r="4" fill="#4CAF50" class="point" /><circle cx="750" cy="247.7125" r="4" fill="#4CAF50" class="point" /><polyline points="50,286.80625 400,258.5875 750,248.4375" class="line" stroke="#2196F3" /><circle cx="50" cy="286.80625" r="4" fill="#2196F3" class="point" /><circle cx="400" cy="258.5875" r="4" fill="#2196F3" class="point" /><circle cx="750" cy="248.4375" r="4" fill="#2196F3" class="point" /><polyline points="50,301.11875 400,283.7875 750,273.69375" class="line" stroke="#FFC107" /><circle cx="50" cy="301.11875" r="4" fill="#FFC107" class="point" /><circle cx="400" cy="283.7875" r="4" fill="#FFC107" class="point" /><circle cx="750" cy="273.69375" r="4" fill="#FFC107" class="point" /><polyline points="50,348.84375 400,344.73125 750,340.83125" class="line" stroke="#FF5722" /><circle cx="50" cy="348.84375" r="4" fill="#FF5722" class="point" /><circle cx="400" cy="344.73125" r="4" fill="#FF5722" class="point" /><circle cx="750" cy="340.83125" r="4" fill="#FF5722" class="point" /><line x1="55" y1="50" x2="75" y2="50" class="line dashed" stroke="#4CAF50" /><text x="115" y="54" class="label" text-anchor="start">pull(JIT)</text><line x1="55" y1="70" x2="75" y2="70" class="line dashed" stroke="#2196F3" /><text x="115" y="74" class="label" text-anchor="start">stream(JIT)</text><line x1="55" y1="90" x2="75" y2="90" class="line dashed" stroke="#FFC107" /><text x="115" y="94" class="label" text-anchor="start">sax2(JIT)</text><line x1="55" y1="110" x2="75" y2="110" class="line dashed" stroke="#FF5722" /><text x="115" y="114" class="label" text-anchor="start">dom(JIT)</text><line x1="55" y1="130" x2="75" y2="130" class="line" stroke="#4CAF50" /><text x="115" y="134" class="label" text-anchor="start">pull</text><line x1="55" y1="150" x2="75" y2="150" class="line" stroke="#2196F3" /><text x="115" y="154" class="label" text-anchor="start">stream</text><line x1="55" y1="170" x2="75" y2="170" class="line" stroke="#FFC107" /><text x="115" y="174" class="label" text-anchor="start">sax2</text><line x1="55" y1="190" x2="75" y2="190" class="line" stroke="#FF5722" /><text x="115" y="194" class="label" text-anchor="start">dom</text></svg>
@@ -0,0 +1,18 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="800" height="400">
2
+ <style>
3
+ .line { fill: none; stroke-width: 2; }
4
+ .dashed { stroke-dasharray: 5, 5; }
5
+ .label { font-size: 18px; text-anchor: middle; }
6
+ .axis { stroke: #000; stroke-width: 1; }
7
+ .grid { stroke: #ccc; stroke-width: 0.5; }
8
+ .point { fill-opacity: 0.8; }
9
+ .title { font-size: 22px; font-weight: bold; text-anchor: middle; }
10
+ </style>
11
+ <!-- 軸 -->
12
+ <line x1="50" y1="350" x2="750" y2="350" class="axis" />
13
+ <line x1="50" y1="50" x2="50" y2="350" class="axis" />
14
+ <!-- タイトル -->
15
+ <text x="400" y="25" class="title">REXML Performance benchmarks</text>
16
+ <text x="400" y="388" class="label">rexml version</text>
17
+ <text x="12" y="200" class="label" transform="rotate(-90, 12, 200)">i/s</text>
18
+ <line x1="50" y1="350.0" x2="750" y2="350.0" class="grid" /><text x="30" y="355.0" class="label" text-anchor="end">18.0</text><line x1="50" y1="279.4117647058823" x2="750" y2="279.4117647058823" class="grid" /><text x="30" y="284.4117647058823" class="label" text-anchor="end">22.0</text><line x1="50" y1="208.8235294117647" x2="750" y2="208.8235294117647" class="grid" /><text x="30" y="213.8235294117647" class="label" text-anchor="end">26.0</text><line x1="50" y1="138.23529411764704" x2="750" y2="138.23529411764704" class="grid" /><text x="30" y="143.23529411764704" class="label" text-anchor="end">30.0</text><line x1="50" y1="67.64705882352939" x2="750" y2="67.64705882352939" class="grid" /><text x="30" y="72.64705882352939" class="label" text-anchor="end">34.0</text><line x1="50" y1="50" x2="50" y2="350" class="grid" /><text x="50" y="370" class="label">3.2.6</text><line x1="400" y1="50" x2="400" y2="350" class="grid" /><text x="400" y="370" class="label">3.4.0</text><line x1="750" y1="50" x2="750" y2="350" class="grid" /><text x="750" y="370" class="label">3.4.1</text><polyline points="50,139.27647058823533 400,83.82941176470592 750,61.188235294117646" class="line" stroke="#4CAF50" /><circle cx="50" cy="139.27647058823533" r="4" fill="#4CAF50" class="point" /><circle cx="400" cy="83.82941176470592" r="4" fill="#4CAF50" class="point" /><circle cx="750" cy="61.188235294117646" r="4" fill="#4CAF50" class="point" /><polyline points="50,171.5705882352941 400,91.89411764705886 750,63.23529411764707" class="line" stroke="#2196F3" /><circle cx="50" cy="171.5705882352941" r="4" fill="#2196F3" class="point" /><circle cx="400" cy="91.89411764705886" r="4" fill="#2196F3" class="point" /><circle cx="750" cy="63.23529411764707" r="4" fill="#2196F3" class="point" /><polyline points="50,211.98235294117643 400,163.0470588235294 750,134.5470588235294" class="line" stroke="#FFC107" /><circle cx="50" cy="211.98235294117643" r="4" fill="#FFC107" class="point" /><circle cx="400" cy="163.0470588235294" r="4" fill="#FFC107" class="point" /><circle cx="750" cy="134.5470588235294" r="4" fill="#FFC107" class="point" /><polyline points="50,346.7352941176471 400,335.1235294117647 750,324.11176470588236" class="line" stroke="#FF5722" /><circle cx="50" cy="346.7352941176471" r="4" fill="#FF5722" class="point" /><circle cx="400" cy="335.1235294117647" r="4" fill="#FF5722" class="point" /><circle cx="750" cy="324.11176470588236" r="4" fill="#FF5722" class="point" /><line x1="55" y1="50" x2="75" y2="50" class="line" stroke="#4CAF50" /><text x="115" y="54" class="label" text-anchor="start">pull</text><line x1="55" y1="70" x2="75" y2="70" class="line" stroke="#2196F3" /><text x="115" y="74" class="label" text-anchor="start">stream</text><line x1="55" y1="90" x2="75" y2="90" class="line" stroke="#FFC107" /><text x="115" y="94" class="label" text-anchor="start">sax2</text><line x1="55" y1="110" x2="75" y2="110" class="line" stroke="#FF5722" /><text x="115" y="114" class="label" text-anchor="start">dom</text></svg>
@@ -0,0 +1,18 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="800" height="400">
2
+ <style>
3
+ .line { fill: none; stroke-width: 2; }
4
+ .dashed { stroke-dasharray: 5, 5; }
5
+ .label { font-size: 18px; text-anchor: middle; }
6
+ .axis { stroke: #000; stroke-width: 1; }
7
+ .grid { stroke: #ccc; stroke-width: 0.5; }
8
+ .point { fill-opacity: 0.8; }
9
+ .title { font-size: 22px; font-weight: bold; text-anchor: middle; }
10
+ </style>
11
+ <!-- 軸 -->
12
+ <line x1="50" y1="350" x2="750" y2="350" class="axis" />
13
+ <line x1="50" y1="50" x2="50" y2="350" class="axis" />
14
+ <!-- タイトル -->
15
+ <text x="400" y="25" class="title">REXML Performance benchmarks</text>
16
+ <text x="400" y="388" class="label">rexml version</text>
17
+ <text x="12" y="200" class="label" transform="rotate(-90, 12, 200)">i/s</text>
18
+ <line x1="50" y1="350.0" x2="750" y2="350.0" class="grid" /><text x="30" y="355.0" class="label" text-anchor="end">25.0</text><line x1="50" y1="284.1463414634146" x2="750" y2="284.1463414634146" class="grid" /><text x="30" y="289.1463414634146" class="label" text-anchor="end">34.0</text><line x1="50" y1="218.29268292682926" x2="750" y2="218.29268292682926" class="grid" /><text x="30" y="223.29268292682926" class="label" text-anchor="end">43.0</text><line x1="50" y1="152.4390243902439" x2="750" y2="152.4390243902439" class="grid" /><text x="30" y="157.4390243902439" class="label" text-anchor="end">52.0</text><line x1="50" y1="86.58536585365852" x2="750" y2="86.58536585365852" class="grid" /><text x="30" y="91.58536585365852" class="label" text-anchor="end">61.0</text><line x1="50" y1="50" x2="50" y2="350" class="grid" /><text x="50" y="370" class="label">3.2.6</text><line x1="400" y1="50" x2="400" y2="350" class="grid" /><text x="400" y="370" class="label">3.4.0</text><line x1="750" y1="50" x2="750" y2="350" class="grid" /><text x="750" y="370" class="label">3.4.1</text><polyline points="50,220.40731707317076 400,94.77317073170732 750,50.790243902439045" class="line dashed" stroke="#4CAF50" /><circle cx="50" cy="220.40731707317076" r="4" fill="#4CAF50" class="point" /><circle cx="400" cy="94.77317073170732" r="4" fill="#4CAF50" class="point" /><circle cx="750" cy="50.790243902439045" r="4" fill="#4CAF50" class="point" /><polyline points="50,247.38536585365853 400,114.02439024390242 750,80.2268292682927" class="line dashed" stroke="#2196F3" /><circle cx="50" cy="247.38536585365853" r="4" fill="#2196F3" class="point" /><circle cx="400" cy="114.02439024390242" r="4" fill="#2196F3" class="point" /><circle cx="750" cy="80.2268292682927" r="4" fill="#2196F3" class="point" /><polyline points="50,265.34878048780485 400,162.22926829268292 750,143.84146341463418" class="line dashed" stroke="#FFC107" /><circle cx="50" cy="265.34878048780485" r="4" fill="#FFC107" class="point" /><circle cx="400" cy="162.22926829268292" r="4" fill="#FFC107" class="point" /><circle cx="750" cy="143.84146341463418" r="4" fill="#FFC107" class="point" /><polyline points="50,343.4439024390244 400,301.8609756097561 750,284.67317073170733" class="line dashed" stroke="#FF5722" /><circle cx="50" cy="343.4439024390244" r="4" fill="#FF5722" class="point" /><circle cx="400" cy="301.8609756097561" r="4" fill="#FF5722" class="point" /><circle cx="750" cy="284.67317073170733" r="4" fill="#FF5722" class="point" /><line x1="55" y1="50" x2="75" y2="50" class="line dashed" stroke="#4CAF50" /><text x="115" y="54" class="label" text-anchor="start">pull(JIT)</text><line x1="55" y1="70" x2="75" y2="70" class="line dashed" stroke="#2196F3" /><text x="115" y="74" class="label" text-anchor="start">stream(JIT)</text><line x1="55" y1="90" x2="75" y2="90" class="line dashed" stroke="#FFC107" /><text x="115" y="94" class="label" text-anchor="start">sax2(JIT)</text><line x1="55" y1="110" x2="75" y2="110" class="line dashed" stroke="#FF5722" /><text x="115" y="114" class="label" text-anchor="start">dom(JIT)</text></svg>
@@ -0,0 +1,905 @@
1
+ = Improvement of REXML and speed up using StringScanner
2
+
3
+ : author
4
+ NAITOH Jun
5
+ : institution
6
+ MedPeer, Inc.
7
+ : content-source
8
+ RubyKaigi 2025
9
+ : date
10
+ 2025-04-17
11
+ : theme
12
+ .
13
+
14
+
15
+ : start-time
16
+ 2025-04-17T11:50:00+09:00
17
+ : end-time
18
+ 2025-04-17T12:20:00+09:00
19
+
20
+ == Slide properties
21
+
22
+ : enable-title-on-image
23
+ false
24
+
25
+ = NAITOH Jun
26
+
27
+ * @naitoh (GitHub and X(Twitter))\n
28
+ (('note:GitHub と X(Twitter) のアカウント'))
29
+ * A new maintainer of the (({rexml})) library\n
30
+ (('note:(({rexml}))ライブラリーの新メンテナー 🆕'))
31
+ * ((<Red Data Tools|URL:https://red-data-tools.github.io/>)) project member\n
32
+ (('note:Red Data Toolsプロジェクトのメンバー'))
33
+ * ((<redmine.tokyo|URL:https://redmine.tokyo/>)) stuff\n
34
+ (('note:redmine.tokyo 勉強会のスタッフ'))
35
+ * Working at MedPeer, Inc.\n
36
+ (('note:MedPeerで働いている'))
37
+
38
+ = (('note:MedPeer'))
39
+
40
+ # img
41
+ # src = images/medpeer_mission.png
42
+ # relative_height = 70
43
+
44
+ == Slide properties
45
+
46
+ : enable-title-on-image
47
+ false
48
+
49
+
50
+ = (('note: '))
51
+
52
+ # img
53
+ # src = images/medpeer.png
54
+ # relative_height = 100
55
+
56
+ == Slide properties
57
+
58
+ : enable-title-on-image
59
+ false
60
+
61
+ = rexml in Ruby 3.4 (1)\n(('note:Ruby 3.4の rexml(1)'))
62
+
63
+ * Faster XML parsing\n(('note:XMLパースの高速化'))
64
+ * It is up to ((*50%*)) faster between\n
65
+ rexml 3.2.6(attached to Ruby 3.3.0) and\n
66
+ rexml 3.4.0(attached to Ruby 3.4.0). \n
67
+ (('note:rexml 3.2.6(Ruby 3.3.0添付)とrexml 3.4.0(Ruby 3.4.0添付)の間で、((*最大50%*))速くなった。'))
68
+
69
+ = Benchmark target file
70
+
71
+ <?xml version="1.0"?>
72
+ <root>
73
+ <child id0="0" id1="0" />
74
+ :
75
+ <child id0="4999" id1="4999" />
76
+ </root>
77
+
78
+ (('tag:center'))
79
+ Parsing XML with 5000 child nodes.\n(('note:5000個の子ノードを持つXMLをパースする'))
80
+
81
+
82
+ = Ruby 3.4 YJIT disable(('note: YJIT 無効'))
83
+
84
+ # img
85
+ # src = images/svg_340_jit_disable.svg
86
+ # relative_height = 60
87
+
88
+ # RT
89
+
90
+ (('tag:small'))parser, (('tag:small'))3.2.6, (('tag:small'))3.4.0, (('tag:small'))Faster?
91
+
92
+ (('tag:center'))(('tag:small'))dom, (('tag:small'))(('tag:center'))18.19 i/s, (('tag:small'))(('tag:center'))18.84 i/s, (('tag:small'))(('tag:center'))1.03x
93
+ (('tag:center'))(('tag:small'))sax2, (('tag:small'))(('tag:center'))25.82 i/s, (('tag:small'))(('tag:center'))28.59 i/s, (('tag:small'))(('tag:center'))1.11x
94
+ (('tag:center'))(('tag:small'))pull, (('tag:small'))(('tag:center'))29.94 i/s, (('tag:small'))(('tag:center'))33.08 i/s, (('tag:small'))(('tag:center'))1.10x
95
+ (('tag:center'))(('tag:small'))stream, (('tag:small'))(('tag:center'))28.11 i/s, (('tag:small'))(('tag:center'))32.62 i/s, (('tag:small'))(('tag:center'))1.16x
96
+
97
+ = Ruby 3.4 YJIT enable(('note: YJIT 有効'))
98
+
99
+ # img
100
+ # src = images/svg_340_jit_enable.svg
101
+ # relative_height = 60
102
+
103
+ # RT
104
+
105
+ (('tag:small'))parser, (('tag:small'))3.2.6, (('tag:small'))3.4.0, (('tag:small'))Faster?
106
+
107
+ (('tag:center'))(('tag:small'))dom, (('tag:small'))(('tag:center'))25.90 i/s, (('tag:small'))(('tag:center'))31.58 i/s, (('tag:small'))(('tag:center'))1.22x
108
+ (('tag:center'))(('tag:small'))sax2, (('tag:small'))(('tag:center'))36.57 i/s, (('tag:small'))(('tag:center'))50.67 i/s, (('tag:small'))(('tag:center'))1.39x
109
+ (('tag:center'))(('tag:small'))pull, (('tag:small'))(('tag:center'))42.71 i/s, (('tag:small'))(('tag:center'))59.88 i/s, (('tag:small'))(('tag:center'))1.40x
110
+ (('tag:center'))(('tag:small'))stream, (('tag:small'))(('tag:center'))39.02 i/s, (('tag:small'))(('tag:center'))57.25 i/s, (('tag:small'))(('tag:center'))((*1.47x*))
111
+
112
+ = rexml in Ruby 3.4 (2)\n(('note:Ruby 3.4の rexml(2)'))
113
+
114
+ * Faster XML parsing\n(('note:XMLパースの高速化'))
115
+ * It is up to ((*60%*)) faster between\n
116
+ rexml 3.2.6(attached to Ruby 3.3.0) and rexml 3.4.1. \n
117
+ (('note:rexml 3.2.6(Ruby 3.3.0添付)とrexml 3.4.1の間で、((*最大60%*))速くなった'))
118
+
119
+ = Ruby 3.4 YJIT disable(('note: YJIT 無効'))
120
+
121
+ # img
122
+ # src = images/svg_341_jit_disable.svg
123
+ # relative_height = 60
124
+
125
+ # RT
126
+
127
+ (('tag:small'))parser, (('tag:small'))3.2.6, (('tag:small'))3.4.0, (('tag:small'))3.4.1, (('tag:small'))Faster?
128
+
129
+ (('tag:center'))(('tag:small'))dom, (('tag:small'))(('tag:center'))18.19 i/s, (('tag:small'))(('tag:center'))18.84 i/s, (('tag:small'))(('tag:center'))19.47 i/s, (('tag:small'))(('tag:center'))1.07x
130
+ (('tag:center'))(('tag:small'))sax2, (('tag:small'))(('tag:center'))25.82 i/s, (('tag:small'))(('tag:center'))28.59 i/s, (('tag:small'))(('tag:center'))30.21 i/s, (('tag:small'))(('tag:center'))1.16x
131
+ (('tag:center'))(('tag:small'))pull, (('tag:small'))(('tag:center'))29.94 i/s, (('tag:small'))(('tag:center'))33.08 i/s, (('tag:small'))(('tag:center'))34.37 i/s, (('tag:small'))(('tag:center'))1.14x
132
+ (('tag:center'))(('tag:small'))stream, (('tag:small'))(('tag:center'))28.11 i/s, (('tag:small'))(('tag:center'))32.62 i/s, (('tag:small'))(('tag:center'))34.25 i/s, (('tag:small'))(('tag:center'))1.21x
133
+
134
+ = Ruby 3.4 YJIT enable(('note: YJIT 有効'))
135
+
136
+ # img
137
+ # src = images/svg_341_jit_enable.svg
138
+ # relative_height = 60
139
+
140
+ # RT
141
+
142
+ (('tag:small'))parser, (('tag:small'))3.2.6, (('tag:small'))3.4.0, (('tag:small'))3.4.1, (('tag:small'))Faster?
143
+
144
+ (('tag:center'))(('tag:small'))dom, (('tag:small'))(('tag:center'))25.90 i/s, (('tag:small'))(('tag:center'))31.58 i/s, (('tag:small'))(('tag:center'))33.93 i/s, (('tag:small'))(('tag:center'))1.31x
145
+ (('tag:center'))(('tag:small'))sax2, (('tag:small'))(('tag:center'))36.57 i/s, (('tag:small'))(('tag:center'))50.67 i/s, (('tag:small'))(('tag:center'))53.18 i/s, (('tag:small'))(('tag:center'))1.45x
146
+ (('tag:center'))(('tag:small'))pull, (('tag:small'))(('tag:center'))42.71 i/s, (('tag:small'))(('tag:center'))59.88 i/s, (('tag:small'))(('tag:center'))65.89 i/s, (('tag:small'))(('tag:center'))1.54x
147
+ (('tag:center'))(('tag:small'))stream, (('tag:small'))(('tag:center'))39.02 i/s, (('tag:small'))(('tag:center'))57.25 i/s, (('tag:small'))(('tag:center'))61.87 i/s, (('tag:small'))(('tag:center'))((*1.58x*))
148
+
149
+ = Ruby 3.4 rexml 3.4.1
150
+
151
+ # img
152
+ # src = images/svg_341.svg
153
+ # relative_height = 80
154
+
155
+ (('tag:center'))
156
+ Up to ((*60%*)) faster.\n
157
+ (('note:((*最大60%*))高速化'))
158
+
159
+ = RubyKaigi 2024 LT
160
+
161
+ # img
162
+ # src = images/RubyKaigi2024LT.png
163
+ # relative_height = 60
164
+
165
+ * Up to 60% faster since rexml 3.2.6.\n
166
+ (('note:rexml 3.2.6から最大((*60%*))速くなった。'))
167
+ (('tag:center'))(('wait'))🤔
168
+
169
+ = The release version 3.2.7 was slowing down.\n(('note:リリース版の3.2.7が遅くなっていた。'))
170
+
171
+ # img
172
+ # src = images/rexml_x_1797256482272235856.png
173
+ # relative_height = 100
174
+
175
+ == Slide properties
176
+
177
+ : enable-title-on-image
178
+ false
179
+
180
+ = Ruby 3.4 rexml 3.2.7
181
+
182
+ # img
183
+ # src = images/svg_327.svg
184
+ # relative_height = 80
185
+
186
+ (('tag:center'))
187
+ It was slow in rexml 3.2.7.\n
188
+ (('note:rexml 3.2.7 で遅くなっていた'))
189
+
190
+
191
+ = Parsing process was slowing down to deal with CVE.\n(('note:CVEに対処するためパース処理が遅くなっていた'))
192
+
193
+ # img
194
+ # src = images/CVE-2024-35176.png
195
+ # relative_height = 80
196
+
197
+ (('tag:center'))
198
+ (('tag:small'))
199
+ ((<CVE-2024-35176: DoS vulnerability in REXML|URL:https://www.ruby-lang.org/en/news/2024/05/16/dos-rexml-cve-2024-35176/>))
200
+
201
+
202
+
203
+ = Make REXML ((*Fast Again*)).\n(('note:REXML を((*再び高速化*))する'))
204
+
205
+ = What's REXML\n(('note:REXML とは?'))
206
+
207
+ * REXML is a standard XML library (Bundled Gem) for Ruby implemented in Pure Ruby.\n
208
+ (('note:REXMLはPure Rubyで実装されたRuby用の標準XMLライブラリ(Bundled Gem)'))
209
+
210
+ = What's XML?\n(('note:XML とは?'))
211
+
212
+ # rouge xml
213
+
214
+ <?xml version="1.0"?>
215
+ <svg xmlns="http://www.w3.org/2000/svg">
216
+ <rect x="0" y="0" width="100" height="60" fill="#ddd" />
217
+ <polygon points="50 10, 70 30, 50 50, 30 30" fill="#99f" />
218
+ </svg>
219
+
220
+ * Describe using tags like HTML.\n
221
+ (('note:HTML の様にタグを用いて記述する'))
222
+ * Highly scalable data exchange format.\n
223
+ (('note:拡張性の高いデータ交換用フォーマット'))
224
+
225
+ = XML-based format example\n(('note:XMLベースのフォーマット例'))
226
+
227
+ * SVG, DOCX, XLSX, MathML, PubMed-XML, CIM-XML, etc.\n
228
+ (('note:SVG, DOCX, XLSX、MathML、PubMed XML, CIM-XML, ..'))
229
+ * Complex expressions are possible.\n
230
+ (('note:複雑な表現が可能'))
231
+
232
+ = XML character encoding.\n(('note:XML の 文字コード'))
233
+
234
+ * XML supports UTF-8 and UTF-16 (required). \n
235
+ (('note:XML は UTF-8 と UTF-16 をサポート(必須)'))
236
+ * Other character encoding can be used by declaring XML encoding (optional).\n
237
+ (('note:XMLエンコーディングを宣言することで、他の文字エンコーディングを使用可能(オプション)'))
238
+
239
+ = How REXML processes XML.(1)\n(('note:REXML の XML処理方法(1)'))
240
+
241
+ * REXML supports UTF-8 and UTF-16. \n
242
+ (('note:REXML は UTF-8 と UTF-16 をサポート'))
243
+ * Reads and parses XML files by tags.\n
244
+ (('note:XMLファイルをタグ単位で読み込み、パース処理を行う'))
245
+
246
+ = How REXML processes XML.(2)\n(('note:REXML の XML処理方法(2)'))
247
+
248
+ * For non-UTF-8 encoding, convert to UTF-8 when reading.\n
249
+ (('note:UTF-8 以外のエンコーディングの場合は、読み込み時にUTF-8 に変換'))
250
+ * Other encoding can basically be used if Ruby supports it.\n
251
+ (('note:Rubyがサポートしていれば他のエンコーディングも基本的に使用可能'))
252
+
253
+ = About REXML's Parser\n(('note:REXMLのパーサーについて'))
254
+
255
+ * REXML has a DOM/SAX2/Pull/Stream parser.\n
256
+ (('note:REXML はDOM/SAX2/Pull/Stream のパーサーがある'))
257
+
258
+ = Types of REXML parsers\n(('note:REXMLのパーサーの種類'))
259
+
260
+ * Tree API (('note:ツリーAPI'))
261
+ * DOM(Document Object Model) parser
262
+ * Streaming API (('note:ストリーミングAPI'))
263
+ * Callback type(passive) (('note:コールバック形式(受動的)'))
264
+ * SAX2 (Simple API for XML) parser
265
+ * Stream parser
266
+ * Pull type(active) (('note:Pull形式(能動的)'))
267
+ * Pull parser
268
+
269
+ = Features of DOM parser.\n(('note:DOMパーサーの特徴'))
270
+
271
+ * DOM-style XML parser.\n
272
+ (('note:DOM スタイルの XML パーサ'))
273
+ * Treat XML as a tree structure.\n
274
+ (('note:XMLを木構造として扱う'))
275
+ * Easy to use as any node can be accessed.\n
276
+ (('note:任意のノードにアクセス可能なので使いやすい'))
277
+ * Keep parsing results in memory.\n
278
+ (('note:パース処理結果をメモリ上に保持する'))
279
+ * Large XML is memory inefficient and slow..\n
280
+ (('note:大きなXMLではメモリ効率が悪く遅い'))
281
+
282
+ = Features of SAX2 parser.(1)\n(('note:SAX2パーサーの特徴(1)'))
283
+
284
+ * Stream-style parser with API equivalent to SAX2.\n
285
+ (('note:SAX2 と同等の API を持つストリーム形式のパーサ '))
286
+ * Sequential processing from the beginning of the file, line by line.\n
287
+ (('note:ファイル先頭からシーケンシャルに1行単位ごとに処理'))
288
+ * By registering an event listener, callbacks are processed on an event-by-event basis.\n
289
+ (('note:イベントリスナを登録することでイベント単位にコールバック処理'))
290
+
291
+ = Features of SAX2 parser.(2)\n(('note:SAX2パーサーの特徴(2)'))
292
+ * Not keep parsing results in memory.\n
293
+ (('note:パース処理結果をメモリ上に保持しない'))
294
+ * Memory efficient, fast even with large XML.\n
295
+ (('note:メモリ効率に優れ、大きなXMLでも高速'))
296
+ * Not easy to use, because access to arbitrary nodes is not possible.\n
297
+ (('note:任意のノードへのアクセスはできないので、使い勝手は悪い'))
298
+
299
+ = Features of Stream parser.\n(('note:Streamパーサーの特徴'))
300
+ * Basically the same as SAX2 parser.\n
301
+ (('note:基本的には SAX2 パーサーと同じ'))
302
+ * Stream parsers are lightweight and fast because of their limited functionality.\n
303
+ (('note:Streamパーサーは 機能が限定的なので軽量のため速い'))
304
+
305
+ = Features of Pull parser.\n(('note:Pullパーサーの特徴'))
306
+ * Stream-style parser, processing one line at a time.\n
307
+ (('note:ストリーム形式のパーサで、1行単位に処理する'))
308
+ * Pull parser reads and processes each event by itself.\n
309
+ (('note:Pullパーサーは各イベントを自分で読み込んで処理する'))
310
+
311
+
312
+
313
+ = Motivation(1)\n(('note:動機(1)'))
314
+
315
+ * I am the author of the PDF export library ((<RBPDF gem|URL:https://github.com/naitoh/rbpdf/>)).\n
316
+ (('note:私は PDF出力ライブラリRBPDF gemの作者'))
317
+ * RBPDF is used by ((*Redmine*))'s PDF output feature.\n
318
+ (('note:RBPDF は ((*Redmine*)) のPDF出力機能で使用されている'))
319
+ * I would like to support PDF output of SVG images in RBPDF using REXML, which is easy to install.\n
320
+ (('note:インストールの容易なREXMLを用いてRBPDFでSVG画像のPDF出力をサポートしたい'))
321
+
322
+ = Motivation(2)\n(('note:動機(2)'))
323
+
324
+ * REXML performance is slower than C extension gem.\n
325
+ (('note:REXMLはパフォーマンスがC拡張gemより遅い'))
326
+ * I would like to improve REXML performance.\n
327
+ (('note:REXMLのパフォーマンスを改善したい'))
328
+
329
+
330
+ = Improvements\n(('note:改善点'))
331
+
332
+ * Up to 50% speedup between rexml 3.2.6 (Ruby 3.3.0 attached) and rexml 3.4.0 (Ruby 3.4.0 attached).\n
333
+ (('note:rexml 3.2.6(Ruby 3.3.0 添付) から、rexml 3.4.0(Ruby 3.4.0 添付) の間で最大50%の高速化を実現'))
334
+ * It is up to ((*60%*)) faster between rexml 3.2.6 and rexml 3.4.1.\n
335
+ (('note:rexml 3.2.6 から rexml 3.4.1 の間で((*最大60%*))の高速化を実現'))
336
+
337
+ = How?\n(('note:どうやって?'))
338
+
339
+ # img
340
+ # src = images/rubykaigi-2019-p35-p78.png
341
+ # relative_height = 60
342
+
343
+ (('tag:center'))
344
+ (('tag:small'))
345
+ "Improving CSV Processing with Ruby 2.6"\n
346
+ at RubyKaigi 2019\n
347
+ (('note:((<URL:https://slide.rabbit-shocker.org/authors/kou/rubykaigi-2019/>))'))
348
+
349
+ = What is StringScanner?(1)\n(('note:StringScanner とは?(1)'))
350
+
351
+ * StringScanner is a sequential string scanner.\n
352
+ (('note:StringScanner は逐次的な文字列スキャナ'))
353
+ * Sequential String Scanning\n(('note:文字列の逐次スキャン'))
354
+ * Regular Expression Matching\n(('note:正規表現マッチング'))
355
+ * State Management\n(('note:状態管理'))
356
+
357
+
358
+ = StringScanner Features(1)\n(('note:StringScanner の特徴(1)'))
359
+
360
+ * Sequential String Scanning\n(('note:文字列の逐次スキャン'))
361
+ * It processes a string from the beginning, moving forward as it matches patterns.\n
362
+ (('note:文字列の先頭から順番に解析しながら先に進む'))
363
+ * Regular Expression Matching\n(('note:正規表現マッチング'))
364
+ * State Management\n(('note:状態管理'))
365
+
366
+ = StringScanner Features(2)\n(('note:StringScanner の特徴(2)'))
367
+
368
+ * Sequential String Scanning\n(('note:文字列の逐次スキャン'))
369
+ * Regular Expression Matching\n(('note:正規表現マッチング'))
370
+ * Use scan(), scan_until(), etc. to look for specific patterns.\n
371
+ (('note:scan(), scan_until() などを使って特定のパターンを探す。'))
372
+ * State Management\n(('note:状態管理'))
373
+
374
+ = StringScanner Features(3)\n(('note:StringScanner の特徴(3)'))
375
+
376
+ * Sequential String Scanning\n(('note:文字列の逐次スキャン'))
377
+ * Regular Expression Matching\n(('note:正規表現マッチング'))
378
+ * State Management\n(('note:状態管理'))
379
+ * pos (current position) and rest (rest of string) to see how far you have parsed.\n
380
+ (('note:pos (現在の位置) や rest (残りの文字列) で、どこまで解析したかを把握できる'))
381
+
382
+ = What is StringScanner?(2)\n(('note:StringScanner とは?(2)'))
383
+ * Available since Ruby 1.8 and default gem since Ruby 2.5.\n
384
+ (('note:Ruby 1.8 から使用可能で Ruby 2.5 以降で default gem になっている'))
385
+ * Uses Ruby's regular expression engine (Onigmo).\n
386
+ (('note:Rubyの正規表現エンジン(Onigmo)を使っている'))
387
+ * ReDoS countermeasure implemented in Ruby 3.2 is also effective.👍\n
388
+ (('note:Ruby 3.2で実装されたReDoS対策も有効'))
389
+
390
+ = StringScanner is fast.(1)\n(('note:StringScanner は速い(1)'))
391
+
392
+ # rouge ruby
393
+
394
+ /\A\w+/.match('test string') #=> 'test'
395
+ s = StringScanner.new('test string')
396
+ s.check(/\w+/) #=> 'test'
397
+ s.check('test') #=> 'test'
398
+
399
+ # RT
400
+
401
+ (('tag:center'))(('tag:small'))Regexp#match, (('tag:center'))(('tag:small')) 5.675M i/s
402
+ (('tag:center'))(('tag:small'))StringScanner\n#check(Regexp), (('tag:center'))(('tag:small')) 8.800M i/s\n (('note:(1.55x faster)'))
403
+ (('tag:center'))(('tag:small'))StringScanner\n#check(String), (('tag:center'))(('tag:small')) 10.27M i/s\n (('note:(1.81x faster)'))
404
+
405
+ = StringScanner is fast.(2)\n(('note:StringScanner は速い(2)'))
406
+
407
+ # RT
408
+
409
+ (('tag:center'))(('tag:small'))Regexp#match, (('tag:center'))(('tag:small')) 5.675M i/s
410
+ (('tag:center'))(('tag:small'))StringScanner\n#check(Regexp), (('tag:center'))(('tag:small')) 8.800M i/s\n (('note:(1.55x faster)'))
411
+ (('tag:center'))(('tag:small'))StringScanner\n#check(String), (('tag:center'))(('tag:small')) 10.27M i/s\n (('note:(((*1.81x*)) faster)'))
412
+
413
+ * StringScanner#check(String) is fast because it uses ((*memcmp()*)) for comparison.\n
414
+ (('note:StringScanner#check(String) は比較に ((*memcmp()*)) を使うので速い'))
415
+
416
+ = StringScanner is fast.(3)\n(('note:StringScanner は速い(3)'))
417
+
418
+ # RT
419
+
420
+ (('tag:center'))(('tag:small'))Regexp#match, (('tag:center'))(('tag:small')) 5.675M i/s
421
+ (('tag:center'))(('tag:small'))StringScanner\n#check(Regexp), (('tag:center'))(('tag:small')) 8.800M i/s\n (('note:(1.55x faster)'))
422
+
423
+ * Regexp#match generates and returns a MatchData Object.\n
424
+ (('note:Regexp#match は MatchData Object を生成して返す'))
425
+ * StringScanner#check copies the matched string and returns it.\n
426
+ (('note:StringScanner#check はマッチした文字列をコピーして返す'))
427
+
428
+ = Without match object generation, performance is equivalent.\n(('note:マッチオブジェクト生成無しの場合、性能は同等'))
429
+
430
+ # RT
431
+
432
+ (('tag:center'))(('tag:small'))Regexp#match?, (('tag:center')) 14.71M i/s
433
+ (('tag:center'))(('tag:small'))StringScanner#match?, (('tag:center')) 14.28M i/s (('note:(1.03x slower)'))
434
+
435
+ * Regexp#match? and StringScanner\n#match? respond with boolean.\n
436
+ (('note:Regexp#match?とStringScanner#match? はboolean で応答'))
437
+ * Performance is equivalent since both are only regular expression processing.\n
438
+ (('note:両方とも正規表現処理のみなのでパフォーマンスは同等'))
439
+
440
+ = rexml in Ruby 3.4 (2)\n(('note:Ruby 3.4のrexml(2)'))
441
+
442
+ (('tag:small:Use StringScanner#scan'))\n
443
+ (('tag:small:instead of Regexp#match'))\n
444
+ (('tag:small:to parse XML.'))\n
445
+ (('note:XMLのパースにRegexp#matchの代わりにStringScanner#scanを使う'))
446
+
447
+ = Example of Regexp class use\n(('note:Regexpクラスを使う例'))
448
+
449
+ * Repeat until a match is found in the regular expression.\n
450
+ (('note:正規表現でマッチするまで繰り返す'))
451
+
452
+ # rouge ruby
453
+
454
+ word = (/\A<[^>]*>/um).match('<!-- foo -->') # Get Tag
455
+ case word[0]
456
+ when /\A<\?xml\s/u 👈 Not Match
457
+ when /\A<!--/u
458
+ /<!--(.*?)-->/um.match(word[0])[0] #=> " foo "
459
+ when /\A<!DOCTYPE\s/um
460
+
461
+ = Example of Regexp class use\n(('note:Regexpクラスを使う例'))
462
+
463
+ * Repeat until a match is found in the regular expression.\n
464
+ (('note:正規表現でマッチするまで繰り返す'))
465
+
466
+ # rouge ruby
467
+
468
+ word = (/\A<[^>]*>/um).match('<!-- foo -->') # Get Tag
469
+ case word[0]
470
+ when /\A<\?xml\s/u
471
+ when /\A<!--/u 👈 Match
472
+ /<!--(.*?)-->/um.match(word[0])[0] #=> " foo "
473
+ when /\A<!DOCTYPE\s/um
474
+
475
+
476
+ = Example of StringScanner use(1)\n(('note:StringScannerの使用例(1)'))
477
+
478
+ * Parses strings sequentially from the beginning.\n
479
+ (('note:文字列の先頭から順番に解析する'))
480
+ * Easy to understand process.\n
481
+ (('note:処理がわかりやすい'))
482
+
483
+ = Example of StringScanner use(1)\n(('note:StringScannerの使用例(1)'))
484
+
485
+ # rouge ruby
486
+
487
+ s = StringScanner.new('<!-- foo -->')
488
+ s.pos = 0 # for Benchmark
489
+ if s.scan("<?") 👈 Not Match
490
+ elsif s.scan("<!")
491
+ if s.scan("--")
492
+ s.scan(/(.*?)-->/um) and s[1] #=> " foo " 
493
+ elsif s.scan("DOCTYPE")
494
+
495
+ # RT
496
+
497
+ (('tag:center'))<,(('tag:center'))!,(('tag:center'))-,(('tag:center'))-, ,(('tag:center'))f,(('tag:center'))o,(('tag:center'))o, ,(('tag:center'))-,(('tag:center'))-,(('tag:center'))>
498
+
499
+ ☝️, , , , , , , , , , ,
500
+
501
+ = Example of StringScanner use(1)\n(('note:StringScannerの使用例(1)'))
502
+
503
+ # rouge ruby
504
+
505
+ s = StringScanner.new('<!-- foo -->')
506
+ s.pos = 0 # for Benchmark
507
+ if s.scan("<?")
508
+ elsif s.scan("<!") 👈 Match
509
+ if s.scan("--")
510
+ s.scan(/(.*?)-->/um) and s[1] #=> " foo " 
511
+ elsif s.scan("DOCTYPE")
512
+
513
+ # RT
514
+
515
+ (('tag:center'))<,(('tag:center'))!,(('tag:center'))-,(('tag:center'))-, ,(('tag:center'))f,(('tag:center'))o,(('tag:center'))o, ,(('tag:center'))-,(('tag:center'))-,(('tag:center'))>
516
+
517
+ ▶︎,▶︎,☝️, , , , , , , , ,
518
+
519
+ = Example of StringScanner use(1)\n(('note:StringScannerの使用例(1)'))
520
+
521
+ # rouge ruby
522
+
523
+ s = StringScanner.new('<!-- foo -->')
524
+ s.pos = 0 # for Benchmark
525
+ if s.scan("<?")
526
+ elsif s.scan("<!") 👈
527
+ if s.scan("--") 👈 Match
528
+ s.scan(/(.*?)-->/um) and s[1] #=> " foo " 
529
+ elsif s.scan("DOCTYPE")
530
+
531
+ # RT
532
+
533
+ (('tag:center'))<,(('tag:center'))!,(('tag:center'))-,(('tag:center'))-, ,(('tag:center'))f,(('tag:center'))o,(('tag:center'))o, ,(('tag:center'))-,(('tag:center'))-,(('tag:center'))>
534
+
535
+ , ,▶︎,▶︎,☝️, , , , , , ,
536
+
537
+ = Example of StringScanner use(1)\n(('note:StringScannerの使用例(1)'))
538
+
539
+ # rouge ruby
540
+
541
+ s = StringScanner.new('<!-- foo -->')
542
+ s.pos = 0 # for Benchmark
543
+ if s.scan("<?")
544
+ elsif s.scan("<!") 👈
545
+ if s.scan("--") 👈
546
+ s.scan(/(.*?)-->/um) and s[1] #=> " foo "👈
547
+ elsif s.scan("DOCTYPE")
548
+
549
+ # RT
550
+
551
+ (('tag:center'))<,(('tag:center'))!,(('tag:center'))-,(('tag:center'))-, ,(('tag:center'))f,(('tag:center'))o,(('tag:center'))o, ,(('tag:center'))-,(('tag:center'))-,(('tag:center'))>
552
+
553
+ , , , ,▶︎,▶︎,▶︎,▶︎,▶︎,▶︎,▶︎,☝️
554
+
555
+ = Benchmark result\n(('note:ベンチマーク結果'))
556
+
557
+ # RT
558
+
559
+ (('tag:center'))(('tag:small'))Regexp#match, (('tag:center')) 1.210M i/s
560
+ (('tag:center'))(('tag:small'))StringScanner#scan, (('tag:center')) 2.225M i/s\n (('note:(1.84x faster)'))
561
+
562
+ * Using StringScanner is 1.8 times faster.\n
563
+ (('note:StringScanner を使った方が 1.8 倍速い'))
564
+
565
+ = rexml in Ruby 3.4 (3)\n(('note:Ruby 3.4のrexml(3)'))
566
+
567
+ (('tag:center'))
568
+ (('tag:small:Use StringScanner#scan_until'))\n
569
+ (('tag:small:instead of Regexp#match'))\n
570
+ (('tag:small:to parse XML.'))\n
571
+ (('note:XMLのパースにRegexp#matchの代わりにStringScanner#scan_until を使う'))
572
+
573
+ # rouge ruby
574
+
575
+ s = StringScanner.new('test string')
576
+ s.scan_until(/str/) # => "test str"
577
+
578
+ = Regexp Class
579
+
580
+ # rouge ruby
581
+
582
+ xml = "<![CDATA[#{'a'*n}]]>"
583
+ md = xml.match(/\A<!\[CDATA\[(.*?)\]\]>/um)
584
+ md[1]
585
+ => "aaa.."
586
+
587
+ # RT
588
+
589
+ , (('tag:center'))(('tag:small'))n=10,(('tag:center'))(('tag:small'))n=100
590
+
591
+ (('tag:center'))(('tag:small'))Regexp#match, (('tag:center'))(('tag:small'))2856k i/s, (('tag:center'))(('tag:small'))976k i/s
592
+
593
+ = StringScanner#check(Regexp)
594
+
595
+ # rouge ruby
596
+
597
+ s = StringScanner.new("<![CDATA[#{'a'*n}]]>")
598
+ s.check(/<!\[CDATA\[(.*?)\]\]>/um) and s[1]
599
+ => "aaa.."
600
+
601
+ # RT
602
+
603
+ , (('tag:center'))(('tag:small'))n=10,(('tag:center'))(('tag:small'))n=100
604
+
605
+ (('tag:center'))(('tag:small'))Regexp#match, (('tag:center'))(('tag:small'))2856k i/s, (('tag:center'))(('tag:small'))976k i/s
606
+ (('tag:center'))(('tag:small'))#scan\n(Regexp), (('tag:center'))(('tag:small'))4146k i/s\n (('note:(1.45x faster)')), (('tag:center'))(('tag:small'))1137k i/s\n (('note:(1.16x faster)'))
607
+
608
+ * (('tag:small'))Using StringScanner is 1.45 times faster.\n
609
+ (('note:StringScanner を使った方が 1.45 倍速い'))
610
+
611
+ = StringScanner#scan_until String
612
+
613
+ # rouge ruby
614
+
615
+ s = StringScanner.new("<![CDATA[#{'a'*n}]]>")
616
+ s.pos = 0 and s.skip("<!") and s.skip("[CDATA[")\
617
+ and s.scan_until("]]>").chomp!("]]>") #=>"aaa.."
618
+
619
+ # RT
620
+
621
+ , (('tag:center'))(('tag:small'))n=10,(('tag:center'))(('tag:small'))n=100
622
+
623
+ (('tag:center'))(('tag:small'))Regexp#match, (('tag:center'))(('tag:small'))2856k i/s, (('tag:center'))(('tag:small'))976k i/s
624
+ (('tag:center'))(('tag:small'))#scan\n(Regexp), (('tag:center'))(('tag:small'))4146k i/s\n (('note:(1.45x faster)')), (('tag:center'))(('tag:small'))1137k i/s\n (('note:(1.16x faster)'))
625
+ (('tag:center'))(('tag:small'))#scan_until\n(String), (('tag:center'))(('tag:small'))4513k i/s\n (('note:(1.58x faster)')), (('tag:center'))(('tag:small'))3574k i/s\n (('note:(((*3.66x*)) faster)'))
626
+
627
+ * (('tag:small'))Using scan_until(String) is 3.6 times faster and less degrading.
628
+ (('note:scan_until(String) の方が3.6倍速く、劣化しにくい'))
629
+
630
+ = rexml in Ruby 3.4 (3)\n(('note:Ruby 3.4のrexml(3)'))
631
+
632
+ * Using string matching\n (instead of regular expressions)\n is faster.\n
633
+ (('note:(正規表現の代わりに)文字列マッチを使うと、より高速'))
634
+ * Even when match strings are long, performance degradation is minimized.\n
635
+ (('note:マッチ文字列が長くなっても、性能劣化を最小限に抑えられる'))
636
+
637
+ = StringScanner#scan_until String
638
+
639
+ * ((<strscan#106|URL:https://github.com/ruby/strscan/pull/106>)) Support for string matching in strscan 3.1.2(attached to Ruby 3.4.0).\n(('note:(Ruby 3.4.0添付の)strscan 3.1.2 で文字列マッチに対応'))
640
+ * StringScanner#scan_until(String) is fast because it uses ((*rb_memsearch()*)) for comparison.\n
641
+ (('note:StringScanner#scan_until(String) は比較に ((*rb_memsearch()*)) を使うので速い'))
642
+
643
+ = rexml in Ruby 3.4 (4)\n(('note:Ruby 3.4のrexml(4)'))
644
+
645
+ (('tag:small:Suppress generation of'))\n
646
+ (('tag:small:unnecessary String Objects.'))\n
647
+ (('note:不要な String Object の生成を抑制する'))
648
+
649
+ = Generating String Object (copying data) takes time\n(('note:文字列 Object の生成(データのコピー)に時間がかかる'))
650
+
651
+ # rouge ruby
652
+
653
+ s = StringScanner.new(' ')
654
+ s.check(/\s+/um) #=> " "
655
+ s.match?(/\s+/um) #=> 1
656
+
657
+ * No match string needed for whitespace removal.\n
658
+ (('note:空白除去の場合はマッチ文字列は不要'))
659
+
660
+ = Benchmark result
661
+
662
+ * Faster if no match string is needed.\n
663
+ (('note:マッチ文字列不要なら速くなる'))
664
+
665
+ # RT
666
+
667
+ , /\s+/um
668
+
669
+ (('tag:center'))check, (('tag:left'))6686K i/s
670
+ (('tag:center'))match?, (('tag:left'))8925K i/s (('note:(1.33x faster)'))
671
+
672
+ = String matching is faster.(1)\n(('note:文字列マッチならより高速(1)'))
673
+
674
+ # rouge ruby
675
+
676
+ s = StringScanner.new('<![CDATA[')
677
+ if s.check(/<!/um) .. #=> "<!"
678
+ if s.match?(/<!/um) .. #=> 2
679
+ if s.check('<!') .. #=> "<!"
680
+ if s.match?('<!') .. #=> 2
681
+
682
+ * Branching process does not need match string.
683
+ (('note: 分岐処理ではマッチ文字列は不要'))
684
+
685
+
686
+ = String matching is faster.(2)\n(('note:文字列マッチならより高速(2)'))
687
+
688
+ * Faster if no match string is needed.\n
689
+ (('note:マッチ文字列不要なら速くなる'))
690
+ * String matching is faster.\n
691
+ (('note:文字列マッチならより高速'))
692
+
693
+ # RT
694
+
695
+ , /<!/um, '<!'
696
+
697
+ (('tag:center'))check, (('tag:center'))10525K i/s, (('tag:center'))14450K i/s (('note:(1.37x faster)'))
698
+ (('tag:center'))match?, (('tag:center'))18731K i/s (('note:(1.78x faster)')), (('tag:center'))31900K i/s (('note:(3.03x faster)'))
699
+
700
+
701
+ = Avoid generating String object(1)\n(('note:文字列オブジェクトの生成を避ける(1)'))
702
+
703
+ # rouge ruby
704
+
705
+ s = StringScanner.new("'test'>")
706
+ s.check(/(['"])/) #=> "'"
707
+
708
+ * Need to determine if double or single quotes are used to get attribute values.\n
709
+ (('note:属性値を取得するためにダブルクォーテーションかシングルクォーテーションかの判断が必要'))
710
+
711
+ = Avoid generating String object(2)\n(('note:文字列オブジェクトの生成を避ける(2)'))
712
+
713
+ # rouge ruby
714
+
715
+ s = StringScanner.new("'test'>")
716
+ case s.peek_byte
717
+ when 34 then '"' # '"'.ord
718
+ when 39 then "'" # "'".ord
719
+ end #=> "'"
720
+
721
+ * If a single byte is returned as a number, no object is created.\n
722
+ (('note: 1バイトなら数値で返せば、オブジェクトは生成されない'))
723
+
724
+ = Benchmark result
725
+
726
+ * Faster without object generation.\n
727
+ (('note:オブジェクト生成無しでより速く'))
728
+
729
+ # RT
730
+
731
+ (('tag:center'))with object, (('tag:left'))10385k i/s
732
+ (('tag:center'))without object, (('tag:left'))32000K i/s (('note:(3.08x faster)'))
733
+
734
+ = StringScanner#peek_byte
735
+
736
+ * New methods added in strscan 3.1.2 (attached to Ruby 3.4.0)\n(('note:(Ruby 3.4.0添付の)strscan 3.1.2 で追加された新しいメソッド'))
737
+ * Referring to ((<Fast Route Parsing in Rails (('tag:small:(by Aaron Patterson)'))|URL:https://www.youtube.com/watch?v=ZE6F3drGhA8>>)), REXML was also made faster using peek_byte.\n
738
+ (('note:Fast Route Parsing in Rails の話を参考に、REXML も peek_byte を使って速くなりました'))
739
+
740
+ = rexml in Ruby 3.4 (5)\n(('note:Ruby 3.4のrexml(5)'))
741
+
742
+ (('tag:small:Use constants or memoization'))\n
743
+ (('tag:small:for slow processes.'))\n
744
+ (('note:遅い処理には定数やメモ化を使う'))
745
+
746
+ = Regexp.escape is slow, so use Constant.\n(('note:Regexp.escape は遅いので定数化'))
747
+
748
+ # rouge ruby
749
+
750
+ REG = /#{Regexp.escape("'")}/
751
+ s = StringScanner.new("test'>")
752
+ s.check_until(REG)
753
+
754
+ # RT
755
+
756
+ (('tag:center'))not use Constant, (('tag:left'))1393K i/s
757
+ (('tag:center'))use Constant, (('tag:left'))9660K i/s (('note:(6.93x faster)'))
758
+
759
+ = Encoding of the read delimiter.\n(('note: 読み取り区切り文字のエンコード'))
760
+
761
+ * REXML reads XML with ">" as read delimiter.\n
762
+ (('note:REXML は ">" を読み込み区切り文字としてXMLを読み込む'))
763
+ * In UTF-16, ">" is 2 byte.\n
764
+ (('note: UTF-16 の場合、">" は 2byte'))
765
+
766
+ # RT
767
+
768
+ ,(('tag:center'))<,,(('tag:center'))f,,(('tag:center'))o,,(('tag:center'))o,,(('tag:center'))>
769
+
770
+ , , , , , , , ,☝️,☝️
771
+
772
+ = Memorize the encoding result of the read delimiter.\n(('note:読み取り区切り文字のエンコード結果のメモ化'))
773
+
774
+ * One character code exists for each XML instance.\n
775
+ (('note:XMLインスタンス毎に文字コードは一つ存在'))
776
+
777
+ # rouge ruby
778
+
779
+ term = '>'
780
+ @term_encord ||= term.encode('UTF-16BE')
781
+
782
+ = ((*Made*)) REXML Fast Again!\n(('note:REXML を再び高速化した!'))
783
+
784
+ # img
785
+ # src = images/svg_327.svg
786
+ # relative_height = 100
787
+
788
+ == Slide properties
789
+
790
+ : enable-title-on-image
791
+ false
792
+
793
+ = Other improvements.\n(('note:他の改善点'))
794
+
795
+ * Enhanced invalid XML check.\n
796
+ (('note:無効XMLチェック強化'))
797
+ * Unification of processing results for each REXML parser (DOM/SAX2/Pull/Stream).\n
798
+ (('note:各パーサー間でのパース処理結果の統一'))
799
+
800
+ = Enhanced invalid XML check(1).\n(('note:無効XMLチェック強化(1)'))
801
+
802
+ # rouge xml
803
+
804
+ <root1></root1>
805
+ <root2></root2>
806
+
807
+ * Multiple root tags.\n
808
+ (('note:複数のルートタグ'))
809
+
810
+ = Enhanced invalid XML check(2).\n(('note:無効XMLチェック強化(2)'))
811
+
812
+ # rouge xml
813
+
814
+ foo
815
+ <root></root>
816
+
817
+ * String before the root tag.\n
818
+ (('note:ルートタグ前の文字列'))
819
+ * ((<rexml#212|URL:https://github.com/ruby/rexml/issues/212>)): If the BOM is broken, it is interpreted as a string and can detect errors.\n
820
+ (('note:BOMが壊れた場合、文字列と解釈されるのでエラー検出できる。'))
821
+
822
+ = Enhanced invalid XML check(3).\n(('note:無効XMLチェック強化(3)'))
823
+
824
+ # rouge xml
825
+
826
+ <root></root>
827
+ bar
828
+
829
+ * String after the root tag.\n
830
+ (('note:ルートタグ後の文字列'))
831
+
832
+ = Enhanced invalid XML check(4).\n(('note:無効XMLチェック強化(4)'))
833
+
834
+ # rouge xml
835
+
836
+ 429 Too Many Requests
837
+
838
+ * String with no root tag.\n
839
+ (('note:ルートタグが無い文字列'))
840
+ * If an error string is responded instead of XML, the XML parser can handle the error.\n
841
+ (('note:XMLではなくエラー文字列が応答された場合に、XMLパーサー側でエラー処理できる。'))
842
+
843
+ = Unification of processing results for each REXML parser.(1)\n(('note:各パーサー間でのパース処理結果の統一(1)'))
844
+
845
+ * REXML has a DOM/SAX2/Pull/Stream parser and there are differences in processing procedures'.\n
846
+ (('note:REXMLはDOM/SAX2/Pull/Streamパーサーがあり処理手順に差がある'))
847
+ * There was a difference in the parsing result, so it was fixed.\n
848
+ (('note:パース処理結果にも差異があったので修正した'))
849
+
850
+ = Unification of processing results for each REXML parser.(2)\n(('note:各パーサー間でのパース処理結果の統一(2)'))
851
+
852
+ * There were also differences in error handling items.\n
853
+ (('note:エラー処理項目にも差があった'))
854
+ * Some of the security measures were implemented only in the DOM parser.\n
855
+ (('note:セキュリティ対策の一部がDOMパーサーのみの実装だった'))
856
+ * ((<CVE-2024-41946: DoS vulnerability in REXML|URL:https://www.ruby-lang.org/en/news/2024/08/01/dos-rexml-cve-2024-41946/>))
857
+ * Fixed in REXML 3.3.3.\n
858
+ (('note:REXML 3.3.3 で修正済'))
859
+
860
+ = Summary: Performance(1)\n(('note:まとめ:性能(1)'))
861
+
862
+ * Use StringScanner instead of Regexp class to parse XML.\n
863
+ (('note:XMLのパースにRegexpクラスの代わりにStringScannerを使う'))
864
+ * Using string matching is faster.\n
865
+ (('note:文字列マッチを使うと、より高速'))
866
+ * Even when match strings are long, performance degradation is minimized.\n
867
+ (('note:マッチ文字列が長くなっても、性能劣化を最小限に抑えられる'))
868
+
869
+ = Summary: Performance(2)\n(('note:まとめ:性能(2)'))
870
+
871
+ * Avoiding generation of String object is faster.\n
872
+ (('note:文字列 Object の生成を避けると速い'))
873
+ * Use constants or memoization \nfor slow processes.\n
874
+ (('note:遅い処理には定数やメモ化を使う'))
875
+ * After eliminating bottlenecks, \nYJIT makes it even faster.\n
876
+ (('note:ボトルネックを解消後、YJITでさらに高速に'))
877
+
878
+ = Summary: Other improvements\n(('note:まとめ:他の改善点'))
879
+
880
+ * Enhanced invalid XML check.\n
881
+ (('note:無効XMLチェック強化'))
882
+ * Unification of processing results for each REXML parser (DOM/SAX2/Pull/Stream).\n
883
+ (('note:各パーサー間でのパース処理結果の統一'))
884
+
885
+
886
+ = Further work(1)\n(('note:今後の改善案(1)'))
887
+
888
+ * Further optimization with new StringScanner features.\n(('note:StringScannerの新機能を用いたさらなる最適化'))
889
+ * Use StringScanner#scan_until(String) and StringScanner#peek_byte more.\n
890
+ (('note:StringScanner#scan_until(String) や StringScanner#peek_byte をより使っていく'))
891
+
892
+ = Further work(2)\n(('note:今後の改善案(2)'))
893
+
894
+ # img
895
+ # src = images/rubykaigi-2019-p35-p78.png
896
+ # relative_height = 50
897
+
898
+ * (('tag:small'))Use StringScanner's new features in other gems.\n(('note:他のgem でもStringScannerの新機能を使う'))\n
899
+ * (('tag:small'))Enhanced StringScanner may also make CSV faster.\n(('note:StringScannerの強化により、CSVもより速くできるかもしれない'))
900
+
901
+
902
+ == Slide properties
903
+
904
+ : enable-title-on-image
905
+ false
data/theme.rb ADDED
@@ -0,0 +1,15 @@
1
+ @title_slide_background_image = 'images/assets/rubykaigi2025_slide_title.png'
2
+ # colors
3
+ foreground = "#ffffff"
4
+ black = "#000000"
5
+ match TitleSlide do |slides|
6
+ slides.prop_set("foreground", foreground)
7
+ end
8
+ include_theme("title-slide-background-image")
9
+
10
+ @slide_logo_image_uninstall = true
11
+ include_theme("clear-code")
12
+
13
+ match(Slide, Table) do |e|
14
+ e.prop_set "size", screen_size(2 * Pango::SCALE)
15
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rabbit-slide-naitoh-rubykaigi-2025
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - NAITOH Jun
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 2025-04-16 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: rabbit
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: 2.0.2
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: 2.0.2
26
+ description: https://rubykaigi.org/2025/
27
+ email:
28
+ - naitoh@gmail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - ".rabbit"
34
+ - Improvement of REXML and speed up using StringScanner.pdf
35
+ - README.md
36
+ - Rakefile
37
+ - config.yaml
38
+ - images/CVE-2024-35176.png
39
+ - images/RubyKaigi2024LT.png
40
+ - images/assets/rubykaigi2025_slide_title.png
41
+ - images/medpeer.png
42
+ - images/medpeer_mission.png
43
+ - images/rexml_x_1797256482272235856.png
44
+ - images/rubykaigi-2019-p35-p78.png
45
+ - images/svg_327.svg
46
+ - images/svg_340_jit_disable.svg
47
+ - images/svg_340_jit_enable.svg
48
+ - images/svg_341.svg
49
+ - images/svg_341_jit_disable.svg
50
+ - images/svg_341_jit_enable.svg
51
+ - pdf/rubykaigi-2025-rubykaigi-2025.pdf
52
+ - rubykaigi-2025.rab
53
+ - theme.rb
54
+ homepage: https://slide.rabbit-shocker.org/authors/naitoh/rubykaigi-2025/
55
+ licenses: []
56
+ metadata: {}
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubygems_version: 3.6.2
72
+ specification_version: 4
73
+ summary: Improvement of REXML and speed up using StringScanner
74
+ test_files: []