Kiwi
A simple unified Crystal interface for key-value stores.
Installation
Add this to your application's shard.yml
:
dependencies:
kiwi:
github: crystal-community/kiwi
version: ~> 0.1.0
Temporarily, if you wan't the newest version from akitaonrails' fork:
dependencies:
kiwi:
github: akitaonrails/kiwi
branch: master
Usage
All the stores have the same simple interface defined by Kiwi::Store:
set(key : String, value : String) : String
get(key : String) : String|Nil
delete(key : String) : String|Nil
clear
[]=(key : String, value) : String
- alias forset
[](key : String) : String
- alias forget
MemoryStore
require "kiwi/memory_store"
store = Kiwi::MemoryStore.new
store.set("key", "value")
store.get("key") # => "value"
store.delete("key")
store.clear
# Or your can use Hash-like methods:
store["key"] = "new value"
store["key"] # => "new "value"
# fetch with a block:
store.fetch("key") do
"value"
end
FileStore
require "kiwi/file_store"
store = Kiwi::FileStore("/tmp/kiwi")
RedisStore
RedisStore requires you to have redis shard.
require "redis"
require "kiwi/redis_store"
store = Kiwi::RedisStore(Redis.new)
LevelDBStore
LevelDBStore requires you to have levelDB shard.
require "leveldb"
require "kiwi/leveldb_store"
leveldb = LevelDB::DB.new("./db")
store = Kiwi::LevelDBStore(leveldb)
MemcachedStore
MemcachedStore requires you to have memcached shard.
require "memcached"
require "kiwi/memcached_store"
store = Kiwi::MemcachedStore.new(Memcached::Client.new)
Expires
Almost all stores, but the FileStore, can receive a "expires_in" argument to set a default expiring time span:
store1 = Kiwi::MemcachedStore.new(Memcached::Client.new, expires_in: 5.minutes)
store2 = Kiwi::RedisStore.new(Redis::PooledClient.new, expires_in: 1.hour)
This is a cache library, so cached data is supposed to eventually expire without manual intervention.
Benchmark
The following table shows operations per second for every particular store on my machine.
| | set | get | get(empty) | delete | | ------------------ | ------- | ------- | ---------- | ------- | | MemoryStore | 2096000 | 3023000 | 3171000 | 3453000 | | LevelDBStore | 690000 | 518000 | 627000 | 360000 | | RedisStore | 24000 | 30000 | 25000 | 13000 | | MemcachedStore | 11000 | 10000 | 11000 | 5000 | | FileStore | 80000 | 118000 | 117000 | 90000 |
Data information:
- Key size: 5-100 bytes.
- Value size: 10-1000 bytes.
- Number of items: 100,000
Environment information:
- CPU: Intel(R) Core(TM) i7-3632QM CPU @ 2.20GHz
- File System: ext4, SSD
- RAM: DDR3, 1600 MHz
- Operating system: 3.16.0-4-amd64 x86_64 GNU/Linux
Results can vary on different systems depending on hardware(CPU, RAM, HDD/SSD) and software(OS, file system, etc).
Running benchmark
make benchmark
Tests
Run specs for all stores:
# you must have docker-compose installed
make test
Run spec for a particular store:
crystal spec ./spec/kiwi/file_store_spec.cr
Contributors
- greyblake Sergey Potapov - creator, maintainer.
- mauricioabreu Mauricio de Abreu Antunes - thanks for MemcachedStore.
- akitaonrails Fabio Akita - adding type checks and expiration feature