Skip to content

memcached: use own small's arena #102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Apr 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions .github/workflows/reusable_testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,6 @@ jobs:
# dependencies when migrating to other OS version.
run: sudo dpkg -i tarantool_*.deb tarantool-common_*.deb tarantool-dev_*.deb

# TODO: Remove this when https://github.com/tarantool/memcached/issues/96
# is resolved.
- name: Get the tarantool version
run: |
TNT_VERSION=$(tarantool --version | grep -e '^Tarantool')
echo "TNT_VERSION=$TNT_VERSION" >> $GITHUB_ENV

- name: Setup python3 for tests
uses: actions/setup-python@v2
with:
Expand All @@ -51,7 +44,3 @@ jobs:

- run: cmake . && make
- run: make test-memcached
# TODO: Remove this when https://github.com/tarantool/memcached/issues/96
# is resolved.
if: ${{ startsWith(env.TNT_VERSION, 'Tarantool 1.10') ||
startsWith(env.TNT_VERSION, 'Tarantool 2.8') }}
11 changes: 9 additions & 2 deletions .github/workflows/testing.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository
strategy:
matrix:
tarantool-version: ['1.10', '2.2', '2.3', '2.4', '2.5', '2.6', '2.7', '2.8']
tarantool-version: ['1.10', '2.2', '2.3', '2.4', '2.5', '2.6', '2.7', '2.8', '2.x-latest']
fail-fast: false
runs-on: [ubuntu-latest]
steps:
Expand All @@ -23,11 +23,18 @@ jobs:
# for running tests.
submodules: recursive

- name: Setup Tarantool
- name: Setup Tarantool (version is not equal to latest 2.x)
if: matrix.tarantool-version != '2.x-latest'
uses: tarantool/setup-tarantool@v1
with:
tarantool-version: ${{ matrix.tarantool-version }}

- name: Setup Tarantool 2.x (latest)
if: matrix.tarantool-version == '2.x-latest'
run: |
curl -L https://tarantool.io/pre-release/2/installer.sh | sudo bash
sudo apt install -y tarantool tarantool-dev

- name: Install build requirements
run: sudo apt-get -y install libsasl2-dev libevent-dev

Expand Down
1 change: 1 addition & 0 deletions .luacheckrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
std = "luajit"
globals = {
"box",
"tonumber64",
}
ignore = {
-- Accessing an undefined field of a global variable <package>.
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ END
## API

* `local memcached = require('memcached')` - acquire a library handle
* `local slab = memcached.slab.info()` - show information about slab arena and quota.
* `local instance = memcached.create(<name>, <uri>, <opts>)` - create a new instance, register it and run
- `name` - a string with instance name
- `uri` - a string with uri to bind to, for example: `0.0.0.0:11211` (only TCP is supported now)
Expand Down
1 change: 1 addition & 0 deletions memcached/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated")

add_library(internalso SHARED
"internal/alloc.c"
"internal/constants.c"
"internal/utils.c"
"internal/proto_bin.c"
Expand Down
44 changes: 42 additions & 2 deletions memcached/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ struct memcached_stat {
uint64_t auth_errors;
};

struct slab_arena_info {
size_t quota_size;
size_t quota_used;
double quota_used_ratio;
};

void
memcached_set_opt (struct memcached_service *srv, int opt, ...);

Expand Down Expand Up @@ -82,6 +88,13 @@ memcached_get_stat (struct memcached_service *);
struct memcached_service *
memcached_create(const char *, uint32_t);

void memcached_slab_arena_create();

void memcached_slab_cache_create();

struct slab_arena_info *
memcached_slab_arena_info();

int memcached_start (struct memcached_service *);
void memcached_stop (struct memcached_service *);
void memcached_free (struct memcached_service *);
Expand Down Expand Up @@ -233,6 +246,12 @@ local RUNNING = 'r'
local STOPPED = 's'
local ERRORED = 'e'

local slab_arena_info_table = {
'quota_size',
'quota_used',
'quota_used_ratio',
}

local stat_table = {
'total_items', 'curr_items',
'curr_conns', 'total_conns',
Expand Down Expand Up @@ -332,7 +351,7 @@ local memcached_methods = {
end
}

local function memcached_init(name, uri, opts)
local function memcached_create_instance(name, uri, opts)
opts = opts or {}
if memcached_services[name] ~= nil then
if not opts.if_not_exists then
Expand Down Expand Up @@ -386,8 +405,29 @@ local function memcached_get(name)
return memcached_services[name]
end

local function memcached_slab_info()
local slab_arena_info = memcached_internal.memcached_slab_arena_info()
local slab_info = {}
for _, v in pairs(slab_arena_info_table) do
slab_info[v] = tonumber64(slab_arena_info[0][v])
end
slab_info['quota_used_ratio'] = string.format('%0.2f%%', slab_info['quota_used_ratio'])

return slab_info
end

local function memcached_init()
memcached_internal.memcached_slab_arena_create()
memcached_internal.memcached_slab_cache_create()
end

memcached_init()

return {
create = memcached_init,
create = memcached_create_instance,
slab = {
info = memcached_slab_info,
},
get = memcached_get,
server = setmetatable({}, {
__index = memcached_services
Expand Down
121 changes: 66 additions & 55 deletions memcached/internal/alloc.c
Original file line number Diff line number Diff line change
@@ -1,76 +1,87 @@
#include <tarantool/module.h>
#include <small/slab_cache.h>
#include <small/quota.h>

#include "memcached_persistent.h"
static struct slab_arena arena;
static struct slab_cache slabc;
static struct quota quota;

void *
box_persistent_malloc(size_t len, size_t *total)
struct slab_arena_info {
uint64_t quota_size;
uint64_t quota_used;
double quota_used_ratio;
};

struct slab_arena_info slab_info;

/*
* Function produce an output with information of total quota size, used quota
* size and quota used ratio. Note that function relies on a fact that
* memcached uses a single slab cache for all allocations it made.
*/
struct slab_arena_info *
memcached_slab_arena_info()
{
struct slab *slab = slab_get(cord_slab_cache(), len);
char *ptr = NULL; size_t sz = 0;
if (slab != NULL) {
ptr = slab_data(slab);
sz = slab_capacity(slab);
}
if (total) *total = sz;
return ptr;
/*
* How much quota has been booked - reflects the total
* size of slabs in various slab caches.
*/
slab_info.quota_used = (uint64_t)quota_used(arena.quota);

slab_info.quota_size = (uint64_t)quota_total(arena.quota);
slab_info.quota_used_ratio = 100 * ((double) slab_info.quota_used /
((double) slab_info.quota_size + 0.0001));

return &slab_info;
}

void *
box_persistent_malloc0(size_t len, size_t *total)
void
memcached_slab_arena_create()
{
size_t sz = 0;
char *ptr = box_persistent_malloc(len, &sz);
if (ptr) memset(ptr, 0, sz);
if (total) *total = sz;
return ptr;
static __thread bool inited = false;
if (inited) return;
size_t quota_size = QUOTA_MAX;
quota_init(&quota, quota_size);
/* Parameters are the same as in src/lib/core/memory.c:memory_init() */
const size_t SLAB_SIZE = 4 * 1024 * 1024;
slab_arena_create(&arena, &quota, 0, SLAB_SIZE, SLAB_ARENA_PRIVATE);
say_info("creating arena with %zu bytes...", quota_size);
inited = 1;
}

void
box_persistent_free(void *ptr) {
if (ptr) slab_put(cord_slab_cache(), slab_from_data(ptr));
memcached_slab_arena_destroy()
{
static __thread bool freed = false;
if (freed) return;
say_info("destroying arena...");
slab_arena_destroy(&arena);
freed = 1;
}

void *
box_persistent_realloc(void *ptr, size_t len, size_t *total)
void
memcached_slab_cache_create()
{
if (len == 0) {
if (ptr) box_persistent_free(ptr);
if (total) *total = 0;
return NULL;
} else if (ptr == NULL) {
return box_persistent_malloc(len, total);
}
struct slab *slab = slab_from_data(ptr);
size_t sz = slab_capacity(slab);
if (len <= sz) {
if (total) *total = sz;
return ptr;
}
char *ptr_new = box_persistent_malloc(len, total);
if (!ptr_new)
return NULL;
memcpy(ptr_new, ptr, sz);
box_persistent_free(ptr);
return ptr_new;
static __thread bool inited = false;
if (inited) return;
slab_cache_set_thread(&slabc);
slab_cache_create(&slabc, &arena);
say_info("allocate slab cache with slab size %u", arena.slab_size);
inited = 1;
}

void *
box_persistent_strdup(const void *str, size_t *total)
void
memcached_slab_cache_destroy()
{
size_t strl = strlen(str);
char *ptr = box_persistent_malloc(strl, total);
if (ptr) {
memcpy(ptr, str, strl);
ptr[strl] = 0;
}
return ptr;
static __thread bool freed = false;
if (freed) return;
say_info("destroying slab cache");
slab_cache_destroy(&slabc);
freed = 1;
}

void *
box_persistent_strndup(const void *str, size_t len, size_t *total)
struct slab_cache *
memcached_slab_cache()
{
char *ptr = box_persistent_malloc(len, total);
if (ptr) strncpy(ptr, str, len);
return ptr;
return &slabc;
}
22 changes: 11 additions & 11 deletions memcached/internal/alloc.h
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
#ifndef ALLOC_H_INCLUDED
#define ALLOC_H_INCLUDED

void *
box_persistent_malloc(size_t len, size_t *total);
void
memcached_slab_arena_create();

void *
box_persistent_malloc0(size_t len, size_t *total);
void
memcached_slab_arena_destroy();

void
box_persistent_free(void *ptr);
memcached_slab_cache_create();

void *
box_persistent_realloc(void *ptr, size_t len, size_t *total);
void
memcached_slab_cache_destroy();

void *
box_persistent_strdup(const void *str, size_t *total);
struct slab_cache *
memcached_slab_cache();

void *
box_persistent_strndup(const void *str, size_t len, size_t *total);
struct slab_arena_info *
memcached_slab_arena_info();

#endif /* ALLOC_H_INCLUDED */
9 changes: 8 additions & 1 deletion memcached/internal/memcached.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <small/ibuf.h>
#include <small/obuf.h>

#include "alloc.h"
#include "memcached.h"
#include "memcached_layer.h"
#include "error.h"
Expand All @@ -46,6 +47,12 @@
#include "expiration.h"
#include "mc_sasl.h"

__attribute__((destructor)) static void
destroy_allocations() {
memcached_slab_cache_destroy();
memcached_slab_arena_destroy();
}

static inline int
memcached_skip_request(struct memcached_connection *con) {
struct ibuf *in = con->in;
Expand Down Expand Up @@ -250,7 +257,7 @@ memcached_handler(struct memcached_service *p, int fd)
assert(0); /* unreacheable */
}

region_create(&con.gc, cord_slab_cache());
region_create(&con.gc, memcached_slab_cache());

/* read-write cycle */
con.cfg->stat.curr_conns++;
Expand Down
9 changes: 5 additions & 4 deletions memcached/internal/network.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <small/ibuf.h>
#include <small/obuf.h>

#include "alloc.h"
#include "memcached.h"
#include "constants.h"
#include "network.h"
Expand All @@ -31,8 +32,8 @@ iobuf_mempool_create()
{
static __thread bool inited = false;
if (inited) return;
mempool_create(&ibuf_pool, cord_slab_cache(), sizeof(struct ibuf));
mempool_create(&obuf_pool, cord_slab_cache(), sizeof(struct obuf));
mempool_create(&ibuf_pool, memcached_slab_cache(), sizeof(struct ibuf));
mempool_create(&obuf_pool, memcached_slab_cache(), sizeof(struct obuf));
inited = 1;
}

Expand All @@ -48,7 +49,7 @@ ibuf_new()
{
void *ibuf = mempool_alloc(&ibuf_pool);
if (ibuf == NULL) return NULL;
ibuf_create((struct ibuf *)ibuf, cord_slab_cache(), iobuf_readahead);
ibuf_create((struct ibuf *)ibuf, memcached_slab_cache(), iobuf_readahead);
return ibuf;
}

Expand All @@ -57,7 +58,7 @@ obuf_new()
{
void *obuf = mempool_alloc(&obuf_pool);
if (obuf == NULL) return NULL;
obuf_create((struct obuf *)obuf, cord_slab_cache(), iobuf_readahead);
obuf_create((struct obuf *)obuf, memcached_slab_cache(), iobuf_readahead);
return obuf;
}

Expand Down
Loading