Eagerly require date - #695

Merged
tenderlove merged 1 commit into
ruby:masterfrom
tdeo:tdeo/fix_date_require
Nov 20, 2024
Merged

Eagerly require date#695
tenderlove merged 1 commit into
ruby:masterfrom
tdeo:tdeo/fix_date_require

Conversation

@tdeo

@tdeotdeo commented Nov 13, 2024

Copy link
Copy Markdown
Contributor

Fixes#694.

When picking up only the test changes (and not require 'date' explicitly anymore), such failures start to appear:

Error: test_spec_sequence_key_shortcut(Psych_Unit_Tests): NameError: uninitialized constant Psych_Unit_Tests::Date
/Users/thierry/workspace_personal/psych/test/psych/test_yaml.rb:299:in `test_spec_sequence_key_shortcut'
296: def test_spec_sequence_key_shortcut
297: # Shortcut sequence map
298: assert_parse_only(
=> 299: { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ),
300: 'bill-to' => 'Chris Dumars', 'product' =>
301: [ { 'item' => 'Super Hoop', 'quantity' => 1 },
302: { 'item' => 'Basketball', 'quantity' => 4 },
=======================================================================================================================
Finished in 0.390079 seconds.
-----------------------------------------------------------------------------------------------------------------------
609 tests, 1481 assertions, 0 failures, 21 errors, 0 pendings, 0 omissions, 0 notifications
96.5517% passed

The autoload :Date statement gets moved to a more appropriate file (the one actually loading the constant), and moved to the top-level so it requires ::Date and not try to require Psych::ClassLoader::Date

Performance-wise, reusing the benchmark from 06db36f#diff-6a459e056cadf37665f54005bd2dde09d9ba8e66c9807eb0dc67145f9b841771R7, it seems to further improve performance quite unsignificantly:

With those changes:

$ ruby /tmp/bench-yaml.rb
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
Warming up --------------------------------------
100 dates 464.000 i/100ms
Calculating -------------------------------------
100 dates 4.605k (± 2.3%) i/s (217.18 μs/i) - 23.200k in 5.041382s

On current master:

$ ruby /tmp/bench-yaml.rb
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
Warming up --------------------------------------
100 dates 439.000 i/100ms
Calculating -------------------------------------
100 dates 4.515k (± 1.9%) i/s (221.49 μs/i) - 22.828k in 5.058050s

@tdeotdeo mentioned this pull request Nov 18, 2024

@byrootbyroot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any test, so it's hard to confirm it's indeed the cause.

Comment threadlib/psych/class_loader.rb Outdated
require_relative 'omap'
require_relative 'set'

autoload :Date, "date"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should set consts on Object like that.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you rather change it to a require 'date' statement at the top-level?

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

I don't see any test, so it's hard to confirm it's indeed the cause.

I tried to write some tests but unfortunately Kernel.remove_const(:Date) is impossible because Date is a built-in. I meant in the PR description that if you try to run the test suite without the autoload statement, you'll get a failure.
You would also get failures if that statement is within Psych::ScalarScanner, in which case it's trying to autoload Psych::ScalarScanner::Date instead of ::Date

@byroot

Copy link
Copy Markdown
Member

You can probably use a subprocess.

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

You can probably use a subprocess.

I was able indeed to add a test case with this technique, thanks for the suggestion

@byroot

Copy link
Copy Markdown
Member

There's a test helper for that: assert_separatly.

But no worries, I'll take care of it. I need to run some errand but I'll fix this in a couple hours.

Also I think we should just stop lazy requiring libraries like that, it's stupid.

Comment threadtest/psych/test_string.rb Outdated
end

def test_string_matching_date
assert_separately(%w[-r ./lib/psych], <<~RUBY)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert_separately(%w[-r./lib/psych],<<~RUBY)
assert_separately(%w[-Ilib-rpsych],<<~RUBY)

I think you need to pass -I otherwise it risks loading the extension from stdlib.

Comment threadlib/psych/class_loader.rb Outdated
# frozen_string_literal: true
require_relative 'omap'
require_relative 'set'
require 'date'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably should declare date in the gemspec?

@byrootbyroot changed the title Autoload date properly when neededEagerly require dateNov 19, 2024
@byroot

Copy link
Copy Markdown
Member

I updated your PR.

cc @tenderlove what do you think?

Comment threadpsych.gemspec
s.add_dependency 'stringio'
end

s.add_dependency 'date'

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that make sense for the stdlib?

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

Thanks for wrapping it up

@tenderlovetenderlove left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to do this? The change seems fine, I'm just not following why.

@byroot

Copy link
Copy Markdown
Member

Right, sorry Aaron, I should have explained.

In YAMLTree#visit_String, there's this condition to figure if a string should be quoted:

elsif not String === @ss.tokenize(o)or/\A0[0-7]*[89]/.match?(o)style=Nodes::Scalar::SINGLE_QUOTED

So we end up in:

class_loader.date.strptime(string,'%F',Date::GREGORIAN)

Which further end up trying ClassLoader#resolve of "Date", and this uses path2class, so it's resolved as essentially ::Date, so the scoped autoload I introduced isn't triggered in this case.

Hence why the initial version of this PR was to move the autoload at the top level, but at that point I think we should just eager load.

@tenderlove

Copy link
Copy Markdown
Member

@byroot ah, gotcha. I somewhat worry this might have downstream effects (maybe on Bundler or RubyGems). But I like the change so I'll merge it.

@tenderlove
tenderlove merged commit a1ce01c into ruby:masterNov 20, 2024
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Breaking change in 5.2.0

3 participants

@tdeo@byroot@tenderlove
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Eagerly require date - #695

Merged
tenderlove merged 1 commit into
ruby:masterfrom
tdeo:tdeo/fix_date_require
Nov 20, 2024
Merged

Eagerly require date#695
tenderlove merged 1 commit into
ruby:masterfrom
tdeo:tdeo/fix_date_require

Conversation

@tdeo

@tdeotdeo commented Nov 13, 2024

Copy link
Copy Markdown
Contributor

Fixes#694.

When picking up only the test changes (and not require 'date' explicitly anymore), such failures start to appear:

Error: test_spec_sequence_key_shortcut(Psych_Unit_Tests): NameError: uninitialized constant Psych_Unit_Tests::Date
/Users/thierry/workspace_personal/psych/test/psych/test_yaml.rb:299:in `test_spec_sequence_key_shortcut'
296: def test_spec_sequence_key_shortcut
297: # Shortcut sequence map
298: assert_parse_only(
=> 299: { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ),
300: 'bill-to' => 'Chris Dumars', 'product' =>
301: [ { 'item' => 'Super Hoop', 'quantity' => 1 },
302: { 'item' => 'Basketball', 'quantity' => 4 },
=======================================================================================================================
Finished in 0.390079 seconds.
-----------------------------------------------------------------------------------------------------------------------
609 tests, 1481 assertions, 0 failures, 21 errors, 0 pendings, 0 omissions, 0 notifications
96.5517% passed

The autoload :Date statement gets moved to a more appropriate file (the one actually loading the constant), and moved to the top-level so it requires ::Date and not try to require Psych::ClassLoader::Date

Performance-wise, reusing the benchmark from 06db36f#diff-6a459e056cadf37665f54005bd2dde09d9ba8e66c9807eb0dc67145f9b841771R7, it seems to further improve performance quite unsignificantly:

With those changes:

$ ruby /tmp/bench-yaml.rb
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
Warming up --------------------------------------
100 dates 464.000 i/100ms
Calculating -------------------------------------
100 dates 4.605k (± 2.3%) i/s (217.18 μs/i) - 23.200k in 5.041382s

On current master:

$ ruby /tmp/bench-yaml.rb
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
Warming up --------------------------------------
100 dates 439.000 i/100ms
Calculating -------------------------------------
100 dates 4.515k (± 1.9%) i/s (221.49 μs/i) - 22.828k in 5.058050s

@tdeotdeo mentioned this pull request Nov 18, 2024

@byrootbyroot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any test, so it's hard to confirm it's indeed the cause.

Comment threadlib/psych/class_loader.rb Outdated
require_relative 'omap'
require_relative 'set'

autoload :Date, "date"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should set consts on Object like that.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you rather change it to a require 'date' statement at the top-level?

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

I don't see any test, so it's hard to confirm it's indeed the cause.

I tried to write some tests but unfortunately Kernel.remove_const(:Date) is impossible because Date is a built-in. I meant in the PR description that if you try to run the test suite without the autoload statement, you'll get a failure.
You would also get failures if that statement is within Psych::ScalarScanner, in which case it's trying to autoload Psych::ScalarScanner::Date instead of ::Date

@byroot

Copy link
Copy Markdown
Member

You can probably use a subprocess.

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

You can probably use a subprocess.

I was able indeed to add a test case with this technique, thanks for the suggestion

@byroot

Copy link
Copy Markdown
Member

There's a test helper for that: assert_separatly.

But no worries, I'll take care of it. I need to run some errand but I'll fix this in a couple hours.

Also I think we should just stop lazy requiring libraries like that, it's stupid.

Comment threadtest/psych/test_string.rb Outdated
end

def test_string_matching_date
assert_separately(%w[-r ./lib/psych], <<~RUBY)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert_separately(%w[-r./lib/psych],<<~RUBY)
assert_separately(%w[-Ilib-rpsych],<<~RUBY)

I think you need to pass -I otherwise it risks loading the extension from stdlib.

Comment threadlib/psych/class_loader.rb Outdated
# frozen_string_literal: true
require_relative 'omap'
require_relative 'set'
require 'date'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably should declare date in the gemspec?

@byrootbyroot changed the title Autoload date properly when neededEagerly require dateNov 19, 2024
@byroot

Copy link
Copy Markdown
Member

I updated your PR.

cc @tenderlove what do you think?

Comment threadpsych.gemspec
s.add_dependency 'stringio'
end

s.add_dependency 'date'

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that make sense for the stdlib?

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

Thanks for wrapping it up

@tenderlovetenderlove left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to do this? The change seems fine, I'm just not following why.

@byroot

Copy link
Copy Markdown
Member

Right, sorry Aaron, I should have explained.

In YAMLTree#visit_String, there's this condition to figure if a string should be quoted:

elsif not String === @ss.tokenize(o)or/\A0[0-7]*[89]/.match?(o)style=Nodes::Scalar::SINGLE_QUOTED

So we end up in:

class_loader.date.strptime(string,'%F',Date::GREGORIAN)

Which further end up trying ClassLoader#resolve of "Date", and this uses path2class, so it's resolved as essentially ::Date, so the scoped autoload I introduced isn't triggered in this case.

Hence why the initial version of this PR was to move the autoload at the top level, but at that point I think we should just eager load.

@tenderlove

Copy link
Copy Markdown
Member

@byroot ah, gotcha. I somewhat worry this might have downstream effects (maybe on Bundler or RubyGems). But I like the change so I'll merge it.

@tenderlove
tenderlove merged commit a1ce01c into ruby:masterNov 20, 2024
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Breaking change in 5.2.0

3 participants

@tdeo@byroot@tenderlove
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Eagerly require date - #695

Merged
tenderlove merged 1 commit into
ruby:masterfrom
tdeo:tdeo/fix_date_require
Nov 20, 2024
Merged

Eagerly require date#695
tenderlove merged 1 commit into
ruby:masterfrom
tdeo:tdeo/fix_date_require

Conversation

@tdeo

@tdeotdeo commented Nov 13, 2024

Copy link
Copy Markdown
Contributor

Fixes#694.

When picking up only the test changes (and not require 'date' explicitly anymore), such failures start to appear:

Error: test_spec_sequence_key_shortcut(Psych_Unit_Tests): NameError: uninitialized constant Psych_Unit_Tests::Date
/Users/thierry/workspace_personal/psych/test/psych/test_yaml.rb:299:in `test_spec_sequence_key_shortcut'
296: def test_spec_sequence_key_shortcut
297: # Shortcut sequence map
298: assert_parse_only(
=> 299: { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ),
300: 'bill-to' => 'Chris Dumars', 'product' =>
301: [ { 'item' => 'Super Hoop', 'quantity' => 1 },
302: { 'item' => 'Basketball', 'quantity' => 4 },
=======================================================================================================================
Finished in 0.390079 seconds.
-----------------------------------------------------------------------------------------------------------------------
609 tests, 1481 assertions, 0 failures, 21 errors, 0 pendings, 0 omissions, 0 notifications
96.5517% passed

The autoload :Date statement gets moved to a more appropriate file (the one actually loading the constant), and moved to the top-level so it requires ::Date and not try to require Psych::ClassLoader::Date

Performance-wise, reusing the benchmark from 06db36f#diff-6a459e056cadf37665f54005bd2dde09d9ba8e66c9807eb0dc67145f9b841771R7, it seems to further improve performance quite unsignificantly:

With those changes:

$ ruby /tmp/bench-yaml.rb
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
Warming up --------------------------------------
100 dates 464.000 i/100ms
Calculating -------------------------------------
100 dates 4.605k (± 2.3%) i/s (217.18 μs/i) - 23.200k in 5.041382s

On current master:

$ ruby /tmp/bench-yaml.rb
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
Warming up --------------------------------------
100 dates 439.000 i/100ms
Calculating -------------------------------------
100 dates 4.515k (± 1.9%) i/s (221.49 μs/i) - 22.828k in 5.058050s

@tdeotdeo mentioned this pull request Nov 18, 2024

@byrootbyroot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any test, so it's hard to confirm it's indeed the cause.

Comment threadlib/psych/class_loader.rb Outdated
require_relative 'omap'
require_relative 'set'

autoload :Date, "date"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should set consts on Object like that.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you rather change it to a require 'date' statement at the top-level?

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

I don't see any test, so it's hard to confirm it's indeed the cause.

I tried to write some tests but unfortunately Kernel.remove_const(:Date) is impossible because Date is a built-in. I meant in the PR description that if you try to run the test suite without the autoload statement, you'll get a failure.
You would also get failures if that statement is within Psych::ScalarScanner, in which case it's trying to autoload Psych::ScalarScanner::Date instead of ::Date

@byroot

Copy link
Copy Markdown
Member

You can probably use a subprocess.

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

You can probably use a subprocess.

I was able indeed to add a test case with this technique, thanks for the suggestion

@byroot

Copy link
Copy Markdown
Member

There's a test helper for that: assert_separatly.

But no worries, I'll take care of it. I need to run some errand but I'll fix this in a couple hours.

Also I think we should just stop lazy requiring libraries like that, it's stupid.

Comment threadtest/psych/test_string.rb Outdated
end

def test_string_matching_date
assert_separately(%w[-r ./lib/psych], <<~RUBY)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert_separately(%w[-r./lib/psych],<<~RUBY)
assert_separately(%w[-Ilib-rpsych],<<~RUBY)

I think you need to pass -I otherwise it risks loading the extension from stdlib.

Comment threadlib/psych/class_loader.rb Outdated
# frozen_string_literal: true
require_relative 'omap'
require_relative 'set'
require 'date'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably should declare date in the gemspec?

@byrootbyroot changed the title Autoload date properly when neededEagerly require dateNov 19, 2024
@byroot

Copy link
Copy Markdown
Member

I updated your PR.

cc @tenderlove what do you think?

Comment threadpsych.gemspec
s.add_dependency 'stringio'
end

s.add_dependency 'date'

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that make sense for the stdlib?

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

Thanks for wrapping it up

@tenderlovetenderlove left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to do this? The change seems fine, I'm just not following why.

@byroot

Copy link
Copy Markdown
Member

Right, sorry Aaron, I should have explained.

In YAMLTree#visit_String, there's this condition to figure if a string should be quoted:

elsif not String === @ss.tokenize(o)or/\A0[0-7]*[89]/.match?(o)style=Nodes::Scalar::SINGLE_QUOTED

So we end up in:

class_loader.date.strptime(string,'%F',Date::GREGORIAN)

Which further end up trying ClassLoader#resolve of "Date", and this uses path2class, so it's resolved as essentially ::Date, so the scoped autoload I introduced isn't triggered in this case.

Hence why the initial version of this PR was to move the autoload at the top level, but at that point I think we should just eager load.

@tenderlove

Copy link
Copy Markdown
Member

@byroot ah, gotcha. I somewhat worry this might have downstream effects (maybe on Bundler or RubyGems). But I like the change so I'll merge it.

@tenderlove
tenderlove merged commit a1ce01c into ruby:masterNov 20, 2024
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Breaking change in 5.2.0

3 participants

@tdeo@byroot@tenderlove
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Eagerly require date - #695

Merged
tenderlove merged 1 commit into
ruby:masterfrom
tdeo:tdeo/fix_date_require
Nov 20, 2024
Merged

Eagerly require date#695
tenderlove merged 1 commit into
ruby:masterfrom
tdeo:tdeo/fix_date_require

Conversation

@tdeo

@tdeotdeo commented Nov 13, 2024

Copy link
Copy Markdown
Contributor

Fixes#694.

When picking up only the test changes (and not require 'date' explicitly anymore), such failures start to appear:

Error: test_spec_sequence_key_shortcut(Psych_Unit_Tests): NameError: uninitialized constant Psych_Unit_Tests::Date
/Users/thierry/workspace_personal/psych/test/psych/test_yaml.rb:299:in `test_spec_sequence_key_shortcut'
296: def test_spec_sequence_key_shortcut
297: # Shortcut sequence map
298: assert_parse_only(
=> 299: { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ),
300: 'bill-to' => 'Chris Dumars', 'product' =>
301: [ { 'item' => 'Super Hoop', 'quantity' => 1 },
302: { 'item' => 'Basketball', 'quantity' => 4 },
=======================================================================================================================
Finished in 0.390079 seconds.
-----------------------------------------------------------------------------------------------------------------------
609 tests, 1481 assertions, 0 failures, 21 errors, 0 pendings, 0 omissions, 0 notifications
96.5517% passed

The autoload :Date statement gets moved to a more appropriate file (the one actually loading the constant), and moved to the top-level so it requires ::Date and not try to require Psych::ClassLoader::Date

Performance-wise, reusing the benchmark from 06db36f#diff-6a459e056cadf37665f54005bd2dde09d9ba8e66c9807eb0dc67145f9b841771R7, it seems to further improve performance quite unsignificantly:

With those changes:

$ ruby /tmp/bench-yaml.rb
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
Warming up --------------------------------------
100 dates 464.000 i/100ms
Calculating -------------------------------------
100 dates 4.605k (± 2.3%) i/s (217.18 μs/i) - 23.200k in 5.041382s

On current master:

$ ruby /tmp/bench-yaml.rb
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
Warming up --------------------------------------
100 dates 439.000 i/100ms
Calculating -------------------------------------
100 dates 4.515k (± 1.9%) i/s (221.49 μs/i) - 22.828k in 5.058050s

@tdeotdeo mentioned this pull request Nov 18, 2024

@byrootbyroot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any test, so it's hard to confirm it's indeed the cause.

Comment threadlib/psych/class_loader.rb Outdated
require_relative 'omap'
require_relative 'set'

autoload :Date, "date"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should set consts on Object like that.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you rather change it to a require 'date' statement at the top-level?

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

I don't see any test, so it's hard to confirm it's indeed the cause.

I tried to write some tests but unfortunately Kernel.remove_const(:Date) is impossible because Date is a built-in. I meant in the PR description that if you try to run the test suite without the autoload statement, you'll get a failure.
You would also get failures if that statement is within Psych::ScalarScanner, in which case it's trying to autoload Psych::ScalarScanner::Date instead of ::Date

@byroot

Copy link
Copy Markdown
Member

You can probably use a subprocess.

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

You can probably use a subprocess.

I was able indeed to add a test case with this technique, thanks for the suggestion

@byroot

Copy link
Copy Markdown
Member

There's a test helper for that: assert_separatly.

But no worries, I'll take care of it. I need to run some errand but I'll fix this in a couple hours.

Also I think we should just stop lazy requiring libraries like that, it's stupid.

Comment threadtest/psych/test_string.rb Outdated
end

def test_string_matching_date
assert_separately(%w[-r ./lib/psych], <<~RUBY)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert_separately(%w[-r./lib/psych],<<~RUBY)
assert_separately(%w[-Ilib-rpsych],<<~RUBY)

I think you need to pass -I otherwise it risks loading the extension from stdlib.

Comment threadlib/psych/class_loader.rb Outdated
# frozen_string_literal: true
require_relative 'omap'
require_relative 'set'
require 'date'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably should declare date in the gemspec?

@byrootbyroot changed the title Autoload date properly when neededEagerly require dateNov 19, 2024
@byroot

Copy link
Copy Markdown
Member

I updated your PR.

cc @tenderlove what do you think?

Comment threadpsych.gemspec
s.add_dependency 'stringio'
end

s.add_dependency 'date'

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that make sense for the stdlib?

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

Thanks for wrapping it up

@tenderlovetenderlove left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to do this? The change seems fine, I'm just not following why.

@byroot

Copy link
Copy Markdown
Member

Right, sorry Aaron, I should have explained.

In YAMLTree#visit_String, there's this condition to figure if a string should be quoted:

elsif not String === @ss.tokenize(o)or/\A0[0-7]*[89]/.match?(o)style=Nodes::Scalar::SINGLE_QUOTED

So we end up in:

class_loader.date.strptime(string,'%F',Date::GREGORIAN)

Which further end up trying ClassLoader#resolve of "Date", and this uses path2class, so it's resolved as essentially ::Date, so the scoped autoload I introduced isn't triggered in this case.

Hence why the initial version of this PR was to move the autoload at the top level, but at that point I think we should just eager load.

@tenderlove

Copy link
Copy Markdown
Member

@byroot ah, gotcha. I somewhat worry this might have downstream effects (maybe on Bundler or RubyGems). But I like the change so I'll merge it.

@tenderlove
tenderlove merged commit a1ce01c into ruby:masterNov 20, 2024
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Breaking change in 5.2.0

3 participants

@tdeo@byroot@tenderlove
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Eagerly require date - #695

Merged
tenderlove merged 1 commit into
ruby:masterfrom
tdeo:tdeo/fix_date_require
Nov 20, 2024
Merged

Eagerly require date#695
tenderlove merged 1 commit into
ruby:masterfrom
tdeo:tdeo/fix_date_require

Conversation

@tdeo

@tdeotdeo commented Nov 13, 2024

Copy link
Copy Markdown
Contributor

Fixes#694.

When picking up only the test changes (and not require 'date' explicitly anymore), such failures start to appear:

Error: test_spec_sequence_key_shortcut(Psych_Unit_Tests): NameError: uninitialized constant Psych_Unit_Tests::Date
/Users/thierry/workspace_personal/psych/test/psych/test_yaml.rb:299:in `test_spec_sequence_key_shortcut'
296: def test_spec_sequence_key_shortcut
297: # Shortcut sequence map
298: assert_parse_only(
=> 299: { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ),
300: 'bill-to' => 'Chris Dumars', 'product' =>
301: [ { 'item' => 'Super Hoop', 'quantity' => 1 },
302: { 'item' => 'Basketball', 'quantity' => 4 },
=======================================================================================================================
Finished in 0.390079 seconds.
-----------------------------------------------------------------------------------------------------------------------
609 tests, 1481 assertions, 0 failures, 21 errors, 0 pendings, 0 omissions, 0 notifications
96.5517% passed

The autoload :Date statement gets moved to a more appropriate file (the one actually loading the constant), and moved to the top-level so it requires ::Date and not try to require Psych::ClassLoader::Date

Performance-wise, reusing the benchmark from 06db36f#diff-6a459e056cadf37665f54005bd2dde09d9ba8e66c9807eb0dc67145f9b841771R7, it seems to further improve performance quite unsignificantly:

With those changes:

$ ruby /tmp/bench-yaml.rb
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
Warming up --------------------------------------
100 dates 464.000 i/100ms
Calculating -------------------------------------
100 dates 4.605k (± 2.3%) i/s (217.18 μs/i) - 23.200k in 5.041382s

On current master:

$ ruby /tmp/bench-yaml.rb
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
Warming up --------------------------------------
100 dates 439.000 i/100ms
Calculating -------------------------------------
100 dates 4.515k (± 1.9%) i/s (221.49 μs/i) - 22.828k in 5.058050s

@tdeotdeo mentioned this pull request Nov 18, 2024

@byrootbyroot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any test, so it's hard to confirm it's indeed the cause.

Comment threadlib/psych/class_loader.rb Outdated
require_relative 'omap'
require_relative 'set'

autoload :Date, "date"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should set consts on Object like that.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you rather change it to a require 'date' statement at the top-level?

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

I don't see any test, so it's hard to confirm it's indeed the cause.

I tried to write some tests but unfortunately Kernel.remove_const(:Date) is impossible because Date is a built-in. I meant in the PR description that if you try to run the test suite without the autoload statement, you'll get a failure.
You would also get failures if that statement is within Psych::ScalarScanner, in which case it's trying to autoload Psych::ScalarScanner::Date instead of ::Date

@byroot

Copy link
Copy Markdown
Member

You can probably use a subprocess.

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

You can probably use a subprocess.

I was able indeed to add a test case with this technique, thanks for the suggestion

@byroot

Copy link
Copy Markdown
Member

There's a test helper for that: assert_separatly.

But no worries, I'll take care of it. I need to run some errand but I'll fix this in a couple hours.

Also I think we should just stop lazy requiring libraries like that, it's stupid.

Comment threadtest/psych/test_string.rb Outdated
end

def test_string_matching_date
assert_separately(%w[-r ./lib/psych], <<~RUBY)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert_separately(%w[-r./lib/psych],<<~RUBY)
assert_separately(%w[-Ilib-rpsych],<<~RUBY)

I think you need to pass -I otherwise it risks loading the extension from stdlib.

Comment threadlib/psych/class_loader.rb Outdated
# frozen_string_literal: true
require_relative 'omap'
require_relative 'set'
require 'date'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably should declare date in the gemspec?

@byrootbyroot changed the title Autoload date properly when neededEagerly require dateNov 19, 2024
@byroot

Copy link
Copy Markdown
Member

I updated your PR.

cc @tenderlove what do you think?

Comment threadpsych.gemspec
s.add_dependency 'stringio'
end

s.add_dependency 'date'

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that make sense for the stdlib?

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

Thanks for wrapping it up

@tenderlovetenderlove left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to do this? The change seems fine, I'm just not following why.

@byroot

Copy link
Copy Markdown
Member

Right, sorry Aaron, I should have explained.

In YAMLTree#visit_String, there's this condition to figure if a string should be quoted:

elsif not String === @ss.tokenize(o)or/\A0[0-7]*[89]/.match?(o)style=Nodes::Scalar::SINGLE_QUOTED

So we end up in:

class_loader.date.strptime(string,'%F',Date::GREGORIAN)

Which further end up trying ClassLoader#resolve of "Date", and this uses path2class, so it's resolved as essentially ::Date, so the scoped autoload I introduced isn't triggered in this case.

Hence why the initial version of this PR was to move the autoload at the top level, but at that point I think we should just eager load.

@tenderlove

Copy link
Copy Markdown
Member

@byroot ah, gotcha. I somewhat worry this might have downstream effects (maybe on Bundler or RubyGems). But I like the change so I'll merge it.

@tenderlove
tenderlove merged commit a1ce01c into ruby:masterNov 20, 2024
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Breaking change in 5.2.0

3 participants

@tdeo@byroot@tenderlove
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Eagerly require date - #695

Merged
tenderlove merged 1 commit into
ruby:masterfrom
tdeo:tdeo/fix_date_require
Nov 20, 2024
Merged

Eagerly require date#695
tenderlove merged 1 commit into
ruby:masterfrom
tdeo:tdeo/fix_date_require

Conversation

@tdeo

@tdeotdeo commented Nov 13, 2024

Copy link
Copy Markdown
Contributor

Fixes#694.

When picking up only the test changes (and not require 'date' explicitly anymore), such failures start to appear:

Error: test_spec_sequence_key_shortcut(Psych_Unit_Tests): NameError: uninitialized constant Psych_Unit_Tests::Date
/Users/thierry/workspace_personal/psych/test/psych/test_yaml.rb:299:in `test_spec_sequence_key_shortcut'
296: def test_spec_sequence_key_shortcut
297: # Shortcut sequence map
298: assert_parse_only(
=> 299: { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ),
300: 'bill-to' => 'Chris Dumars', 'product' =>
301: [ { 'item' => 'Super Hoop', 'quantity' => 1 },
302: { 'item' => 'Basketball', 'quantity' => 4 },
=======================================================================================================================
Finished in 0.390079 seconds.
-----------------------------------------------------------------------------------------------------------------------
609 tests, 1481 assertions, 0 failures, 21 errors, 0 pendings, 0 omissions, 0 notifications
96.5517% passed

The autoload :Date statement gets moved to a more appropriate file (the one actually loading the constant), and moved to the top-level so it requires ::Date and not try to require Psych::ClassLoader::Date

Performance-wise, reusing the benchmark from 06db36f#diff-6a459e056cadf37665f54005bd2dde09d9ba8e66c9807eb0dc67145f9b841771R7, it seems to further improve performance quite unsignificantly:

With those changes:

$ ruby /tmp/bench-yaml.rb
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
Warming up --------------------------------------
100 dates 464.000 i/100ms
Calculating -------------------------------------
100 dates 4.605k (± 2.3%) i/s (217.18 μs/i) - 23.200k in 5.041382s

On current master:

$ ruby /tmp/bench-yaml.rb
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
Warming up --------------------------------------
100 dates 439.000 i/100ms
Calculating -------------------------------------
100 dates 4.515k (± 1.9%) i/s (221.49 μs/i) - 22.828k in 5.058050s

@tdeotdeo mentioned this pull request Nov 18, 2024

@byrootbyroot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any test, so it's hard to confirm it's indeed the cause.

Comment threadlib/psych/class_loader.rb Outdated
require_relative 'omap'
require_relative 'set'

autoload :Date, "date"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should set consts on Object like that.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you rather change it to a require 'date' statement at the top-level?

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

I don't see any test, so it's hard to confirm it's indeed the cause.

I tried to write some tests but unfortunately Kernel.remove_const(:Date) is impossible because Date is a built-in. I meant in the PR description that if you try to run the test suite without the autoload statement, you'll get a failure.
You would also get failures if that statement is within Psych::ScalarScanner, in which case it's trying to autoload Psych::ScalarScanner::Date instead of ::Date

@byroot

Copy link
Copy Markdown
Member

You can probably use a subprocess.

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

You can probably use a subprocess.

I was able indeed to add a test case with this technique, thanks for the suggestion

@byroot

Copy link
Copy Markdown
Member

There's a test helper for that: assert_separatly.

But no worries, I'll take care of it. I need to run some errand but I'll fix this in a couple hours.

Also I think we should just stop lazy requiring libraries like that, it's stupid.

Comment threadtest/psych/test_string.rb Outdated
end

def test_string_matching_date
assert_separately(%w[-r ./lib/psych], <<~RUBY)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert_separately(%w[-r./lib/psych],<<~RUBY)
assert_separately(%w[-Ilib-rpsych],<<~RUBY)

I think you need to pass -I otherwise it risks loading the extension from stdlib.

Comment threadlib/psych/class_loader.rb Outdated
# frozen_string_literal: true
require_relative 'omap'
require_relative 'set'
require 'date'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably should declare date in the gemspec?

@byrootbyroot changed the title Autoload date properly when neededEagerly require dateNov 19, 2024
@byroot

Copy link
Copy Markdown
Member

I updated your PR.

cc @tenderlove what do you think?

Comment threadpsych.gemspec
s.add_dependency 'stringio'
end

s.add_dependency 'date'

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that make sense for the stdlib?

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

Thanks for wrapping it up

@tenderlovetenderlove left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to do this? The change seems fine, I'm just not following why.

@byroot

Copy link
Copy Markdown
Member

Right, sorry Aaron, I should have explained.

In YAMLTree#visit_String, there's this condition to figure if a string should be quoted:

elsif not String === @ss.tokenize(o)or/\A0[0-7]*[89]/.match?(o)style=Nodes::Scalar::SINGLE_QUOTED

So we end up in:

class_loader.date.strptime(string,'%F',Date::GREGORIAN)

Which further end up trying ClassLoader#resolve of "Date", and this uses path2class, so it's resolved as essentially ::Date, so the scoped autoload I introduced isn't triggered in this case.

Hence why the initial version of this PR was to move the autoload at the top level, but at that point I think we should just eager load.

@tenderlove

Copy link
Copy Markdown
Member

@byroot ah, gotcha. I somewhat worry this might have downstream effects (maybe on Bundler or RubyGems). But I like the change so I'll merge it.

@tenderlove
tenderlove merged commit a1ce01c into ruby:masterNov 20, 2024
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Breaking change in 5.2.0

3 participants

@tdeo@byroot@tenderlove
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Eagerly require date - #695

Merged
tenderlove merged 1 commit into
ruby:masterfrom
tdeo:tdeo/fix_date_require
Nov 20, 2024
Merged

Eagerly require date#695
tenderlove merged 1 commit into
ruby:masterfrom
tdeo:tdeo/fix_date_require

Conversation

@tdeo

@tdeotdeo commented Nov 13, 2024

Copy link
Copy Markdown
Contributor

Fixes#694.

When picking up only the test changes (and not require 'date' explicitly anymore), such failures start to appear:

Error: test_spec_sequence_key_shortcut(Psych_Unit_Tests): NameError: uninitialized constant Psych_Unit_Tests::Date
/Users/thierry/workspace_personal/psych/test/psych/test_yaml.rb:299:in `test_spec_sequence_key_shortcut'
296: def test_spec_sequence_key_shortcut
297: # Shortcut sequence map
298: assert_parse_only(
=> 299: { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ),
300: 'bill-to' => 'Chris Dumars', 'product' =>
301: [ { 'item' => 'Super Hoop', 'quantity' => 1 },
302: { 'item' => 'Basketball', 'quantity' => 4 },
=======================================================================================================================
Finished in 0.390079 seconds.
-----------------------------------------------------------------------------------------------------------------------
609 tests, 1481 assertions, 0 failures, 21 errors, 0 pendings, 0 omissions, 0 notifications
96.5517% passed

The autoload :Date statement gets moved to a more appropriate file (the one actually loading the constant), and moved to the top-level so it requires ::Date and not try to require Psych::ClassLoader::Date

Performance-wise, reusing the benchmark from 06db36f#diff-6a459e056cadf37665f54005bd2dde09d9ba8e66c9807eb0dc67145f9b841771R7, it seems to further improve performance quite unsignificantly:

With those changes:

$ ruby /tmp/bench-yaml.rb
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
Warming up --------------------------------------
100 dates 464.000 i/100ms
Calculating -------------------------------------
100 dates 4.605k (± 2.3%) i/s (217.18 μs/i) - 23.200k in 5.041382s

On current master:

$ ruby /tmp/bench-yaml.rb
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
Warming up --------------------------------------
100 dates 439.000 i/100ms
Calculating -------------------------------------
100 dates 4.515k (± 1.9%) i/s (221.49 μs/i) - 22.828k in 5.058050s

@tdeotdeo mentioned this pull request Nov 18, 2024

@byrootbyroot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any test, so it's hard to confirm it's indeed the cause.

Comment threadlib/psych/class_loader.rb Outdated
require_relative 'omap'
require_relative 'set'

autoload :Date, "date"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should set consts on Object like that.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you rather change it to a require 'date' statement at the top-level?

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

I don't see any test, so it's hard to confirm it's indeed the cause.

I tried to write some tests but unfortunately Kernel.remove_const(:Date) is impossible because Date is a built-in. I meant in the PR description that if you try to run the test suite without the autoload statement, you'll get a failure.
You would also get failures if that statement is within Psych::ScalarScanner, in which case it's trying to autoload Psych::ScalarScanner::Date instead of ::Date

@byroot

Copy link
Copy Markdown
Member

You can probably use a subprocess.

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

You can probably use a subprocess.

I was able indeed to add a test case with this technique, thanks for the suggestion

@byroot

Copy link
Copy Markdown
Member

There's a test helper for that: assert_separatly.

But no worries, I'll take care of it. I need to run some errand but I'll fix this in a couple hours.

Also I think we should just stop lazy requiring libraries like that, it's stupid.

Comment threadtest/psych/test_string.rb Outdated
end

def test_string_matching_date
assert_separately(%w[-r ./lib/psych], <<~RUBY)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert_separately(%w[-r./lib/psych],<<~RUBY)
assert_separately(%w[-Ilib-rpsych],<<~RUBY)

I think you need to pass -I otherwise it risks loading the extension from stdlib.

Comment threadlib/psych/class_loader.rb Outdated
# frozen_string_literal: true
require_relative 'omap'
require_relative 'set'
require 'date'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably should declare date in the gemspec?

@byrootbyroot changed the title Autoload date properly when neededEagerly require dateNov 19, 2024
@byroot

Copy link
Copy Markdown
Member

I updated your PR.

cc @tenderlove what do you think?

Comment threadpsych.gemspec
s.add_dependency 'stringio'
end

s.add_dependency 'date'

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that make sense for the stdlib?

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

Thanks for wrapping it up

@tenderlovetenderlove left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to do this? The change seems fine, I'm just not following why.

@byroot

Copy link
Copy Markdown
Member

Right, sorry Aaron, I should have explained.

In YAMLTree#visit_String, there's this condition to figure if a string should be quoted:

elsif not String === @ss.tokenize(o)or/\A0[0-7]*[89]/.match?(o)style=Nodes::Scalar::SINGLE_QUOTED

So we end up in:

class_loader.date.strptime(string,'%F',Date::GREGORIAN)

Which further end up trying ClassLoader#resolve of "Date", and this uses path2class, so it's resolved as essentially ::Date, so the scoped autoload I introduced isn't triggered in this case.

Hence why the initial version of this PR was to move the autoload at the top level, but at that point I think we should just eager load.

@tenderlove

Copy link
Copy Markdown
Member

@byroot ah, gotcha. I somewhat worry this might have downstream effects (maybe on Bundler or RubyGems). But I like the change so I'll merge it.

@tenderlove
tenderlove merged commit a1ce01c into ruby:masterNov 20, 2024
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Breaking change in 5.2.0

3 participants

@tdeo@byroot@tenderlove
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Eagerly require date - #695

Merged
tenderlove merged 1 commit into
ruby:masterfrom
tdeo:tdeo/fix_date_require
Nov 20, 2024
Merged

Eagerly require date#695
tenderlove merged 1 commit into
ruby:masterfrom
tdeo:tdeo/fix_date_require

Conversation

@tdeo

@tdeotdeo commented Nov 13, 2024

Copy link
Copy Markdown
Contributor

Fixes#694.

When picking up only the test changes (and not require 'date' explicitly anymore), such failures start to appear:

Error: test_spec_sequence_key_shortcut(Psych_Unit_Tests): NameError: uninitialized constant Psych_Unit_Tests::Date
/Users/thierry/workspace_personal/psych/test/psych/test_yaml.rb:299:in `test_spec_sequence_key_shortcut'
296: def test_spec_sequence_key_shortcut
297: # Shortcut sequence map
298: assert_parse_only(
=> 299: { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ),
300: 'bill-to' => 'Chris Dumars', 'product' =>
301: [ { 'item' => 'Super Hoop', 'quantity' => 1 },
302: { 'item' => 'Basketball', 'quantity' => 4 },
=======================================================================================================================
Finished in 0.390079 seconds.
-----------------------------------------------------------------------------------------------------------------------
609 tests, 1481 assertions, 0 failures, 21 errors, 0 pendings, 0 omissions, 0 notifications
96.5517% passed

The autoload :Date statement gets moved to a more appropriate file (the one actually loading the constant), and moved to the top-level so it requires ::Date and not try to require Psych::ClassLoader::Date

Performance-wise, reusing the benchmark from 06db36f#diff-6a459e056cadf37665f54005bd2dde09d9ba8e66c9807eb0dc67145f9b841771R7, it seems to further improve performance quite unsignificantly:

With those changes:

$ ruby /tmp/bench-yaml.rb
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
Warming up --------------------------------------
100 dates 464.000 i/100ms
Calculating -------------------------------------
100 dates 4.605k (± 2.3%) i/s (217.18 μs/i) - 23.200k in 5.041382s

On current master:

$ ruby /tmp/bench-yaml.rb
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
Warming up --------------------------------------
100 dates 439.000 i/100ms
Calculating -------------------------------------
100 dates 4.515k (± 1.9%) i/s (221.49 μs/i) - 22.828k in 5.058050s

@tdeotdeo mentioned this pull request Nov 18, 2024

@byrootbyroot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any test, so it's hard to confirm it's indeed the cause.

Comment threadlib/psych/class_loader.rb Outdated
require_relative 'omap'
require_relative 'set'

autoload :Date, "date"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should set consts on Object like that.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you rather change it to a require 'date' statement at the top-level?

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

I don't see any test, so it's hard to confirm it's indeed the cause.

I tried to write some tests but unfortunately Kernel.remove_const(:Date) is impossible because Date is a built-in. I meant in the PR description that if you try to run the test suite without the autoload statement, you'll get a failure.
You would also get failures if that statement is within Psych::ScalarScanner, in which case it's trying to autoload Psych::ScalarScanner::Date instead of ::Date

@byroot

Copy link
Copy Markdown
Member

You can probably use a subprocess.

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

You can probably use a subprocess.

I was able indeed to add a test case with this technique, thanks for the suggestion

@byroot

Copy link
Copy Markdown
Member

There's a test helper for that: assert_separatly.

But no worries, I'll take care of it. I need to run some errand but I'll fix this in a couple hours.

Also I think we should just stop lazy requiring libraries like that, it's stupid.

Comment threadtest/psych/test_string.rb Outdated
end

def test_string_matching_date
assert_separately(%w[-r ./lib/psych], <<~RUBY)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert_separately(%w[-r./lib/psych],<<~RUBY)
assert_separately(%w[-Ilib-rpsych],<<~RUBY)

I think you need to pass -I otherwise it risks loading the extension from stdlib.

Comment threadlib/psych/class_loader.rb Outdated
# frozen_string_literal: true
require_relative 'omap'
require_relative 'set'
require 'date'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably should declare date in the gemspec?

@byrootbyroot changed the title Autoload date properly when neededEagerly require dateNov 19, 2024
@byroot

Copy link
Copy Markdown
Member

I updated your PR.

cc @tenderlove what do you think?

Comment threadpsych.gemspec
s.add_dependency 'stringio'
end

s.add_dependency 'date'

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that make sense for the stdlib?

@tdeo

tdeo commented Nov 19, 2024

Copy link
Copy Markdown
ContributorAuthor

Thanks for wrapping it up

@tenderlovetenderlove left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to do this? The change seems fine, I'm just not following why.

@byroot

Copy link
Copy Markdown
Member

Right, sorry Aaron, I should have explained.

In YAMLTree#visit_String, there's this condition to figure if a string should be quoted:

elsif not String === @ss.tokenize(o)or/\A0[0-7]*[89]/.match?(o)style=Nodes::Scalar::SINGLE_QUOTED

So we end up in:

class_loader.date.strptime(string,'%F',Date::GREGORIAN)

Which further end up trying ClassLoader#resolve of "Date", and this uses path2class, so it's resolved as essentially ::Date, so the scoped autoload I introduced isn't triggered in this case.

Hence why the initial version of this PR was to move the autoload at the top level, but at that point I think we should just eager load.

@tenderlove

Copy link
Copy Markdown
Member

@byroot ah, gotcha. I somewhat worry this might have downstream effects (maybe on Bundler or RubyGems). But I like the change so I'll merge it.

@tenderlove
tenderlove merged commit a1ce01c into ruby:masterNov 20, 2024
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Breaking change in 5.2.0

3 participants

@tdeo@byroot@tenderlove