faster_path 0.3.9 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Cargo.lock +18 -43
- data/Cargo.toml +5 -7
- data/Gemfile +4 -7
- data/README.md +106 -33
- data/Rakefile +11 -2
- data/faster_path.gemspec +6 -3
- data/lib/faster_path/version.rb +1 -1
- data/lib/faster_path.rb +10 -3
- data/src/basename.rs +166 -69
- data/src/chop_basename.rs +84 -21
- data/src/cleanpath_aggressive.rs +87 -71
- data/src/cleanpath_conservative.rs +175 -79
- data/src/dirname.rs +96 -32
- data/src/extname.rs +150 -20
- data/src/lib.rs +54 -104
- data/src/path_parsing.rs +282 -21
- data/src/pathname.rs +297 -296
- data/src/plus.rs +93 -79
- data/src/prepend_prefix.rs +11 -13
- data/src/relative_path_from.rs +72 -48
- data/src/ruby.rs +530 -0
- metadata +19 -20
- data/src/debug.rs +0 -29
- data/src/helpers.rs +0 -51
- data/src/memrnchr.rs +0 -70
- data/src/pathname_sys.rs +0 -55
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5e04d827e927a1e405d74ccf0fe49946faaf67650c935ad1e5a5dec744254d27
|
|
4
|
+
data.tar.gz: '067897cef2171835830c97c8340397ad2d4a97ad1c72b15a88c0876bf58a1690'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 16298d55d4cd08d92555ed02e995a55520430527e37d057d7372182e7b9f12758bbf730d2f5969740f806e4bc3221b32843e2a90a8aacb96a57d95500995e477
|
|
7
|
+
data.tar.gz: c09f83ba8f3687b3dc509536fbf985435528a160161795285baf612edf965f409bbac07f6b6de7075be3b5df29d23263de41176ad478d90ade20a567e1fb2a8d
|
data/Cargo.lock
CHANGED
|
@@ -1,64 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
version =
|
|
4
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 4
|
|
5
4
|
|
|
6
5
|
[[package]]
|
|
7
6
|
name = "faster_path"
|
|
8
|
-
version = "0.0
|
|
7
|
+
version = "0.1.0"
|
|
9
8
|
dependencies = [
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
13
|
-
"ruby-sys 0.3.0 (git+https://github.com/danielpclark/ruby-sys?branch=playground)",
|
|
14
|
-
"ruru 0.9.3 (git+https://github.com/danielpclark/ruru?branch=playground)",
|
|
9
|
+
"memchr",
|
|
10
|
+
"rutie",
|
|
15
11
|
]
|
|
16
12
|
|
|
17
13
|
[[package]]
|
|
18
14
|
name = "lazy_static"
|
|
19
|
-
version = "
|
|
20
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
21
|
-
|
|
22
|
-
[[package]]
|
|
23
|
-
name = "lazy_static"
|
|
24
|
-
version = "1.0.0"
|
|
15
|
+
version = "1.5.1"
|
|
25
16
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
17
|
+
checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb"
|
|
26
18
|
|
|
27
19
|
[[package]]
|
|
28
20
|
name = "libc"
|
|
29
|
-
version = "0.2.
|
|
21
|
+
version = "0.2.189"
|
|
30
22
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
23
|
+
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
|
31
24
|
|
|
32
25
|
[[package]]
|
|
33
26
|
name = "memchr"
|
|
34
|
-
version = "2.
|
|
27
|
+
version = "2.8.3"
|
|
35
28
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
36
|
-
|
|
37
|
-
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
38
|
-
]
|
|
29
|
+
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
|
39
30
|
|
|
40
31
|
[[package]]
|
|
41
|
-
name = "
|
|
42
|
-
version = "0.
|
|
43
|
-
source = "
|
|
44
|
-
|
|
45
|
-
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
46
|
-
]
|
|
47
|
-
|
|
48
|
-
[[package]]
|
|
49
|
-
name = "ruru"
|
|
50
|
-
version = "0.9.3"
|
|
51
|
-
source = "git+https://github.com/danielpclark/ruru?branch=playground#ab84ad4b97c41bfe6fd6d0f8540b2efd77583561"
|
|
32
|
+
name = "rutie"
|
|
33
|
+
version = "0.10.2"
|
|
34
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
35
|
+
checksum = "a97641d6bd3731d263d914141e960a8b515bf5ff4ca6c961b25ca4b2694c6490"
|
|
52
36
|
dependencies = [
|
|
53
|
-
"lazy_static
|
|
54
|
-
"
|
|
37
|
+
"lazy_static",
|
|
38
|
+
"libc",
|
|
55
39
|
]
|
|
56
|
-
|
|
57
|
-
[metadata]
|
|
58
|
-
"checksum array_tool 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271"
|
|
59
|
-
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
|
|
60
|
-
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
|
|
61
|
-
"checksum libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)" = "f54263ad99207254cf58b5f701ecb432c717445ea2ee8af387334bdd1a03fdff"
|
|
62
|
-
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
|
|
63
|
-
"checksum ruby-sys 0.3.0 (git+https://github.com/danielpclark/ruby-sys?branch=playground)" = "<none>"
|
|
64
|
-
"checksum ruru 0.9.3 (git+https://github.com/danielpclark/ruru?branch=playground)" = "<none>"
|
data/Cargo.toml
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "faster_path"
|
|
3
|
-
version = "0.0
|
|
3
|
+
version = "0.1.0"
|
|
4
4
|
authors = ["Daniel P. Clark <6ftdan@gmail.com>"]
|
|
5
5
|
description = "Alternative to Pathname"
|
|
6
6
|
homepage = "https://github.com/danielpclark/faster_path"
|
|
7
7
|
repository = "https://github.com/danielpclark/faster_path"
|
|
8
8
|
license = "MIT OR Apache-2.0"
|
|
9
9
|
readme = "README.md"
|
|
10
|
+
edition = "2021"
|
|
10
11
|
|
|
11
12
|
[package.metadata.thermite]
|
|
12
13
|
github_releases = true
|
|
13
14
|
|
|
14
15
|
[lib]
|
|
15
16
|
name = "faster_path"
|
|
16
|
-
crate-type = ["
|
|
17
|
+
crate-type = ["cdylib"]
|
|
17
18
|
|
|
18
19
|
[dependencies]
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
array_tool = "1.0"
|
|
22
|
-
lazy_static = "1.0"
|
|
23
|
-
memchr = "2.0.1"
|
|
20
|
+
rutie = "0.10.2"
|
|
21
|
+
memchr = "2"
|
data/Gemfile
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
source 'https://rubygems.org'
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
gem 'coveralls', require: false
|
|
6
|
-
end
|
|
7
|
-
end
|
|
1
|
+
source 'https://rubygems.org'
|
|
2
|
+
|
|
3
|
+
# Specify your gem's dependencies in faster_path.gemspec
|
|
4
|
+
gemspec
|
data/README.md
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
# FasterPath
|
|
2
2
|
[](https://badge.fury.io/rb/faster_path)
|
|
3
|
-
[](https://ci.appveyor.com/project/danielpclark/faster-path/branch/master)
|
|
3
|
+
[](https://github.com/danielpclark/faster_path/actions/workflows/ci.yml)
|
|
5
4
|
[](https://github.com/danielpclark/faster_path/tags)
|
|
6
|
-
[](https://github.com/danielpclark/faster_path/pulse)
|
|
7
6
|
[](https://github.com/danielpclark/faster_path/releases)
|
|
8
|
-
[](https://coveralls.io/github/danielpclark/faster_path?branch=master)
|
|
9
7
|
[](http://inch-ci.org/github/danielpclark/faster_path)
|
|
10
8
|
[](https://www.codetriage.com/danielpclark/faster_path)
|
|
11
|
-
[](https://twitter.com/share?url=https%3A%2F%2Fgithub.com%2Fdanielpclark%2Ffaster_path&via=6ftdan&hashtags=Ruby&text=You%20could%20save%2015%25%20or%20more%20on%20website%20page%20load%20time%20by%20switching%20to%20the%20FasterPath%20gem.)
|
|
12
9
|
|
|
13
10
|
#### This gem shaves off more than 30% of my Rails application page load time.
|
|
14
11
|
|
|
@@ -94,13 +91,31 @@ I've said this about Sprockets but this required two other gems to be updated as
|
|
|
94
91
|
|sass 3.2.19|sass 5.0.4|
|
|
95
92
|
|bootstrap-sass 3.3.4.1|bootstrap-sass 3.3.6|
|
|
96
93
|
|
|
94
|
+
## Performance Specifics
|
|
95
|
+
|
|
96
|
+
The headline for the amount for improvement on this library is specific to only the improvement made with the method `chop_basename`. Just so you know; in my initial release I had a bug in which that method immediately returned nothing. Now the good thing about this is that it gave me some very valuable information. First I found that all my Rails site tests still passed. Second I found that all my assets no longer loaded in the website. And third, and most importantly, I found my Rails web pages loaded just more than 66% faster without the cost of time that `chop_basename` took.
|
|
97
|
+
|
|
98
|
+
**That's right; the path handling for assets in your website \*consumes more than 2/3rds of your websites page load time.**
|
|
99
|
+
|
|
100
|
+
So now we have some real numbers to work with We can be generoues and use 66% as our margin of area to improve over _(for `chop_basename` specifically, not counting the benefit from improving the performance in other file path related methods)_. That means we want to remove as much of that percentage from the overall systems page load time. The original headline boasts over 33% performance improvement — that was when `chop_basename` was improved by just over 50%. Now `chop_basename` is improved by 83.4%. That alone should make your site run 55.044% faster now _(given your performance profile stats are similar to mine)_.
|
|
101
|
+
|
|
102
|
+
## What Rails Versions Will This Apply To?
|
|
103
|
+
|
|
104
|
+
As mentioned earlier Sprockets, which handles assets, changed away from using `Pathname` at all when moving from major version 2 to 3. So if you're using Sprockets 3 or later you won't reap the biggest performance rewards from using this gem for now _(it's my goal to have this project become a core feature that Rails depends on and yes… that's a big ask)_. That is unless you write you're own implementation to re-integrate the use of `Pathname` and `FasterPath` into your asset handling library. For now just know that the Sprockets 2 series primarily works with Rails 4.1 and earlier. It may work in later Rails versions but I have not investigated this.
|
|
105
|
+
|
|
97
106
|
## Status
|
|
98
107
|
|
|
99
108
|
* Rust compilation is working
|
|
100
109
|
* Methods are stable
|
|
101
110
|
* Thoroughly tested
|
|
102
111
|
* Testers and developers are most welcome
|
|
103
|
-
* Windows
|
|
112
|
+
* Windows: paths follow Ruby's Windows rules (`\` and `/` separators, drive letters, UNC paths)
|
|
113
|
+
* Paths keep their encoding, as with Ruby's own methods
|
|
114
|
+
|
|
115
|
+
## Requirements
|
|
116
|
+
|
|
117
|
+
* Ruby 2.5, 2.6 or 2.7 (the Rust extension is built with [Rutie](https://github.com/danielpclark/rutie) 0.10, which supports these)
|
|
118
|
+
* Rust 1.71 or later
|
|
104
119
|
|
|
105
120
|
## Installation
|
|
106
121
|
|
|
@@ -109,13 +124,13 @@ Ensure Rust is installed:
|
|
|
109
124
|
[Rust Downloads](https://www.rust-lang.org/downloads.html)
|
|
110
125
|
|
|
111
126
|
```
|
|
112
|
-
curl -sSf https://
|
|
127
|
+
curl -sSf https://sh.rustup.rs | sh
|
|
113
128
|
```
|
|
114
129
|
|
|
115
130
|
Add this line to your application's Gemfile:
|
|
116
131
|
|
|
117
132
|
```ruby
|
|
118
|
-
gem 'faster_path', '~> 0.
|
|
133
|
+
gem 'faster_path', '~> 0.4.0'
|
|
119
134
|
```
|
|
120
135
|
|
|
121
136
|
And then execute:
|
|
@@ -136,27 +151,35 @@ improvement result for the `chop_basename` method.
|
|
|
136
151
|
|
|
137
152
|
## Usage
|
|
138
153
|
|
|
154
|
+
Add the proper require to your project.
|
|
155
|
+
|
|
156
|
+
```ruby
|
|
157
|
+
require "faster_path"
|
|
158
|
+
```
|
|
159
|
+
|
|
139
160
|
Current methods implemented:
|
|
140
161
|
|
|
141
|
-
|FasterPath Rust Implementation|Ruby 2.
|
|
142
|
-
|
|
143
|
-
| `FasterPath.absolute?` | `Pathname#absolute?` | 95.
|
|
144
|
-
| `FasterPath.add_trailing_separator` | `Pathname#add_trailing_separator` |
|
|
145
|
-
| `FasterPath.basename` | `File.basename` |
|
|
146
|
-
| `FasterPath.children` | `Pathname#children` |
|
|
147
|
-
| `FasterPath.chop_basename` | `Pathname#chop_basename` |
|
|
148
|
-
| `FasterPath.cleanpath_aggressive` | `Pathname#cleanpath_aggressive` |
|
|
149
|
-
| `FasterPath.cleanpath_conservative` | `Pathname#cleanpath_conservative` |
|
|
150
|
-
| `FasterPath.del_trailing_separator` | `Pathname#del_trailing_separator` | 85.
|
|
151
|
-
| `FasterPath.directory?` | `Pathname#directory?` |
|
|
152
|
-
| `FasterPath.dirname` | `File.dirname` |
|
|
153
|
-
| `FasterPath.entries` | `Pathname#entries` |
|
|
154
|
-
| `FasterPath.extname` | `File.extname` |
|
|
155
|
-
| `FasterPath.has_trailing_separator?` | `Pathname#has_trailing_separator` | 88.
|
|
156
|
-
| `FasterPath.
|
|
157
|
-
| `FasterPath.plus` | `Pathname#plus` |
|
|
158
|
-
| `FasterPath.relative?` | `Pathname#relative?` | 92.
|
|
159
|
-
| `FasterPath.relative_path_from` | `Pathname#relative_path_from` | 93.
|
|
162
|
+
|FasterPath Rust Implementation|Ruby Implementation|Time Shaved Off (Ruby 2.7)|Time Shaved Off (Ruby 2.5)|
|
|
163
|
+
|---|---|:---:|:---:|
|
|
164
|
+
| `FasterPath.absolute?` | `Pathname#absolute?` | 95.7% | 96.7% |
|
|
165
|
+
| `FasterPath.add_trailing_separator` | `Pathname#add_trailing_separator` | 85.4% | 83.0% |
|
|
166
|
+
| `FasterPath.basename` | `File.basename` | 42.4% | 39.1% |
|
|
167
|
+
| `FasterPath.children` | `Pathname#children` | 54.7% | 47.8% |
|
|
168
|
+
| `FasterPath.chop_basename` | `Pathname#chop_basename` | 70.4% | 75.1% |
|
|
169
|
+
| `FasterPath.cleanpath_aggressive` | `Pathname#cleanpath_aggressive` | 90.3% | 90.6% |
|
|
170
|
+
| `FasterPath.cleanpath_conservative` | `Pathname#cleanpath_conservative` | 89.6% | 91.6% |
|
|
171
|
+
| `FasterPath.del_trailing_separator` | `Pathname#del_trailing_separator` | 85.3% | 87.6% |
|
|
172
|
+
| `FasterPath.directory?` | `Pathname#directory?` | 34.3% | 37.5% |
|
|
173
|
+
| `FasterPath.dirname` | `File.dirname` | 56.8% | 54.7% |
|
|
174
|
+
| `FasterPath.entries` | `Pathname#entries` | 38.0% | 33.9% |
|
|
175
|
+
| `FasterPath.extname` | `File.extname` | 74.0% | 73.1% |
|
|
176
|
+
| `FasterPath.has_trailing_separator?` | `Pathname#has_trailing_separator` | 88.5% | 89.1% |
|
|
177
|
+
| `FasterPath.join` | `Pathname#join` | 88.1% | 90.3% |
|
|
178
|
+
| `FasterPath.plus` | `Pathname#plus` | 91.7% | 93.4% |
|
|
179
|
+
| `FasterPath.relative?` | `Pathname#relative?` | 92.8% | 95.2% |
|
|
180
|
+
| `FasterPath.relative_path_from` | `Pathname#relative_path_from` | 92.5% | 93.6% |
|
|
181
|
+
|
|
182
|
+
See [Benchmarks](#benchmarks) for how these are measured.
|
|
160
183
|
|
|
161
184
|
You may choose to use the methods directly, or scope change to rewrite behavior on the
|
|
162
185
|
standard library with the included refinements, or even call a method to monkeypatch
|
|
@@ -182,14 +205,66 @@ FasterPath.sledgehammer_everything!
|
|
|
182
205
|
|
|
183
206
|
These will **not** be included by default in monkey-patches. To try them with monkeypatching use the environment flag of `WITH_REGRESSION`. These methods are here to be improved upon.
|
|
184
207
|
|
|
185
|
-
|FasterPath Implementation|Ruby Implementation|
|
|
186
|
-
|
|
187
|
-
| `FasterPath.entries_compat` | `Pathname.entries` |
|
|
188
|
-
| `FasterPath.children_compat` | `Pathname.children` |
|
|
208
|
+
|FasterPath Implementation|Ruby Implementation|Time Shaved Off (Ruby 2.7)|Time Shaved Off (Ruby 2.5)|
|
|
209
|
+
|---|---|:---:|:---:|
|
|
210
|
+
| `FasterPath.entries_compat` | `Pathname.entries` | 16.8% | 9.2% |
|
|
211
|
+
| `FasterPath.children_compat` | `Pathname.children` | 32.1% | 26.6% |
|
|
189
212
|
|
|
190
213
|
It's been my observation (and some others) that the Rust implementation of the C code for `File` has similar results but
|
|
191
214
|
performance seems to vary based on CPU cache on possibly 64bit/32bit system environments. These are not included by default when the monkey patch method `FasterPath.sledgehammer_everything!` is executed.
|
|
192
215
|
|
|
216
|
+
## Benchmarks
|
|
217
|
+
|
|
218
|
+
The "Time Shaved Off" figures come from the project's Pinch-bench (`rake pbench`, in
|
|
219
|
+
`test/pbench`): each method runs against Ruby's own implementation, and the result is how much
|
|
220
|
+
less time FasterPath took. They are the median of 3 runs of `LONG_RUN=10 rake pbench` (500,000
|
|
221
|
+
calls of each method, 5 times) on Linux x86_64 with Ruby 2.7.8 and 2.5.7, built with Rust 1.97.
|
|
222
|
+
Expect a few points of difference from run to run.
|
|
223
|
+
|
|
224
|
+
`rake pbench` is also the performance regression test: each method has a floor in
|
|
225
|
+
`test/pbench/pbench_suite.rb` (about half of the improvement in the table above) and the task
|
|
226
|
+
fails when a method measures below it, so a change that makes a method slower shows up in
|
|
227
|
+
`rake test`. On Windows, where `join` is currently slower than Ruby's
|
|
228
|
+
([#185](https://github.com/danielpclark/faster_path/issues/185)), the floors are reported but not
|
|
229
|
+
enforced.
|
|
230
|
+
|
|
231
|
+
### Before and after the Rutie 0.10 upgrade
|
|
232
|
+
|
|
233
|
+
Measured the same way, alternating runs of the code before the upgrade (built with Rutie 0.6)
|
|
234
|
+
and after it. Higher is better; the change is in percentage points.
|
|
235
|
+
|
|
236
|
+
|Method|Ruby 2.7 before|Ruby 2.7 after|Change|Ruby 2.5 before|Ruby 2.5 after|Change|
|
|
237
|
+
|---|:---:|:---:|:---:|:---:|:---:|:---:|
|
|
238
|
+
| `absolute?` | 93.3% | 95.7% | +2.4 | 96.1% | 96.7% | +0.6 |
|
|
239
|
+
| `add_trailing_separator` | 66.6% | 85.4% | **+18.8** | 64.3% | 83.0% | **+18.7** |
|
|
240
|
+
| `basename` | 42.4% | 42.4% | 0.0 | 32.1% | 39.1% | **+7.0** |
|
|
241
|
+
| `children` | 52.8% | 54.7% | +1.9 | 46.5% | 47.8% | +1.3 |
|
|
242
|
+
| `children_compat` | −1.2% | 32.1% | **+33.3** | 1.1% | 26.6% | **+25.5** |
|
|
243
|
+
| `chop_basename` | 71.2% | 70.4% | −0.8 | 74.7% | 75.1% | +0.4 |
|
|
244
|
+
| `cleanpath_aggressive` | 90.3% | 90.3% | 0.0 | 92.7% | 90.6% | −2.1 |
|
|
245
|
+
| `cleanpath_conservative` | 89.8% | 89.6% | −0.2 | 91.7% | 91.6% | −0.1 |
|
|
246
|
+
| `del_trailing_separator` | 86.5% | 85.3% | −1.2 | 87.0% | 87.6% | +0.6 |
|
|
247
|
+
| `directory?` | 33.2% | 34.3% | +1.1 | 37.2% | 37.5% | +0.3 |
|
|
248
|
+
| `dirname` | 49.8% | 56.8% | **+7.0** | 51.2% | 54.7% | +3.5 |
|
|
249
|
+
| `entries` | 40.4% | 38.0% | −2.4 | 33.6% | 33.9% | +0.3 |
|
|
250
|
+
| `entries_compat` | −29.8% | 16.8% | **+46.6** | −23.3% | 9.2% | **+32.5** |
|
|
251
|
+
| `extname` | 70.3% | 74.0% | +3.7 | 74.0% | 73.1% | −0.9 |
|
|
252
|
+
| `has_trailing_separator?` | 87.5% | 88.5% | +1.0 | 87.1% | 89.1% | +2.0 |
|
|
253
|
+
| `join` | crashes | 88.1% | | crashes | 90.3% | |
|
|
254
|
+
| `plus` | 92.3% | 91.7% | −0.6 | 93.0% | 93.4% | +0.4 |
|
|
255
|
+
| `relative?` | 90.7% | 92.8% | +2.1 | 93.6% | 95.2% | +1.6 |
|
|
256
|
+
| `relative_path_from` | 92.7% | 92.5% | −0.2 | 94.0% | 93.6% | −0.4 |
|
|
257
|
+
|
|
258
|
+
Before the upgrade, `FasterPath.join` segfaulted, so its benchmark can't be measured.
|
|
259
|
+
`add_trailing_separator`, `dirname` and the `_compat` methods gained the most:
|
|
260
|
+
`add_trailing_separator` no longer builds a temporary string, no method checks its arguments
|
|
261
|
+
for valid UTF-8 any more, and the `_compat` methods build `Pathname` objects without calling
|
|
262
|
+
`Pathname.new`. `basename` was re-measured after it was made to take a shorter path on Unix
|
|
263
|
+
and skip an empty extension; it was the one method that first measured slower on Ruby 2.5.
|
|
264
|
+
Its timings vary a lot from run to run (Ruby 2.5 before: 40.0%, 32.1%, 28.7%; after: 29.6%,
|
|
265
|
+
39.1%, 39.2%), so its instruction counts from `valgrind --tool=callgrind` are a steadier
|
|
266
|
+
measure. They went from 2439 to 2331 per call on Ruby 2.5 and from 2689 to 2561 on Ruby 2.7.
|
|
267
|
+
|
|
193
268
|
## Getting Started with Development
|
|
194
269
|
|
|
195
270
|
The primary methods to target are mostly listed in the **Why** section above. You may find the Ruby
|
|
@@ -205,8 +280,6 @@ Whenever feasible implement it in Rust.
|
|
|
205
280
|
After checking out the repo, make sure you have Rust installed, then run `bundle`.
|
|
206
281
|
Run `rake test` to run the tests, and `rake bench` for benchmarks.
|
|
207
282
|
|
|
208
|
-
Learn and share performance tips on the [wiki](https://github.com/danielpclark/faster_path/wiki)!
|
|
209
|
-
|
|
210
283
|
### Building and running tests
|
|
211
284
|
|
|
212
285
|
First, bundle the gem's development dependencies by running `bundle`. Rust compilation is included in the current rake commands.
|
data/Rakefile
CHANGED
|
@@ -46,7 +46,14 @@ end
|
|
|
46
46
|
|
|
47
47
|
desc "Run Rust Tests"
|
|
48
48
|
task :cargo do
|
|
49
|
-
|
|
49
|
+
ruby_lib = RbConfig::CONFIG['libdir']
|
|
50
|
+
sh(
|
|
51
|
+
{
|
|
52
|
+
'LD_LIBRARY_PATH' => ruby_lib,
|
|
53
|
+
'DYLD_LIBRARY_PATH' => ruby_lib
|
|
54
|
+
},
|
|
55
|
+
'cargo -vv test -- --nocapture'
|
|
56
|
+
)
|
|
50
57
|
end
|
|
51
58
|
|
|
52
59
|
Rake::TestTask.new(minitest: :build_lib) do |t|
|
|
@@ -62,7 +69,9 @@ task :init_mspec do |_t|
|
|
|
62
69
|
end
|
|
63
70
|
|
|
64
71
|
task test: [:cargo, :minitest, :lint, :pbench, :init_mspec] do |_t|
|
|
65
|
-
|
|
72
|
+
# Run through Ruby so this also works on Windows
|
|
73
|
+
exec Gem.ruby, 'spec/mspec/bin/mspec', '--format', 'spec',
|
|
74
|
+
'core/file/basename', 'core/file/extname', 'core/file/dirname', 'library/pathname'
|
|
66
75
|
end
|
|
67
76
|
|
|
68
77
|
desc "Full mspec results w/o encoding"
|
data/faster_path.gemspec
CHANGED
|
@@ -24,11 +24,14 @@ Gem::Specification.new do |spec|
|
|
|
24
24
|
spec.extensions = ['ext/Rakefile']
|
|
25
25
|
spec.require_paths = ['lib']
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
spec.
|
|
27
|
+
# Rutie 0.10, which the Rust extension is built with, supports Ruby 2.5 to 2.7
|
|
28
|
+
spec.required_ruby_version = ['>= 2.5', '< 3.0']
|
|
29
|
+
|
|
30
|
+
spec.add_dependency 'bundler', '>= 1.12'
|
|
31
|
+
spec.add_dependency 'rake', '>= 12.3'
|
|
29
32
|
spec.add_dependency 'thermite', '0.13.0'
|
|
30
33
|
spec.add_development_dependency 'read_source', '~> 0.2.6'
|
|
31
|
-
spec.add_development_dependency 'minitest', '~> 5.
|
|
34
|
+
spec.add_development_dependency 'minitest', '~> 5.11'
|
|
32
35
|
spec.add_development_dependency 'minitest-reporters', '~> 1.1'
|
|
33
36
|
spec.add_development_dependency 'color_pound_spec_reporter', '~> 0.0.9'
|
|
34
37
|
spec.add_development_dependency 'rubocop', '0.53'
|
data/lib/faster_path/version.rb
CHANGED
data/lib/faster_path.rb
CHANGED
|
@@ -6,8 +6,13 @@ require 'fiddle'
|
|
|
6
6
|
require 'fiddle/import'
|
|
7
7
|
|
|
8
8
|
# FasterPath module behaves as a singleton object with the alternative method
|
|
9
|
-
# implementations for Pathname
|
|
9
|
+
# implementations for `Pathname`, and some for `File`, available directly on it.
|
|
10
10
|
#
|
|
11
|
+
# New projects are recommend to reference methods defined directly on `FasterPath`.
|
|
12
|
+
# Existing websites may use the `FasterPath.sledgehammer_everything!` method to
|
|
13
|
+
# directly injet the more performant implementations of path handling in to their
|
|
14
|
+
# existing code ecosystem. To do so you will need to
|
|
15
|
+
# `require 'faster_path/optional/monkeypatches'` beforehand.
|
|
11
16
|
module FasterPath
|
|
12
17
|
FFI_LIBRARY = begin
|
|
13
18
|
toplevel_dir = File.dirname(__dir__)
|
|
@@ -17,7 +22,7 @@ module FasterPath
|
|
|
17
22
|
end
|
|
18
23
|
|
|
19
24
|
Fiddle::Function.
|
|
20
|
-
new(Fiddle.dlopen(FFI_LIBRARY)['Init_faster_pathname'], [], Fiddle::
|
|
25
|
+
new(Fiddle.dlopen(FFI_LIBRARY)['Init_faster_pathname'], [], Fiddle::TYPE_VOID).
|
|
21
26
|
call
|
|
22
27
|
|
|
23
28
|
Public.class_eval do
|
|
@@ -35,7 +40,9 @@ module FasterPath
|
|
|
35
40
|
# The Ruby architecture bit width: 64bits or 32bits
|
|
36
41
|
# @return [Integer]
|
|
37
42
|
def self.ruby_arch_bits
|
|
38
|
-
1.size
|
|
43
|
+
# The width of a pointer; `1.size` is the width of a C `long`, which is
|
|
44
|
+
# 4 bytes on 64-bit Windows.
|
|
45
|
+
[0].pack('J').bytesize * 8
|
|
39
46
|
end
|
|
40
47
|
|
|
41
48
|
# A very fast way to check if a string is blank
|