Repository: icyleaf/fast-crystal
Branch: master
Commit: da672edb3b67
Files: 38
Total size: 27.6 KB
Directory structure:
gitextract_y1nbnp85/
├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── code/
│ ├── array/
│ │ ├── first-vs-index[0].cr
│ │ ├── insert-vs-unshift.cr
│ │ ├── last-vs-index[-1].cr
│ │ └── range-vs-times.map.cr
│ ├── enumerable/
│ │ ├── each-push-vs-map.cr
│ │ ├── each-vs-loop.cr
│ │ ├── each_with_index-vs-while-loop.cr
│ │ ├── map-flatten-vs-flat_map.cr
│ │ ├── reverse.each-vs-reverse_each.cr
│ │ └── sort-vs-sort_by.cr
│ ├── general/
│ │ ├── assignment.cr
│ │ ├── hash-vs-struct-vs-namedtuple.cr
│ │ ├── loop-vs-while_true.cr
│ │ ├── positional_argument-vs-named_argument.cr
│ │ └── property-vs-getter_and_setter.cr
│ ├── hash/
│ │ ├── []?-vs-has_key?.cr
│ │ ├── bracket-vs-fetch.cr
│ │ ├── clone-vs-dup.cr
│ │ ├── keys-each-vs-each_key.cr
│ │ └── merge-bang-vs-[]=.cr
│ ├── namedtuple/
│ │ ├── bracket-vs-fetch.cr
│ │ └── fetch-vs-fetch_with_block.cr
│ ├── proc-and-block/
│ │ ├── block-vs-to_proc.cr
│ │ └── proc-call-vs-yield.cr
│ └── string/
│ ├── concatenation.cr
│ ├── ends-string-matching-match-vs-end_with.cr
│ ├── equal-substring-of-char.cr
│ ├── equal-vs-match.cr
│ ├── gsub-vs-sub.cr
│ ├── includes-vs-to_s.includes.cr
│ ├── nil-vs-to_s.empty.cr
│ └── sub-vs-chomp.cr
├── shard.yml
└── src/
└── fast-crystal.cr
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
/doc/
/lib/
/bin/
/.shards/
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2017-2019 icyleaf
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: Makefile
================================================
CRYSTAL_BIN ?= $(shell which crystal)
PREFIX ?= /usr/local
run: build
./bin/fast-crystal
clean:
rm -rf bin
mkdir bin
build: clean
$(CRYSTAL_BIN) build --release --no-debug -o bin/fast-crystal src/fast-crystal.cr $(CRFLAGS)
================================================
FILE: README.md
================================================
# 💎 Fast Crystal
It's Crystal version based on [ruby version](https://github.com/JuanitoFatas/fast-ruby).
Each idiom has a corresponding code example that resides in [code](code).
All results listed in README.md are running with Crystal 0.25.0 (2018-06-15) LLVM 5.0.1 on OS X 10.13.5.
Machine information: MacBook Pro (Retina, 15-inch, Mid 2015), 2.2 GHz Intel Core i7, 16 GB 1600 MHz DDR3.
Your results may vary, but you get the idea. : )
> Doubt the results? please discuss in [Crystal Issue#4383](https://github.com/crystal-lang/crystal/issues/4383).
**Let's write faster code, together! :trollface:**
## Measurement Tool
Use Crystal's built-in [benchmark](https://crystal-lang.org/api/0.22.0/Benchmark.html).
## Run the Benchmarks
```bash
$ make
```
### Template
```crystal
require "benchmark"
def fast
end
def slow
end
Benchmark.ips do |x|
x.report("fast code description") { fast }
x.report("slow code description") { slow }
end
```
## Idioms
### Index
- [Array](#array)
- [Enumerable](#enumerable)
- [General](#general)
- [Hash](#hash)
- [NamedTuple](#namedtuple)
- [Proc & Block](#proc--block)
- [String](#string)
> Test in Crystal 0.35.1 (2020-06-19) LLVM: 10.0.0 Default target: x86_64-apple-macosx
### Array
#### `first` vs `index[0]` [code](code/array/first-vs-index[0].cr)
```
$ crystal build --release --no-debug -o bin/code/array/first-vs-index[0] code/array/first-vs-index[0].cr
$ ./bin/code/array/first-vs-index[0]
Array#first 265.31M ( 3.77ns) (±11.17%) 0.0B/op 1.01× slower
Array#[0] 267.85M ( 3.73ns) (± 6.86%) 0.0B/op fastest
```
#### `insert` vs `unshift` [code](code/array/insert-vs-unshift.cr)
```
$ crystal build --release --no-debug -o bin/code/array/insert-vs-unshift code/array/insert-vs-unshift.cr
$ ./bin/code/array/insert-vs-unshift
Array#insert 1.30 (768.66ms) (± 1.33%) 1.5MB/op fastest
Array#unshift 1.29 (775.05ms) (± 1.81%) 1.5MB/op 1.01× slower
```
#### `last` vs `index[-1]` [code](code/array/last-vs-index[-1].cr)
```
$ crystal build --release --no-debug -o bin/code/array/last-vs-index[-1] code/array/last-vs-index[-1].cr
$ ./bin/code/array/last-vs-index[-1]
Array#[-1] 273.97M ( 3.65ns) (± 4.16%) 0.0B/op fastest
Array#last 273.61M ( 3.65ns) (± 4.75%) 0.0B/op 1.00× slower
```
#### `range` vs `times.map` [code](code/array/range-vs-times.map.cr)
```
$ crystal build --release --no-debug -o bin/code/array/range-vs-times.map code/array/range-vs-times.map.cr
$ ./bin/code/array/range-vs-times.map
Range#to_a 1.11M (897.91ns) (±17.84%) 1.67kB/op fastest
Times#to_a 1.02M (980.17ns) (±17.56%) 1.69kB/op 1.09× slower
```
### Enumerable
#### `each push` vs `map` [code](code/enumerable/each-push-vs-map.cr)
```
$ crystal build --release --no-debug -o bin/code/enumerable/each-push-vs-map code/enumerable/each-push-vs-map.cr
$ ./bin/code/enumerable/each-push-vs-map
Array#map 507.91k ( 1.97µs) (±11.92%) 3.96kB/op fastest
Array#each + push 145.04k ( 6.89µs) (±18.89%) 12.7kB/op 3.50× slower
Array#each_with_object 155.85k ( 6.42µs) (±17.07%) 12.7kB/op 3.26× slower
```
#### `each` vs `loop` [code](code/enumerable/each-vs-loop.cr)
```
$ crystal build --release --no-debug -o bin/code/enumerable/each-vs-loop code/enumerable/each-vs-loop.cr
$ ./bin/code/enumerable/each-vs-loop
While Loop 1.64M (609.64ns) (± 7.66%) 0.0B/op 159.20× slower
#each 261.15M ( 3.83ns) (±10.82%) 0.0B/op fastest
```
#### `each_with_index` vs `while loop` [code](code/enumerable/each_with_index-vs-while-loop.cr)
```
$ crystal build --release --no-debug -o bin/code/enumerable/each_with_index-vs-while-loop code/enumerable/each_with_index-vs-while-loop.cr
$ ./bin/code/enumerable/each_with_index-vs-while-loop
While Loop 1.51M (661.13ns) (± 9.29%) 0.0B/op 6.94× slower
each_with_index 10.50M ( 95.23ns) (±17.95%) 0.0B/op fastest
```
#### `map flatten` vs `flat_map` [code](code/enumerable/map-flatten-vs-flat_map.cr)
```
$ crystal build --release --no-debug -o bin/code/enumerable/map-flatten-vs-flat_map code/enumerable/map-flatten-vs-flat_map.cr
$ ./bin/code/enumerable/map-flatten-vs-flat_map
Array#flat_map (Tuple) 902.86k ( 1.11µs) (± 6.63%) 3.65kB/op fastest
Array#map.flatten (Tuple) 664.00k ( 1.51µs) (± 6.00%) 4.69kB/op 1.36× slower
Array#flat_map (Array) 238.37k ( 4.20µs) (± 5.73%) 7.18kB/op 3.79× slower
Array#map.flatten (Array) 193.64k ( 5.16µs) (± 3.78%) 9.39kB/op 4.66× slower
```
#### `reverse.each` vs `reverse_each` [code](code/enumerable/reverse.each-vs-reverse_each.cr)
```
$ crystal build --release --no-debug -o bin/code/enumerable/reverse.each-vs-reverse_each code/enumerable/reverse.each-vs-reverse_each.cr
$ ./bin/code/enumerable/reverse.each-vs-reverse_each
Array#reverse.each 4.03M (248.39ns) (± 5.02%) 480B/op 4.94× slower
Array#reverse_each 19.88M ( 50.30ns) (± 2.49%) 0.0B/op fastest
```
#### `sort` vs `sort_by` [code](code/enumerable/sort-vs-sort_by.cr)
```
$ crystal build --release --no-debug -o bin/code/enumerable/sort-vs-sort_by code/enumerable/sort-vs-sort_by.cr
$ ./bin/code/enumerable/sort-vs-sort_by
Enumerable#sort 145.32k ( 6.88µs) (± 2.89%) 3.07kB/op 1.17× slower
Enumerable#sort_by 170.71k ( 5.86µs) (± 4.47%) 1.04kB/op fastest
```
### General
#### Assignment [code](code/general/assignment.cr)
```
$ crystal build --release --no-debug -o bin/code/general/assignment code/general/assignment.cr
$ ./bin/code/general/assignment
Sequential Assignment 611.21M ( 1.64ns) (± 4.98%) 0.0B/op 1.00× slower
Parallel Assignment 613.61M ( 1.63ns) (± 5.04%) 0.0B/op fastest
```
#### `hash` vs `struct` vs `namedtuple` [code](code/general/hash-vs-struct-vs-namedtuple.cr)
```
$ crystal build --release --no-debug -o bin/code/general/hash-vs-struct-vs-namedtuple code/general/hash-vs-struct-vs-namedtuple.cr
$ ./bin/code/general/hash-vs-struct-vs-namedtuple
NamedTuple 515.36M ( 1.94ns) (± 4.05%) 0.0B/op fastest
Struct 503.85M ( 1.98ns) (± 6.54%) 0.0B/op 1.02× slower
Hash 9.60M (104.18ns) (± 2.76%) 208B/op 53.69× slower
```
#### `loop` vs `while_true` [code](code/general/loop-vs-while_true.cr)
```
$ crystal build --release --no-debug -o bin/code/general/loop-vs-while_true code/general/loop-vs-while_true.cr
$ ./bin/code/general/loop-vs-while_true
While Loop 512.11M ( 1.95ns) (± 5.15%) 0.0B/op fastest
Kernel Loop 482.98M ( 2.07ns) (±16.94%) 0.0B/op 1.06× slower
```
#### `positional_argument` vs `named_argument` [code](code/general/positional_argument-vs-named_argument.cr)
```
$ crystal build --release --no-debug -o bin/code/general/positional_argument-vs-named_argument code/general/positional_argument-vs-named_argument.cr
$ ./bin/code/general/positional_argument-vs-named_argument
Named arguments 564.18M ( 1.77ns) (±16.11%) 0.0B/op 1.03× slower
Positional arguments 578.90M ( 1.73ns) (±10.46%) 0.0B/op fastest
```
#### `property` vs `getter_and_setter` [code](code/general/property-vs-getter_and_setter.cr)
```
$ crystal build --release --no-debug -o bin/code/general/property-vs-getter_and_setter code/general/property-vs-getter_and_setter.cr
$ ./bin/code/general/property-vs-getter_and_setter
property 50.89M ( 19.65ns) (± 5.34%) 32.0B/op fastest
getter_and_setter 49.68M ( 20.13ns) (± 7.27%) 32.0B/op 1.02× slower
```
### Hash
#### `[]?` vs `has_key?` [code](code/hash/[]?-vs-has_key?.cr)
```
$ crystal build --release --no-debug -o bin/code/hash/[]?-vs-has_key? code/hash/[]?-vs-has_key?.cr
$ ./bin/code/hash/[]?-vs-has_key?
Hash#[]? 41.12M ( 24.32ns) (±12.09%) 0.0B/op 1.01× slower
Hash#has_key? 41.48M ( 24.11ns) (± 8.25%) 0.0B/op fastest
```
#### `bracket` vs `fetch` [code](code/hash/bracket-vs-fetch.cr)
```
$ crystal build --release --no-debug -o bin/code/hash/bracket-vs-fetch code/hash/bracket-vs-fetch.cr
$ ./bin/code/hash/bracket-vs-fetch
Hash#[] 95.60M ( 10.46ns) (± 6.16%) 0.0B/op 1.02× slower
Hash#fetch 97.08M ( 10.30ns) (± 9.36%) 0.0B/op fastest
```
#### `clone` vs `dup` [code](code/hash/clone-vs-dup.cr)
```
$ crystal build --release --no-debug -o bin/code/hash/clone-vs-dup code/hash/clone-vs-dup.cr
$ ./bin/code/hash/clone-vs-dup
Hash#dup 5.39M (185.50ns) (±17.96%) 480B/op fastest
Hash#clone 293.35k ( 3.41µs) (±10.17%) 5.94kB/op 18.38× slower
```
#### `keys each` vs `each_key` [code](code/hash/keys-each-vs-each_key.cr)
```
$ crystal build --release --no-debug -o bin/code/hash/keys-each-vs-each_key code/hash/keys-each-vs-each_key.cr
$ ./bin/code/hash/keys-each-vs-each_key
Hash#keys.each 4.25M (235.11ns) (± 8.09%) 240B/op 1.11× slower
Hash#each_key 4.71M (212.43ns) (±22.16%) 160B/op fastest
```
#### `merge bang` vs `[]=` [code](code/hash/merge-bang-vs-[]=.cr)
```
$ crystal build --release --no-debug -o bin/code/hash/merge-bang-vs-[]= code/hash/merge-bang-vs-[]=.cr
$ ./bin/code/hash/merge-bang-vs-[]=
Hash#merge! 67.40k ( 14.84µs) (±23.77%) 16.6kB/op 4.19× slower
Hash#[]= 282.73k ( 3.54µs) (±21.37%) 4.14kB/op fastest
```
### Namedtuple
#### `bracket` vs `fetch` [code](code/namedtuple/bracket-vs-fetch.cr)
```
$ crystal build --release --no-debug -o bin/code/namedtuple/bracket-vs-fetch code/namedtuple/bracket-vs-fetch.cr
$ ./bin/code/namedtuple/bracket-vs-fetch
NamedTuple#[] 294.37M ( 3.40ns) (±19.52%) 0.0B/op 1.00× slower
NamedTuple#fetch 295.49M ( 3.38ns) (±19.80%) 0.0B/op fastest
```
#### `fetch` vs `fetch_with_block` [code](code/namedtuple/fetch-vs-fetch_with_block.cr)
```
$ crystal build --release --no-debug -o bin/code/namedtuple/fetch-vs-fetch_with_block code/namedtuple/fetch-vs-fetch_with_block.cr
$ ./bin/code/namedtuple/fetch-vs-fetch_with_block
NamedTuple#fetch + const 168.24M ( 5.94ns) (± 6.53%) 0.0B/op 1.81× slower
NamedTuple#fetch + block 304.53M ( 3.28ns) (± 4.50%) 0.0B/op fastest
NamedTuple#fetch + arg 296.07M ( 3.38ns) (± 6.99%) 0.0B/op 1.03× slower
```
### Proc & Block
#### `block` vs `to_proc` [code](code/proc-and-block/block-vs-to_proc.cr)
```
$ crystal build --release --no-debug -o bin/code/proc-and-block/block-vs-to_proc code/proc-and-block/block-vs-to_proc.cr
$ ./bin/code/proc-and-block/block-vs-to_proc
Block 331.06k ( 3.02µs) (±13.18%) 2.6kB/op 1.10× slower
Symbol#to_proc 362.78k ( 2.76µs) (± 5.27%) 2.6kB/op fastest
```
#### `proc call` vs `yield` [code](code/proc-and-block/proc-call-vs-yield.cr)
```
$ crystal build --release --no-debug -o bin/code/proc-and-block/proc-call-vs-yield code/proc-and-block/proc-call-vs-yield.cr
$ ./bin/code/proc-and-block/proc-call-vs-yield
block.call 513.72M ( 1.95ns) (± 4.51%) 0.0B/op fastest
block + yield 501.67M ( 1.99ns) (± 7.25%) 0.0B/op 1.02× slower
block argument 512.94M ( 1.95ns) (± 5.41%) 0.0B/op 1.00× slower
yield 482.96M ( 2.07ns) (±15.43%) 0.0B/op 1.06× slower
```
### String
#### Concatenation [code](code/string/concatenation.cr)
```
$ crystal build --release --no-debug -o bin/code/string/concatenation code/string/concatenation.cr
$ ./bin/code/string/concatenation
String#+ 44.62M ( 22.41ns) (± 8.00%) 32.0B/op fastest
String#{} 23.68M ( 42.22ns) (±16.74%) 32.0B/op 1.88× slower
String#% 4.28M (233.43ns) (±20.03%) 176B/op 10.41× slower
```
#### `ends string-matching-match` vs `end_with` [code](code/string/ends-string-matching-match-vs-end_with.cr)
```
$ crystal build --release --no-debug -o bin/code/string/ends-string-matching-match-vs-end_with code/string/ends-string-matching-match-vs-end_with.cr
$ ./bin/code/string/ends-string-matching-match-vs-end_with
String#end_with? 238.71M ( 4.19ns) (±11.61%) 0.0B/op fastest
String#=~ 7.93M (126.04ns) (± 4.61%) 16.0B/op 30.09× slower
```
#### Equal-substring-of-char [code](code/string/equal-substring-of-char.cr)
```
$ crystal build --release --no-debug -o bin/code/string/equal-substring-of-char code/string/equal-substring-of-char.cr
$ ./bin/code/string/equal-substring-of-char
"==="[0] == '=' 298.29M ( 3.35ns) (± 7.06%) 0.0B/op fastest
"==="[0].to_s == "=" 23.29M ( 42.94ns) (± 6.52%) 48.0B/op 12.81× slower
"==="[0] == "=".chars[0] 27.62M ( 36.21ns) (± 4.66%) 48.0B/op 10.80× slower
```
#### `equal` vs `match` [code](code/string/equal-vs-match.cr)
```
$ crystal build --release --no-debug -o bin/code/string/equal-vs-match code/string/equal-vs-match.cr
$ ./bin/code/string/equal-vs-match
String#match 15.00M ( 66.65ns) (± 8.74%) 16.0B/op 1.02× slower
Regexp#=== 15.32M ( 65.27ns) (± 9.61%) 16.0B/op fastest
String#=~ 14.67M ( 68.17ns) (± 8.60%) 16.0B/op 1.04× slower
```
#### `gsub` vs `sub` [code](code/string/gsub-vs-sub.cr)
```
$ crystal build --release --no-debug -o bin/code/string/gsub-vs-sub code/string/gsub-vs-sub.cr
$ ./bin/code/string/gsub-vs-sub
String#sub 3.67M (272.77ns) (± 5.43%) 1.22kB/op fastest
String#gsub 1.37M (728.87ns) (± 4.13%) 1.22kB/op 2.67× slower
```
#### `includes` vs `to_s.includes` [code](code/string/includes-vs-to_s.includes.cr)
```
$ crystal build --release --no-debug -o bin/code/string/includes-vs-to_s.includes code/string/includes-vs-to_s.includes.cr
$ ./bin/code/string/includes-vs-to_s.includes
String#includes? 368.22M ( 2.72ns) (± 8.30%) 0.0B/op 1.02× slower
Nil#to_s#includes? 376.21M ( 2.66ns) (± 6.76%) 0.0B/op fastest
```
#### `nil` vs `to_s.empty` [code](code/string/nil-vs-to_s.empty.cr)
```
$ crystal build --release --no-debug -o bin/code/string/nil-vs-to_s.empty code/string/nil-vs-to_s.empty.cr
$ ./bin/code/string/nil-vs-to_s.empty
String#nil? 468.25M ( 2.14ns) (±14.49%) 0.0B/op fastest
Nil#to_s#empty? 450.24M ( 2.22ns) (±14.74%) 0.0B/op 1.04× slower
```
#### `sub` vs `chomp` [code](code/string/sub-vs-chomp.cr)
```
$ crystal build --release --no-debug -o bin/code/string/sub-vs-chomp code/string/sub-vs-chomp.cr
$ ./bin/code/string/sub-vs-chomp
String#chomp"string" 43.85M ( 22.81ns) (±12.35%) 32.0B/op fastest
String#sub/regexp/ 3.57M (280.13ns) (± 5.92%) 176B/op 12.28× slower
```
## You may also like
- [halite](https://github.com/icyleaf/halite) - HTTP Requests Client with a chainable REST API, built-in sessions and middlewares.
- [totem](https://github.com/icyleaf/totem) - Load and parse a configuration file or string in JSON, YAML, dotenv formats.
- [markd](https://github.com/icyleaf/markd) - Yet another markdown parser built for speed, Compliant to CommonMark specification.
- [poncho](https://github.com/icyleaf/poncho) - A .env parser/loader improved for performance.
- [popcorn](https://github.com/icyleaf/popcorn) - Easy and Safe casting from one type to another.
================================================
FILE: code/array/first-vs-index[0].cr
================================================
require "benchmark"
ARRAY = (1..100).to_a
def fast
ARRAY.first
end
def slow
ARRAY[0]
end
Benchmark.ips do |x|
x.report("Array#first") { fast }
x.report("Array#[0]") { slow }
end
================================================
FILE: code/array/insert-vs-unshift.cr
================================================
require "benchmark"
Benchmark.ips do |x|
x.report("Array#insert") do
array = [] of Int32
100_000.times { |i| array.insert(0, i) }
end
x.report("Array#unshift") do
array = [] of Int32
100_000.times { |i| array.unshift(i) }
end
end
================================================
FILE: code/array/last-vs-index[-1].cr
================================================
require "benchmark"
ARRAY = (1..100).to_a
def fast
ARRAY[-1]
end
def slow
ARRAY.last
end
Benchmark.ips do |x|
x.report("Array#[-1]") { fast }
x.report("Array#last") { slow }
end
================================================
FILE: code/array/range-vs-times.map.cr
================================================
require "benchmark"
Benchmark.ips do |x|
x.report("Range#to_a") do
(1..100).to_a
end
x.report("Times#to_a") do
100.times.map { |i| i + 1 }.to_a
end
end
================================================
FILE: code/enumerable/each-push-vs-map.cr
================================================
require "benchmark"
ARRAY = (1..1000).to_a
def fastest
ARRAY.map { |i| i }
end
def fast
array = [] of Int32
ARRAY.each { |i| array.push i }
array
end
def slow
ARRAY.each_with_object([] of Int32) { |i, obj| obj << i }
end
Benchmark.ips do |x|
x.report("Array#map") { fastest }
x.report("Array#each + push") { fast }
x.report("Array#each_with_object") { slow }
end
================================================
FILE: code/enumerable/each-vs-loop.cr
================================================
require "benchmark"
ARRAY = (1..100).to_a
def fast
i = 0
while i < ARRAY.size
ARRAY[i]
i += 1
end
end
def slow
ARRAY.each do |number|
number
end
end
Benchmark.ips do |x|
x.report("While Loop") { fast }
x.report("#each") { slow }
end
================================================
FILE: code/enumerable/each_with_index-vs-while-loop.cr
================================================
require "benchmark"
ARRAY = (1..100).to_a
def fast
index = 0
while index < ARRAY.size
ARRAY[index] + index
index += 1
end
ARRAY
end
def slow
ARRAY.each_with_index do |number, index|
number + index
end
end
Benchmark.ips do |x|
x.report("While Loop") { fast }
x.report("each_with_index") { slow }
end
================================================
FILE: code/enumerable/map-flatten-vs-flat_map.cr
================================================
require "benchmark"
ARRAY = (1..100).to_a
def fastest
ARRAY.flat_map { |e| {e, e} }
end
def fast
ARRAY.map { |e| {e, e} }.flatten
end
def slow
ARRAY.flat_map { |e| [e, e] }
end
def slowest
ARRAY.map { |e| [e, e] }.flatten
end
Benchmark.ips do |x|
x.report("Array#flat_map (Tuple)") { fastest }
x.report("Array#map.flatten (Tuple)") { fast }
x.report("Array#flat_map (Array)") { slow }
x.report("Array#map.flatten (Array)") { slowest }
end
================================================
FILE: code/enumerable/reverse.each-vs-reverse_each.cr
================================================
require "benchmark"
ARRAY = (1..100).to_a
def slow
ARRAY.reverse.each { |x| x }
end
def fast
ARRAY.reverse_each { |x| x }
end
Benchmark.ips do |x|
x.report("Array#reverse.each") { slow }
x.report("Array#reverse_each") { fast }
end
================================================
FILE: code/enumerable/sort-vs-sort_by.cr
================================================
require "benchmark"
struct User
property name
def initialize(@name : String)
end
end
ARRAY = Array.new(100) do
User.new(sprintf "%010d", rand(1_000_000_000))
end
def fast
ARRAY.sort_by(&.name)
end
def slow
ARRAY.sort { |a, b| a.name <=> b.name }
end
Benchmark.ips do |x|
x.report("Enumerable#sort") { fast }
x.report("Enumerable#sort_by") { slow }
end
================================================
FILE: code/general/assignment.cr
================================================
require "benchmark"
def fast
_a, _b, _c, _d, _e, _f, _g, _h = 1, 2, 3, 4, 5, 6, 7, 8
nil
end
def slow
_a = 1
_b = 2
_c = 3
_d = 4
_e = 5
_f = 6
_g = 7
_h = 8
nil
end
Benchmark.ips do |x|
x.report("Sequential Assignment") { slow }
x.report("Parallel Assignment") { fast }
end
================================================
FILE: code/general/hash-vs-struct-vs-namedtuple.cr
================================================
require "benchmark"
struct SampleStruct
property name, year
def initialize(@name : String, @year : Int32)
end
end
def slow
{"name" => "Crystal", "year" => 2011}
end
def fast
SampleStruct.new("Crystal", 2011)
end
def fastest
{name: "Crystal", year: 2011}
end
Benchmark.ips do |x|
x.report("NamedTuple") { fastest }
x.report("Struct") { fast }
x.report("Hash") { slow }
end
================================================
FILE: code/general/loop-vs-while_true.cr
================================================
require "benchmark"
NUMBER = 100_000_000
def fast
index = 0
while true
break if index > NUMBER
index += 1
end
end
def slow
index = 0
loop do
break if index > NUMBER
index += 1
end
end
Benchmark.ips do |x|
x.report("While Loop") { fast }
x.report("Kernel Loop") { slow }
end
================================================
FILE: code/general/positional_argument-vs-named_argument.cr
================================================
require "benchmark"
module M
def self.func(a, b, c)
end
end
def fast
M.func(a: 1, b: 2, c: 3)
end
def slow
M.func(1, 2, 3)
end
Benchmark.ips do |x|
x.report("Named arguments") { fast }
x.report("Positional arguments") { slow }
end
================================================
FILE: code/general/property-vs-getter_and_setter.cr
================================================
require "benchmark"
class User
property :first_name
def initialize
@first_name = ""
@last_name = ""
end
def last_name
@last_name
end
def last_name=(value)
@last_name = value
end
end
def slow
user = User.new
user.last_name = "Wang"
user.last_name
end
def fast
user = User.new
user.first_name = "Wang"
user.first_name
end
Benchmark.ips do |x|
x.report("property") { fast }
x.report("getter_and_setter") { slow }
end
================================================
FILE: code/hash/[]?-vs-has_key?.cr
================================================
require "benchmark"
HASH = {"a" => "z"}
Benchmark.ips do |x|
x.report("Hash#[]?") do
HASH["a"]?
HASH["b"]?
end
x.report("Hash#has_key?") do
HASH.has_key? "a"
HASH.has_key? "b"
end
end
================================================
FILE: code/hash/bracket-vs-fetch.cr
================================================
require "benchmark"
HASH = {"fast" => "ruby"}
NAMEDTUPLE = {fast: "ruby"}
Benchmark.ips do |x|
x.report("Hash#[]") do
HASH["fast"]
end
x.report("Hash#fetch") do
HASH.fetch("fast") { }
end
end
================================================
FILE: code/hash/clone-vs-dup.cr
================================================
require "benchmark"
HASH = ("a".."z").map { |v| {v => v.bytes} }
def fast
HASH.dup
end
def slow
HASH.clone
end
Benchmark.ips do |x|
x.report("Hash#dup") { fast }
x.report("Hash#clone") { slow }
end
================================================
FILE: code/hash/keys-each-vs-each_key.cr
================================================
require "benchmark"
HASH = {
"provider" => "facebook",
"uid" => "1234567",
"info" => {
"nickname" => "jbloggs",
"email" => "joe@bloggs.com",
"name" => "Joe Bloggs",
"first_name" => "Joe",
"last_name" => "Bloggs",
"image" => "http://graph.facebook.com/1234567/picture?type=square",
"urls" => {"Facebook" => "http://www.facebook.com/jbloggs"},
"location" => "Palo Alto, California",
"verified" => true,
},
"credentials" => {
"token" => "ABCDEF...",
"expires_at" => 1321747205,
"expires" => true,
},
"extra" => {
"raw_info" => {
"id" => "1234567",
"name" => "Joe Bloggs",
"first_name" => "Joe",
"last_name" => "Bloggs",
"link" => "http://www.facebook.com/jbloggs",
"username" => "jbloggs",
"location" => {"id" => "123456789", "name" => "Palo Alto, California"},
"gender" => "male",
"email" => "joe@bloggs.com",
"timezone" => -8,
"locale" => "en_US",
"verified" => true,
"updated_time" => "2011-11-11T06:21:03+0000",
},
},
}
def slow
HASH.keys.each(&.downcase)
end
def fast
HASH.each_key(&.downcase)
end
Benchmark.ips do |x|
x.report("Hash#keys.each") { slow }
x.report("Hash#each_key") { fast }
end
================================================
FILE: code/hash/merge-bang-vs-[]=.cr
================================================
require "benchmark"
ENUM = (1..100)
def slow
ENUM.each_with_object({} of Int32 => Int32) do |e, h|
h.merge!({e => e})
end
end
def fast
ENUM.each_with_object({} of Int32 => Int32) do |e, h|
h[e] = e
end
end
Benchmark.ips do |x|
x.report("Hash#merge!") { slow }
x.report("Hash#[]=") { fast }
end
================================================
FILE: code/namedtuple/bracket-vs-fetch.cr
================================================
require "benchmark"
NAMEDTUPLE = {fast: "ruby"}
def fast
NAMEDTUPLE[:fast]
end
def slow
NAMEDTUPLE.fetch(:fast, "")
end
Benchmark.ips do |x|
x.report("NamedTuple#[]") { fast }
x.report("NamedTuple#fetch") { slow }
end
================================================
FILE: code/namedtuple/fetch-vs-fetch_with_block.cr
================================================
require "benchmark"
HASH = {writing: :fast_ruby}
DEFAULT = "fast ruby"
Benchmark.ips do |x|
x.report("NamedTuple#fetch + const") { HASH.fetch(:writing, DEFAULT) }
x.report("NamedTuple#fetch + block") { HASH.fetch(:writing) { "fast ruby" } }
x.report("NamedTuple#fetch + arg") { HASH.fetch(:writing, "fast ruby") }
end
================================================
FILE: code/proc-and-block/block-vs-to_proc.cr
================================================
require "benchmark"
RANGE = (1..100)
def slow
RANGE.map { |i| i.to_s }
end
def fast
RANGE.map(&.to_s)
end
Benchmark.ips do |x|
x.report("Block") { slow }
x.report("Symbol#to_proc") { fast }
end
================================================
FILE: code/proc-and-block/proc-call-vs-yield.cr
================================================
require "benchmark"
def slow(&block)
block.call
end
def slow2(&block)
yield
end
def slow3(&block)
end
def fast
yield
end
Benchmark.ips do |x|
x.report("block.call") { slow { 1 + 1 } }
x.report("block + yield") { slow2 { 1 + 1 } }
x.report("block argument") { slow3 { 1 + 1 } }
x.report("yield") { fast { 1 + 1 } }
end
================================================
FILE: code/string/concatenation.cr
================================================
require "benchmark"
WORLD = "world"
def fastest
"hello " + WORLD
end
def fast
"hello #{WORLD}"
end
def slow
"hello %s" % WORLD
end
Benchmark.ips do |x|
x.report("String#+") { fastest }
x.report("String\#{}") { fast }
x.report("String#%") { slow }
end
================================================
FILE: code/string/ends-string-matching-match-vs-end_with.cr
================================================
require "benchmark"
SLUG = "root_url"
def fast
SLUG.ends_with?("_url")
end
def slow
SLUG =~ /_url$/
end
Benchmark.ips do |x|
x.report("String#end_with?") { fast }
x.report("String#=~") { slow }
end
================================================
FILE: code/string/equal-substring-of-char.cr
================================================
require "benchmark"
def fastest
"===="[0] == '='
end
def fast
"===="[0].to_s == "="
end
def slow
"===="[0] == "=".chars[0]
end
Benchmark.ips do |x|
x.report("\"===\"[0] == '='") { fastest }
x.report("\"===\"[0].to_s == \"=\"") { fast }
x.report("\"===\"[0] == \"=\".chars[0]") { slow }
end
================================================
FILE: code/string/equal-vs-match.cr
================================================
require "benchmark"
def fastest
"foo".match(/boo/)
end
def fast
/boo/ === "foo"
end
def slow
"foo" =~ /boo/
end
Benchmark.ips do |x|
x.report("String#match") { fastest }
x.report("Regexp#===") { fast }
x.report("String#=~") { slow }
end
================================================
FILE: code/string/gsub-vs-sub.cr
================================================
require "benchmark"
URL = "http://www.thelongestlistofthelongeststuffatthelongestdomainnameatlonglast.com/wearejustdoingthistobestupidnowsincethiscangoonforeverandeverandeverbutitstilllookskindaneatinthebrowsereventhoughitsabigwasteoftimeandenergyandhasnorealpointbutwehadtodoitanyways.html"
def slow
URL.gsub("http://", "https://")
end
def fast
URL.sub("http://", "https://")
end
Benchmark.ips do |x|
x.report("String#sub") { fast }
x.report("String#gsub") { slow }
end
================================================
FILE: code/string/includes-vs-to_s.includes.cr
================================================
require "benchmark"
def slow
"foobar".includes?("crystal")
end
def fast
nil.to_s.includes?("crystal")
end
Benchmark.ips do |x|
x.report("String#includes?") { fast }
x.report("Nil#to_s#includes?") { slow }
end
================================================
FILE: code/string/nil-vs-to_s.empty.cr
================================================
require "benchmark"
def slow
nil.to_s.empty?
end
def fast
"".nil?
end
Benchmark.ips do |x|
x.report("String#nil?") { fast }
x.report("Nil#to_s#empty?") { slow }
end
================================================
FILE: code/string/sub-vs-chomp.cr
================================================
require "benchmark"
SLUG = "YourSubclassType"
def fast
SLUG.chomp("Type")
end
def slow
SLUG.sub(/Type\z/, "")
end
Benchmark.ips do |x|
x.report("String#chomp\"string\"") { fast }
x.report("String#sub/regexp/") { slow }
end
================================================
FILE: shard.yml
================================================
name: fast-crystal
version: 0.2.2
authors:
- icyleaf <icyleaf.cn@gmail.com>
targets:
fast-crystal:
main: src/fast-crystal.cr
crystal: 0.35.1
license: MIT
================================================
FILE: src/fast-crystal.cr
================================================
require "file_utils"
BIN_PATH = "bin/code"
SOURCE_PATH = File.expand_path("code")
CRYSTAL_BIN = `which crystal`.strip
CRYSTAL_VERSION = `#{CRYSTAL_BIN} -v`.strip
if Dir.exists?(BIN_PATH)
FileUtils.rm_rf(BIN_PATH)
end
puts
puts "> Test in #{CRYSTAL_VERSION.split("\n").join(" ")}"
puts
section = ""
files = if (file = ARGV[0]?) && File.exists? file
{file}
else
Dir.glob("code/**/*.cr").sort
end
files.each do |file|
test_file = File.basename(file)
test_section = file.sub(test_file, "").sub("code/", "")[0..-2]
bin_section = File.join(BIN_PATH, test_section)
bin_file = File.join(bin_section, File.basename(test_file, File.extname(test_file)))
FileUtils.mkdir_p(bin_section)
if section.empty? || section != test_section
section = test_section
puts "### " + (section == "proc-and-block" ? "Proc & Block" : section.capitalize)
puts
end
compile_command = [CRYSTAL_BIN, "build", "--release", "--no-debug", "-o", bin_file, file]
print_title(file)
puts
puts "```"
puts "$ " + compile_command.join(" ")
`#{compile_command.join(" ")}`
puts "$ ./" + bin_file
puts
puts `./#{bin_file}`
puts "```"
puts
end
def print_title(file)
filename = File.basename(file)
file_path = file.sub(SOURCE_PATH, "")
title = filename.sub(File.extname(filename), "")
title = if title.includes?("-vs-")
title_sections = [] of String
title.split("-vs-").each do |str|
title_sections << "`" + (str.includes?("[-1]") ? str : str.sub("-", " ")) + "`"
end
title_sections.join(" vs ")
else
title.capitalize
end
puts "#### " + title + " [code](" + file_path + ")"
end
gitextract_y1nbnp85/
├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── code/
│ ├── array/
│ │ ├── first-vs-index[0].cr
│ │ ├── insert-vs-unshift.cr
│ │ ├── last-vs-index[-1].cr
│ │ └── range-vs-times.map.cr
│ ├── enumerable/
│ │ ├── each-push-vs-map.cr
│ │ ├── each-vs-loop.cr
│ │ ├── each_with_index-vs-while-loop.cr
│ │ ├── map-flatten-vs-flat_map.cr
│ │ ├── reverse.each-vs-reverse_each.cr
│ │ └── sort-vs-sort_by.cr
│ ├── general/
│ │ ├── assignment.cr
│ │ ├── hash-vs-struct-vs-namedtuple.cr
│ │ ├── loop-vs-while_true.cr
│ │ ├── positional_argument-vs-named_argument.cr
│ │ └── property-vs-getter_and_setter.cr
│ ├── hash/
│ │ ├── []?-vs-has_key?.cr
│ │ ├── bracket-vs-fetch.cr
│ │ ├── clone-vs-dup.cr
│ │ ├── keys-each-vs-each_key.cr
│ │ └── merge-bang-vs-[]=.cr
│ ├── namedtuple/
│ │ ├── bracket-vs-fetch.cr
│ │ └── fetch-vs-fetch_with_block.cr
│ ├── proc-and-block/
│ │ ├── block-vs-to_proc.cr
│ │ └── proc-call-vs-yield.cr
│ └── string/
│ ├── concatenation.cr
│ ├── ends-string-matching-match-vs-end_with.cr
│ ├── equal-substring-of-char.cr
│ ├── equal-vs-match.cr
│ ├── gsub-vs-sub.cr
│ ├── includes-vs-to_s.includes.cr
│ ├── nil-vs-to_s.empty.cr
│ └── sub-vs-chomp.cr
├── shard.yml
└── src/
└── fast-crystal.cr
Condensed preview — 38 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (32K chars).
[
{
"path": ".gitignore",
"chars": 28,
"preview": "/doc/\n/lib/\n/bin/\n/.shards/\n"
},
{
"path": "LICENSE",
"chars": 1079,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2017-2019 icyleaf\n\nPermission is hereby granted, free of charge, to any person obta"
},
{
"path": "Makefile",
"chars": 230,
"preview": "CRYSTAL_BIN ?= $(shell which crystal)\nPREFIX ?= /usr/local\n\nrun: build\n\t./bin/fast-crystal\n\nclean:\n\trm -rf bin\n\tmkdir bi"
},
{
"path": "README.md",
"chars": 14833,
"preview": "# 💎 Fast Crystal\n\nIt's Crystal version based on [ruby version](https://github.com/JuanitoFatas/fast-ruby).\n\nEach idiom h"
},
{
"path": "code/array/first-vs-index[0].cr",
"chars": 190,
"preview": "require \"benchmark\"\n\nARRAY = (1..100).to_a\n\ndef fast\n ARRAY.first\nend\n\ndef slow\n ARRAY[0]\nend\n\nBenchmark.ips do |x|\n "
},
{
"path": "code/array/insert-vs-unshift.cr",
"chars": 256,
"preview": "require \"benchmark\"\n\nBenchmark.ips do |x|\n x.report(\"Array#insert\") do\n array = [] of Int32\n 100_000.times { |i| "
},
{
"path": "code/array/last-vs-index[-1].cr",
"chars": 190,
"preview": "require \"benchmark\"\n\nARRAY = (1..100).to_a\n\ndef fast\n ARRAY[-1]\nend\n\ndef slow\n ARRAY.last\nend\n\nBenchmark.ips do |x|\n "
},
{
"path": "code/array/range-vs-times.map.cr",
"chars": 170,
"preview": "require \"benchmark\"\n\nBenchmark.ips do |x|\n x.report(\"Range#to_a\") do\n (1..100).to_a\n end\n\n x.report(\"Times#to_a\") "
},
{
"path": "code/enumerable/each-push-vs-map.cr",
"chars": 384,
"preview": "require \"benchmark\"\n\nARRAY = (1..1000).to_a\n\ndef fastest\n ARRAY.map { |i| i }\nend\n\ndef fast\n array = [] of Int32\n ARR"
},
{
"path": "code/enumerable/each-vs-loop.cr",
"chars": 263,
"preview": "require \"benchmark\"\n\nARRAY = (1..100).to_a\n\ndef fast\n i = 0\n while i < ARRAY.size\n ARRAY[i]\n i += 1\n end\nend\n\nd"
},
{
"path": "code/enumerable/each_with_index-vs-while-loop.cr",
"chars": 331,
"preview": "require \"benchmark\"\n\nARRAY = (1..100).to_a\n\ndef fast\n index = 0\n while index < ARRAY.size\n ARRAY[index] + index\n "
},
{
"path": "code/enumerable/map-flatten-vs-flat_map.cr",
"chars": 461,
"preview": "require \"benchmark\"\n\nARRAY = (1..100).to_a\n\ndef fastest\n ARRAY.flat_map { |e| {e, e} }\nend\n\ndef fast\n ARRAY.map { |e| "
},
{
"path": "code/enumerable/reverse.each-vs-reverse_each.cr",
"chars": 243,
"preview": "require \"benchmark\"\n\nARRAY = (1..100).to_a\n\ndef slow\n ARRAY.reverse.each { |x| x }\nend\n\ndef fast\n ARRAY.reverse_each {"
},
{
"path": "code/enumerable/sort-vs-sort_by.cr",
"chars": 374,
"preview": "require \"benchmark\"\n\nstruct User\n property name\n\n def initialize(@name : String)\n end\nend\n\nARRAY = Array.new(100) do\n"
},
{
"path": "code/general/assignment.cr",
"chars": 304,
"preview": "require \"benchmark\"\n\ndef fast\n _a, _b, _c, _d, _e, _f, _g, _h = 1, 2, 3, 4, 5, 6, 7, 8\n nil\nend\n\ndef slow\n _a = 1\n _"
},
{
"path": "code/general/hash-vs-struct-vs-namedtuple.cr",
"chars": 396,
"preview": "require \"benchmark\"\n\nstruct SampleStruct\n property name, year\n\n def initialize(@name : String, @year : Int32)\n end\nen"
},
{
"path": "code/general/loop-vs-while_true.cr",
"chars": 310,
"preview": "require \"benchmark\"\n\nNUMBER = 100_000_000\n\ndef fast\n index = 0\n while true\n break if index > NUMBER\n index += 1\n"
},
{
"path": "code/general/positional_argument-vs-named_argument.cr",
"chars": 247,
"preview": "require \"benchmark\"\n\nmodule M\n def self.func(a, b, c)\n end\nend\n\ndef fast\n M.func(a: 1, b: 2, c: 3)\nend\n\ndef slow\n M."
},
{
"path": "code/general/property-vs-getter_and_setter.cr",
"chars": 467,
"preview": "require \"benchmark\"\n\nclass User\n property :first_name\n\n def initialize\n @first_name = \"\"\n @last_name = \"\"\n end\n"
},
{
"path": "code/hash/[]?-vs-has_key?.cr",
"chars": 211,
"preview": "require \"benchmark\"\n\nHASH = {\"a\" => \"z\"}\n\nBenchmark.ips do |x|\n x.report(\"Hash#[]?\") do\n HASH[\"a\"]?\n HASH[\"b\"]?\n "
},
{
"path": "code/hash/bracket-vs-fetch.cr",
"chars": 217,
"preview": "require \"benchmark\"\n\nHASH = {\"fast\" => \"ruby\"}\nNAMEDTUPLE = {fast: \"ruby\"}\n\nBenchmark.ips do |x|\n x.report(\"Hash#"
},
{
"path": "code/hash/clone-vs-dup.cr",
"chars": 210,
"preview": "require \"benchmark\"\n\nHASH = (\"a\"..\"z\").map { |v| {v => v.bytes} }\n\ndef fast\n HASH.dup\nend\n\ndef slow\n HASH.clone\nend\n\nB"
},
{
"path": "code/hash/keys-each-vs-each_key.cr",
"chars": 1370,
"preview": "require \"benchmark\"\n\nHASH = {\n \"provider\" => \"facebook\",\n \"uid\" => \"1234567\",\n \"info\" => {\n \"nickname\" "
},
{
"path": "code/hash/merge-bang-vs-[]=.cr",
"chars": 318,
"preview": "require \"benchmark\"\n\nENUM = (1..100)\n\ndef slow\n ENUM.each_with_object({} of Int32 => Int32) do |e, h|\n h.merge!({e ="
},
{
"path": "code/namedtuple/bracket-vs-fetch.cr",
"chars": 230,
"preview": "require \"benchmark\"\n\nNAMEDTUPLE = {fast: \"ruby\"}\n\ndef fast\n NAMEDTUPLE[:fast]\nend\n\ndef slow\n NAMEDTUPLE.fetch(:fast, \""
},
{
"path": "code/namedtuple/fetch-vs-fetch_with_block.cr",
"chars": 329,
"preview": "require \"benchmark\"\n\nHASH = {writing: :fast_ruby}\nDEFAULT = \"fast ruby\"\n\nBenchmark.ips do |x|\n x.report(\"NamedTuple#"
},
{
"path": "code/proc-and-block/block-vs-to_proc.cr",
"chars": 206,
"preview": "require \"benchmark\"\n\nRANGE = (1..100)\n\ndef slow\n RANGE.map { |i| i.to_s }\nend\n\ndef fast\n RANGE.map(&.to_s)\nend\n\nBenchm"
},
{
"path": "code/proc-and-block/proc-call-vs-yield.cr",
"chars": 337,
"preview": "require \"benchmark\"\n\ndef slow(&block)\n block.call\nend\n\ndef slow2(&block)\n yield\nend\n\ndef slow3(&block)\nend\n\ndef fast\n "
},
{
"path": "code/string/concatenation.cr",
"chars": 268,
"preview": "require \"benchmark\"\n\nWORLD = \"world\"\n\ndef fastest\n \"hello \" + WORLD\nend\n\ndef fast\n \"hello #{WORLD}\"\nend\n\ndef slow\n \"h"
},
{
"path": "code/string/ends-string-matching-match-vs-end_with.cr",
"chars": 210,
"preview": "require \"benchmark\"\n\nSLUG = \"root_url\"\n\ndef fast\n SLUG.ends_with?(\"_url\")\nend\n\ndef slow\n SLUG =~ /_url$/\nend\n\nBenchmar"
},
{
"path": "code/string/equal-substring-of-char.cr",
"chars": 306,
"preview": "require \"benchmark\"\n\ndef fastest\n \"====\"[0] == '='\nend\n\ndef fast\n \"====\"[0].to_s == \"=\"\nend\n\ndef slow\n \"====\"[0] == \""
},
{
"path": "code/string/equal-vs-match.cr",
"chars": 253,
"preview": "require \"benchmark\"\n\ndef fastest\n \"foo\".match(/boo/)\nend\n\ndef fast\n /boo/ === \"foo\"\nend\n\ndef slow\n \"foo\" =~ /boo/\nend"
},
{
"path": "code/string/gsub-vs-sub.cr",
"chars": 483,
"preview": "require \"benchmark\"\n\nURL = \"http://www.thelongestlistofthelongeststuffatthelongestdomainnameatlonglast.com/wearejustdoin"
},
{
"path": "code/string/includes-vs-to_s.includes.cr",
"chars": 220,
"preview": "require \"benchmark\"\n\ndef slow\n \"foobar\".includes?(\"crystal\")\nend\n\ndef fast\n nil.to_s.includes?(\"crystal\")\nend\n\nBenchma"
},
{
"path": "code/string/nil-vs-to_s.empty.cr",
"chars": 176,
"preview": "require \"benchmark\"\n\ndef slow\n nil.to_s.empty?\nend\n\ndef fast\n \"\".nil?\nend\n\nBenchmark.ips do |x|\n x.report(\"String#nil"
},
{
"path": "code/string/sub-vs-chomp.cr",
"chars": 235,
"preview": "require \"benchmark\"\n\nSLUG = \"YourSubclassType\"\n\ndef fast\n SLUG.chomp(\"Type\")\nend\n\ndef slow\n SLUG.sub(/Type\\z/, \"\")\nend"
},
{
"path": "shard.yml",
"chars": 166,
"preview": "name: fast-crystal\nversion: 0.2.2\n\nauthors:\n - icyleaf <icyleaf.cn@gmail.com>\n\ntargets:\n fast-crystal:\n main: src/f"
},
{
"path": "src/fast-crystal.cr",
"chars": 1747,
"preview": "require \"file_utils\"\n\nBIN_PATH = \"bin/code\"\nSOURCE_PATH = File.expand_path(\"code\")\nCRYSTAL_BIN = `which c"
}
]
About this extraction
This page contains the full source code of the icyleaf/fast-crystal GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 38 files (27.6 KB), approximately 11.2k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.