Skip to content

Commit

Permalink
Create profile.yml (#42)
Browse files Browse the repository at this point in the history
* Create profile.yml

* update profile

* Update profile.yml

* comment out set

* Update profile.yml

* try simplest

* Update profile.yml

* local dalli

* Update profile.yml

* ok

* profile both get and set

* improvements on bench and add multi to profiles

* raw bench

* Update profile.yml
  • Loading branch information
danmayer authored Feb 4, 2025
1 parent 6104ccd commit 3700ea5
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 14 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/profile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Profiles

on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Install Memcached 1.6.23
working-directory: scripts
env:
MEMCACHED_VERSION: 1.6.23
run: |
chmod +x ./install_memcached.sh
./install_memcached.sh
memcached -d
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.4
bundler-cache: true # 'bundle install' and cache
- name: Run Profiles
run: RUBY_YJIT_ENABLE=1 BENCH_TARGET=all bundle exec bin/profile
- name: Upload profile results
uses: actions/upload-artifact@v4
with:
name: profile-results
path: |
client_get_profile.json
socket_get_profile.json
client_set_profile.json
socket_set_profile.json
client_get_multi_profile.json
socket_get_multi_profile.json
client_set_multi_profile.json
socket_set_multi_profile.json
11 changes: 4 additions & 7 deletions bin/benchmark
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,13 @@ bench_target = ENV['BENCH_TARGET'] || 'set'
bench_time = (ENV['BENCH_TIME'] || 10).to_i
bench_warmup = (ENV['BENCH_WARMUP'] || 3).to_i
bench_payload_size = (ENV['BENCH_PAYLOAD_SIZE'] || 700_000).to_i
payload = 'B' * bench_payload_size
TERMINATOR = "\r\n"
puts "yjit: #{RubyVM::YJIT.enabled?}"

client = Dalli::Client.new('localhost', serializer: StringSerializer, compress: false)
multi_client = Dalli::Client.new('localhost:112111,localhost:11222', serializer: StringSerializer, compress: false)
string_client = Dalli::Client.new('localhost', serializer: StringSerializer, compress: false)
client = Dalli::Client.new('localhost', serializer: StringSerializer, compress: false, raw: true)
multi_client = Dalli::Client.new('localhost:11211,localhost:11222', serializer: StringSerializer, compress: false, raw: true)

# The raw socket implementation is used to benchmark the performance of dalli & the overhead of the various abstractions
# in the library.
sock = TCPSocket.new('127.0.0.1', '11211', connect_timeout: 1)
Expand All @@ -58,12 +59,8 @@ sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
# Benchamrks did see an improvement in performance when increasing the SO_SNDBUF buffer size
sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, 1024 * 1024 * 8)

TERMINATOR = "\r\n"
payload = 'B' * bench_payload_size

# ensure the clients are all connected and working
client.set('key', payload)
string_client.set('string_key', payload)
sock.write("set sock_key 0 3600 #{payload.bytesize}\r\n")
sock.write(payload)
sock.write(TERMINATOR)
Expand Down
69 changes: 62 additions & 7 deletions bin/profile
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ require 'json'

gemfile do
source 'https://rubygems.org'
gem 'dalli'
gem 'benchmark-ips'
gem 'vernier'
gem 'logger'
end

require 'dalli'
require_relative '../lib/dalli'
require 'benchmark/ips'
require 'vernier'

Expand Down Expand Up @@ -46,7 +45,6 @@ TERMINATOR = "\r\n"
puts "yjit: #{RubyVM::YJIT.enabled?}"

client = Dalli::Client.new('localhost', serializer: StringSerializer, compress: false)
multi_client = Dalli::Client.new('localhost:112111,localhost:11222', serializer: StringSerializer, compress: false)

# The raw socket implementation is used to benchmark the performance of dalli & the overhead of the various abstractions
# in the library.
Expand Down Expand Up @@ -96,15 +94,31 @@ def sock_get_multi(sock, pairs)
next unless line.start_with?('VA ') || last_result

_, value_length, _flags, key = line.split
value = sock.read(value_length.to_i + TERMINATOR.length)
results[key[1..]] = value.chomp!(0..-TERMINATOR.length)
results[key[1..]] = sock.read(value_length.to_i)
sock.read(TERMINATOR.length)
break if results.size == pairs.size
break if last_result
end
results
end

if bench_target == 'get'
def sock_set_multi(sock, pairs)
count = pairs.length
tail = ''
ttl = 3600

pairs.each do |key, value|
count -= 1
tail = count.zero? ? '' : 'q'
sock.write(String.new("ms #{key} #{value.bytesize} c F0 T#{ttl} MS #{tail}\r\n", capacity: key.size + value.bytesize + 40))
sock.write(value)
sock.write(TERMINATOR)
end
sock.flush
sock.gets(TERMINATOR) # clear the buffer
end

if %w[all get].include?(bench_target)
Vernier.profile(out: 'client_get_profile.json') do
start_time = Time.now
client.get(dalli_key) while Time.now - start_time < bench_time
Expand All @@ -118,5 +132,46 @@ if bench_target == 'get'
sock.read(payload.bytesize)
end
end
exit 0
end

if %w[all set].include?(bench_target)
Vernier.profile(out: 'client_set_profile.json') do
start_time = Time.now
client.set(dalli_key, payload, 3600, raw: true) while Time.now - start_time < bench_time
end

Vernier.profile(out: 'socket_set_profile.json') do
start_time = Time.now
while Time.now - start_time < bench_time
sock.write("ms sock_key #{payload.bytesize} T3600 MS\r\n")
sock.write(payload)
sock.write("\r\n")
sock.flush
sock.readline # clear the buffer
end
end
end

if %w[all get_multi].include?(bench_target)
Vernier.profile(out: 'client_get_multi_profile.json') do
start_time = Time.now
client.get_multi(pairs.keys) while Time.now - start_time < bench_time
end

Vernier.profile(out: 'socket_get_multi_profile.json') do
start_time = Time.now
sock_get_multi(sock, pairs) while Time.now - start_time < bench_time
end
end

if %w[all set_multi].include?(bench_target)
Vernier.profile(out: 'client_set_multi_profile.json') do
start_time = Time.now
client.set_multi(pairs, 3600, raw: true) while Time.now - start_time < bench_time
end

Vernier.profile(out: 'socket_set_multi_profile.json') do
start_time = Time.now
sock_set_multi(sock, pairs) while Time.now - start_time < bench_time
end
end

0 comments on commit 3700ea5

Please sign in to comment.