rails-brotli-cache 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 01d8f09dfdea5ea7f2c19ce63e44b88322b319bfcda33f9efeeb679710e78f87
4
- data.tar.gz: bd6df6fadfd6206ed598dab1ced924d59e5c27da6f1c8a0eaeed434f934219c6
3
+ metadata.gz: ed8813c2a9849358eb4d1756cd39eda4acf03846ea166880b956d9c630a5f3ee
4
+ data.tar.gz: cdff030d0d6bdd7e2b7790c5aea0441ecc89e184165c38e899dc5abdc7f5c900
5
5
  SHA512:
6
- metadata.gz: 7919aaad175395d8494f20f1e40b6b5d96e6bd68a3aa60036dd0aa9682b8251e06139fa56748cfe4a5660be3aea5f09f9b7609806336b47b954cefadca227c1d
7
- data.tar.gz: 41ddc8e815662f7f0e9037e5b0beaeacf48cb62eac1c05380b3be44664ed951256cf185d2ecc730f406f7b8a7ee615cad782e68f037907a37b56a1a658766f1d
6
+ metadata.gz: 5bf99730b2b31ed9591157fe75764fb15c17cf84cfd664d148a339e8552ed27dc62512cdff39f84552bc151aa4105d8720546eef38aa9e2da0552427d05ab86f
7
+ data.tar.gz: 7aa77827f595e73d55dc838ac8c6159a3f0f9138ed5bcdf57b2a0876060e01b66704dfd93f2eb8dc6502d109a0933f825bfc9d422858cbb786b03a75569f32d6
data/README.md CHANGED
@@ -9,8 +9,8 @@ This gem enables support for compressing Ruby on Rails cache entries using the [
9
9
  Brotli cache works as a proxy layer wrapping the underlying cache data store.
10
10
 
11
11
  ```ruby
12
- default_cache = ActiveSupport::Cache::RedisCacheStore.new(redis: $redis)
13
- brotli_cache = RailsBrotliCache::Store.new(default_cache)
12
+ redis_cache = ActiveSupport::Cache::RedisCacheStore.new
13
+ brotli_redis_cache = RailsBrotliCache::Store.new(redis_cache)
14
14
  ```
15
15
 
16
16
  **~25%** better compression of a sample JSON object:
@@ -18,8 +18,8 @@ brotli_cache = RailsBrotliCache::Store.new(default_cache)
18
18
  ```ruby
19
19
  json = File.read("sample.json") # sample 435kb JSON text
20
20
  json.size # => 435662
21
- default_cache.write("json", json)
22
- brotli_cache.write("json", json)
21
+ redis_cache.write("json", json)
22
+ brotli_redis_cache.write("json", json)
23
23
 
24
24
  ## Check the size of cache entry stored in Redis
25
25
  $redis.get("json").size # => 31698
@@ -30,8 +30,8 @@ $redis.get("br-json").size # => 24058
30
30
 
31
31
  ```ruby
32
32
  users = User.limit(100).to_a # 100 ActiveRecord objects
33
- default_cache.write("users", users)
34
- brotli_cache.write("users", users)
33
+ redis_cache.write("users", users)
34
+ brotli_redis_cache.write("users", users)
35
35
  $redis.get("users").size # => 12331
36
36
  $redis.get("br-users").size # => 10299
37
37
  ```
@@ -39,27 +39,44 @@ $redis.get("br-users").size # => 10299
39
39
  **~25%** faster performance for reading/writing a larger JSON file:
40
40
 
41
41
  ```ruby
42
- json = File.read("sample.json") # sample 435kb JSON text
42
+ json = File.read("sample.json") # sample ~1mb JSON text
43
43
 
44
44
  Benchmark.bm do |x|
45
- x.report("default_cache") do
46
- 1000.times do
47
- default_cache.write("test", json)
48
- default_cache.read("test")
45
+ x.report("redis_cache") do
46
+ 100.times do
47
+ redis_cache.write("test", json)
48
+ redis_cache.read("test")
49
49
  end
50
50
  end
51
51
 
52
- x.report("brotli_cache") do
53
- 1000.times do
54
- brotli_cache.write("test", json)
55
- brotli_cache.read("test")
52
+ x.report("brotli_redis_cache") do
53
+ 100.times do
54
+ brotli_redis_cache.write("test", json)
55
+ brotli_redis_cache.read("test")
56
56
  end
57
57
  end
58
+
59
+ # ...
58
60
  end
59
61
 
60
- # user system total real
61
- # default_cache 5.177678 0.216435 5.394113 ( 8.296072)
62
- # brotli_cache 3.513312 0.323601 3.836913 ( 6.114179)
62
+ # memory_cache 2.081221 0.051615 2.132836 ( 2.132877)
63
+ # brotli_memory_cache 1.134411 0.032996 1.167407 ( 1.167418)
64
+ # redis_cache 1.782225 0.049936 1.832161 ( 2.523317)
65
+ # brotli_redis_cache 1.218365 0.051084 1.269449 ( 1.850894)
66
+ # memcached_cache 1.766268 0.045351 1.811619 ( 2.504233)
67
+ # brotli_memcached_cache 1.194646 0.051750 1.246396 ( 1.752982)
68
+ ```
69
+
70
+ Regardless of the underlying data store, Brotli cache offers between 20%-40% performance improvment.
71
+
72
+ You can run the benchmarks yourself by executing:
73
+
74
+ ```ruby
75
+ cp docker-compose.yml.sample docker-compose.yml
76
+ docker compose up -d
77
+ cd benchmarks
78
+ bundle install
79
+ ruby main.rb
63
80
  ```
64
81
 
65
82
  ## Configuration
@@ -84,12 +101,13 @@ config.cache_store = RailsBrotliCache::Store.new(
84
101
  )
85
102
  ```
86
103
 
87
- Gem appends `br-` to the cache key names to prevent conflicts with previously saved cache entries. You can disable this behaviour by adding the following initializer file:
88
-
89
- `app/config/initializers/rails-brotli-cache.rb`
104
+ Gem appends `br-` to the cache key names to prevent conflicts with previously saved cache entries. You can disable this behaviour by passing `{ prefix: nil }` during initialization:
90
105
 
91
106
  ```ruby
92
- Rails.cache.disable_prefix!
107
+ config.cache_store = RailsBrotliCache::Store.new(
108
+ ActiveSupport::Cache::MemoryStore.new,
109
+ { prefix: nil }
110
+ )
93
111
  ```
94
112
 
95
113
  ## Testing
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rails-brotli-cache'
@@ -0,0 +1,69 @@
1
+ require 'rails'
2
+ require 'net/http'
3
+ require 'rails-brotli-cache'
4
+
5
+ memory_cache = ActiveSupport::Cache::MemoryStore.new(compress: true) # memory store does not use compression by default
6
+ brotli_memory_cache = RailsBrotliCache::Store.new(memory_cache)
7
+ redis_cache = ActiveSupport::Cache::RedisCacheStore.new
8
+ brotli_redis_cache = RailsBrotliCache::Store.new(redis_cache)
9
+ memcached_cache = ActiveSupport::Cache::MemCacheStore.new
10
+ brotli_memcached_cache = RailsBrotliCache::Store.new(memcached_cache)
11
+
12
+ json_uri = URI("https://raw.githubusercontent.com/pawurb/rails-brotli-cache/main/spec/fixtures/sample.json")
13
+ json = Net::HTTP.get(json_uri)
14
+
15
+ puts "Uncompressed JSON size: #{json.size}"
16
+ redis_cache.write("gz-json", json)
17
+ gzip_json_size = redis_cache.redis.get("gz-json").size
18
+ puts "Gzip JSON size: #{gzip_json_size}"
19
+ brotli_redis_cache.write("json", json)
20
+ br_json_size = redis_cache.redis.get("br-json").size
21
+ puts "Brotli JSON size: #{br_json_size}"
22
+ puts "~#{((gzip_json_size - br_json_size).to_f / gzip_json_size.to_f * 100).round}% improvment"
23
+ puts ""
24
+
25
+ iterations = 100
26
+
27
+ Benchmark.bm do |x|
28
+ x.report("memory_cache") do
29
+ iterations.times do
30
+ memory_cache.write("test", json)
31
+ memory_cache.read("test")
32
+ end
33
+ end
34
+
35
+ x.report("brotli_memory_cache") do
36
+ iterations.times do
37
+ brotli_memory_cache.write("test", json)
38
+ brotli_memory_cache.read("test")
39
+ end
40
+ end
41
+
42
+ x.report("redis_cache") do
43
+ iterations.times do
44
+ redis_cache.write("test", json)
45
+ redis_cache.read("test")
46
+ end
47
+ end
48
+
49
+ x.report("brotli_redis_cache") do
50
+ iterations.times do
51
+ brotli_redis_cache.write("test", json)
52
+ brotli_redis_cache.read("test")
53
+ end
54
+ end
55
+
56
+ x.report("memcached_cache") do
57
+ iterations.times do
58
+ memcached_cache.write("test", json)
59
+ memcached_cache.read("test")
60
+ end
61
+ end
62
+
63
+ x.report("brotli_memcached_cache") do
64
+ iterations.times do
65
+ brotli_memcached_cache.write("test", json)
66
+ brotli_memcached_cache.read("test")
67
+ end
68
+ end
69
+ end
@@ -9,9 +9,15 @@ module RailsBrotliCache
9
9
  COMPRESS_QUALITY = ENV.fetch("BR_CACHE_COMPRESS_QUALITY", 5).to_i
10
10
  MARK_BR_COMPRESSED = "\x02".b
11
11
 
12
+ attr_reader :core_store
13
+
12
14
  def initialize(core_store, options = {})
13
15
  @core_store = core_store
14
- @prefix = "br-"
16
+ @prefix = if options.key?(:prefix)
17
+ options.fetch(:prefix)
18
+ else
19
+ "br-"
20
+ end
15
21
  end
16
22
 
17
23
  def fetch(name, options = nil, &block)
@@ -74,10 +80,6 @@ module RailsBrotliCache
74
80
  @core_store.clear
75
81
  end
76
82
 
77
- def disable_prefix!
78
- @@prefix = nil
79
- end
80
-
81
83
  private
82
84
 
83
85
  def cache_key(name)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsBrotliCache
4
- VERSION = "0.2.0"
4
+ VERSION = "0.2.2"
5
5
  end
@@ -73,12 +73,4 @@ describe RailsBrotliCache do
73
73
  expect(cache_store.read("test-key")).to eq nil
74
74
  end
75
75
  end
76
-
77
- describe "disable_prefix!" do
78
- it "saves brotli cache entries without `br-` prefix" do
79
- cache_store.disable_prefix!
80
- cache_store.fetch("test-key") { 123 }
81
- cache_store.instance_variable_set(:@prefix, "br-")
82
- end
83
- end
84
76
  end
@@ -5,9 +5,14 @@ require 'spec_helper'
5
5
  return unless ENV['RAILS_CACHE_STORE'] == 'redis_cache_store'
6
6
 
7
7
  describe RailsBrotliCache do
8
+ let(:options) do
9
+ {}
10
+ end
11
+
8
12
  subject(:cache_store) do
9
13
  RailsBrotliCache::Store.new(
10
- ActiveSupport::Cache::RedisCacheStore.new(redis: $redis)
14
+ ActiveSupport::Cache::RedisCacheStore.new(redis: $redis),
15
+ options
11
16
  )
12
17
  end
13
18
 
@@ -27,4 +32,26 @@ describe RailsBrotliCache do
27
32
  cache_store.write("test-key", json)
28
33
  expect($redis.get("gz-test-key").size > $redis.get("br-test-key").size).to eq true
29
34
  end
35
+
36
+ describe "disable_prefix" do
37
+ context "default prefix" do
38
+ it "appends 'br-' prefix" do
39
+ cache_store.fetch("test-key") { 123 }
40
+ expect($redis.get("test-key")).to eq nil
41
+ expect($redis.get("br-test-key")).to be_present
42
+ end
43
+ end
44
+
45
+ context "no prefix" do
46
+ let(:options) do
47
+ { prefix: nil }
48
+ end
49
+
50
+ it "saves brotli cache entries without `br-` prefix" do
51
+ cache_store.fetch("test-key") { 123 }
52
+ expect($redis.get("br-test-key")).to eq nil
53
+ expect($redis.get("test-key")).to be_present
54
+ end
55
+ end
56
+ end
30
57
  end
@@ -40,6 +40,12 @@ describe RailsBrotliCache do
40
40
  end
41
41
  end
42
42
 
43
+ describe "#core_store" do
44
+ it "exposes the underlying data store" do
45
+ expect(cache_store.core_store.class).to eq ActiveSupport::Cache::MemoryStore
46
+ end
47
+ end
48
+
43
49
  describe "#read and #write" do
44
50
  it "reads values stored in Rails cache with a prefix" do
45
51
  expect(cache_store.read("test-key")).to eq nil
@@ -67,12 +73,4 @@ describe RailsBrotliCache do
67
73
  expect(cache_store.read("test-key")).to eq nil
68
74
  end
69
75
  end
70
-
71
- describe "disable_prefix!" do
72
- it "saves brotli cache entries without `br-` prefix" do
73
- cache_store.disable_prefix!
74
- cache_store.fetch("test-key") { 123 }
75
- cache_store.instance_variable_set(:@prefix, "br-")
76
- end
77
- end
78
76
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-brotli-cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - pawurb
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-18 00:00:00.000000000 Z
11
+ date: 2023-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -108,6 +108,8 @@ files:
108
108
  - LICENSE.txt
109
109
  - README.md
110
110
  - Rakefile
111
+ - benchmarks/Gemfile
112
+ - benchmarks/main.rb
111
113
  - docker-compose.yml.sample
112
114
  - lib/rails-brotli-cache.rb
113
115
  - lib/rails-brotli-cache/store.rb