Skip to content

Commit

Permalink
Merge pull request #2459 from pbalcer/obj-alloc-stats
Browse files Browse the repository at this point in the history
obj: implement statistics boilerplate macros
  • Loading branch information
krzycz committed Dec 20, 2017
2 parents e5e6a46 + 8ab8c6c commit 488df51
Show file tree
Hide file tree
Showing 35 changed files with 519 additions and 25 deletions.
16 changes: 16 additions & 0 deletions doc/libpmemobj/pmemobj_ctl_get.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,22 @@ The required class identifier will be stored in the `class_id` field of the
This function returns 0 if the allocation class has been successfully created,
-1 otherwise.

stats.enabled | rw | - | int | int | - | boolean

Enables or disables runtime collection of statistics. Statistics are not
recalculated after enabling; any operations that occur between disabling and
re-enabling will not be reflected in subsequent values.

Statistics are disabled by default. Enabling them may have non-trivial
performance impact.

Always returns 0.

stats.heap.allocated_curr | r- | - | int | - | - | -

Returns the number of bytes currently allocated in the heap. If statistics were
disabled at any time in the lifetime of the heap, this value may be
inaccurate.

# CTL EXTERNAL CONFIGURATION #

Expand Down
4 changes: 4 additions & 0 deletions src/benchmarks/pmembench.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">CompileAsC</CompileAs>
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">CompileAsC</CompileAs>
</ClCompile>
<ClCompile Include="..\libpmemobj\stats.c">
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">CompileAsC</CompileAs>
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">CompileAsC</CompileAs>
</ClCompile>
<ClCompile Include="..\libpmemobj\ctl.c">
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">CompileAsC</CompileAs>
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">CompileAsC</CompileAs>
Expand Down
3 changes: 2 additions & 1 deletion src/libpmemobj/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ SOURCE +=\
redo.c\
ringbuf.c\
sync.c\
tx.c
tx.c\
stats.c

include ../Makefile.inc

Expand Down
4 changes: 3 additions & 1 deletion src/libpmemobj/heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1170,7 +1170,8 @@ heap_buckets_init(struct palloc_heap *heap)
*/
int
heap_boot(struct palloc_heap *heap, void *heap_start, uint64_t heap_size,
uint64_t run_id, void *base, struct pmem_ops *p_ops)
uint64_t run_id, void *base, struct pmem_ops *p_ops,
struct stats *stats)
{
struct heap_rt *h = Malloc(sizeof(*h));
int err;
Expand Down Expand Up @@ -1207,6 +1208,7 @@ heap_boot(struct palloc_heap *heap, void *heap_start, uint64_t heap_size,
heap->rt = h;
heap->size = heap_size;
heap->base = base;
heap->stats = stats;
VALGRIND_DO_CREATE_MEMPOOL(heap->layout, 0, 0);

for (unsigned i = 0; i < h->narenas; ++i)
Expand Down
3 changes: 2 additions & 1 deletion src/libpmemobj/heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@
#define BIT_IS_CLR(a, i) (!((a) & (1ULL << (i))))

int heap_boot(struct palloc_heap *heap, void *heap_start, uint64_t heap_size,
uint64_t run_id, void *base, struct pmem_ops *p_ops);
uint64_t run_id, void *base, struct pmem_ops *p_ops,
struct stats *stats);
int heap_init(void *heap_start, uint64_t heap_size, struct pmem_ops *p_ops);
void heap_cleanup(struct palloc_heap *heap);
int heap_check(void *heap_start, uint64_t heap_size);
Expand Down
2 changes: 2 additions & 0 deletions src/libpmemobj/libpmemobj.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
<ClCompile Include="container_ctree.c" />
<ClCompile Include="container_seglists.c" />
<ClCompile Include="alloc_class.c" />
<ClCompile Include="stats.c" />
<ClCompile Include="ringbuf.c" />
</ItemGroup>
<ItemGroup>
Expand Down Expand Up @@ -104,6 +105,7 @@
<ClInclude Include="container_seglists.h" />
<ClInclude Include="container.h" />
<ClInclude Include="alloc_class.h" />
<ClInclude Include="stats.h" />
</ItemGroup>
<ItemGroup>
<None Include="libpmemobj.def" />
Expand Down
6 changes: 6 additions & 0 deletions src/libpmemobj/libpmemobj.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@
<ClCompile Include="ringbuf.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="stats.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\common\os_thread_windows.c">
<Filter>Source Files</Filter>
</ClCompile>
Expand Down Expand Up @@ -264,6 +267,9 @@
<ClInclude Include="alloc_class.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="stats.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ctl.h">
<Filter>Header Files</Filter>
</ClInclude>
Expand Down
13 changes: 11 additions & 2 deletions src/libpmemobj/obj.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ obj_ctl_init_and_load(PMEMobjpool *pop)
if (pop) {
tx_ctl_register(pop);
pmalloc_ctl_register(pop);
stats_ctl_register(pop);
}

char *env_config = os_getenv(OBJ_CONFIG_ENV_VARIABLE);
Expand Down Expand Up @@ -1097,6 +1098,13 @@ obj_runtime_init(PMEMobjpool *pop, int rdonly, int boot, unsigned nlanes)
return -1;
}

pop->stats = stats_new(pop);
if (pop->stats == NULL) {
tx_params_delete(pop->tx_params);
errno = ENOMEM;
return -1;
}

VALGRIND_REMOVE_PMEM_MAPPING(&pop->mutex_head,
sizeof(pop->mutex_head));
VALGRIND_REMOVE_PMEM_MAPPING(&pop->rwlock_head,
Expand All @@ -1109,8 +1117,7 @@ obj_runtime_init(PMEMobjpool *pop, int rdonly, int boot, unsigned nlanes)

if (boot) {
if ((errno = obj_boot(pop)) != 0)
return -1;

goto err;

#ifdef USE_VG_MEMCHECK
if (On_valgrind) {
Expand Down Expand Up @@ -1152,6 +1159,7 @@ obj_runtime_init(PMEMobjpool *pop, int rdonly, int boot, unsigned nlanes)

return 0;
err:
stats_delete(pop, pop->stats);
tx_params_delete(pop->tx_params);

return -1;
Expand Down Expand Up @@ -1789,6 +1797,7 @@ obj_pool_cleanup(PMEMobjpool *pop)
{
LOG(3, "pop %p", pop);

stats_delete(pop, pop->stats);
tx_params_delete(pop->tx_params);
ctl_delete(pop->ctl);

Expand Down
8 changes: 6 additions & 2 deletions src/libpmemobj/obj.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "ctl.h"
#include "ringbuf.h"
#include "sync.h"
#include "stats.h"

#define PMEMOBJ_LOG_PREFIX "libpmemobj"
#define PMEMOBJ_LOG_LEVEL_VAR "PMEMOBJ_LOG_LEVEL"
Expand Down Expand Up @@ -135,7 +136,9 @@ struct pmemobjpool {
*/
uint64_t conversion_flags;

char pmem_reserved[512]; /* must be zeroed */
struct stats_persistent stats_persistent;

char pmem_reserved[504]; /* must be zeroed */

/* some run-time state, allocated out of memory pool... */
void *addr; /* mapped region */
Expand All @@ -148,6 +151,7 @@ struct pmemobjpool {
int is_dev_dax; /* true if mapped on device dax */

struct ctl *ctl;
struct stats *stats;
struct ringbuf *tx_postcommit_tasks;

struct pool_set *set; /* pool set info */
Expand Down Expand Up @@ -191,7 +195,7 @@ struct pmemobjpool {

/* padding to align size of this structure to page boundary */
/* sizeof(unused2) == 8192 - offsetof(struct pmemobjpool, unused2) */
char unused2[1012];
char unused2[996];
};

/*
Expand Down
16 changes: 14 additions & 2 deletions src/libpmemobj/palloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,18 @@ palloc_finalize_heap_action(struct palloc_heap *heap,
const struct pobj_action_internal *act, int canceled)
{
if (act->new_state == MEMBLOCK_ALLOCATED) {
STATS_INC(heap->stats, persistent, heap_curr_allocated,
act->m.m_ops->get_real_size(&act->m));

palloc_reservation_finalize(heap, act, canceled);
} else if (!canceled && act->new_state == MEMBLOCK_FREE) {
if (heap->stats->enabled) {
struct memory_block m =
memblock_from_offset(heap, act->offset);
STATS_SUB(heap->stats, persistent, heap_curr_allocated,
m.m_ops->get_real_size(&m));
}

heap_memblock_on_free(heap, &act->m);
}
}
Expand Down Expand Up @@ -682,9 +692,11 @@ palloc_is_allocated(struct palloc_heap *heap, uint64_t off)
*/
int
palloc_boot(struct palloc_heap *heap, void *heap_start, uint64_t heap_size,
uint64_t run_id, void *base, struct pmem_ops *p_ops)
uint64_t run_id, void *base, struct pmem_ops *p_ops,
struct stats *stats)
{
return heap_boot(heap, heap_start, heap_size, run_id, base, p_ops);
return heap_boot(heap, heap_start, heap_size, run_id, base, p_ops,
stats);
}

/*
Expand Down
6 changes: 5 additions & 1 deletion src/libpmemobj/palloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,16 @@
#include "memops.h"
#include "redo.h"
#include "valgrind_internal.h"
#include "stats.h"

struct palloc_heap {
struct pmem_ops p_ops;
struct heap_layout *layout;
struct heap_rt *rt;
uint64_t size;

struct stats *stats;

void *base;
};

Expand Down Expand Up @@ -93,7 +96,8 @@ uint16_t palloc_flags(struct palloc_heap *heap, uint64_t off);
int palloc_is_allocated(struct palloc_heap *heap, uint64_t off);

int palloc_boot(struct palloc_heap *heap, void *heap_start, uint64_t run_id,
uint64_t heap_size, void *base, struct pmem_ops *p_ops);
uint64_t heap_size, void *base, struct pmem_ops *p_ops,
struct stats *stats);
int palloc_buckets_init(struct palloc_heap *heap);

int palloc_init(void *heap_start, uint64_t heap_size, struct pmem_ops *p_ops);
Expand Down
3 changes: 2 additions & 1 deletion src/libpmemobj/pmalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,8 @@ static int
pmalloc_boot(PMEMobjpool *pop)
{
int ret = palloc_boot(&pop->heap, (char *)pop + pop->heap_offset,
pop->heap_size, pop->run_id, pop, &pop->p_ops);
pop->heap_size, pop->run_id, pop, &pop->p_ops,
pop->stats);
if (ret)
return ret;

Expand Down
126 changes: 126 additions & 0 deletions src/libpmemobj/stats.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Copyright 2017, Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*
* stats.c -- implementation of statistics
*/

#include "obj.h"
#include "stats.h"

STATS_CTL_HANDLER(persistent, curr_allocated, heap_curr_allocated);

static const struct ctl_node CTL_NODE(heap)[] = {
STATS_CTL_LEAF(persistent, curr_allocated),

CTL_NODE_END
};

/*
* CTL_READ_HANDLER(enabled) -- returns whether or not statistics are enabled
*/
static int
CTL_READ_HANDLER(enabled)(PMEMobjpool *pop,
enum ctl_query_source source, void *arg,
struct ctl_indexes *indexes)
{
int *arg_out = arg;

*arg_out = pop->stats->enabled;

return 0;
}

/*
* CTL_WRITE_HANDLER(enabled) -- enables or disables statistics counting
*/
static int
CTL_WRITE_HANDLER(enabled)(PMEMobjpool *pop,
enum ctl_query_source source, void *arg,
struct ctl_indexes *indexes)
{
int arg_in = *(int *)arg;

pop->stats->enabled = arg_in;

return 0;
}

static struct ctl_argument CTL_ARG(enabled) = CTL_ARG_BOOLEAN;

static const struct ctl_node CTL_NODE(stats)[] = {
CTL_CHILD(heap),
CTL_LEAF_RW(enabled),

CTL_NODE_END
};

/*
* stats_new -- allocates and initializes statistics instance
*/
struct stats *
stats_new(PMEMobjpool *pop)
{
struct stats *s = Malloc(sizeof(*s));
s->enabled = 0;
s->persistent = &pop->stats_persistent;
s->transient = Zalloc(sizeof(struct stats_transient));
if (s->transient == NULL)
goto error_transient_alloc;

return s;

error_transient_alloc:
Free(s);
return NULL;
}

/*
* stats_delete -- deletes statistics instance
*/
void
stats_delete(PMEMobjpool *pop, struct stats *s)
{
pmemops_persist(&pop->p_ops, s->persistent,
sizeof(struct stats_persistent));
Free(s->transient);
Free(s);
}

/*
* stats_ctl_register -- registers ctl nodes for statistics
*/
void
stats_ctl_register(PMEMobjpool *pop)
{
CTL_REGISTER_MODULE(pop->ctl, stats);
}

0 comments on commit 488df51

Please sign in to comment.