Commit 7b68db65 authored by Peter W. Draper's avatar Peter W. Draper
Browse files

Extract rnodes into separate file in prep for MPI logger

parent dcf71f9e
......@@ -52,7 +52,7 @@ include_HEADERS = space.h runner.h queue.h task.h lock.h cell.h part.h const.h \
logger_io.h tracers_io.h tracers.h tracers_struct.h star_formation_io.h fof.h \
star_formation_struct.h star_formation.h star_formation_iact.h \
star_formation_logger.h star_formation_logger_struct.h \
velociraptor_struct.h velociraptor_io.h random.h memuse.h black_holes.h black_holes_io.h \
velociraptor_struct.h velociraptor_io.h random.h memuse.h memuse_rnodes.h black_holes.h black_holes_io.h \
black_holes_properties.h black_holes_struct.h feedback.h feedback_struct.h feedback_properties.h
# source files for EAGLE cooling
......@@ -78,7 +78,7 @@ AM_SOURCES = space.c runner.c queue.c task.c cell.c engine.c engine_maketasks.c
part_type.c xmf.c gravity_properties.c gravity.c \
collectgroup.c hydro_space.c equation_of_state.c \
chemistry.c cosmology.c restart.c mesh_gravity.c velociraptor_interface.c \
outputlist.c velociraptor_dummy.c logger_io.c memuse.c fof.c \
outputlist.c velociraptor_dummy.c logger_io.c memuse.c memuse_rnodes.c fof.c \
hashmap.c \
$(EAGLE_COOLING_SOURCES) $(EAGLE_FEEDBACK_SOURCES)
......
......@@ -20,6 +20,7 @@
/**
* @file memuse.c
* @brief file of routines to report about memory use in SWIFT.
* Includes MPI exchanges made by the tasks.
* Note reports are in KB.
*/
......@@ -29,6 +30,8 @@
/* Standard includes. */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
......@@ -39,6 +42,8 @@
#include "atomic.h"
#include "clocks.h"
#include "engine.h"
#include "error.h"
#include "memuse_rnodes.h"
#ifdef SWIFT_MEMUSE_REPORTS
......@@ -101,254 +106,10 @@ struct memuse_labelled_item {
size_t count;
};
/* A radix node, this has a single byte key and a pointer to some related
* resource. It also holds a sorted list of children, if any. */
struct memuse_rnode {
/* Byte key of this node. */
uint8_t keypart;
/* Value of this node, if set. */
void *ptr;
/* Sorted pointers to children of this node. */
struct memuse_rnode **children;
unsigned int count;
};
/* Persistent radix trie root node. Holds active logs between dumps. */
static struct memuse_rnode *memuse_rnode_root;
static int memuse_rnode_root_init = 1;
#ifdef MEMUSE_RNODE_DUMP
/**
* @brief Dump a representation of the radix tree rooted at a node to stdout.
*
* @param depth the depth of the node in the tree, root is 0.
* @param node the node at which to start dumping.
* @param full if not zero then nodes that are not storing a value
* are also reported.
*/
static void memuse_rnode_dump(int depth, struct memuse_rnode *node, int full) {
/* Value of the full key, to this depth. Assumes full key is a pointer,
* so uncomment when using strings. */
static union {
// uint8_t key[MEMUSE_MAXLABLEN];
// char ptr[MEMUSE_MAXLABLEN];
uint8_t key[sizeof(uintptr_t)];
void *ptr;
} keyparts = {0};
/* Record keypart at this depth. Root has no keypart. */
if (depth != 0) keyparts.key[depth - 1] = node->keypart;
// if (node->ptr != NULL || full) {
// keyparts.key[depth] = '\0';
//
// /* Gather children's keys if full. */
// char fullkey[MEMUSE_MAXLABLEN];
// if (full) {
// for (size_t k = 0; k < node->count; k++) {
// fullkey[k] = node->children[k]->keypart;
// }
// fullkey[node->count] = '\0';
// printf("dump @ depth: %d keypart: %d key: %s value: %p fullkey: %s\n",
// depth, node->keypart, keyparts.ptr, node->ptr, fullkey);
// } else {
// printf("dump @ depth: %d keypart: %d key: %s value: %p\n", depth,
// node->keypart, keyparts.ptr, node->ptr);
// }
//}
if (node->ptr != NULL || full) {
printf("dump @ depth: %d keypart: %d key: %p value: %p\n", depth,
node->keypart, keyparts.ptr, node->ptr);
}
/* Recurse to all children. */
for (size_t k = 0; k < node->count; k++) {
memuse_rnode_dump(depth + 1, node->children[k], full);
}
}
#endif
/**
* @brief Return the position of a keypart for a list of children.
* If not found returns where it would be inserted.
*
* @param keypart the keypart to locate.
* @param children the list of sorted children.
* @param count the number of children
*
* @return the index of key or where it should be inserted.
*/
static unsigned int memuse_rnode_bsearch(uint8_t keypart,
struct memuse_rnode **children,
unsigned int count) {
/* Search for lower bound. */
unsigned int lower = 0;
unsigned int upper = count;
while (lower < upper) {
unsigned int middle = (upper + lower) / 2;
if (keypart > children[middle]->keypart)
lower = middle + 1;
else
upper = middle;
}
return lower;
}
/**
* @brief Insert a child, if needed, into a list of children. Assumes
* we have sufficient room.
*
* @param child the child to insert, if needed.
* @param children the list of sorted children.
* @param count the number of children
*/
static void memuse_rnode_binsert_child(struct memuse_rnode *child,
struct memuse_rnode **children,
unsigned int *count) {
unsigned int pos = 0;
if (*count > 0) {
/* Find the child or insertion point. */
pos = memuse_rnode_bsearch(child->keypart, children, *count);
/* If not found move all children to make a space, unless we're inserting
* after the end. */
if (pos < *count && children[pos]->keypart != child->keypart) {
memmove(&children[pos + 1], &children[pos],
(*count - pos) * sizeof(struct memuse_rnode *));
}
}
/* Insert new child */
children[pos] = child;
*count += 1;
}
/**
* @brief Add a child rnode to an rnode. Making sure we have room and keeping
* the sort order.
*
* @param node the parent node.
* @param child the node to add to the parent,
*/
static void memuse_rnode_add_child(struct memuse_rnode *node,
struct memuse_rnode *child) {
/* Extend the children list to include a new entry .*/
void *mem = realloc(node->children,
(node->count + 1) * sizeof(struct memuse_rnode *));
if (mem == NULL) error("Failed to reallocate rnodes\n");
node->children = mem;
/* Insert the new child. */
memuse_rnode_binsert_child(child, node->children, &node->count);
}
/**
* @brief Find a child of a node with the given key part.
*
* @param node the node to search.
* @param keypart the key part of the child.
* @return NULL if not found.
*/
static struct memuse_rnode *memuse_rnode_lookup(const struct memuse_rnode *node,
uint8_t keypart) {
/* Locate the key, or where it would be inserted. */
if (node->count > 0) {
unsigned int index =
memuse_rnode_bsearch(keypart, node->children, node->count);
if (index < node->count && keypart == node->children[index]->keypart) {
return node->children[index];
}
}
return NULL;
}
/**
* @brief insert a child into a node's children list and add a pointer, iff
* this is the destination node for the given key.
*
* @param node the parent node.
* @param depth the depth of the parent node.
* @param key the full key of the eventual leaf node.
* @param keylen the numbers of bytes in the full key.
* @param value pointer that will be stored as the value of the leaf node.
*/
static void memuse_rnode_insert_child(struct memuse_rnode *node, uint8_t depth,
uint8_t *key, uint8_t keylen,
void *value) {
/* Check if keypart this already exists at this level and add new child if
* not. */
uint8_t keypart = key[depth];
struct memuse_rnode *child = memuse_rnode_lookup(node, keypart);
if (child == NULL) {
child = calloc(1, sizeof(struct memuse_rnode));
child->keypart = keypart;
memuse_rnode_add_child(node, child);
}
/* Are we at the lowest level yet? */
depth++;
if (depth == keylen) {
/* Our destination node. */
#if SWIFT_DEBUG_CHECKS
if (child->ptr != NULL)
message("Overwriting rnode value: %p with %p", child->ptr, value);
#endif
child->ptr = value;
return;
}
/* Down we go to the next level. */
memuse_rnode_insert_child(child, depth, key, keylen, value);
return;
}
/**
* @brief Find a child node for the given full key.
*
* @param node the current parent node.
* @param depth the depth of the parent node, 0 for first call.
* @param key the full key of the expected child node.
* @param keylen the number of bytes in the key.
*/
static struct memuse_rnode *memuse_rnode_find_child(struct memuse_rnode *node,
uint8_t depth, uint8_t *key,
uint8_t keylen) {
uint8_t keypart = key[depth];
struct memuse_rnode *child = NULL;
if (node->count > 0) child = memuse_rnode_lookup(node, keypart);
if (child != NULL && (depth + 1) < keylen) {
return memuse_rnode_find_child(child, depth + 1, key, keylen);
}
return child;
}
/**
* @brief Free all resources associated with a node.
*
* @param node the rnode.
*/
static void memuse_rnode_cleanup(struct memuse_rnode *node) {
if (!node) return;
for (size_t k = 0; k < node->count; k++) {
memuse_rnode_cleanup(node->children[k]);
free(node->children[k]);
}
if (node->count > 0) free(node->children);
}
/**
* @brief reallocate the entries log if space is needed.
*/
......
/*******************************************************************************
* This file is part of SWIFT.
* Copyright (c) 2019 Peter W. Draper (p.w.draper@durham.ac.uk)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
/**
* @file memuse_rnode.c
* @brief file of routines used for radix nodes in memory loggers.
*/
/* Config parameters. */
#include "../config.h"
/* Standard includes. */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
/* Local defines. */
#include "memuse_rnodes.h"
/* Local includes. */
#include "atomic.h"
#include "clocks.h"
#include "error.h"
/**
* @brief Return the position of a keypart for a list of children.
* If not found returns where it would be inserted.
*
* @param keypart the keypart to locate.
* @param children the list of sorted children.
* @param count the number of children
*
* @return the index of key or where it should be inserted.
*/
static unsigned int memuse_rnode_bsearch(uint8_t keypart,
struct memuse_rnode **children,
unsigned int count) {
/* Search for lower bound. */
unsigned int lower = 0;
unsigned int upper = count;
while (lower < upper) {
unsigned int middle = (upper + lower) / 2;
if (keypart > children[middle]->keypart)
lower = middle + 1;
else
upper = middle;
}
return lower;
}
/**
* @brief Insert a child, if needed, into a list of children. Assumes
* we have sufficient room.
*
* @param child the child to insert, if needed.
* @param children the list of sorted children.
* @param count the number of children
*/
static void memuse_rnode_binsert_child(struct memuse_rnode *child,
struct memuse_rnode **children,
unsigned int *count) {
unsigned int pos = 0;
if (*count > 0) {
/* Find the child or insertion point. */
pos = memuse_rnode_bsearch(child->keypart, children, *count);
/* If not found move all children to make a space, unless we're inserting
* after the end. */
if (pos < *count && children[pos]->keypart != child->keypart) {
memmove(&children[pos + 1], &children[pos],
(*count - pos) * sizeof(struct memuse_rnode *));
}
}
/* Insert new child */
children[pos] = child;
*count += 1;
}
/**
* @brief Add a child rnode to an rnode. Making sure we have room and keeping
* the sort order.
*
* @param node the parent node.
* @param child the node to add to the parent,
*/
static void memuse_rnode_add_child(struct memuse_rnode *node,
struct memuse_rnode *child) {
/* Extend the children list to include a new entry .*/
void *mem = realloc(node->children,
(node->count + 1) * sizeof(struct memuse_rnode *));
if (mem == NULL) error("Failed to reallocate rnodes\n");
node->children = mem;
/* Insert the new child. */
memuse_rnode_binsert_child(child, node->children, &node->count);
}
/**
* @brief Find a child of a node with the given key part.
*
* @param node the node to search.
* @param keypart the key part of the child.
* @return NULL if not found.
*/
static struct memuse_rnode *memuse_rnode_lookup(const struct memuse_rnode *node,
uint8_t keypart) {
/* Locate the key, or where it would be inserted. */
if (node->count > 0) {
unsigned int index =
memuse_rnode_bsearch(keypart, node->children, node->count);
if (index < node->count && keypart == node->children[index]->keypart) {
return node->children[index];
}
}
return NULL;
}
/**
* @brief insert a child into a node's children list and add a pointer, iff
* this is the destination node for the given key.
*
* @param node the parent node.
* @param depth the depth of the parent node.
* @param key the full key of the eventual leaf node.
* @param keylen the numbers of bytes in the full key.
* @param value pointer that will be stored as the value of the leaf node.
*/
void memuse_rnode_insert_child(struct memuse_rnode *node, uint8_t depth,
uint8_t *key, uint8_t keylen,
void *value) {
/* Check if keypart this already exists at this level and add new child if
* not. */
uint8_t keypart = key[depth];
struct memuse_rnode *child = memuse_rnode_lookup(node, keypart);
if (child == NULL) {
child = calloc(1, sizeof(struct memuse_rnode));
child->keypart = keypart;
memuse_rnode_add_child(node, child);
}
/* Are we at the lowest level yet? */
depth++;
if (depth == keylen) {
/* Our destination node. */
#if SWIFT_DEBUG_CHECKS
if (child->ptr != NULL)
message("Overwriting rnode value: %p with %p", child->ptr, value);
#endif
child->ptr = value;
return;
}
/* Down we go to the next level. */
memuse_rnode_insert_child(child, depth, key, keylen, value);
return;
}
/**
* @brief Find a child node for the given full key.
*
* @param node the current parent node.
* @param depth the depth of the parent node, 0 for first call.
* @param key the full key of the expected child node.
* @param keylen the number of bytes in the key.
*/
struct memuse_rnode *memuse_rnode_find_child(struct memuse_rnode *node,
uint8_t depth, uint8_t *key,
uint8_t keylen) {
uint8_t keypart = key[depth];
struct memuse_rnode *child = NULL;
if (node->count > 0) child = memuse_rnode_lookup(node, keypart);
if (child != NULL && (depth + 1) < keylen) {
return memuse_rnode_find_child(child, depth + 1, key, keylen);
}
return child;
}
/**
* @brief Free all resources associated with a node.
*
* @param node the rnode.
*/
void memuse_rnode_cleanup(struct memuse_rnode *node) {
if (!node) return;
for (size_t k = 0; k < node->count; k++) {
memuse_rnode_cleanup(node->children[k]);
free(node->children[k]);
}
if (node->count > 0) free(node->children);
}
/**
* @brief Dump a representation of the radix tree rooted at a node to stdout.
*
* Debugging code.
*
* @param depth the depth of the node in the tree, root is 0.
* @param node the node at which to start dumping.
* @param full if not zero then nodes that are not storing a value
* are also reported.
*/
void memuse_rnode_dump(int depth, struct memuse_rnode *node, int full) {
/* Value of the full key, to this depth. Assumes full key is a pointer,
* so uncomment when using strings. */
static union {
// uint8_t key[MEMUSE_MAXLABLEN];
// char ptr[MEMUSE_MAXLABLEN];
uint8_t key[sizeof(uintptr_t)];
void *ptr;
} keyparts = {0};
/* Record keypart at this depth. Root has no keypart. */
if (depth != 0) keyparts.key[depth - 1] = node->keypart;
// if (node->ptr != NULL || full) {
// keyparts.key[depth] = '\0';
//
// /* Gather children's keys if full. */
// char fullkey[MEMUSE_MAXLABLEN];
// if (full) {
// for (size_t k = 0; k < node->count; k++) {
// fullkey[k] = node->children[k]->keypart;
// }
// fullkey[node->count] = '\0';
// printf("dump @ depth: %d keypart: %d key: %s value: %p fullkey: %s\n",
// depth, node->keypart, keyparts.ptr, node->ptr, fullkey);
// } else {
// printf("dump @ depth: %d keypart: %d key: %s value: %p\n", depth,
// node->keypart, keyparts.ptr, node->ptr);
// }
//}
if (node->ptr != NULL || full) {
printf("dump @ depth: %d keypart: %d key: %p value: %p\n", depth,
node->keypart, keyparts.ptr, node->ptr);
}
/* Recurse to all children. */
for (size_t k = 0; k < node->count; k++) {
memuse_rnode_dump(depth + 1, node->children[k], full);
}
}
/*******************************************************************************
* This file is part of SWIFT.
* Copyright (c) 2018 Peter W. Draper (p.w.draper@durham.ac.uk)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef SWIFT_MEMUSE_RNODE_H
#define SWIFT_MEMUSE_RNODE_H
/* Config parameters. */
#include "../config.h"
/* Includes. */
#include <stdlib.h>
/* A radix node, this has a single byte key and a pointer to some related
* resource. It also holds a sorted list of children, if any. */
struct memuse_rnode {
/* Byte key of this node. */
uint8_t keypart;
/* Value of this node, if set. */
void *ptr;
/* Sorted pointers to children of this node. */
struct memuse_rnode **children;
unsigned int count;
};
void memuse_rnode_dump(int depth, struct memuse_rnode *node, int full);
void memuse_rnode_insert_child(struct memuse_rnode *node, uint8_t depth,
uint8_t *key, uint8_t keylen,
void *value);
struct memuse_rnode *memuse_rnode_find_child(struct memuse_rnode *node,
uint8_t depth, uint8_t *key,
uint8_t keylen);
void memuse_rnode_cleanup(struct memuse_rnode *node);
#endif /* SWIFT_MEMUSE_RNODE_H */
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment