Skip to content

Instantly share code, notes, and snippets.

View nevans's full-sized avatar

nicholas a. evans nevans

View GitHub Profile
nevans / ractor_shenanigans.rb
Last active August 24, 2022 18:27
freezing procs
# frozen_string_literal: true
# requires ruby 3.1+
# Ractor.make_shareable(proc) only succeeds if everything on the proc's binding is shareable.
# This makes it difficult to create wrappers around that accept an arbitrary block.
# Even this would still require the block declare any outer variables as block-locals, even if
# they aren't used.
class ProcFreezer
def initialize = freeze
nevans / rfc9051-syntax.abnf
Last active June 17, 2022 18:46
RFC-9051 Formal Syntax
TEXT-CHAR = %x01-09 / %x0B-0C / %x0E-7F
; <any CHAR except CR and LF>
; %x01-09 / %x0B-0C / %x0E-7F
any-TEXT-CHAR-except-quoted-specials = %x01-09 / %x0B-0C / %x0E-21 / %x23-5B / %x5D-7F
; <any TEXT-CHAR except quoted-specials>
; '"' = %x22
; '\' = %x5C
ATOM-CHAR = %x21 / %x23-24 / %x26-27 / %x2B-5B / %x5E-7A / %x7C-7E
nevans / ruby_priority_queues.txt
Last active March 24, 2021 17:27
Benchmarks for some pure ruby priority queue implementations
# Run on an Intel(R) Core(TM) i7-1065G7
# using ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-linux]
# n.b. when running these benchmarks, I did not shut down other
# processes (including web browser) nor did I run the benchmark
# multiple times (using "--repeat-count"). The numbers would be
# slightly faster and more stable/reliable if I'd done that.
# Maybe (maybe) I'll re-run them later.
Warming up --------------------------------------
nevans /
Last active November 28, 2023 12:48
IMAP Specifications

IMAP specifications

(TODO) All IANA registered IMAP capabilities, response codes, keywords, mailbox attributes, the most relevant SASL mechanisms, and other relevant specifications.

  • ⛔️: obsolete specifications that have been deprecated or replaced
  • ⏭️: extensions that have been completely or partially included in [IMAP4rev2].
  • ✨: extensions that are recommended for [IMAP4rev2] servers and clients. The IETF EXTRA WG decided that requiring them as a part of IMAP4rev2 would push the bar to implement too high for new implementations.
  • 🗑: extensions that have been completely or partially deprecated or removed in [IMAP4rev2].
  • 🍋: extensions that are included in the "Lemonade" profile [RFC5550].
#!/usr/bin/env bash
set -eo pipefail
bundle show |
grep -v '^Gems' |
sed 's/^ \* \|(\|)//g' |
while read -r line; do
gemname=$(echo "$line" | cut -f1 -d" ")
version=$(echo "$line" | cut -f2 -d" ")
gitsha1=$(echo "$line" | cut -f3 -d" ")
# frozen_string_literal: true
require "fiber" # needed for transfer
RootFiberException =
RootFiberTestSignal =
# Warning: this is only safe to call from the root fiber for a thread.
# Unfortunately, your code may not know if it is in the root fiber. This will
# raise an exception in the root fiber of the current thread. If you are in the
nevans / verify_and_decrypt_session_cookie.rb
Last active June 12, 2023 03:36
Rails 5.2.4: verifying and decrypting session cookies, to be used from rails console or in a script with the rails application loaded
nevans / http_connection_bm.rb
Last active August 29, 2015 14:00
HTTP with or without TCP_NODELAY (client or server)
require "benchmark"
require "typhoeus"
require "excon"
require "net/http/persistent"
reps = ENV.fetch("HTTP_BM_REPS", 1000).to_i
url = ENV.fetch("HTTP_BM_URL", "http://localhost:5984/")
nodelay = ENV.fetch("HTTP_BM_NODELAY", "true") == "true"
Excon.defaults[:tcp_nodelay] = nodelay
nevans / gist:9374041
Last active February 16, 2023 23:12
simple ruby console histogram generator
# Pass in an enumeration of data and
# (optionally) a block to extract the grouping aspect of the data.
# Optional: sort_by lambda (operates on group key and count)
def puts_hist(data, sort_by:nil, &blk)
data = if blk
counts = data.each_with_object( {|k,h| h[k]+=1}
max = counts.values.max
width = Pry::Terminal.size!.last
nevans /
Last active August 28, 2020 12:48
Improving speed on slow CouchDB reduce functions

A common pattern in my CouchDB view reductions is to "merge" together the objects generated by the map function while preserving the original form, and only query that view with group=true. It's easiest to write the view reductions naively, so they continue merging the data all the way up to the top-level reduction (group=false).

But because CouchDB stores its b+trees with the reduction for each b+tree node stored in that node, moderately sized objects can result in a lot of extra writes to disk, and moderately complicated functions can cause a lot of wasted CPU time in the indexer running merge javascript that is never queried. Re-balancing the b+tree compounds this problem. This can cause the initial creation of large indexes to slow down tremendously. If the index becomes terribly fragmented, this will also affect query speed.

One solution: once the reduction is beyond the keys at the group level I care about, stop running the merge code and return the simplest data that works (e.g. null or