Skip to content

Instantly share code, notes, and snippets.

Avatar
👾

Jamie Gaskins jgaskins

👾
View GitHub Profile
@jgaskins
jgaskins / require.cr
Created May 11, 2022
Project-local requires in Crystal
View require.cr
# Experiment with macros to allow for project-local requires
# https://forum.crystal-lang.org/t/project-relative-require/4617
{% begin %}
ROOT = "{{system("pwd").strip.id}}"
{% end %}
macro spec(file)
macro load_spec
\{% path = __DIR__.gsub(%r{\A{{ROOT.id}}}, "").gsub(%r{[^/]+}, "..").id %}
require "\{{path[1..]}}/spec/{{file.id}}"
@jgaskins
jgaskins / elasticsearch_example.cr
Last active Jan 30, 2022
Elasticsearch Example in Crystal
View elasticsearch_example.cr
require "http"
require "json"
require "uuid/json"
require "db"
require "interro" # github: jgaskins/interro
require "faker" # github: askn/faker
ES = ElasticSearch::Client.new
pg = DB.open("postgres:///")
Interro.config { |c| c.db = pg }
@jgaskins
jgaskins / immutable_each_array.cr
Last active Jan 5, 2022
Array that does not let you mutate while inside an `each` block
View immutable_each_array.cr
class ImmutableEachArray(T)
include Enumerable(T)
@iterating = Atomic(Int32).new(0)
@array = Array(T).new
def <<(value : T) : self
raise CannotMutateWhileIterating.new("you iteratin bruh") if @iterating.get > 0
@array << value
@jgaskins
jgaskins / 000-highlights.md
Last active May 28, 2021
Benchmarking Redis drivers: Ruby gem, Hiredis, and a custom Ruby implementation
View 000-highlights.md

Drivers

Name Description
ruby The redis gem with the plain-Ruby driver
hiredis The redis gem with the hiredis driver (compiled as a C extension)
myredis Pure-Ruby, optimized for the specific operation

Benchmarks

@jgaskins
jgaskins / benchmark.rb
Last active Jun 25, 2022
Benchmarking redis gem vs hiredis vs custom Redis client
View benchmark.rb
require 'bundler/inline'
require 'socket'
class MyRedis
CRLF = "\r\n"
def initialize
@connection = TCPSocket.new('localhost', 6379)
@connection.sync = false
end
@jgaskins
jgaskins / app.cr
Created Jan 18, 2021
Roda-like routing mixin for Crystal
View app.cr
require "http"
require "./route"
class App
include HTTP::Handler
include Route
def call(context)
route context do |r, response|
@jgaskins
jgaskins / bench_allocations.cr
Created Dec 3, 2020
Benchmarking allocation time of Crystal objects with various quantities of instance variables
View bench_allocations.cr
require "benchmark"
value = nil
Benchmark.ips do |x|
x.report "1 ivar" { value = OneIVar.new }
x.report "2 ivars" { value = TwoIVars.new }
x.report "4 ivars" { value = FourIVars.new }
x.report "8 ivars" { value = EightIVars.new }
x.report "16 ivars" { value = SixteenIVars.new }
end
@jgaskins
jgaskins / bench_parse_int.cr
Created Jun 28, 2020
Compare parsing an int as intermediate strings vs using a byte parser directly on the IO
View bench_parse_int.cr
require "benchmark"
int = 0
[1, 12, 1234, 12345678, 1234567812345678].each do |number|
puts "Parsing #{number}..."
io = IO::Memory.new
io << ":#{number}\r\n" # Redis integer format
io.rewind
Benchmark.ips do |x|
@jgaskins
jgaskins / redis.cr
Created May 28, 2020
Simple Redis implementation in Crystal
View redis.cr
require "socket"
module Redis
alias Type = String | Int64 | Nil | Array(Type)
class Future
property! value : Type
end
module Commands
@jgaskins
jgaskins / redis_ext.cr
Created May 28, 2020
Adding stream support to Crystal Redis
View redis_ext.cr
class Redis
module Commands
def xadd(stream, id, params : Hash)
params = params.each_with_object(Array(String).new(params.size * 2)) do |(key, value), array|
array << key << value.to_s
end
string_command(["XADD", stream, id] + params)
end
def xrange(stream, start, finish)