LCOV - code coverage report
Current view: top level - datahandlinglibs/test/apps - test_lb_allocation_app.cxx (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 58 0
Test Date: 2026-10-11 15:05:20 Functions: 0.0 % 16 0

            Line data    Source code
       1              : /**
       2              :  * @file test_lb_allocation_app.cxx Test application for LB allocations.
       3              :  *
       4              :  * This is part of the DUNE DAQ Application Framework, copyright 2020.
       5              :  * Licensing/copyright details are in the COPYING file that you should have
       6              :  * received with this code.
       7              :  */
       8              : 
       9              : #include "datahandlinglibs/concepts/RawDataProcessorConcept.hpp"
      10              : #include "datahandlinglibs/models/IterableQueueModel.hpp"
      11              : #include "datahandlinglibs/models/SkipListLatencyBufferModel.hpp"
      12              : #include "logging/Logging.hpp"
      13              : 
      14              : #include "CLI/App.hpp"
      15              : #include "CLI/Config.hpp"
      16              : #include "CLI/Formatter.hpp"
      17              : 
      18              : #include <atomic>
      19              : #include <chrono>
      20              : #include <memory>
      21              : #include <random>
      22              : #include <string>
      23              : #include <vector>
      24              : 
      25              : #ifdef WITH_LIBNUMA_SUPPORT
      26              : #include <numaif.h>
      27              : #endif
      28              : 
      29              : // #define REGISTER (*(volatile unsigned char*)0x1234)
      30              : 
      31              : using namespace dunedaq::datahandlinglibs;
      32              : 
      33              : namespace {
      34              : 
      35              : struct kBlock // Dummy data type for LB test
      36              : {
      37            0 :   kBlock() {};
      38              :   char data[1024];
      39              : };
      40              : 
      41              : std::size_t lb_capacity = 1000; // LB capacity
      42              : 
      43              : bool numa_aware_test = false;
      44              : int num_numa_nodes = 2;
      45              : bool intrinsic_test = false;
      46              : bool aligned_test = false;
      47              : bool prefill = false; // Prefill the LB
      48              : std::size_t alignment_size = 4096;
      49              : }
      50              : 
      51              : int
      52            0 : main(int argc, char** argv)
      53              : {
      54            0 :   int runsecs = 5;
      55              : 
      56              :   // Run marker
      57            0 :   std::atomic<bool> marker{ true };
      58              : 
      59              :   // Counter for ops/s
      60            0 :   std::atomic<int> newops = 0;
      61              : 
      62            0 :   CLI::App app{ "datahandlinglibs_test_lb_allocation" };
      63            0 :   app.add_option("-c", lb_capacity, "Capacity/size of latency buffer.");
      64            0 :   app.add_flag("--numa_aware", numa_aware_test, "Test NUMA aware allocator.");
      65            0 :   app.add_option("--num_numa_nodes", num_numa_nodes, "Number of NUMA nodes to test allocation on.");
      66            0 :   app.add_flag("--intrinsic", intrinsic_test, "Test Intrinsic allocator.");
      67            0 :   app.add_flag("--aligned", aligned_test, "Test aligned allocator.");
      68            0 :   app.add_option("--alignment_size", alignment_size, "Set alignment size. Default: 4096");
      69            0 :   app.add_flag("--prefill", prefill, "Interface to init");
      70            0 :   CLI11_PARSE(app, argc, argv);
      71              : 
      72            0 :   if (numa_aware_test) { // check if test is issued...
      73              : #ifdef WITH_LIBNUMA_SUPPORT
      74            0 :     TLOG() << "NUMA aware allocator test...";
      75              : 
      76            0 :     for (int i = 0; i < num_numa_nodes; ++i) { // for number of nodes...
      77            0 :       TLOG() << "  # Allocating NUMA aware LB on node " << i;
      78            0 :       IterableQueueModel<kBlock> numaIQM(lb_capacity, true, i, false, 0);
      79              : 
      80            0 :       if (prefill) { // Force page-fault issues?
      81            0 :         TLOG() << "  -> Prefilling LB...";
      82            0 :         numaIQM.force_pagefault();
      83              :       }
      84              : 
      85            0 :       for (std::size_t i = 0; i < lb_capacity - 1; ++i) { // Fill the LB
      86            0 :         numaIQM.write(kBlock());
      87              :       }
      88              : 
      89              :       // Test if the elements' pointers are on correct NUMA node.
      90              :       // Virtual addresses might be misleading between virt. and phys. addresses due to IOMMU!
      91            0 :       int numa_node = -1;
      92            0 :       get_mempolicy(&numa_node, NULL, 0, (void*)numaIQM.front(), MPOL_F_NODE | MPOL_F_ADDR);
      93            0 :       if (i != numa_node) {
      94            0 :         TLOG() << "Discrepancy in expected NUMA node and first element residency!";
      95              :       }
      96            0 :       TLOG() << "  -> NUMA " << i << " IQM front virt.addr.: " << std::hex << (void*)numaIQM.front()
      97            0 :              << " is on: " << numa_node << std::dec;
      98            0 :       get_mempolicy(&numa_node, NULL, 0, (void*)numaIQM.back(), MPOL_F_NODE | MPOL_F_ADDR);
      99            0 :       if (i != numa_node) {
     100            0 :         TLOG() << "Discrepancy in expected NUMA node and last element residency!";
     101              :       }
     102            0 :       TLOG() << "  -> NUMA " << i << " IQM back virt.addr.: " << std::hex << (void*)numaIQM.back()
     103            0 :              << " is on: " << numa_node << std::dec;
     104            0 :     }
     105            0 :     TLOG() << "  -> Done.";
     106              : #else
     107              :     TLOG() << "  -> NUMA support is turned off build-time. Passed on NUMA demo.";
     108              : #endif
     109              :   }
     110              : 
     111            0 :   if (intrinsic_test) {
     112            0 :     TLOG() << "Intrinsic allocator test...";
     113            0 :     IterableQueueModel<kBlock> intrIQM(lb_capacity, false, 0, true, alignment_size);
     114            0 :     if (prefill) {
     115            0 :       TLOG() << "  -> Prefilling LB...";
     116            0 :       intrIQM.force_pagefault();
     117              :     }
     118              : 
     119            0 :     for (std::size_t i = 0; i < lb_capacity - 1; ++i) { // Fill the LB
     120            0 :       intrIQM.write(kBlock());
     121              :     }
     122              : 
     123            0 :     TLOG() << "  -> Done.";
     124            0 :   }
     125              : 
     126            0 :   if (aligned_test) {
     127            0 :     TLOG() << "Aligned allocator test...";
     128            0 :     IterableQueueModel<kBlock> alignedIQM(lb_capacity, false, 0, false, alignment_size);
     129            0 :     if (prefill) {
     130            0 :       TLOG() << "  -> Prefilling LB...";
     131            0 :       alignedIQM.force_pagefault();
     132              :     }
     133              : 
     134            0 :     for (std::size_t i = 0; i < lb_capacity - 1; ++i) { // Fill the LB
     135            0 :       alignedIQM.write(kBlock());
     136              :     }
     137              : 
     138            0 :     TLOG() << "  -> Done.";
     139            0 :   }
     140              : 
     141              :   // Test app ends. Below there are general producer/consumer/stats threads.
     142              :   return 0;
     143              : 
     144              :   // Stats
     145              :   auto stats = std::thread([&]() {
     146              :     TLOG() << "Spawned stats thread...";
     147              :     while (marker) {
     148              :       TLOG() << "ops/s ->  " << newops.exchange(0);
     149              :       std::this_thread::sleep_for(std::chrono::seconds(1));
     150              :     }
     151              :   });
     152              : 
     153              :   // Producer
     154              :   auto producer = std::thread([&]() {
     155              :     TLOG() << "Spawned producer thread...";
     156              :     while (marker) {
     157              :       std::this_thread::sleep_for(std::chrono::seconds(1));
     158              :     }
     159              :   });
     160              : 
     161              :   // Consumer
     162              :   auto consumer = std::thread([&]() {
     163              :     TLOG() << "Spawned consumer thread...";
     164              :     while (marker) {
     165              :       std::this_thread::sleep_for(std::chrono::seconds(1));
     166              :     }
     167              :   });
     168              : 
     169              :   // Killswitch that flips the run marker
     170              :   auto killswitch = std::thread([&]() {
     171              :     TLOG() << "Application will terminate in 5s...";
     172              :     std::this_thread::sleep_for(std::chrono::seconds(runsecs));
     173              :     marker.store(false);
     174              :   });
     175              : 
     176              :   // Join local threads
     177              :   TLOG() << "Flipping killswitch in order to stop...";
     178              :   if (killswitch.joinable()) {
     179              :     killswitch.join();
     180              :   }
     181              : 
     182              :   // Exit
     183              :   TLOG() << "Exiting.";
     184              :   return 0;
     185            0 : }
        

Generated by: LCOV version 2.0-1