faster_path 0.2.6 → 0.3.1
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 +4 -4
- data/Cargo.toml +3 -0
- data/README.md +10 -14
- data/Rakefile +13 -32
- data/ext/Rakefile +7 -0
- data/faster_path.gemspec +4 -3
- data/lib/faster_path.rb +8 -3
- data/lib/faster_path.so +0 -0
- data/lib/faster_path/optional/monkeypatches.rb +4 -4
- data/lib/faster_path/version.rb +1 -1
- data/src/extname.rs +56 -6
- data/src/path_parsing.rs +0 -6
- metadata +23 -9
- data/ext/faster_path/extconf.rb +0 -19
- data/lib/faster_path/platform.rb +0 -60
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84e796cda8b8704b7a6f5e2a2e69acc012f611b66f89642f34149f88c645ae34
|
4
|
+
data.tar.gz: 8b20ae9b2bcaebaf44dbc56500ad539e5082169d729a24685c0c9a446ee4dd6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '091d419f3c849b46f493a3ae47fcf59d064c83ffec898856032ffa47d84e68ace558e882437f95a662bd84b77cdbe0182f7b62c5cd1316fd250a54d49afe3046'
|
7
|
+
data.tar.gz: ecbdcad442c08c9eee827f30672f585f34450e0b4a72905936fe49a7eb251a7e8c461a0a5fcaa10d19a1e36ef304ada0b8b8f1bff1d0cab31017bad35ddd3743
|
data/Cargo.toml
CHANGED
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
[](https://travis-ci.org/danielpclark/faster_path)
|
4
4
|
[](https://ci.appveyor.com/project/danielpclark/faster-path/branch/master)
|
5
5
|
[](https://github.com/danielpclark/faster_path/tags)
|
6
|
-
[](https://github.com/danielpclark/faster_path/pulse)
|
7
7
|
[](https://github.com/danielpclark/faster_path/releases)
|
8
8
|
[](https://coveralls.io/github/danielpclark/faster_path)
|
9
9
|
[](http://inch-ci.org/github/danielpclark/faster_path)
|
@@ -55,7 +55,7 @@ Running `stackprof tmp/2016-06-09T00:42:10-04:00-stackprof-cpu-myapp.dump`. Exec
|
|
55
55
|
108 (1.5%) 14 (0.2%) ActionView::Helpers::AssetUrlHelper#asset_path
|
56
56
|
```
|
57
57
|
|
58
|
-
Here are some
|
58
|
+
Here are some additional stats. From Rails loading to my home page, these methods are called _(not directly, Rails & gems call them)_ this many times. And the home page has minimal content.
|
59
59
|
```ruby
|
60
60
|
Pathname#to_s called 29172 times.
|
61
61
|
Pathname#<=> called 24963 times.
|
@@ -97,8 +97,10 @@ I've said this about Sprockets but this required two other gems to be updated as
|
|
97
97
|
## Status
|
98
98
|
|
99
99
|
* Rust compilation is working
|
100
|
-
* Methods are
|
101
|
-
*
|
100
|
+
* Methods are stable
|
101
|
+
* Thoroughly tested
|
102
|
+
* Testers and developers are most welcome
|
103
|
+
* Windows & encoding support is underway!
|
102
104
|
|
103
105
|
## Installation
|
104
106
|
|
@@ -113,7 +115,7 @@ curl -sSf https://static.rust-lang.org/rustup.sh | sh
|
|
113
115
|
Add this line to your application's Gemfile:
|
114
116
|
|
115
117
|
```ruby
|
116
|
-
gem 'faster_path', '~> 0.
|
118
|
+
gem 'faster_path', '~> 0.3.1'
|
117
119
|
```
|
118
120
|
|
119
121
|
And then execute:
|
@@ -147,6 +149,7 @@ Current methods implemented:
|
|
147
149
|
| `FasterPath.del_trailing_separator` | `Pathname#del_trailing_separator` | 80.6% |
|
148
150
|
| `FasterPath.directory?` | `Pathname#directory?` | 11.3% |
|
149
151
|
| `FasterPath.entries` | `Pathname#entries` | 8.4% |
|
152
|
+
| `FasterPath.extname` | `File.extname` | 41.2% |
|
150
153
|
| `FasterPath.has_trailing_separator?` | `Pathname#has_trailing_separator` | 67.6% |
|
151
154
|
| `FasterPath.plus` | `Pathname#join` | 66.4% |
|
152
155
|
| `FasterPath.plus` | `Pathname#plus` | 81.4% |
|
@@ -181,10 +184,9 @@ These will **not** be included by default in monkey-patches. Be cautious when u
|
|
181
184
|
|---|---|
|
182
185
|
| `FasterPath.dirname` | `File.dirname` |
|
183
186
|
| `FasterPath.basename` | `File.basename` |
|
184
|
-
| `FasterPath.extname` | `File.extname` |
|
185
187
|
|
186
188
|
It's been my observation (and some others) that the Rust implementation of the C code for `File` has similar results but
|
187
|
-
performance seems to vary based on CPU cache on possibly 64bit/32bit system
|
189
|
+
performance seems to vary based on CPU cache on possibly 64bit/32bit system environments. When these methods were initially written, and somewhat simplistic, they were faster than the C implementations on `File`. After the implementations have been perfected to match the behavior in Ruby they don't perform as well and are therefore not included by default when the monkey patch method `FasterPath.sledgehammer_everything!` is executed.
|
188
190
|
|
189
191
|
## Getting Started with Development
|
190
192
|
|
@@ -205,13 +207,7 @@ Learn and share performance tips on the [wiki](https://github.com/danielpclark/f
|
|
205
207
|
|
206
208
|
### Building and running tests
|
207
209
|
|
208
|
-
First, bundle the gem's development dependencies by running `bundle`.
|
209
|
-
|
210
|
-
Then, build the rust code:
|
211
|
-
|
212
|
-
```sh
|
213
|
-
rake build_src
|
214
|
-
```
|
210
|
+
First, bundle the gem's development dependencies by running `bundle`. Rust compilation is included in the current rake commands.
|
215
211
|
|
216
212
|
FasterPath is tested with [The Ruby Spec Suite](https://github.com/ruby/spec) to ensure it is compatible with the
|
217
213
|
native implementation, and also has its own test suite testing its monkey-patching and refinements functionality.
|
data/Rakefile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require '
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'thermite/tasks'
|
4
4
|
|
5
5
|
desc 'System Details'
|
6
6
|
task :sysinfo do
|
@@ -24,6 +24,8 @@ task :sysinfo do
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
thermite = Thermite::Tasks.new
|
28
|
+
|
27
29
|
desc "Generate Contriburs.md Manifest"
|
28
30
|
task :contrib do
|
29
31
|
puts "Generating Contriburs.md Manifest"
|
@@ -61,36 +63,16 @@ task :libruby_debug do
|
|
61
63
|
puts "libruby.so copied."
|
62
64
|
end
|
63
65
|
|
64
|
-
desc
|
65
|
-
task
|
66
|
-
|
67
|
-
sh "cargo build --release"
|
68
|
-
end
|
69
|
-
|
70
|
-
desc "Clean up Rust build"
|
71
|
-
task :clean_src do
|
72
|
-
puts "Cleaning up build..."
|
73
|
-
# Remove all but library file
|
74
|
-
FileUtils.
|
75
|
-
rm_rf(
|
76
|
-
Dir.
|
77
|
-
glob('target/release/*').
|
78
|
-
keep_if do |f|
|
79
|
-
!f[/\.(?:so|dll|dylib|deps)\z/]
|
80
|
-
end
|
81
|
-
)
|
66
|
+
desc 'Build + clean up Rust extension'
|
67
|
+
task build_lib: 'thermite:build' do
|
68
|
+
thermite.run_cargo 'clean'
|
82
69
|
end
|
83
70
|
|
84
|
-
desc
|
85
|
-
task build_lib: [:build_src, :clean_src] do
|
86
|
-
puts "Completed build!"
|
87
|
-
end
|
88
|
-
|
89
|
-
desc "Code Quality Check"
|
71
|
+
desc 'Code Quality Check'
|
90
72
|
task :lint do
|
91
73
|
puts
|
92
|
-
puts
|
93
|
-
sh
|
74
|
+
puts 'Quality check starting...'
|
75
|
+
sh 'rubocop'
|
94
76
|
puts
|
95
77
|
end
|
96
78
|
|
@@ -100,9 +82,8 @@ task cargo: :libruby_debug do
|
|
100
82
|
end
|
101
83
|
|
102
84
|
Rake::TestTask.new(minitest: :build_lib) do |t|
|
103
|
-
t.libs
|
104
|
-
t.
|
105
|
-
t.test_files = FileList['test/**/*_test.rb']
|
85
|
+
t.libs = %w[lib test]
|
86
|
+
t.pattern = 'test/**/*_test.rb'
|
106
87
|
end
|
107
88
|
|
108
89
|
task :init_mspec do |_t|
|
data/ext/Rakefile
ADDED
data/faster_path.gemspec
CHANGED
@@ -16,21 +16,22 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.files = [
|
17
17
|
"Cargo.lock", "Cargo.toml", "Gemfile",
|
18
18
|
"MIT-LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup",
|
19
|
-
"ext/
|
19
|
+
"ext/Rakefile", "faster_path.gemspec"
|
20
20
|
]
|
21
21
|
spec.files += Dir['lib/**/*']
|
22
22
|
spec.files += Dir['src/**/*']
|
23
23
|
|
24
|
-
spec.extensions
|
24
|
+
spec.extensions = ["ext/Rakefile"]
|
25
25
|
spec.require_paths = ["lib"]
|
26
26
|
|
27
27
|
spec.add_dependency "bundler", "~> 1.12"
|
28
28
|
spec.add_dependency "rake", "~> 12.0"
|
29
|
+
spec.add_dependency "thermite", "~> 0.13.0"
|
29
30
|
spec.add_development_dependency "read_source", "~> 0.2.6"
|
30
31
|
spec.add_development_dependency "minitest", "~> 5.10"
|
31
32
|
spec.add_development_dependency "minitest-reporters", "~> 1.1"
|
32
33
|
spec.add_development_dependency "color_pound_spec_reporter", "~> 0.0.9"
|
33
|
-
spec.add_development_dependency "rubocop", "
|
34
|
+
spec.add_development_dependency "rubocop", "0.53"
|
34
35
|
spec.add_development_dependency "stop_watch", "~> 1.0"
|
35
36
|
if !ENV['CI'] && ENV['GRAPH']
|
36
37
|
spec.add_development_dependency "gruff", "~> 0.7.0"
|
data/lib/faster_path.rb
CHANGED
@@ -1,11 +1,16 @@
|
|
1
|
-
require
|
1
|
+
require 'faster_path/version'
|
2
2
|
require 'pathname'
|
3
|
-
require '
|
3
|
+
require 'thermite/config'
|
4
4
|
require 'fiddle'
|
5
5
|
require 'fiddle/import'
|
6
6
|
|
7
7
|
module FasterPath
|
8
|
-
FFI_LIBRARY =
|
8
|
+
FFI_LIBRARY = begin
|
9
|
+
toplevel_dir = File.dirname(__dir__)
|
10
|
+
config = Thermite::Config.new(cargo_project_path: toplevel_dir,
|
11
|
+
ruby_project_path: toplevel_dir)
|
12
|
+
config.ruby_extension_path
|
13
|
+
end
|
9
14
|
|
10
15
|
Fiddle::Function.
|
11
16
|
new(Fiddle.dlopen(FFI_LIBRARY)['Init_faster_pathname'], [], Fiddle::TYPE_VOIDP).
|
data/lib/faster_path.so
ADDED
Binary file
|
@@ -10,7 +10,7 @@ module FasterPath
|
|
10
10
|
pth = pth.to_path if pth.respond_to? :to_path
|
11
11
|
raise TypeError unless pth.is_a?(String) && ext.is_a?(String)
|
12
12
|
FasterPath.basename(pth, ext)
|
13
|
-
end
|
13
|
+
end if !!ENV['WITH_REGRESSION']
|
14
14
|
|
15
15
|
def self.extname(pth)
|
16
16
|
pth = pth.to_path if pth.respond_to? :to_path
|
@@ -22,7 +22,7 @@ module FasterPath
|
|
22
22
|
pth = pth.to_path if pth.respond_to? :to_path
|
23
23
|
raise TypeError unless pth.is_a? String
|
24
24
|
FasterPath.dirname(pth)
|
25
|
-
end
|
25
|
+
end if !!ENV['WITH_REGRESSION']
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -96,8 +96,8 @@ module FasterPath
|
|
96
96
|
end
|
97
97
|
private_constant :MonkeyPatches
|
98
98
|
|
99
|
-
def self.sledgehammer_everything!(
|
100
|
-
MonkeyPatches._ruby_core_file!
|
99
|
+
def self.sledgehammer_everything!()
|
100
|
+
MonkeyPatches._ruby_core_file!
|
101
101
|
MonkeyPatches._ruby_library_pathname!
|
102
102
|
"CAUTION: Monkey patching effects everything! Be very sure you want this!"
|
103
103
|
end
|
data/lib/faster_path/version.rb
CHANGED
data/src/extname.rs
CHANGED
@@ -1,13 +1,63 @@
|
|
1
|
-
use path_parsing::
|
1
|
+
use path_parsing::SEP;
|
2
|
+
use std::str;
|
3
|
+
|
4
|
+
struct ExtnameCoords {
|
5
|
+
word: bool,
|
6
|
+
pred: bool,
|
7
|
+
dot: bool,
|
8
|
+
start: usize,
|
9
|
+
end: usize,
|
10
|
+
}
|
11
|
+
|
12
|
+
impl ExtnameCoords {
|
13
|
+
pub fn dec(&mut self) {
|
14
|
+
self.start -= 1;
|
15
|
+
if !self.word {
|
16
|
+
self.end -= 1;
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}
|
2
20
|
|
3
21
|
pub fn extname(pth: &str) -> &str {
|
4
|
-
let
|
22
|
+
let path = pth.as_bytes();
|
23
|
+
let mut extname = ExtnameCoords {
|
24
|
+
word: false,
|
25
|
+
pred: false,
|
26
|
+
dot: false,
|
27
|
+
start: path.len(),
|
28
|
+
end: path.len(),
|
29
|
+
};
|
5
30
|
|
6
|
-
|
7
|
-
if
|
8
|
-
|
31
|
+
for &item in path.iter().rev() {
|
32
|
+
if (item == b'.' && !extname.dot) || item == SEP {
|
33
|
+
if item == SEP && extname.word {
|
34
|
+
return ""
|
35
|
+
}
|
36
|
+
|
37
|
+
if !extname.pred {
|
38
|
+
extname.dec();
|
39
|
+
}
|
40
|
+
|
41
|
+
if extname.word {
|
42
|
+
extname.dot = true;
|
43
|
+
}
|
44
|
+
} else {
|
45
|
+
if extname.dot {
|
46
|
+
extname.pred = true;
|
47
|
+
break;
|
48
|
+
} else {
|
49
|
+
extname.word = true;
|
50
|
+
}
|
51
|
+
|
52
|
+
if !extname.pred {
|
53
|
+
extname.dec()
|
54
|
+
}
|
9
55
|
}
|
10
56
|
}
|
11
57
|
|
12
|
-
|
58
|
+
if !extname.pred {
|
59
|
+
return "";
|
60
|
+
}
|
61
|
+
|
62
|
+
str::from_utf8(&path[extname.start..extname.end]).unwrap_or("")
|
13
63
|
}
|
data/src/path_parsing.rs
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
extern crate memchr;
|
2
|
-
use self::memchr::memrchr;
|
3
2
|
use std::path::MAIN_SEPARATOR;
|
4
3
|
use std::str;
|
5
4
|
|
@@ -8,11 +7,6 @@ lazy_static! {
|
|
8
7
|
pub static ref SEP_STR: &'static str = str::from_utf8(&[SEP]).unwrap();
|
9
8
|
}
|
10
9
|
|
11
|
-
pub fn extract_last_path_segment(path: &str) -> &str {
|
12
|
-
let end = (last_non_sep_i(path) + 1) as usize;
|
13
|
-
&path[memrchr(SEP, &path.as_bytes()[..end]).unwrap_or(0)..end]
|
14
|
-
}
|
15
|
-
|
16
10
|
// Returns the byte offset of the last byte preceding a MAIN_SEPARATOR.
|
17
11
|
pub fn last_non_sep_i(path: &str) -> isize {
|
18
12
|
last_non_sep_i_before(path, path.len() as isize - 1)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: faster_path
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel P. Clark
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-03-
|
11
|
+
date: 2018-03-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '12.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: thermite
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.13.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.13.0
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: read_source
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -98,16 +112,16 @@ dependencies:
|
|
98
112
|
name: rubocop
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
|
-
- -
|
115
|
+
- - '='
|
102
116
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0.
|
117
|
+
version: '0.53'
|
104
118
|
type: :development
|
105
119
|
prerelease: false
|
106
120
|
version_requirements: !ruby/object:Gem::Requirement
|
107
121
|
requirements:
|
108
|
-
- -
|
122
|
+
- - '='
|
109
123
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0.
|
124
|
+
version: '0.53'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: stop_watch
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -127,7 +141,7 @@ email:
|
|
127
141
|
- 6ftdan@gmail.com
|
128
142
|
executables: []
|
129
143
|
extensions:
|
130
|
-
- ext/
|
144
|
+
- ext/Rakefile
|
131
145
|
extra_rdoc_files: []
|
132
146
|
files:
|
133
147
|
- Cargo.lock
|
@@ -138,12 +152,12 @@ files:
|
|
138
152
|
- Rakefile
|
139
153
|
- bin/console
|
140
154
|
- bin/setup
|
141
|
-
- ext/
|
155
|
+
- ext/Rakefile
|
142
156
|
- faster_path.gemspec
|
143
157
|
- lib/faster_path.rb
|
158
|
+
- lib/faster_path.so
|
144
159
|
- lib/faster_path/optional/monkeypatches.rb
|
145
160
|
- lib/faster_path/optional/refinements.rb
|
146
|
-
- lib/faster_path/platform.rb
|
147
161
|
- lib/faster_path/version.rb
|
148
162
|
- src/basename.rs
|
149
163
|
- src/chop_basename.rs
|
data/ext/faster_path/extconf.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
require 'mkmf'
|
2
|
-
|
3
|
-
have_header('Dummy Makefile')
|
4
|
-
|
5
|
-
unless find_executable('cargo')
|
6
|
-
puts "You need to have Rust installed for this gem to build natively."
|
7
|
-
puts "Please install the latest nightly build:"
|
8
|
-
puts
|
9
|
-
puts "curl -sSf https://static.rust-lang.org/rustup.sh | sudo sh -s -- --channel=nightly"
|
10
|
-
puts
|
11
|
-
at_exit { puts "Exiting..."}
|
12
|
-
end
|
13
|
-
|
14
|
-
Dir.chdir(File.expand_path("../../", File.dirname(__FILE__))) do
|
15
|
-
`rake build_src`
|
16
|
-
`rake clean_src`
|
17
|
-
end
|
18
|
-
|
19
|
-
create_makefile('faster_path/dummy')
|
data/lib/faster_path/platform.rb
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
module FasterPath
|
2
|
-
module Platform
|
3
|
-
class << self
|
4
|
-
def ffi_library
|
5
|
-
file = [
|
6
|
-
lib_prefix,
|
7
|
-
"faster_path.",
|
8
|
-
lib_suffix
|
9
|
-
]
|
10
|
-
|
11
|
-
File.join(rust_release, file.join())
|
12
|
-
end
|
13
|
-
|
14
|
-
def operating_system
|
15
|
-
case host_os()
|
16
|
-
when /linux|bsd|solaris/
|
17
|
-
"linux"
|
18
|
-
when /darwin/
|
19
|
-
"darwin"
|
20
|
-
when /mingw|mswin/
|
21
|
-
"windows"
|
22
|
-
else
|
23
|
-
host_os()
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def lib_prefix
|
28
|
-
case operating_system()
|
29
|
-
when /windows/
|
30
|
-
''
|
31
|
-
when /cygwin/
|
32
|
-
'cyg'
|
33
|
-
else
|
34
|
-
'lib'
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def lib_suffix
|
39
|
-
case operating_system()
|
40
|
-
when /darwin/
|
41
|
-
'dylib'
|
42
|
-
when /linux/
|
43
|
-
'so'
|
44
|
-
when /windows|cygwin/
|
45
|
-
'dll'
|
46
|
-
else
|
47
|
-
'so'
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def rust_release
|
52
|
-
File.expand_path("../../target/release/", __dir__)
|
53
|
-
end
|
54
|
-
|
55
|
-
def host_os
|
56
|
-
RbConfig::CONFIG['host_os'].downcase
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|