Skip to content

Commit fe8866f

Browse files
committed
Avoid calling respond_to? on every read
`Object#respond_to?` isn't very fast because it can't benefit from inline cache, it's best avoided when decent alternatives are possible.
1 parent f3ee6cb commit fe8866f

File tree

1 file changed

+29
-11
lines changed

1 file changed

+29
-11
lines changed

lib/maxmind/db/file_reader.rb

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,36 @@ module MaxMind
66
class DB
77
# @!visibility private
88
class FileReader
9+
if ::File.method_defined?(:pread)
10+
PReadFile = ::File
11+
else
12+
# For Windows support
13+
class PReadFile
14+
def initialize(filename, mode)
15+
@mutex = Mutex.new
16+
@file = File.new(filename, mode)
17+
end
18+
19+
def size
20+
@file.size
21+
end
22+
23+
def close
24+
@file.close
25+
end
26+
27+
def pread(size, offset)
28+
@mutex.synchronize do
29+
@file.seek(offset, IO::SEEK_SET)
30+
@file.read(size)
31+
end
32+
end
33+
end
34+
end
35+
936
def initialize(filename)
10-
@fh = File.new(filename, 'rb')
37+
@fh = PReadFile.new(filename, 'rb')
1138
@size = @fh.size
12-
@mutex = Mutex.new
1339
end
1440

1541
attr_reader :size
@@ -21,15 +47,7 @@ def close
2147
def read(offset, size)
2248
return ''.b if size == 0
2349

24-
# When we support only Ruby 2.5+, remove this and require pread.
25-
if @fh.respond_to?(:pread)
26-
buf = @fh.pread(size, offset)
27-
else
28-
@mutex.synchronize do
29-
@fh.seek(offset, IO::SEEK_SET)
30-
buf = @fh.read(size)
31-
end
32-
end
50+
buf = @fh.pread(size, offset)
3351

3452
raise InvalidDatabaseError, 'The MaxMind DB file contains bad data' if buf.nil? || buf.length != size
3553

0 commit comments

Comments
 (0)