Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/tools/mm/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 6 kB image not shown  

Quelle  thp_swap_allocator_test.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * thp_swap_allocator_test
 *
 * The purpose of this test program is helping check if THP swpout
 * can correctly get swap slots to swap out as a whole instead of
 * being split. It randomly releases swap entries through madvise
 * DONTNEED and swapin/out on two memory areas: a memory area for
 * 64KB THP and the other area for small folios. The second memory
 * can be enabled by "-s".
 * Before running the program, we need to setup a zRAM or similar
 * swap device by:
 *  echo lzo > /sys/block/zram0/comp_algorithm
 *  echo 64M > /sys/block/zram0/disksize
 *  echo never > /sys/kernel/mm/transparent_hugepage/hugepages-2048kB/enabled
 *  echo always > /sys/kernel/mm/transparent_hugepage/hugepages-64kB/enabled
 *  mkswap /dev/zram0
 *  swapon /dev/zram0
 * The expected result should be 0% anon swpout fallback ratio w/ or
 * w/o "-s".
 *
 * Author(s): Barry Song <v-songbaohua@oppo.com>
 */


#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <linux/mman.h>
#include <sys/mman.h>
#include <errno.h>
#include <time.h>

#define MEMSIZE_MTHP (60 * 1024 * 1024)
#define MEMSIZE_SMALLFOLIO (4 * 1024 * 1024)
#define ALIGNMENT_MTHP (64 * 1024)
#define ALIGNMENT_SMALLFOLIO (4 * 1024)
#define TOTAL_DONTNEED_MTHP (16 * 1024 * 1024)
#define TOTAL_DONTNEED_SMALLFOLIO (1 * 1024 * 1024)
#define MTHP_FOLIO_SIZE (64 * 1024)

#define SWPOUT_PATH \
 "/sys/kernel/mm/transparent_hugepage/hugepages-64kB/stats/swpout"
#define SWPOUT_FALLBACK_PATH \
 "/sys/kernel/mm/transparent_hugepage/hugepages-64kB/stats/swpout_fallback"

static void *aligned_alloc_mem(size_t size, size_t alignment)
{
 void *mem = NULL;

 if (posix_memalign(&mem, alignment, size) != 0) {
  perror("posix_memalign");
  return NULL;
 }
 return mem;
}

/*
 * This emulates the behavior of native libc and Java heap,
 * as well as process exit and munmap. It helps generate mTHP
 * and ensures that iterations can proceed with mTHP, as we
 * currently don't support large folios swap-in.
 */

static void random_madvise_dontneed(void *mem, size_t mem_size,
  size_t align_size, size_t total_dontneed_size)
{
 size_t num_pages = total_dontneed_size / align_size;
 size_t i;
 size_t offset;
 void *addr;

 for (i = 0; i < num_pages; ++i) {
  offset = (rand() % (mem_size / align_size)) * align_size;
  addr = (char *)mem + offset;
  if (madvise(addr, align_size, MADV_DONTNEED) != 0)
   perror("madvise dontneed");

  memset(addr, 0x11, align_size);
 }
}

static void random_swapin(void *mem, size_t mem_size,
  size_t align_size, size_t total_swapin_size)
{
 size_t num_pages = total_swapin_size / align_size;
 size_t i;
 size_t offset;
 void *addr;

 for (i = 0; i < num_pages; ++i) {
  offset = (rand() % (mem_size / align_size)) * align_size;
  addr = (char *)mem + offset;
  memset(addr, 0x11, align_size);
 }
}

static unsigned long read_stat(const char *path)
{
 FILE *file;
 unsigned long value;

 file = fopen(path, "r");
 if (!file) {
  perror("fopen");
  return 0;
 }

 if (fscanf(file, "%lu", &value) != 1) {
  perror("fscanf");
  fclose(file);
  return 0;
 }

 fclose(file);
 return value;
}

int main(int argc, char *argv[])
{
 int use_small_folio = 0, aligned_swapin = 0;
 void *mem1 = NULL, *mem2 = NULL;
 int i;

 for (i = 1; i < argc; ++i) {
  if (strcmp(argv[i], "-s") == 0)
   use_small_folio = 1;
  else if (strcmp(argv[i], "-a") == 0)
   aligned_swapin = 1;
 }

 mem1 = aligned_alloc_mem(MEMSIZE_MTHP, ALIGNMENT_MTHP);
 if (mem1 == NULL) {
  fprintf(stderr, "Failed to allocate large folios memory\n");
  return EXIT_FAILURE;
 }

 if (madvise(mem1, MEMSIZE_MTHP, MADV_HUGEPAGE) != 0) {
  perror("madvise hugepage for mem1");
  free(mem1);
  return EXIT_FAILURE;
 }

 if (use_small_folio) {
  mem2 = aligned_alloc_mem(MEMSIZE_SMALLFOLIO, ALIGNMENT_MTHP);
  if (mem2 == NULL) {
   fprintf(stderr, "Failed to allocate small folios memory\n");
   free(mem1);
   return EXIT_FAILURE;
  }

  if (madvise(mem2, MEMSIZE_SMALLFOLIO, MADV_NOHUGEPAGE) != 0) {
   perror("madvise nohugepage for mem2");
   free(mem1);
   free(mem2);
   return EXIT_FAILURE;
  }
 }

 /* warm-up phase to occupy the swapfile */
 memset(mem1, 0x11, MEMSIZE_MTHP);
 madvise(mem1, MEMSIZE_MTHP, MADV_PAGEOUT);
 if (use_small_folio) {
  memset(mem2, 0x11, MEMSIZE_SMALLFOLIO);
  madvise(mem2, MEMSIZE_SMALLFOLIO, MADV_PAGEOUT);
 }

 /* iterations with newly created mTHP, swap-in, and swap-out */
 for (i = 0; i < 100; ++i) {
  unsigned long initial_swpout;
  unsigned long initial_swpout_fallback;
  unsigned long final_swpout;
  unsigned long final_swpout_fallback;
  unsigned long swpout_inc;
  unsigned long swpout_fallback_inc;
  double fallback_percentage;

  initial_swpout = read_stat(SWPOUT_PATH);
  initial_swpout_fallback = read_stat(SWPOUT_FALLBACK_PATH);

  /*
 * The following setup creates a 1:1 ratio of mTHP to small folios
 * since large folio swap-in isn't supported yet. Once we support
 * mTHP swap-in, we'll likely need to reduce MEMSIZE_MTHP and
 * increase MEMSIZE_SMALLFOLIO to maintain the ratio.
 */

  random_swapin(mem1, MEMSIZE_MTHP,
    aligned_swapin ? ALIGNMENT_MTHP : ALIGNMENT_SMALLFOLIO,
    TOTAL_DONTNEED_MTHP);
  random_madvise_dontneed(mem1, MEMSIZE_MTHP, ALIGNMENT_MTHP,
    TOTAL_DONTNEED_MTHP);

  if (use_small_folio) {
   random_swapin(mem2, MEMSIZE_SMALLFOLIO,
     ALIGNMENT_SMALLFOLIO,
     TOTAL_DONTNEED_SMALLFOLIO);
  }

  if (madvise(mem1, MEMSIZE_MTHP, MADV_PAGEOUT) != 0) {
   perror("madvise pageout for mem1");
   free(mem1);
   if (mem2 != NULL)
    free(mem2);
   return EXIT_FAILURE;
  }

  if (use_small_folio) {
   if (madvise(mem2, MEMSIZE_SMALLFOLIO, MADV_PAGEOUT) != 0) {
    perror("madvise pageout for mem2");
    free(mem1);
    free(mem2);
    return EXIT_FAILURE;
   }
  }

  final_swpout = read_stat(SWPOUT_PATH);
  final_swpout_fallback = read_stat(SWPOUT_FALLBACK_PATH);

  swpout_inc = final_swpout - initial_swpout;
  swpout_fallback_inc = final_swpout_fallback - initial_swpout_fallback;

  fallback_percentage = (double)swpout_fallback_inc /
   (swpout_fallback_inc + swpout_inc) * 100;

  printf("Iteration %d: swpout inc: %lu, swpout fallback inc: %lu, Fallback percentage: %.2f%%\n",
    i + 1, swpout_inc, swpout_fallback_inc, fallback_percentage);
 }

 free(mem1);
 if (mem2 != NULL)
  free(mem2);

 return EXIT_SUCCESS;
}

Messung V0.5
C=95 H=89 G=91

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.