mirror of
https://github.com/schoebel/mars
synced 2025-03-30 23:36:37 +00:00
improve cache footprint of MARS
This commit is contained in:
parent
2e923f145e
commit
d5cb69b391
17
Kconfig
17
Kconfig
@ -99,6 +99,23 @@ config MARS_LOADAVG_LIMIT
|
||||
---help---
|
||||
Normally ON.
|
||||
|
||||
config MARS_LINEAR_CACHE_SIZE
|
||||
int "cache size for linear scans of logfiles (in MB)"
|
||||
depends on MARS
|
||||
default 64
|
||||
---help---
|
||||
Setting this to high numbers (or disabling by setting to 0)
|
||||
may disturb the application performance, because MARS will
|
||||
pollute the page cache with pages from the MARS logfiles.
|
||||
Setting this to low numbers will prevent such a pollution,
|
||||
at the cost of (sometimes) more IO operations.
|
||||
EXCEPTION: when you run MARS on a standalone storage server
|
||||
(e.g. exporting devices via iSCSI), you should use high numbers
|
||||
here or even disable this feature. THEN (and ONLY THEN)
|
||||
you want MARS to use all the memory for its own caching,
|
||||
since there is no other application competing for main memory.
|
||||
In unsure, take the default of 64.
|
||||
|
||||
#config MARS_HUNG
|
||||
# bool "hangup on kernel stacktrace (EXPERIMENTAL!!!)"
|
||||
# depends on MARS && MARS_BIGMODULE!=m
|
||||
|
61
mars_aio.c
61
mars_aio.c
@ -669,6 +669,50 @@ void fd_uninstall(unsigned int fd)
|
||||
EXPORT_SYMBOL(fd_uninstall);
|
||||
#endif
|
||||
|
||||
static
|
||||
void _mapfree_pages(struct aio_output *output, bool force)
|
||||
{
|
||||
struct aio_brick *brick = output->brick;
|
||||
struct address_space *mapping;
|
||||
pgoff_t start;
|
||||
pgoff_t end;
|
||||
pgoff_t gap;
|
||||
|
||||
if (brick->linear_cache_size <= 0)
|
||||
goto done;
|
||||
|
||||
if (!force && ++output->rounds < brick->linear_cache_rounds)
|
||||
goto done;
|
||||
|
||||
if (unlikely(!output->filp || !(mapping = output->filp->f_mapping)))
|
||||
goto done;
|
||||
|
||||
if (unlikely(brick->linear_cache_rounds <= 0))
|
||||
brick->linear_cache_rounds = 1024;
|
||||
|
||||
if (force) {
|
||||
start = 0;
|
||||
end = -1;
|
||||
} else {
|
||||
gap = brick->linear_cache_size * (1024 * 1024 / PAGE_SIZE);
|
||||
end = output->min_pos / PAGE_SIZE - gap;
|
||||
if (end <= 0)
|
||||
goto done;
|
||||
|
||||
start = end - gap * 4;
|
||||
if (start < 0)
|
||||
start = 0;
|
||||
}
|
||||
|
||||
output->min_pos = 0;
|
||||
output->rounds = 0;
|
||||
atomic_inc(&output->total_mapfree_count);
|
||||
|
||||
invalidate_mapping_pages(mapping, start, end);
|
||||
|
||||
done:;
|
||||
}
|
||||
|
||||
static int aio_submit_thread(void *data)
|
||||
{
|
||||
struct aio_threadinfo *tinfo = data;
|
||||
@ -718,6 +762,8 @@ static int aio_submit_thread(void *data)
|
||||
int sleeptime;
|
||||
int err;
|
||||
|
||||
_mapfree_pages(output, false);
|
||||
|
||||
wait_event_interruptible_timeout(
|
||||
tinfo->event,
|
||||
kthread_should_stop() ||
|
||||
@ -729,8 +775,14 @@ static int aio_submit_thread(void *data)
|
||||
continue;
|
||||
}
|
||||
|
||||
// check for reads exactly at EOF (special case)
|
||||
mref = mref_a->object;
|
||||
err = -EINVAL;
|
||||
CHECK_PTR(mref, err);
|
||||
|
||||
if (!output->min_pos || mref->ref_pos < output->min_pos)
|
||||
output->min_pos = mref->ref_pos;
|
||||
|
||||
// check for reads exactly at EOF (special case)
|
||||
if (mref->ref_pos == mref->ref_total_size &&
|
||||
!mref->ref_rw &&
|
||||
mref->ref_timeout > 0) {
|
||||
@ -786,6 +838,7 @@ static int aio_submit_thread(void *data)
|
||||
sleeptime += 1000 / HZ;
|
||||
}
|
||||
}
|
||||
err:
|
||||
if (unlikely(err < 0)) {
|
||||
_complete(output, mref, err);
|
||||
}
|
||||
@ -856,7 +909,8 @@ char *aio_statistics(struct aio_brick *brick, int verbose)
|
||||
"delays = %d "
|
||||
"msleeps = %d "
|
||||
"fdsyncs = %d "
|
||||
"fdsync_waits = %d | "
|
||||
"fdsync_waits = %d "
|
||||
"map_free = %d | "
|
||||
"flying reads = %d "
|
||||
"writes = %d "
|
||||
"allocs = %d "
|
||||
@ -871,6 +925,7 @@ char *aio_statistics(struct aio_brick *brick, int verbose)
|
||||
atomic_read(&output->total_msleep_count),
|
||||
atomic_read(&output->total_fdsync_count),
|
||||
atomic_read(&output->total_fdsync_wait_count),
|
||||
atomic_read(&output->total_mapfree_count),
|
||||
atomic_read(&output->read_count),
|
||||
atomic_read(&output->write_count),
|
||||
atomic_read(&output->alloc_count),
|
||||
@ -900,6 +955,7 @@ void aio_reset_statistics(struct aio_brick *brick)
|
||||
atomic_set(&output->total_msleep_count, 0);
|
||||
atomic_set(&output->total_fdsync_count, 0);
|
||||
atomic_set(&output->total_fdsync_wait_count, 0);
|
||||
atomic_set(&output->total_mapfree_count, 0);
|
||||
for (i = 0; i < 3; i++) {
|
||||
struct aio_threadinfo *tinfo = &output->tinfo[i];
|
||||
atomic_set(&tinfo->total_enqueue_count, 0);
|
||||
@ -1008,6 +1064,7 @@ cleanup:
|
||||
|
||||
if (brick->power.led_off) {
|
||||
if (output->filp) {
|
||||
_mapfree_pages(output, true);
|
||||
filp_close(output->filp, NULL);
|
||||
output->filp = NULL;
|
||||
}
|
||||
|
@ -34,6 +34,8 @@ struct aio_brick {
|
||||
MARS_BRICK(aio);
|
||||
// parameters
|
||||
int readahead;
|
||||
int linear_cache_size; // in MB
|
||||
int linear_cache_rounds;
|
||||
bool o_direct;
|
||||
bool o_fdsync;
|
||||
bool wait_during_fdsync;
|
||||
@ -59,6 +61,8 @@ struct aio_output {
|
||||
// private
|
||||
struct file *filp;
|
||||
int fd; // FIXME: remove this!
|
||||
int rounds;
|
||||
loff_t min_pos;
|
||||
struct aio_threadinfo tinfo[3];
|
||||
aio_context_t ctxp;
|
||||
wait_queue_head_t fdsync_event;
|
||||
@ -71,6 +75,7 @@ struct aio_output {
|
||||
atomic_t total_msleep_count;
|
||||
atomic_t total_fdsync_count;
|
||||
atomic_t total_fdsync_wait_count;
|
||||
atomic_t total_mapfree_count;
|
||||
atomic_t read_count;
|
||||
atomic_t write_count;
|
||||
atomic_t alloc_count;
|
||||
|
@ -13,6 +13,9 @@
|
||||
|
||||
#define _STRATEGY
|
||||
#include "mars.h"
|
||||
#include "mars_bio.h"
|
||||
#include "mars_aio.h"
|
||||
#include "mars_sio.h"
|
||||
|
||||
///////////////////////// own type definitions ////////////////////////
|
||||
|
||||
@ -202,6 +205,63 @@ void _clean_list(struct server_brick *brick, struct list_head *start)
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int _set_server_sio_params(struct mars_brick *_brick, void *private)
|
||||
{
|
||||
struct sio_brick *sio_brick = (void*)_brick;
|
||||
if (_brick->type != (void*)_sio_brick_type) {
|
||||
MARS_ERR("bad brick type\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
sio_brick->o_direct = false;
|
||||
sio_brick->o_fdsync = false;
|
||||
MARS_INF("name = '%s' path = '%s'\n", _brick->brick_name, _brick->brick_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int _set_server_aio_params(struct mars_brick *_brick, void *private)
|
||||
{
|
||||
struct aio_brick *aio_brick = (void*)_brick;
|
||||
if (_brick->type == (void*)_sio_brick_type) {
|
||||
return _set_server_sio_params(_brick, private);
|
||||
}
|
||||
if (_brick->type != (void*)_aio_brick_type) {
|
||||
MARS_ERR("bad brick type\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
aio_brick->readahead = 1;
|
||||
aio_brick->linear_cache_size = CONFIG_MARS_LINEAR_CACHE_SIZE;
|
||||
aio_brick->o_direct = false;
|
||||
aio_brick->o_fdsync = false;
|
||||
aio_brick->wait_during_fdsync = false;
|
||||
MARS_INF("name = '%s' path = '%s'\n", _brick->brick_name, _brick->brick_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int _set_server_bio_params(struct mars_brick *_brick, void *private)
|
||||
{
|
||||
struct bio_brick *bio_brick;
|
||||
if (_brick->type == (void*)_aio_brick_type) {
|
||||
return _set_server_aio_params(_brick, private);
|
||||
}
|
||||
if (_brick->type == (void*)_sio_brick_type) {
|
||||
return _set_server_sio_params(_brick, private);
|
||||
}
|
||||
if (_brick->type != (void*)_bio_brick_type) {
|
||||
MARS_ERR("bad brick type\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
bio_brick = (void*)_brick;
|
||||
bio_brick->ra_pages = 1;
|
||||
bio_brick->do_noidle = true;
|
||||
bio_brick->do_sync = true;
|
||||
bio_brick->do_unplug = true;
|
||||
MARS_INF("name = '%s' path = '%s'\n", _brick->brick_name, _brick->brick_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
struct task_struct *_grab_handler(struct server_brick *brick)
|
||||
{
|
||||
@ -299,7 +359,7 @@ int handler_thread(void *data)
|
||||
mars_global,
|
||||
NULL,
|
||||
true,
|
||||
NULL,
|
||||
_set_server_bio_params,
|
||||
NULL,
|
||||
10 * HZ,
|
||||
path,
|
||||
|
@ -247,6 +247,18 @@ int _set_aio_params(struct mars_brick *_brick, void *private)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int _set_aio_params_nocache(struct mars_brick *_brick, void *private)
|
||||
{
|
||||
int res;
|
||||
res = _set_aio_params(_brick, private);
|
||||
if (_brick->type == (void*)&aio_brick_type) {
|
||||
struct aio_brick *aio_brick = (void*)_brick;
|
||||
aio_brick->linear_cache_size = CONFIG_MARS_LINEAR_CACHE_SIZE;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static
|
||||
int _set_bio_params(struct mars_brick *_brick, void *private)
|
||||
{
|
||||
@ -274,6 +286,16 @@ int _set_bio_params(struct mars_brick *_brick, void *private)
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int _set_bio_params_nocache(struct mars_brick *_brick, void *private)
|
||||
{
|
||||
if (_brick->type == (void*)&aio_brick_type) {
|
||||
return _set_aio_params_nocache(_brick, private);
|
||||
}
|
||||
return _set_bio_params(_brick, private);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int _set_if_params(struct mars_brick *_brick, void *private)
|
||||
{
|
||||
@ -655,7 +677,7 @@ int __make_copy(
|
||||
make_brick_all(global,
|
||||
NULL,
|
||||
false,
|
||||
_set_bio_params,
|
||||
_set_bio_params_nocache,
|
||||
NULL,
|
||||
10 * HZ,
|
||||
NULL,
|
||||
@ -1690,7 +1712,7 @@ int make_log_init(void *buf, struct mars_dent *dent)
|
||||
make_brick_all(global,
|
||||
aio_dent,
|
||||
false,
|
||||
_set_aio_params,
|
||||
_set_aio_params_nocache,
|
||||
NULL,
|
||||
10 * HZ,
|
||||
aio_path,
|
||||
|
Loading…
Reference in New Issue
Block a user