Skip to content

Fix frozen string literal warning in magic detection #123

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

FrancescoK
Copy link

With latest Ruby 3.4.x, using marcel emits the following warning:
lib/ruby/gems/3.4.0/gems/marcel-1.0.4/lib/marcel/magic.rb:120: warning: literal string will be frozen in the future

This occurs because the code was creating an empty string literal used as mutable buffer for I/O operations.

This pull request replaces "".dup.encode(Encoding::BINARY) with (+"").encode(Encoding::BINARY) in the buffer creation. Using the unary plus operator to explicitly create a mutable string benchmarked slightly faster than .dup.encode() on my local machine.

Benchmark Results

String Creation Performance (1M iterations)

Method Time (seconds) Relative Performance
"".dup.encode() 0.135 baseline
(+"").encode() 0.136 similar
String.new(encoding:) 0.173 28% slower

Memory Allocation (100K iterations)

Method Objects Allocated Relative Memory
"".dup.encode() 200,005 baseline
(+"").encode() 200,002 same
String.new(encoding:) 300,003 50% more

Real-world Usage (10K magic detection operations)

Method Time (seconds) Performance Improvement
"".dup.encode() 0.0099 baseline
(+"").encode() 0.0072 27% faster
String.new(encoding:) 0.0079 20% faster

@FrancescoK
Copy link
Author

Tests pass on my machine and GH Actions, the Buildkite build erroring out seems unrelated and not fixable from this PR.

@FrancescoK FrancescoK marked this pull request as draft May 25, 2025 17:03
@@ -119,7 +119,7 @@ def self.magic_match(io, method)

io.binmode if io.respond_to?(:binmode)
io.set_encoding(Encoding::BINARY) if io.respond_to?(:set_encoding)
buffer = "".encode(Encoding::BINARY)
buffer = (+"").encode(Encoding::BINARY)

Choose a reason for hiding this comment

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

Perhaps this is better for readability:

Suggested change
buffer = (+"").encode(Encoding::BINARY)
buffer = String.new.encode(Encoding::BINARY)

Choose a reason for hiding this comment

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

I see from the bench-marking that you did already consider that option. Also this is more succinct hence better.

Suggested change
buffer = (+"").encode(Encoding::BINARY)
buffer = String.new(encoding: Encoding::BINARY)

Choose a reason for hiding this comment

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

Please disregard!

Choose a reason for hiding this comment

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

I think what you want here is to declare a mutable string with binary encoding. That's

String.new(encoding: Encoding::BINARY)

@FrancescoK
Copy link
Author

I’m not sure whether this actually fixes the issue I was trying to fix — tried to bundle install marcel from my repo and it still appeared — but this should still be a slight improvement

@FrancescoK FrancescoK marked this pull request as ready for review June 1, 2025 15:36
simonbaird added a commit to tiddlyhost/tiddlyhost-com that referenced this pull request Jun 2, 2025
As mentioned in the comments,
rails/marcel#123 PR should make this go
away.

This is just for cosmetic reasons. The warning makes the test suite
output look untidy.
@@ -119,7 +119,7 @@ def self.magic_match(io, method)

io.binmode if io.respond_to?(:binmode)
io.set_encoding(Encoding::BINARY) if io.respond_to?(:set_encoding)
buffer = "".encode(Encoding::BINARY)
buffer = (+"").encode(Encoding::BINARY)

Choose a reason for hiding this comment

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

Suggested change
buffer = (+"").encode(Encoding::BINARY)
buffer = String.new(encoding: Encoding::BINARY)

Sign up for free to 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.

3 participants