diff --git a/examples/main.c b/examples/main.c
index 79d002594eb6255163c9eeff88a89dd6cab510c7..b816039e73795a6e1e338f1f0a020b0b7cc2b810 100644
--- a/examples/main.c
+++ b/examples/main.c
@@ -1036,6 +1036,20 @@ int main(int argc, char *argv[]) {
   /* unused parameters */
   parser_write_params_to_file(params, "unused_parameters.yml", 0);
 
+  /* Dump memory use report if collected for the 0 step. */
+#ifdef SWIFT_MEMUSE_REPORTS
+  {
+    char dumpfile[40];
+#ifdef WITH_MPI
+    snprintf(dumpfile, 40, "memuse_report-rank%d-step%d.dat", engine_rank, 0);
+#else
+    snprintf(dumpfile, 40, "memuse_report-step%d.dat", 0);
+#endif  // WITH_MPI
+    memuse_log_dump(dumpfile);
+  }
+#endif
+
+
   /* Main simulation loop */
   /* ==================== */
   int force_stop = 0, resubmit = 0;
@@ -1083,6 +1097,20 @@ int main(int argc, char *argv[]) {
       task_dump_stats(dumpfile, &e, /* header = */ 0, /* allranks = */ 1);
     }
 
+    /* Dump memory use report if collected. */
+#ifdef SWIFT_MEMUSE_REPORTS
+    {
+      char dumpfile[40];
+#ifdef WITH_MPI
+      snprintf(dumpfile, 40, "memuse_report-rank%d-step%d.dat", engine_rank,
+               j + 1);
+#else
+      snprintf(dumpfile, 40, "memuse_report-step%d.dat", j + 1);
+#endif  // WITH_MPI
+      memuse_log_dump(dumpfile);
+    }
+#endif
+
 #ifdef SWIFT_DEBUG_THREADPOOL
     /* Dump the task data using the given frequency. */
     if (dump_threadpool && (dump_threadpool == 1 || j % dump_threadpool == 1)) {
diff --git a/src/engine.c b/src/engine.c
index c05e265e10bc3a0dbefa87805e0d23dd2fa00834..9481f653efaa0758acf92bedbf30472e9b11d639 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -167,6 +167,7 @@ void engine_addlink(struct engine *e, struct link **l, struct task *t) {
 /**
  * Do the exchange of one type of particles with all the other nodes.
  *
+ * @param label a label for the memory allocations of this particle type.
  * @param counts 2D array with the counts of particles to exchange with
  *               each other node.
  * @param parts the particle data to exchange
@@ -181,19 +182,17 @@ void engine_addlink(struct engine *e, struct link **l, struct task *t) {
  * @result new particle data constructed from all the exchanges with the
  *         given alignment.
  */
-static void *engine_do_redistribute(int *counts, char *parts,
+static void *engine_do_redistribute(const char * label, int *counts, char *parts,
                                     size_t new_nr_parts, size_t sizeofparts,
                                     size_t alignsize, MPI_Datatype mpi_type,
                                     int nr_nodes, int nodeID) {
 
   /* Allocate a new particle array with some extra margin */
   char *parts_new = NULL;
-  if (posix_memalign(
+  if (swift_memalign(label,
           (void **)&parts_new, alignsize,
           sizeofparts * new_nr_parts * engine_redistribute_alloc_margin) != 0)
     error("Failed to allocate new particle data.");
-  memuse_report("new_parts", 
-                sizeofparts * new_nr_parts * engine_redistribute_alloc_margin);
 
   /* Prepare MPI requests for the asynchronous communications */
   MPI_Request *reqs;
@@ -866,35 +865,35 @@ void engine_redistribute(struct engine *e) {
    * under control. */
 
   /* SPH particles. */
-  void *new_parts = engine_do_redistribute(
+  void *new_parts = engine_do_redistribute("parts",
       counts, (char *)s->parts, nr_parts_new, sizeof(struct part), part_align,
       part_mpi_type, nr_nodes, nodeID);
-  free(s->parts);
+  swift_free("parts", s->parts);
   s->parts = (struct part *)new_parts;
   s->nr_parts = nr_parts_new;
   s->size_parts = engine_redistribute_alloc_margin * nr_parts_new;
 
   /* Extra SPH particle properties. */
-  new_parts = engine_do_redistribute(counts, (char *)s->xparts, nr_parts_new,
+  new_parts = engine_do_redistribute("xparts", counts, (char *)s->xparts, nr_parts_new,
                                      sizeof(struct xpart), xpart_align,
                                      xpart_mpi_type, nr_nodes, nodeID);
-  free(s->xparts);
+  swift_free("xparts", s->xparts);
   s->xparts = (struct xpart *)new_parts;
 
   /* Gravity particles. */
-  new_parts = engine_do_redistribute(g_counts, (char *)s->gparts, nr_gparts_new,
+  new_parts = engine_do_redistribute("gparts", g_counts, (char *)s->gparts, nr_gparts_new,
                                      sizeof(struct gpart), gpart_align,
                                      gpart_mpi_type, nr_nodes, nodeID);
-  free(s->gparts);
+  swift_free("gparts", s->gparts);
   s->gparts = (struct gpart *)new_parts;
   s->nr_gparts = nr_gparts_new;
   s->size_gparts = engine_redistribute_alloc_margin * nr_gparts_new;
 
   /* Star particles. */
-  new_parts = engine_do_redistribute(s_counts, (char *)s->sparts, nr_sparts_new,
+  new_parts = engine_do_redistribute("sparts", s_counts, (char *)s->sparts, nr_sparts_new,
                                      sizeof(struct spart), spart_align,
                                      spart_mpi_type, nr_nodes, nodeID);
-  free(s->sparts);
+  swift_free("sparts", s->sparts);
   s->sparts = (struct spart *)new_parts;
   s->nr_sparts = nr_sparts_new;
   s->size_sparts = engine_redistribute_alloc_margin * nr_sparts_new;
@@ -1166,13 +1165,6 @@ void engine_exchange_cells(struct engine *e) {
   /* Exchange the cell structure with neighbouring ranks. */
   proxy_cells_exchange(e->proxies, e->nr_proxies, e->s, with_gravity);
 
-  memuse_report("parts_foreign", sizeof(struct part) * e->s->size_parts_foreign);
-
-  memuse_report("gparts_foreign",
-                sizeof(struct gpart) * e->s->size_gparts_foreign);
-
-  memuse_report("sparts_foreign",
-                sizeof(struct spart) * e->s->size_sparts_foreign);
   if (e->verbose)
     message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
             clocks_getunit());
@@ -1369,15 +1361,15 @@ void engine_exchange_strays(struct engine *e, const size_t offset_parts,
     s->size_parts = (offset_parts + count_parts_in) * engine_parts_size_grow;
     struct part *parts_new = NULL;
     struct xpart *xparts_new = NULL;
-    if (posix_memalign((void **)&parts_new, part_align,
+    if (swift_memalign("parts", (void **)&parts_new, part_align,
                        sizeof(struct part) * s->size_parts) != 0 ||
-        posix_memalign((void **)&xparts_new, xpart_align,
+        swift_memalign("xparts", (void **)&xparts_new, xpart_align,
                        sizeof(struct xpart) * s->size_parts) != 0)
       error("Failed to allocate new part data.");
     memcpy(parts_new, s->parts, sizeof(struct part) * offset_parts);
     memcpy(xparts_new, s->xparts, sizeof(struct xpart) * offset_parts);
-    free(s->parts);
-    free(s->xparts);
+    swift_free("parts", s->parts);
+    swift_free("xparts", s->xparts);
     s->parts = parts_new;
     s->xparts = xparts_new;
 
@@ -1388,18 +1380,16 @@ void engine_exchange_strays(struct engine *e, const size_t offset_parts,
       }
     }
   }
-  memuse_report("parts", sizeof(struct part) * s->size_parts);
-  memuse_report("xparts", sizeof(struct xpart) * s->size_parts);
 
   if (offset_sparts + count_sparts_in > s->size_sparts) {
     message("re-allocating sparts array.");
     s->size_sparts = (offset_sparts + count_sparts_in) * engine_parts_size_grow;
     struct spart *sparts_new = NULL;
-    if (posix_memalign((void **)&sparts_new, spart_align,
+    if (swift_memalign("sparts", (void **)&sparts_new, spart_align,
                        sizeof(struct spart) * s->size_sparts) != 0)
       error("Failed to allocate new spart data.");
     memcpy(sparts_new, s->sparts, sizeof(struct spart) * offset_sparts);
-    free(s->sparts);
+    swift_free("sparts", s->sparts);
     s->sparts = sparts_new;
 
     /* Reset the links */
@@ -1409,17 +1399,16 @@ void engine_exchange_strays(struct engine *e, const size_t offset_parts,
       }
     }
   }
-  memuse_report("sparts", sizeof(struct spart) * s->size_sparts);
 
   if (offset_gparts + count_gparts_in > s->size_gparts) {
     message("re-allocating gparts array.");
     s->size_gparts = (offset_gparts + count_gparts_in) * engine_parts_size_grow;
     struct gpart *gparts_new = NULL;
-    if (posix_memalign((void **)&gparts_new, gpart_align,
+    if (swift_memalign("gparts", (void **)&gparts_new, gpart_align,
                        sizeof(struct gpart) * s->size_gparts) != 0)
       error("Failed to allocate new gpart data.");
     memcpy(gparts_new, s->gparts, sizeof(struct gpart) * offset_gparts);
-    free(s->gparts);
+    swift_free("gparts", s->gparts);
     s->gparts = gparts_new;
 
     /* Reset the links */
@@ -1431,7 +1420,6 @@ void engine_exchange_strays(struct engine *e, const size_t offset_parts,
       }
     }
   }
-  memuse_report("gparts", sizeof(struct gpart) * s->size_gparts);
 
   /* Collect the requests for the particle data from the proxies. */
   int nr_in = 0, nr_out = 0;
@@ -1673,12 +1661,12 @@ void engine_exchange_proxy_multipoles(struct engine *e) {
 
   /* Allocate the buffers for the packed data */
   struct gravity_tensors *buffer_send = NULL;
-  if (posix_memalign((void **)&buffer_send, SWIFT_CACHE_ALIGNMENT,
+  if (swift_memalign("send_gravity_tensors", (void **)&buffer_send, SWIFT_CACHE_ALIGNMENT,
                      count_send_cells * sizeof(struct gravity_tensors)) != 0)
     error("Unable to allocate memory for multipole transactions");
 
   struct gravity_tensors *buffer_recv = NULL;
-  if (posix_memalign((void **)&buffer_recv, SWIFT_CACHE_ALIGNMENT,
+  if (swift_memalign("recv_gravity_tensors", (void **)&buffer_recv, SWIFT_CACHE_ALIGNMENT,
                      count_recv_cells * sizeof(struct gravity_tensors)) != 0)
     error("Unable to allocate memory for multipole transactions");
 
@@ -1839,33 +1827,30 @@ void engine_allocate_foreign_particles(struct engine *e) {
 
   /* Allocate space for the foreign particles we will receive */
   if (count_parts_in > s->size_parts_foreign) {
-    if (s->parts_foreign != NULL) free(s->parts_foreign);
+    if (s->parts_foreign != NULL) swift_free("sparts_foreign", s->parts_foreign);
     s->size_parts_foreign = engine_foreign_alloc_margin * count_parts_in;
-    if (posix_memalign((void **)&s->parts_foreign, part_align,
+    if (swift_memalign("parts_foreign", (void **)&s->parts_foreign, part_align,
                        sizeof(struct part) * s->size_parts_foreign) != 0)
       error("Failed to allocate foreign part data.");
   }
-  memuse_report("parts_foreign", sizeof(struct part) * s->size_parts_foreign);
 
   /* Allocate space for the foreign particles we will receive */
   if (count_gparts_in > s->size_gparts_foreign) {
-    if (s->gparts_foreign != NULL) free(s->gparts_foreign);
+    if (s->gparts_foreign != NULL) swift_free("gparts_foreign", s->gparts_foreign);
     s->size_gparts_foreign = engine_foreign_alloc_margin * count_gparts_in;
-    if (posix_memalign((void **)&s->gparts_foreign, gpart_align,
+    if (swift_memalign("gparts_foreign", (void **)&s->gparts_foreign, gpart_align,
                        sizeof(struct gpart) * s->size_gparts_foreign) != 0)
       error("Failed to allocate foreign gpart data.");
   }
-  memuse_report("gparts_foreign", sizeof(struct gpart) * s->size_gparts_foreign);
 
   /* Allocate space for the foreign particles we will receive */
   if (count_sparts_in > s->size_sparts_foreign) {
-    if (s->sparts_foreign != NULL) free(s->sparts_foreign);
+    if (s->sparts_foreign != NULL) swift_free("sparts_foreign", s->sparts_foreign);
     s->size_sparts_foreign = engine_foreign_alloc_margin * count_sparts_in;
-    if (posix_memalign((void **)&s->sparts_foreign, spart_align,
+    if (swift_memalign("sparts_foreign", (void **)&s->sparts_foreign, spart_align,
                        sizeof(struct spart) * s->size_sparts_foreign) != 0)
       error("Failed to allocate foreign spart data.");
   }
-  memuse_report("sparts_foreign", sizeof(struct spart) * s->size_sparts_foreign);
 
   if (e->verbose)
     message("Allocating %zd/%zd/%zd foreign part/gpart/spart (%zd/%zd/%zd MB)",
@@ -3262,7 +3247,6 @@ void engine_step(struct engine *e) {
 
   /* Create a restart file if needed. */
   engine_dump_restarts(e, 0, e->restart_onexit && engine_is_done(e));
-  memuse_report_str("step", memuse_process());
 
   engine_check_for_dumps(e);
 
@@ -3377,7 +3361,7 @@ void engine_check_for_dumps(struct engine *e) {
         /* Free the memory allocated for VELOCIraptor i/o. */
         if (with_stf && e->snapshot_invoke_stf) {
 #ifdef HAVE_VELOCIRAPTOR
-          free(e->s->gpart_group_data);
+          swift_free("gpart_group_data", e->s->gpart_group_data);
           e->s->gpart_group_data = NULL;
 #endif
         }
@@ -3906,20 +3890,18 @@ void engine_split(struct engine *e, struct partition *initial_partition) {
   s->size_parts = s->nr_parts * engine_redistribute_alloc_margin;
   struct part *parts_new = NULL;
   struct xpart *xparts_new = NULL;
-  if (posix_memalign((void **)&parts_new, part_align,
+  if (swift_memalign("parts", (void **)&parts_new, part_align,
                      sizeof(struct part) * s->size_parts) != 0 ||
-      posix_memalign((void **)&xparts_new, xpart_align,
+      swift_memalign("xparts", (void **)&xparts_new, xpart_align,
                      sizeof(struct xpart) * s->size_parts) != 0)
     error("Failed to allocate new part data.");
-  memuse_report("parts", sizeof(struct part) * s->size_parts);
-  memuse_report("xparts", sizeof(struct xpart) * s->size_parts);
 
   if (s->nr_parts > 0) {
     memcpy(parts_new, s->parts, sizeof(struct part) * s->nr_parts);
     memcpy(xparts_new, s->xparts, sizeof(struct xpart) * s->nr_parts);
   }
-  free(s->parts);
-  free(s->xparts);
+  swift_free("parts", s->parts);
+  swift_free("xparts", s->xparts);
   s->parts = parts_new;
   s->xparts = xparts_new;
 
@@ -3933,14 +3915,13 @@ void engine_split(struct engine *e, struct partition *initial_partition) {
             (size_t)(s->nr_sparts * engine_redistribute_alloc_margin));
   s->size_sparts = s->nr_sparts * engine_redistribute_alloc_margin;
   struct spart *sparts_new = NULL;
-  if (posix_memalign((void **)&sparts_new, spart_align,
+  if (swift_memalign("sparts", (void **)&sparts_new, spart_align,
                      sizeof(struct spart) * s->size_sparts) != 0)
     error("Failed to allocate new spart data.");
-  memuse_report("sparts", sizeof(struct spart) * s->size_sparts);
 
   if (s->nr_sparts > 0)
     memcpy(sparts_new, s->sparts, sizeof(struct spart) * s->nr_sparts);
-  free(s->sparts);
+  swift_free("sparts", s->sparts);
   s->sparts = sparts_new;
 
   /* Re-link the gparts to their sparts. */
@@ -3953,14 +3934,13 @@ void engine_split(struct engine *e, struct partition *initial_partition) {
             (size_t)(s->nr_gparts * engine_redistribute_alloc_margin));
   s->size_gparts = s->nr_gparts * engine_redistribute_alloc_margin;
   struct gpart *gparts_new = NULL;
-  if (posix_memalign((void **)&gparts_new, gpart_align,
+  if (swift_memalign("gparts", (void **)&gparts_new, gpart_align,
                      sizeof(struct gpart) * s->size_gparts) != 0)
     error("Failed to allocate new gpart data.");
-  memuse_report("gparts", sizeof(struct gpart) * s->size_gparts);
 
   if (s->nr_gparts > 0)
     memcpy(gparts_new, s->gparts, sizeof(struct gpart) * s->nr_gparts);
-  free(s->gparts);
+  swift_free("gparts", s->gparts);
   s->gparts = gparts_new;
 
   /* Re-link the parts. */
@@ -4053,7 +4033,7 @@ void engine_collect_stars_counter(struct engine *e) {
 
   free(n_sparts);
   free(n_sparts_in);
-  free(sparts);
+  swift_free("sparts", sparts);
 #endif
 }
 
@@ -4890,10 +4870,9 @@ void engine_config(int restart, struct engine *e, struct swift_params *params,
       parser_get_opt_param_int(params, "Scheduler:mpi_message_limit", 4) * 1024;
 
   /* Allocate and init the threads. */
-  if (posix_memalign((void **)&e->runners, SWIFT_CACHE_ALIGNMENT,
+  if (swift_memalign("runners", (void **)&e->runners, SWIFT_CACHE_ALIGNMENT,
                      e->nr_threads * sizeof(struct runner)) != 0)
     error("Failed to allocate threads array.");
-  memuse_report("runners", e->nr_threads * sizeof(struct runner));
 
   for (int k = 0; k < e->nr_threads; k++) {
     e->runners[k].id = k;
@@ -5399,7 +5378,7 @@ void engine_clean(struct engine *e) {
     gravity_cache_clean(&e->runners[i].ci_gravity_cache);
     gravity_cache_clean(&e->runners[i].cj_gravity_cache);
   }
-  free(e->runners);
+  swift_free("runners", e->runners);
   free(e->snapshot_units);
 
   output_list_clean(&e->output_list_snapshots);
diff --git a/src/memuse.c b/src/memuse.c
index f3d3a0370fd7b54c70215d2cbcc2c2944980b3a2..ea66e7733179cda3580625102a1a253806f89ece 100644
--- a/src/memuse.c
+++ b/src/memuse.c
@@ -28,6 +28,7 @@
 
 /* Standard includes. */
 #include <stdio.h>
+#include <stdlib.h>
 #include <sys/types.h>
 #include <unistd.h>
 
@@ -35,55 +36,170 @@
 #include "memuse.h"
 
 /* Local includes. */
+#include "atomic.h"
 #include "clocks.h"
 #include "engine.h"
 
 #ifdef SWIFT_MEMUSE_REPORTS
 
-/* For output messages. */
+/* Also recorded in logger. */
 extern int engine_rank;
 extern int engine_cstep;
 
+/* Entry for logger of memory allocations and deallocations in a step. */
+#define MEMUSE_MAXLAB 64
+struct memuse_log_entry {
+
+  /* Rank in action. */
+  int rank;
+
+  /* Step of action. */
+  int step;
+
+  /* Whether allocated or deallocated. */
+  int allocated;
+
+  /* Memory allocated in bytes. */
+  size_t size;
+
+  /* Address of memory. */
+  void *ptr;
+
+  /* Time of this action. */
+  ticks tic;
+
+  /* Label associated with the memory. */
+  char label[MEMUSE_MAXLAB + 1];
+};
+
+/* The log of allocations and frees. */
+static struct memuse_log_entry *memuse_log = NULL;
+static size_t log_size = 0;
+static size_t log_count = 0;
+static size_t log_done = 0;
+
+#define MEMUSE_INITLOG 10000
+static void log_reallocate(size_t ind) {
+
+  if (ind == 0) {
+
+    /* Need to perform initialization. Be generous. */
+    if ((memuse_log = (struct memuse_log_entry *)
+         malloc(sizeof(struct memuse_log_entry) * MEMUSE_INITLOG)) == NULL)
+      error("Failed to allocate memuse log.");
+
+    /* Last action. */
+    log_size = MEMUSE_INITLOG;
+
+  } else {
+    message("reallocated");
+    struct memuse_log_entry *new_log;
+    if ((new_log = (struct memuse_log_entry *)
+         malloc(sizeof(struct memuse_log_entry) * log_size * 2)) == NULL)
+      error("Failed to re-allocate memuse log.");
+
+    /* Wait for all writes to the old buffer to complete. */
+    while (log_done < log_size);
+
+    /* Copy to new buffer. */
+    memcpy(new_log, memuse_log, sizeof(struct memuse_log_entry) * log_count);
+    free(memuse_log);
+    memuse_log = new_log;
+
+    /* Last action. */
+    log_size *= 2;
+  }
+}
+
+static void log_allocation(const char *label, void *ptr, int allocated,
+                           size_t size) {
+  size_t ind = atomic_inc(&log_count);
+  if (ind == log_size) log_reallocate(ind);
+
+  /* Other threads wait for space. */
+  while (ind > log_size);
+
+  /* Record the log. */
+  memuse_log[ind].rank = engine_rank;
+  memuse_log[ind].step = engine_cstep;
+  memuse_log[ind].allocated = allocated;
+  memuse_log[ind].size = size;
+  memuse_log[ind].ptr = ptr;
+  strncpy(memuse_log[ind].label, label, MEMUSE_MAXLAB);
+  memuse_log[ind].label[MEMUSE_MAXLAB] = '\0';
+  memuse_log[ind].tic = getticks();
+  atomic_inc(&log_done);
+}
+
 /**
- *  @brief Report a memory allocation or use in bytes.
- *
- *  @param what a name for the report, "parts", "gparts" etc.
- *  @param file caller code file name
- *  @param function caller code function.
- *  @param line caller code file line no.
- *  @param bytes the number of bytes that have been allocated
+ * @brief dump the log to a file and reset, if anything to dump.
  */
-void memuse_report__(const char *what, const char *file, const char *function,
-                     int line, size_t bytes) {
-  char buffer[32];
-  sprintf(buffer, "%zd", bytes / 1024);
-  memuse_report_str__(what, file, function, line, buffer);
+void memuse_log_dump(const char *filename) {
+
+  /* Skip if nothing allocated this step. */
+  if (log_count == 0) return;
+
+  /* Open the output file. */
+  FILE *fd;
+  if ((fd = fopen(filename, "w")) == NULL)
+    error("Failed to create memuse log file '%s'.", filename);
+
+  /* Write a header. */
+  fprintf(fd, "# Current use: %s\n", memuse_process());
+  fprintf(fd, "# cpufreq: %lld\n", clocks_get_cpufreq());
+  fprintf(fd, "# tic adr rank step allocated label size\n");
+
+  for (size_t k = 0; k < log_count; k++) {
+    fprintf(fd, "%lld %p %d %d %d %s %zd\n", memuse_log[k].tic,
+            memuse_log[k].ptr, memuse_log[k].rank, memuse_log[k].step,
+            memuse_log[k].allocated, memuse_log[k].label, memuse_log[k].size);
+  }
+
+  /* Clear the log. */
+  log_count = 0;
+
+  /* Close the file. */
+  fclose(fd);
 }
 
+#endif /* SWIFT_MEMUSE_REPORTS */
+
 /**
- *  @brief Report a memory allocation or use formatted description.
+ * @brief allocate aligned memory. The use and results are the same as the
+ *        posix_memalign function.
  *
- *  @param what a name for the report, "parts", "gparts" etc.
- *  @param file caller code file name
- *  @param function caller code function.
- *  @param line caller code file line no.
- *  @param description the report, values should be in KB, the
- *         result of memuse_process() is suitable.
+ * @param label a symbolic label for the memory, i.e. "parts".
+ * @param memptr pointer to the allocated memory.
+ * @param alignment alignment boundary.
+ * @param size the quantity of bytes to allocate.
+ * @result zero on success, otherwise an error code.
  */
-void memuse_report_str__(const char *what, const char *file,
-                         const char *function, int line,
-                         const char *description) {
-#ifdef WITH_MPI
-  printf("[%04i] %s :memuse: %i:%s %s:%s:%i %s\n", engine_rank,
-         clocks_get_timesincestart(), engine_cstep, what, file, function, line,
-         description);
-#else
-  printf("%s :memuse: %i:%s %s:%s:%i %s\n", clocks_get_timesincestart(),
-         engine_cstep, what, file, function, line, description);
+int swift_memalign(const char *label, void **memptr, size_t alignment,
+                   size_t size) {
+  int result = posix_memalign(memptr, alignment, size);
+
+#ifdef SWIFT_MEMUSE_REPORTS
+  if (result == 0) log_allocation(label, *memptr, 1, size);
 #endif
+  return result;
 }
 
-#endif /* SWIFT_MEMUSE_REPORTS */
+/**
+ * @brief free aligned memory. The use and results are the same as the
+ *        free function.
+ *
+ * @param label a symbolic label for the memory, i.e. "parts", should match
+ *              call used to allocate the memory.
+ * @param ptr pointer to the allocated memory.
+ */
+void swift_free(const char *label, void *ptr) {
+  free(ptr);
+
+#ifdef SWIFT_MEMUSE_REPORTS
+  log_allocation(label, ptr, 0, 0);
+#endif
+  return;
+}
 
 /**
  * @brief parse the process /proc/self/statm file to get the process
diff --git a/src/memuse.h b/src/memuse.h
index 0d0637b3c17ab2baa24e4d6627be102dee1cbaac..3b7f62d5599d454d4860f6737fe43114fed13f2f 100644
--- a/src/memuse.h
+++ b/src/memuse.h
@@ -23,25 +23,16 @@
 #include "../config.h"
 
 /* Public API. */
+int swift_memalign(const char *label, void **memptr, size_t alignment,
+                   size_t size);
+void swift_free(const char *label, void *ptr);
+
 void memuse_use(long *size, long *resident, long *share, long *trs, long *lrs,
                 long *drs, long *dt);
 const char *memuse_process(void);
 
-/* Reports are a no-op unless wanted. */
 #ifdef SWIFT_MEMUSE_REPORTS
-void memuse_report__(const char *what, const char *file, const char *function,
-                     int line, size_t bytes);
-void memuse_report_str__(const char *what, const char *file,
-                         const char *function, int line,
-                         const char *description);
-
-#define memuse_report(what, size) \
-  memuse_report__(what, __FILE__, __FUNCTION__, __LINE__, size)
-#define memuse_report_str(what, description) \
-  memuse_report_str__(what, __FILE__, __FUNCTION__, __LINE__, description)
-#else
-#define memuse_report(what, size)
-#define memuse_report_str(what, description)
+void memuse_log_dump(const char *filename);
 #endif
 
 #endif /* SWIFT_MEMUSE_H */
diff --git a/src/parallel_io.c b/src/parallel_io.c
index caf813402d9e50ac4d165d8b731c2c4145e097a8..5091497b435ea01fa484819721cd91fe342f21e7 100644
--- a/src/parallel_io.c
+++ b/src/parallel_io.c
@@ -473,7 +473,7 @@ void writeArray_chunk(struct engine* e, hid_t h_data,
 
   /* Allocate temporary buffer */
   void* temp = NULL;
-  if (posix_memalign((void**)&temp, IO_BUFFER_ALIGNMENT,
+  if (swift_memalign("temp", (void**)&temp, IO_BUFFER_ALIGNMENT,
                      num_elements * typeSize) != 0)
     error("Unable to allocate temporary i/o buffer");
 
@@ -557,7 +557,7 @@ void writeArray_chunk(struct engine* e, hid_t h_data,
 #endif
 
   /* Free and close everything */
-  free(temp);
+  swift_free("temp", temp);
   H5Sclose(h_memspace);
   H5Sclose(h_filespace);
 }
@@ -816,21 +816,19 @@ void read_ic_parallel(char* fileName, const struct unit_system* internal_units,
   /* Allocate memory to store SPH particles */
   if (with_hydro) {
     *Ngas = N[0];
-    if (posix_memalign((void**)parts, part_align,
+    if (swift_memalign("parts", (void**)parts, part_align,
                        (*Ngas) * sizeof(struct part)) != 0)
       error("Error while allocating memory for particles");
     bzero(*parts, *Ngas * sizeof(struct part));
-    memuse_report("parts", (*Ngas) * sizeof(struct part));
   }
 
   /* Allocate memory to store stars particles */
   if (with_stars) {
     *Nstars = N[swift_type_stars];
-    if (posix_memalign((void**)sparts, spart_align,
+    if (swift_memalign("sparts", (void**)sparts, spart_align,
                        *Nstars * sizeof(struct spart)) != 0)
       error("Error while allocating memory for stars particles");
     bzero(*sparts, *Nstars * sizeof(struct spart));
-    memuse_report("sparts", (*Nstars) * sizeof(struct spart));
   }
 
   /* Allocate memory to store gravity particles */
@@ -839,11 +837,10 @@ void read_ic_parallel(char* fileName, const struct unit_system* internal_units,
     *Ngparts = (with_hydro ? N[swift_type_gas] : 0) +
                N[swift_type_dark_matter] +
                (with_stars ? N[swift_type_stars] : 0);
-    if (posix_memalign((void**)gparts, gpart_align,
+    if (swift_memalign("gparts", (void**)gparts, gpart_align,
                        *Ngparts * sizeof(struct gpart)) != 0)
       error("Error while allocating memory for gravity particles");
     bzero(*gparts, *Ngparts * sizeof(struct gpart));
-    memuse_report("gparts", (*Ngparts) * sizeof(struct gpart));
   }
 
   /* message("Allocated %8.2f MB for particles.", *N * sizeof(struct part) /
@@ -1491,10 +1488,10 @@ void write_output_parallel(struct engine* e, const char* baseName,
           Nparticles = Ngas_written;
 
           /* Allocate temporary arrays */
-          if (posix_memalign((void**)&parts_written, part_align,
+          if (swift_memalign("parts_written", (void**)&parts_written, part_align,
                              Ngas_written * sizeof(struct part)) != 0)
             error("Error while allocating temporart memory for parts");
-          if (posix_memalign((void**)&xparts_written, xpart_align,
+          if (swift_memalign("xparts_written", (void**)&xparts_written, xpart_align,
                              Ngas_written * sizeof(struct xpart)) != 0)
             error("Error while allocating temporart memory for xparts");
 
@@ -1539,12 +1536,12 @@ void write_output_parallel(struct engine* e, const char* baseName,
           Nparticles = Ndm_written;
 
           /* Allocate temporary array */
-          if (posix_memalign((void**)&gparts_written, gpart_align,
+          if (swift_memalign("gparts_written", (void**)&gparts_written, gpart_align,
                              Ndm_written * sizeof(struct gpart)) != 0)
             error("Error while allocating temporart memory for gparts");
 
           if (with_stf) {
-            if (posix_memalign(
+            if (swift_memalign("gpart_group_written",
                     (void**)&gpart_group_data_written, gpart_align,
                     Ndm_written * sizeof(struct velociraptor_gpart_data)) != 0)
               error(
@@ -1586,7 +1583,7 @@ void write_output_parallel(struct engine* e, const char* baseName,
           Nparticles = Nstars_written;
 
           /* Allocate temporary arrays */
-          if (posix_memalign((void**)&sparts_written, spart_align,
+          if (swift_memalign("sparts_written", (void**)&sparts_written, spart_align,
                              Nstars_written * sizeof(struct spart)) != 0)
             error("Error while allocating temporart memory for sparts");
 
@@ -1626,11 +1623,11 @@ void write_output_parallel(struct engine* e, const char* baseName,
     }
 
     /* Free temporary array */
-    if (parts_written) free(parts_written);
-    if (xparts_written) free(xparts_written);
-    if (gparts_written) free(gparts_written);
-    if (gpart_group_data_written) free(gpart_group_data_written);
-    if (sparts_written) free(sparts_written);
+    if (parts_written) swift_free("parts_written", parts_written);
+    if (xparts_written) swift_free("xparts_written", xparts_written);
+    if (gparts_written) swift_free("gparts_written", gparts_written);
+    if (gpart_group_data_written) swift_free("gpart_group_written", gpart_group_data_written);
+    if (sparts_written) swift_free("sparts_written", sparts_written);
 
 #ifdef IO_SPEED_MEASUREMENT
     MPI_Barrier(MPI_COMM_WORLD);
diff --git a/src/proxy.c b/src/proxy.c
index 32c181e64f971efb7e7d1620d61ee5e0e277086d..a2e1817aa364dc6220a7428caf9d97e9e1ee4772 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -90,13 +90,11 @@ void proxy_tags_exchange(struct proxy *proxies, int num_proxies,
   /* Allocate the tags. */
   int *tags_in = NULL;
   int *tags_out = NULL;
-  if (posix_memalign((void **)&tags_in, SWIFT_CACHE_ALIGNMENT,
+  if (swift_memalign("tags_in", (void **)&tags_in, SWIFT_CACHE_ALIGNMENT,
                      sizeof(int) * count_in) != 0 ||
-      posix_memalign((void **)&tags_out, SWIFT_CACHE_ALIGNMENT,
+      swift_memalign("tags_out", (void **)&tags_out, SWIFT_CACHE_ALIGNMENT,
                      sizeof(int) * count_out) != 0)
     error("Failed to allocate tags buffers.");
-  memuse_report("tags_in", sizeof(int) * count_in);
-  memuse_report("tags_out", sizeof(int) * count_out);
 
   /* Pack the local tags. */
   for (int k = 0; k < s->nr_cells; k++) {
@@ -170,8 +168,8 @@ void proxy_tags_exchange(struct proxy *proxies, int num_proxies,
     error("MPI_Waitall on sends failed.");
 
   /* Clean up. */
-  free(tags_in);
-  free(tags_out);
+  swift_free("tags_in", tags_in);
+  swift_free("tags_out", tags_out);
   free(reqs_in);
   free(cids_in);
 
@@ -207,11 +205,10 @@ void proxy_cells_exchange_first(struct proxy *p) {
   // p->size_pcells_out , p->mynodeID , p->nodeID ); fflush(stdout);
 
   /* Allocate and fill the pcell buffer. */
-  if (p->pcells_out != NULL) free(p->pcells_out);
-  if (posix_memalign((void **)&p->pcells_out, SWIFT_STRUCT_ALIGNMENT,
+  if (p->pcells_out != NULL) swift_free("pcells_out", p->pcells_out);
+  if (swift_memalign("pcells_out", (void **)&p->pcells_out, SWIFT_STRUCT_ALIGNMENT,
                      sizeof(struct pcell) * p->size_pcells_out) != 0)
     error("Failed to allocate pcell_out buffer.");
-  memuse_report("pcells_out", sizeof(struct pcell) * p->size_pcells_out);
 
   for (int ind = 0, k = 0; k < p->nr_cells_out; k++) {
     memcpy(&p->pcells_out[ind], p->cells_out[k]->mpi.pcell,
@@ -255,11 +252,10 @@ void proxy_cells_exchange_second(struct proxy *p) {
 #ifdef WITH_MPI
 
   /* Re-allocate the pcell_in buffer. */
-  if (p->pcells_in != NULL) free(p->pcells_in);
-  if (posix_memalign((void **)&p->pcells_in, SWIFT_STRUCT_ALIGNMENT,
+  if (p->pcells_in != NULL) swift_free("pcells_in", p->pcells_in);
+  if (swift_memalign("pcells_in", (void **)&p->pcells_in, SWIFT_STRUCT_ALIGNMENT,
                      sizeof(struct pcell) * p->size_pcells_in) != 0)
     error("Failed to allocate pcell_in buffer.");
-  memuse_report("pcells_in", sizeof(struct pcell) * p->size_pcells_in);
 
   /* Receive the particle buffers. */
   int err = MPI_Irecv(p->pcells_in, p->size_pcells_in, pcell_mpi_type,
@@ -403,10 +399,9 @@ void proxy_cells_exchange(struct proxy *proxies, int num_proxies,
 
   /* Allocate the pcells. */
   struct pcell *pcells = NULL;
-  if (posix_memalign((void **)&pcells, SWIFT_CACHE_ALIGNMENT,
+  if (swift_memalign("pcells", (void **)&pcells, SWIFT_CACHE_ALIGNMENT,
                      sizeof(struct pcell) * count_out) != 0)
     error("Failed to allocate pcell buffer.");
-  memuse_report("pcells", sizeof(struct pcell) * count_out);
 
   tic2 = getticks();
 
@@ -474,7 +469,7 @@ void proxy_cells_exchange(struct proxy *proxies, int num_proxies,
 
   /* Clean up. */
   free(reqs);
-  free(pcells);
+  swift_free("pcells", pcells);
 
 #else
   error("SWIFT was not compiled with MPI support.");
@@ -482,9 +477,6 @@ void proxy_cells_exchange(struct proxy *proxies, int num_proxies,
 }
 
 /**
-  memuse_report("pcells_out", sizeof(struct pcell) * p->size_pcells_out);
-
-  memuse_report("pcells_in", sizeof(struct pcell) * p->size_pcells_in);
  * @brief Add a cell to the given proxy's input list.
  *
  * @param p The #proxy.
diff --git a/src/runner.c b/src/runner.c
index 316fda132fdb4d041bb9002364cc6d0683f0db06..e6cd47cb28d7cb9bbdd0331295b317170eb13e42 100644
--- a/src/runner.c
+++ b/src/runner.c
@@ -823,7 +823,6 @@ void runner_do_hydro_sort(struct runner *r, struct cell *c, int flags,
       allocated += sizeof(struct entry) * (count + 1);
     }
   }
-  memuse_report("cell_sorts", allocated);
 
   /* Does this cell have any progeny? */
   if (c->split) {
diff --git a/src/scheduler.c b/src/scheduler.c
index 249c62c5b20b24f71cd7362a02dd851a81ff228c..97288d267a8c958cecd9d67c49edf683f063f9d5 100644
--- a/src/scheduler.c
+++ b/src/scheduler.c
@@ -81,8 +81,8 @@ static void scheduler_extend_unlocks(struct scheduler *s) {
   /* Copy the buffers. */
   memcpy(unlocks_new, s->unlocks, sizeof(struct task *) * s->size_unlocks);
   memcpy(unlock_ind_new, s->unlock_ind, sizeof(int) * s->size_unlocks);
-  free(s->unlocks);
-  free(s->unlock_ind);
+  swift_free("unlocks", s->unlocks);
+  swift_free("unlock_ind", s->unlock_ind);
   s->unlocks = unlocks_new;
   s->unlock_ind = unlock_ind_new;
 
@@ -1364,7 +1364,7 @@ void scheduler_set_unlocks(struct scheduler *s) {
   }
 
   /* Swap the unlocks. */
-  free(s->unlocks);
+  swift_free("unlocks", s->unlocks);
   s->unlocks = unlocks;
 
   /* Re-set the offsets. */
@@ -1479,7 +1479,7 @@ void scheduler_reset(struct scheduler *s, int size) {
     scheduler_free_tasks(s);
 
     /* Allocate the new lists. */
-    if (posix_memalign((void **)&s->tasks, task_align,
+    if (swift_memalign("tasks", (void **)&s->tasks, task_align,
                        size * sizeof(struct task)) != 0)
       error("Failed to allocate task array.");
 
@@ -1489,9 +1489,6 @@ void scheduler_reset(struct scheduler *s, int size) {
     if ((s->tid_active = (int *)malloc(sizeof(int) * size)) == NULL)
       error("Failed to allocate aactive task lists.");
   }
-  memuse_report("tasks", size * sizeof(struct task));
-  memuse_report("tasks_ind", size * sizeof(int));
-  memuse_report("tid_active", size * sizeof(int));
 
   /* Reset the counters. */
   s->size = size;
@@ -2151,10 +2148,9 @@ void scheduler_init(struct scheduler *s, struct space *space, int nr_tasks,
   lock_init(&s->lock);
 
   /* Allocate the queues. */
-  if (posix_memalign((void **)&s->queues, queue_struct_align,
+  if (swift_memalign("queues", (void **)&s->queues, queue_struct_align,
                      sizeof(struct queue) * nr_queues) != 0)
     error("Failed to allocate queues.");
-  memuse_report("queues", sizeof(struct queue) * nr_queues);
 
   /* Initialize each queue. */
   for (int k = 0; k < nr_queues; k++) queue_init(&s->queues[k], NULL);
@@ -2219,10 +2215,10 @@ void scheduler_print_tasks(const struct scheduler *s, const char *fileName) {
 void scheduler_clean(struct scheduler *s) {
 
   scheduler_free_tasks(s);
-  free(s->unlocks);
-  free(s->unlock_ind);
+  swift_free("unlocks", s->unlocks);
+  swift_free("unlock_ind", s->unlock_ind);
   for (int i = 0; i < s->nr_queues; ++i) queue_clean(&s->queues[i]);
-  free(s->queues);
+  swift_free("queues", s->queues);
 }
 
 /**
@@ -2231,15 +2227,15 @@ void scheduler_clean(struct scheduler *s) {
 void scheduler_free_tasks(struct scheduler *s) {
 
   if (s->tasks != NULL) {
-    free(s->tasks);
+    swift_free("tasks", s->tasks);
     s->tasks = NULL;
   }
   if (s->tasks_ind != NULL) {
-    free(s->tasks_ind);
+    swift_free("tasks_ind", s->tasks_ind);
     s->tasks_ind = NULL;
   }
   if (s->tid_active != NULL) {
-    free(s->tid_active);
+    swift_free("tid_active", s->tid_active);
     s->tid_active = NULL;
   }
   s->size = 0;
diff --git a/src/serial_io.c b/src/serial_io.c
index d4db3400b0e405ccb08e1b14bead2b5c65817b22..234a77d3b94b727126817e70871434820f1b7db5 100644
--- a/src/serial_io.c
+++ b/src/serial_io.c
@@ -365,7 +365,7 @@ void writeArray(const struct engine* e, hid_t grp, char* fileName,
 
   /* Allocate temporary buffer */
   void* temp = NULL;
-  if (posix_memalign((void**)&temp, IO_BUFFER_ALIGNMENT,
+  if (swift_memalign("temp", (void**)&temp, IO_BUFFER_ALIGNMENT,
                      num_elements * typeSize) != 0)
     error("Unable to allocate temporary i/o buffer");
 
@@ -416,7 +416,7 @@ void writeArray(const struct engine* e, hid_t grp, char* fileName,
   if (h_err < 0) error("Error while writing data array '%s'.", props.name);
 
   /* Free and close everything */
-  free(temp);
+  swift_free("temp", temp);
   H5Dclose(h_data);
   H5Sclose(h_memspace);
   H5Sclose(h_filespace);
@@ -615,21 +615,19 @@ void read_ic_serial(char* fileName, const struct unit_system* internal_units,
   /* Allocate memory to store SPH particles */
   if (with_hydro) {
     *Ngas = N[0];
-    if (posix_memalign((void**)parts, part_align,
+    if (swift_memalign("parts", (void**)parts, part_align,
                        *Ngas * sizeof(struct part)) != 0)
       error("Error while allocating memory for SPH particles");
     bzero(*parts, *Ngas * sizeof(struct part));
-    memuse_report("parts", (*Ngas) * sizeof(struct part));
   }
 
   /* Allocate memory to store stars particles */
   if (with_stars) {
     *Nstars = N[swift_type_stars];
-    if (posix_memalign((void**)sparts, spart_align,
+    if (swift_memalign("sparts", (void**)sparts, spart_align,
                        *Nstars * sizeof(struct spart)) != 0)
       error("Error while allocating memory for stars particles");
     bzero(*sparts, *Nstars * sizeof(struct spart));
-    memuse_report("sparts", (*Nstars) * sizeof(struct spart));
   }
 
   /* Allocate memory to store all gravity  particles */
@@ -638,11 +636,10 @@ void read_ic_serial(char* fileName, const struct unit_system* internal_units,
     *Ngparts = (with_hydro ? N[swift_type_gas] : 0) +
                N[swift_type_dark_matter] +
                (with_stars ? N[swift_type_stars] : 0);
-    if (posix_memalign((void**)gparts, gpart_align,
+    if (swift_memalign("gparts", (void**)gparts, gpart_align,
                        *Ngparts * sizeof(struct gpart)) != 0)
       error("Error while allocating memory for gravity particles");
     bzero(*gparts, *Ngparts * sizeof(struct gpart));
-    memuse_report("gparts", (*Ngparts) * sizeof(struct gpart));
   }
 
   /* message("Allocated %8.2f MB for particles.", *N * sizeof(struct part) / */
@@ -1136,10 +1133,10 @@ void write_output_serial(struct engine* e, const char* baseName,
               Nparticles = Ngas_written;
 
               /* Allocate temporary arrays */
-              if (posix_memalign((void**)&parts_written, part_align,
+              if (swift_memalign("parts_written", (void**)&parts_written, part_align,
                                  Ngas_written * sizeof(struct part)) != 0)
                 error("Error while allocating temporart memory for parts");
-              if (posix_memalign((void**)&xparts_written, xpart_align,
+              if (swift_memalign("xparts_written", (void**)&xparts_written, xpart_align,
                                  Ngas_written * sizeof(struct xpart)) != 0)
                 error("Error while allocating temporart memory for xparts");
 
@@ -1185,12 +1182,12 @@ void write_output_serial(struct engine* e, const char* baseName,
               Nparticles = Ndm_written;
 
               /* Allocate temporary array */
-              if (posix_memalign((void**)&gparts_written, gpart_align,
+              if (swift_memalign("gparts_written", (void**)&gparts_written, gpart_align,
                                  Ndm_written * sizeof(struct gpart)) != 0)
                 error("Error while allocating temporart memory for gparts");
 
               if (with_stf) {
-                if (posix_memalign(
+                if (swift_memalign("gpart_group_written",
                         (void**)&gpart_group_data_written, gpart_align,
                         Ndm_written * sizeof(struct velociraptor_gpart_data)) !=
                     0)
@@ -1233,7 +1230,7 @@ void write_output_serial(struct engine* e, const char* baseName,
               Nparticles = Nstars_written;
 
               /* Allocate temporary arrays */
-              if (posix_memalign((void**)&sparts_written, spart_align,
+              if (swift_memalign("sparts_written", (void**)&sparts_written, spart_align,
                                  Nstars_written * sizeof(struct spart)) != 0)
                 error("Error while allocating temporart memory for sparts");
 
@@ -1274,11 +1271,12 @@ void write_output_serial(struct engine* e, const char* baseName,
         }
 
         /* Free temporary array */
-        if (parts_written) free(parts_written);
-        if (xparts_written) free(xparts_written);
-        if (gparts_written) free(gparts_written);
-        if (gpart_group_data_written) free(gpart_group_data_written);
-        if (sparts_written) free(sparts_written);
+        if (parts_written) swift_free("parts_written", parts_written);
+        if (xparts_written) swift_free("xparts_written", xparts_written);
+        if (gparts_written) swift_free("gparts_written", gparts_written);
+        if (gpart_group_data_written) swift_free("gpart_group_written",
+                                                 gpart_group_data_written);
+        if (sparts_written) swift_free("sparts_written", sparts_written);
 
         /* Close particle group */
         H5Gclose(h_grp);
diff --git a/src/single_io.c b/src/single_io.c
index 250f018754e355577600b1acc6d4b36946002fac..531a3f5663480178ebf0cd9dc806fd2e26e30527 100644
--- a/src/single_io.c
+++ b/src/single_io.c
@@ -241,7 +241,7 @@ void writeArray(const struct engine* e, hid_t grp, char* fileName,
 
   /* Allocate temporary buffer */
   void* temp = NULL;
-  if (posix_memalign((void**)&temp, IO_BUFFER_ALIGNMENT,
+  if (swift_memalign("temp", (void**)&temp, IO_BUFFER_ALIGNMENT,
                      num_elements * typeSize) != 0)
     error("Unable to allocate temporary i/o buffer");
 
@@ -503,21 +503,19 @@ void read_ic_single(const char* fileName,
   /* Allocate memory to store SPH particles */
   if (with_hydro) {
     *Ngas = N[swift_type_gas];
-    if (posix_memalign((void**)parts, part_align,
+    if (swift_memalign("parts", (void**)parts, part_align,
                        *Ngas * sizeof(struct part)) != 0)
       error("Error while allocating memory for SPH particles");
     bzero(*parts, *Ngas * sizeof(struct part));
-    memuse_report("parts", (*Ngas) * sizeof(struct part));
   }
 
   /* Allocate memory to store star particles */
   if (with_stars) {
     *Nstars = N[swift_type_stars];
-    if (posix_memalign((void**)sparts, spart_align,
+    if (swift_memalign("sparts", (void**)sparts, spart_align,
                        *Nstars * sizeof(struct spart)) != 0)
       error("Error while allocating memory for stars particles");
     bzero(*sparts, *Nstars * sizeof(struct spart));
-    memuse_report("sparts", (*Nstars) * sizeof(struct spart));
   }
 
   /* Allocate memory to store all gravity particles */
@@ -526,11 +524,10 @@ void read_ic_single(const char* fileName,
     *Ngparts = (with_hydro ? N[swift_type_gas] : 0) +
                N[swift_type_dark_matter] +
                (with_stars ? N[swift_type_stars] : 0);
-    if (posix_memalign((void**)gparts, gpart_align,
+    if (swift_memalign("gparts", (void**)gparts, gpart_align,
                        *Ngparts * sizeof(struct gpart)) != 0)
       error("Error while allocating memory for gravity particles");
     bzero(*gparts, *Ngparts * sizeof(struct gpart));
-    memuse_report("gparts", (*Ngparts) * sizeof(struct gpart));
   }
 
   /* message("Allocated %8.2f MB for particles.", *N * sizeof(struct part) /
@@ -939,10 +936,10 @@ void write_output_single(struct engine* e, const char* baseName,
           N = Ngas_written;
 
           /* Allocate temporary arrays */
-          if (posix_memalign((void**)&parts_written, part_align,
+          if (swift_memalign("parts_written", (void**)&parts_written, part_align,
                              Ngas_written * sizeof(struct part)) != 0)
             error("Error while allocating temporart memory for parts");
-          if (posix_memalign((void**)&xparts_written, xpart_align,
+          if (swift_memalign("xparts_written", (void**)&xparts_written, xpart_align,
                              Ngas_written * sizeof(struct xpart)) != 0)
             error("Error while allocating temporart memory for xparts");
 
@@ -987,12 +984,12 @@ void write_output_single(struct engine* e, const char* baseName,
           N = Ndm_written;
 
           /* Allocate temporary array */
-          if (posix_memalign((void**)&gparts_written, gpart_align,
+          if (swift_memalign("gparts_written", (void**)&gparts_written, gpart_align,
                              Ndm_written * sizeof(struct gpart)) != 0)
             error("Error while allocating temporart memory for gparts");
 
           if (with_stf) {
-            if (posix_memalign(
+            if (swift_memalign("gpart_group_written",
                     (void**)&gpart_group_data_written, gpart_align,
                     Ndm_written * sizeof(struct velociraptor_gpart_data)) != 0)
               error(
@@ -1032,7 +1029,7 @@ void write_output_single(struct engine* e, const char* baseName,
           N = Nstars_written;
 
           /* Allocate temporary arrays */
-          if (posix_memalign((void**)&sparts_written, spart_align,
+          if (swift_memalign("sparts_written", (void**)&sparts_written, spart_align,
                              Nstars_written * sizeof(struct spart)) != 0)
             error("Error while allocating temporart memory for sparts");
 
@@ -1072,11 +1069,11 @@ void write_output_single(struct engine* e, const char* baseName,
     }
 
     /* Free temporary arrays */
-    if (parts_written) free(parts_written);
-    if (xparts_written) free(xparts_written);
-    if (gparts_written) free(gparts_written);
-    if (gpart_group_data_written) free(gpart_group_data_written);
-    if (sparts_written) free(sparts_written);
+    if (parts_written) swift_free("parts_written", parts_written);
+    if (xparts_written) swift_free("xparts_written", xparts_written);
+    if (gparts_written) swift_free("gparts_written", gparts_written);
+    if (gpart_group_data_written) swift_free("gpart_group_written", gpart_group_data_written);
+    if (sparts_written) swift_free("sparts_written", sparts_written);
 
     /* Close particle group */
     H5Gclose(h_grp);
diff --git a/src/space.c b/src/space.c
index e4c9e8e6d394302d8524303fb3763107f6af144f..6f45423c66e75f711b029e654344cec9553cff15 100644
--- a/src/space.c
+++ b/src/space.c
@@ -449,12 +449,12 @@ void space_regrid(struct space *s, int verbose) {
     /* Free the old cells, if they were allocated. */
     if (s->cells_top != NULL) {
       space_free_cells(s);
-      free(s->local_cells_with_tasks_top);
-      free(s->local_cells_top);
-      free(s->cells_with_particles_top);
-      free(s->local_cells_with_particles_top);
-      free(s->cells_top);
-      free(s->multipoles_top);
+      swift_free("local_cells_with_tasks_top", s->local_cells_with_tasks_top);
+      swift_free("local_cells_top", s->local_cells_top);
+      swift_free("cells_with_particles_top", s->cells_with_particles_top);
+      swift_free("local_cells_with_particles_top", s->local_cells_with_particles_top);
+      swift_free("cells_top", s->cells_top);
+      swift_free("multipoles_top", s->multipoles_top);
     }
 
     /* Also free the task arrays, these will be regenerated and we can use the
@@ -472,51 +472,44 @@ void space_regrid(struct space *s, int verbose) {
     /* Allocate the highest level of cells. */
     s->tot_cells = s->nr_cells = cdim[0] * cdim[1] * cdim[2];
 
-    if (posix_memalign((void **)&s->cells_top, cell_align,
+    if (swift_memalign("cells_top", (void **)&s->cells_top, cell_align,
                        s->nr_cells * sizeof(struct cell)) != 0)
       error("Failed to allocate top-level cells.");
     bzero(s->cells_top, s->nr_cells * sizeof(struct cell));
-    memuse_report("cells_top", s->nr_cells * sizeof(struct cell));
 
     /* Allocate the multipoles for the top-level cells. */
     if (s->with_self_gravity) {
-      if (posix_memalign((void **)&s->multipoles_top, multipole_align,
+      if (swift_memalign("multipoles_top", (void **)&s->multipoles_top, multipole_align,
                          s->nr_cells * sizeof(struct gravity_tensors)) != 0)
         error("Failed to allocate top-level multipoles.");
       bzero(s->multipoles_top, s->nr_cells * sizeof(struct gravity_tensors));
-      memuse_report("multipoles_top",
-                    s->nr_cells * sizeof(struct gravity_tensors));
     }
 
     /* Allocate the indices of local cells */
-    if (posix_memalign((void **)&s->local_cells_top, SWIFT_STRUCT_ALIGNMENT,
+    if (swift_memalign("local_cells_top", (void **)&s->local_cells_top, SWIFT_STRUCT_ALIGNMENT,
                        s->nr_cells * sizeof(int)) != 0)
       error("Failed to allocate indices of local top-level cells.");
     bzero(s->local_cells_top, s->nr_cells * sizeof(int));
-    memuse_report("local_cells_top", s->nr_cells * sizeof(int));
 
     /* Allocate the indices of local cells with tasks */
-    if (posix_memalign((void **)&s->local_cells_with_tasks_top,
+    if (swift_memalign("local_cells_with_tasks_top",(void **)&s->local_cells_with_tasks_top,
                        SWIFT_STRUCT_ALIGNMENT, s->nr_cells * sizeof(int)) != 0)
       error("Failed to allocate indices of local top-level cells with tasks.");
     bzero(s->local_cells_with_tasks_top, s->nr_cells * sizeof(int));
-    memuse_report("local_cells_with_tasks_top", s->nr_cells * sizeof(struct cell));
 
     /* Allocate the indices of cells with particles */
-    if (posix_memalign((void **)&s->cells_with_particles_top,
+    if (swift_memalign("cells_with_particles_top",(void **)&s->cells_with_particles_top,
                        SWIFT_STRUCT_ALIGNMENT, s->nr_cells * sizeof(int)) != 0)
       error("Failed to allocate indices of top-level cells with particles.");
     bzero(s->cells_with_particles_top, s->nr_cells * sizeof(int));
-    memuse_report("cells_with_particles_top", s->nr_cells * sizeof(int));
 
     /* Allocate the indices of local cells with particles */
-    if (posix_memalign((void **)&s->local_cells_with_particles_top,
+    if (swift_memalign("local_cells_with_particles_top",(void **)&s->local_cells_with_particles_top,
                        SWIFT_STRUCT_ALIGNMENT, s->nr_cells * sizeof(int)) != 0)
       error(
           "Failed to allocate indices of local top-level cells with "
           "particles.");
     bzero(s->local_cells_with_particles_top, s->nr_cells * sizeof(int));
-    memuse_report("local_cells_with_particles_top", s->nr_cells * sizeof(int));
 
     /* Set the cells' locks */
     for (int k = 0; k < s->nr_cells; k++) {
@@ -731,12 +724,12 @@ void space_allocate_extras(struct space *s, int verbose) {
 
       /* Create more space for parts */
       struct gpart *gparts_new = NULL;
-      if (posix_memalign((void **)&gparts_new, gpart_align,
+      if (swift_memalign("gparts", (void **)&gparts_new, gpart_align,
                          sizeof(struct gpart) * size_gparts) != 0)
         error("Failed to allocate new gpart data");
       const ptrdiff_t delta = gparts_new - s->gparts;
       memcpy(gparts_new, s->gparts, sizeof(struct gpart) * s->size_gparts);
-      free(s->gparts);
+      swift_free("gparts", s->gparts);
       s->gparts = gparts_new;
 
       /* Update the counter */
@@ -822,20 +815,20 @@ void space_allocate_extras(struct space *s, int verbose) {
 
       /* Create more space for parts */
       struct part *parts_new = NULL;
-      if (posix_memalign((void **)&parts_new, part_align,
+      if (swift_memalign("parts", (void **)&parts_new, part_align,
                          sizeof(struct part) * size_parts) != 0)
         error("Failed to allocate new part data");
       memcpy(parts_new, s->parts, sizeof(struct part) * s->size_parts);
-      free(s->parts);
+      swift_free("parts", s->parts);
       s->parts = parts_new;
 
       /* Same for xparts */
       struct xpart *xparts_new = NULL;
-      if (posix_memalign((void **)&xparts_new, xpart_align,
+      if (swift_memalign("xparts", (void **)&xparts_new, xpart_align,
                          sizeof(struct xpart) * size_parts) != 0)
         error("Failed to allocate new xpart data");
       memcpy(xparts_new, s->xparts, sizeof(struct xpart) * s->size_parts);
-      free(s->xparts);
+      swift_free("xparts", s->xparts);
       s->xparts = xparts_new;
 
       /* Update the counter */
@@ -911,11 +904,11 @@ void space_allocate_extras(struct space *s, int verbose) {
 
       /* Create more space for parts */
       struct spart *sparts_new = NULL;
-      if (posix_memalign((void **)&sparts_new, spart_align,
+      if (swift_memalign("sparts", (void **)&sparts_new, spart_align,
                          sizeof(struct spart) * size_sparts) != 0)
         error("Failed to allocate new spart data");
       memcpy(sparts_new, s->sparts, sizeof(struct spart) * s->size_sparts);
-      free(s->sparts);
+      swift_free("sparts", s->sparts);
       s->sparts = sparts_new;
 
       /* Update the counter */
@@ -2251,7 +2244,7 @@ void space_parts_sort(struct part *parts, struct xpart *xparts,
                       ptrdiff_t parts_offset) {
   /* Create the offsets array. */
   size_t *offsets = NULL;
-  if (posix_memalign((void **)&offsets, SWIFT_STRUCT_ALIGNMENT,
+  if (swift_memalign("offsets", (void **)&offsets, SWIFT_STRUCT_ALIGNMENT,
                      sizeof(size_t) * (num_bins + 1)) != 0)
     error("Failed to allocate temporary cell offsets array.");
 
@@ -2296,7 +2289,7 @@ void space_parts_sort(struct part *parts, struct xpart *xparts,
       error("Bad offsets after shuffle.");
 #endif /* SWIFT_DEBUG_CHECKS */
 
-  free(offsets);
+  swift_free("offsets", offsets);
 }
 
 /**
@@ -2314,7 +2307,7 @@ void space_sparts_sort(struct spart *sparts, int *restrict ind,
                        ptrdiff_t sparts_offset) {
   /* Create the offsets array. */
   size_t *offsets = NULL;
-  if (posix_memalign((void **)&offsets, SWIFT_STRUCT_ALIGNMENT,
+  if (swift_memalign("offsets", (void **)&offsets, SWIFT_STRUCT_ALIGNMENT,
                      sizeof(size_t) * (num_bins + 1)) != 0)
     error("Failed to allocate temporary cell offsets array.");
 
@@ -2356,7 +2349,7 @@ void space_sparts_sort(struct spart *sparts, int *restrict ind,
       error("Bad offsets after shuffle.");
 #endif /* SWIFT_DEBUG_CHECKS */
 
-  free(offsets);
+  swift_free("offsets", offsets);
 }
 
 /**
@@ -2374,7 +2367,7 @@ void space_gparts_sort(struct gpart *gparts, struct part *parts,
                        int *restrict counts, int num_bins) {
   /* Create the offsets array. */
   size_t *offsets = NULL;
-  if (posix_memalign((void **)&offsets, SWIFT_STRUCT_ALIGNMENT,
+  if (swift_memalign("offsets", (void **)&offsets, SWIFT_STRUCT_ALIGNMENT,
                      sizeof(size_t) * (num_bins + 1)) != 0)
     error("Failed to allocate temporary cell offsets array.");
 
@@ -2422,7 +2415,7 @@ void space_gparts_sort(struct gpart *gparts, struct part *parts,
       error("Bad offsets after shuffle.");
 #endif /* SWIFT_DEBUG_CHECKS */
 
-  free(offsets);
+  swift_free("offsets", offsets);
 }
 
 /**
@@ -2623,7 +2616,7 @@ void space_split_recursive(struct space *s, struct cell *c,
   const int allocate_buffer = (buff == NULL && gbuff == NULL && sbuff == NULL);
   if (allocate_buffer) {
     if (count > 0) {
-      if (posix_memalign((void **)&buff, SWIFT_STRUCT_ALIGNMENT,
+      if (swift_memalign("tempbuff", (void **)&buff, SWIFT_STRUCT_ALIGNMENT,
                          sizeof(struct cell_buff) * count) != 0)
         error("Failed to allocate temporary indices.");
       for (int k = 0; k < count; k++) {
@@ -2639,7 +2632,7 @@ void space_split_recursive(struct space *s, struct cell *c,
       }
     }
     if (gcount > 0) {
-      if (posix_memalign((void **)&gbuff, SWIFT_STRUCT_ALIGNMENT,
+      if (swift_memalign("tempgbuff", (void **)&gbuff, SWIFT_STRUCT_ALIGNMENT,
                          sizeof(struct cell_buff) * gcount) != 0)
         error("Failed to allocate temporary indices.");
       for (int k = 0; k < gcount; k++) {
@@ -2655,7 +2648,7 @@ void space_split_recursive(struct space *s, struct cell *c,
       }
     }
     if (scount > 0) {
-      if (posix_memalign((void **)&sbuff, SWIFT_STRUCT_ALIGNMENT,
+      if (swift_memalign("tempsbuff", (void **)&sbuff, SWIFT_STRUCT_ALIGNMENT,
                          sizeof(struct cell_buff) * scount) != 0)
         error("Failed to allocate temporary indices.");
       for (int k = 0; k < scount; k++) {
@@ -3033,9 +3026,9 @@ void space_split_recursive(struct space *s, struct cell *c,
 
   /* Clean up. */
   if (allocate_buffer) {
-    if (buff != NULL) free(buff);
-    if (gbuff != NULL) free(gbuff);
-    if (sbuff != NULL) free(sbuff);
+    if (buff != NULL) swift_free("tempbuff", buff);
+    if (gbuff != NULL) swift_free("tempgbuff", gbuff);
+    if (sbuff != NULL) swift_free("tempsbuff", sbuff);
   }
 }
 
@@ -3175,10 +3168,9 @@ void space_getcells(struct space *s, int nr_cells, struct cell **cells) {
 
     /* Is the cell buffer empty? */
     if (s->cells_sub == NULL) {
-      if (posix_memalign((void **)&s->cells_sub, cell_align,
+      if (swift_memalign("cells_sub", (void **)&s->cells_sub, cell_align,
                          space_cellallocchunk * sizeof(struct cell)) != 0)
         error("Failed to allocate more cells.");
-      memuse_report("cells_sub", space_cellallocchunk * sizeof(struct cell));
 
       /* Clear the newly-allocated cells. */
       bzero(s->cells_sub, sizeof(struct cell) * space_cellallocchunk);
@@ -3191,12 +3183,10 @@ void space_getcells(struct space *s, int nr_cells, struct cell **cells) {
 
     /* Is the multipole buffer empty? */
     if (s->with_self_gravity && s->multipoles_sub == NULL) {
-      if (posix_memalign(
+      if (swift_memalign("multipoles_sub",
               (void **)&s->multipoles_sub, multipole_align,
               space_cellallocchunk * sizeof(struct gravity_tensors)) != 0)
         error("Failed to allocate more multipoles.");
-      memuse_report("multipoles_sub",
-                    space_cellallocchunk * sizeof(struct gravity_tensors));
 
       /* Constructed a linked list */
       for (int k = 0; k < space_cellallocchunk - 1; k++)
@@ -3963,11 +3953,10 @@ void space_init(struct space *s, struct swift_params *params,
 
   /* Allocate the extra parts array for the gas particles. */
   if (Npart > 0) {
-    if (posix_memalign((void **)&s->xparts, xpart_align,
+      if (swift_memalign("xparts", (void **)&s->xparts, xpart_align,
                        Npart * sizeof(struct xpart)) != 0)
       error("Failed to allocate xparts.");
     bzero(s->xparts, Npart * sizeof(struct xpart));
-    memuse_report("xparts", Npart * sizeof(struct xpart));
   }
 
   hydro_space_init(&s->hs, s);
@@ -4019,20 +4008,17 @@ void space_replicate(struct space *s, int replicate, int verbose) {
   struct gpart *gparts = NULL;
   struct spart *sparts = NULL;
 
-  if (posix_memalign((void **)&parts, part_align,
+  if (swift_memalign("parts", (void **)&parts, part_align,
                      s->nr_parts * sizeof(struct part)) != 0)
     error("Failed to allocate new part array.");
-  memuse_report("parts", s->nr_parts * sizeof(struct part));
 
-  if (posix_memalign((void **)&gparts, gpart_align,
+  if (swift_memalign("gparts", (void **)&gparts, gpart_align,
                      s->nr_gparts * sizeof(struct gpart)) != 0)
     error("Failed to allocate new gpart array.");
-  memuse_report("gparts", s->nr_gparts * sizeof(struct gpart));
 
-  if (posix_memalign((void **)&sparts, spart_align,
+  if (swift_memalign("sparts", (void **)&sparts, spart_align,
                      s->nr_sparts * sizeof(struct spart)) != 0)
     error("Failed to allocate new spart array.");
-  memuse_report("sparts", s->nr_sparts * sizeof(struct spart));
 
   /* Replicate everything */
   for (int i = 0; i < replicate; ++i) {
@@ -4092,9 +4078,9 @@ void space_replicate(struct space *s, int replicate, int verbose) {
   }
 
   /* Replace the content of the space */
-  free(s->parts);
-  free(s->gparts);
-  free(s->sparts);
+  swift_free("parts", s->parts);
+  swift_free("gparts", s->gparts);
+  swift_free("sparts", s->sparts);
   s->parts = parts;
   s->gparts = gparts;
   s->sparts = sparts;
@@ -4152,15 +4138,13 @@ void space_generate_gas(struct space *s, const struct cosmology *cosmo,
   struct part *parts = NULL;
   struct gpart *gparts = NULL;
 
-  if (posix_memalign((void **)&parts, part_align,
+  if (swift_memalign("parts", (void **)&parts, part_align,
                      s->nr_parts * sizeof(struct part)) != 0)
     error("Failed to allocate new part array.");
-  memuse_report("parts", s->nr_parts * sizeof(struct part));
 
-  if (posix_memalign((void **)&gparts, gpart_align,
+  if (swift_memalign("gparts", (void **)&gparts, gpart_align,
                      s->nr_gparts * sizeof(struct gpart)) != 0)
     error("Failed to allocate new gpart array.");
-  memuse_report("gparts", s->nr_gparts * sizeof(struct gpart));
 
   /* Start by copying the gparts */
   memcpy(gparts, s->gparts, nr_gparts * sizeof(struct gpart));
@@ -4244,7 +4228,7 @@ void space_generate_gas(struct space *s, const struct cosmology *cosmo,
   }
 
   /* Replace the content of the space */
-  free(s->gparts);
+  swift_free("gparts", s->gparts);
   s->parts = parts;
   s->gparts = gparts;
 }
@@ -4430,16 +4414,16 @@ void space_reset_task_counters(struct space *s) {
 void space_clean(struct space *s) {
 
   for (int i = 0; i < s->nr_cells; ++i) cell_clean(&s->cells_top[i]);
-  free(s->cells_top);
-  free(s->multipoles_top);
-  free(s->local_cells_top);
-  free(s->local_cells_with_tasks_top);
-  free(s->cells_with_particles_top);
-  free(s->local_cells_with_particles_top);
-  free(s->parts);
-  free(s->xparts);
-  free(s->gparts);
-  free(s->sparts);
+  swift_free("cells_top", s->cells_top);
+  swift_free("multipoles_top", s->multipoles_top);
+  swift_free("local_cells_top", s->local_cells_top);
+  swift_free("local_cells_with_tasks_top", s->local_cells_with_tasks_top);
+  swift_free("cells_with_particles_top", s->cells_with_particles_top);
+  swift_free("local_cells_with_particles_top", s->local_cells_with_particles_top);
+  swift_free("parts", s->parts);
+  swift_free("xparts", s->xparts);
+  swift_free("gparts", s->gparts);
+  swift_free("sparts", s->sparts);
 }
 
 /**
@@ -4507,15 +4491,13 @@ void space_struct_restore(struct space *s, FILE *stream) {
   if (s->nr_parts > 0) {
 
     /* Need the memory for these. */
-    if (posix_memalign((void **)&s->parts, part_align,
+    if (swift_memalign("parts", (void **)&s->parts, part_align,
                        s->size_parts * sizeof(struct part)) != 0)
       error("Failed to allocate restore part array.");
-    memuse_report("parts", s->nr_parts * sizeof(struct part));
 
-    if (posix_memalign((void **)&s->xparts, xpart_align,
+    if (swift_memalign("xparts", (void **)&s->xparts, xpart_align,
                        s->size_parts * sizeof(struct xpart)) != 0)
       error("Failed to allocate restore xpart array.");
-    memuse_report("xparts", s->nr_parts * sizeof(struct xpart));
 
     restart_read_blocks(s->parts, s->nr_parts, sizeof(struct part), stream,
                         NULL, "parts");
@@ -4524,10 +4506,9 @@ void space_struct_restore(struct space *s, FILE *stream) {
   }
   s->gparts = NULL;
   if (s->nr_gparts > 0) {
-    if (posix_memalign((void **)&s->gparts, gpart_align,
+    if (swift_memalign("gparts", (void **)&s->gparts, gpart_align,
                        s->size_gparts * sizeof(struct gpart)) != 0)
       error("Failed to allocate restore gpart array.");
-    memuse_report("gparts", s->nr_gparts * sizeof(struct gpart));
 
     restart_read_blocks(s->gparts, s->nr_gparts, sizeof(struct gpart), stream,
                         NULL, "gparts");
@@ -4535,10 +4516,9 @@ void space_struct_restore(struct space *s, FILE *stream) {
 
   s->sparts = NULL;
   if (s->nr_sparts > 0) {
-    if (posix_memalign((void **)&s->sparts, spart_align,
+    if (swift_memalign("sparts", (void **)&s->sparts, spart_align,
                        s->size_sparts * sizeof(struct spart)) != 0)
       error("Failed to allocate restore spart array.");
-    memuse_report("sparts", s->nr_sparts * sizeof(struct spart));
 
     restart_read_blocks(s->sparts, s->nr_sparts, sizeof(struct spart), stream,
                         NULL, "sparts");
diff --git a/src/swift.h b/src/swift.h
index e166dde5dd3baed07fb5c081c64ce941d6c6ce6d..0b5eda65e73cd6600eb69c25bc6a3f0a2e6e675f 100644
--- a/src/swift.h
+++ b/src/swift.h
@@ -49,6 +49,7 @@
 #include "logger.h"
 #include "logger_io.h"
 #include "map.h"
+#include "memuse.h"
 #include "mesh_gravity.h"
 #include "multipole.h"
 #include "outputlist.h"