Skip to content

Commit 0afa341

Browse files
authored
Merge pull request #1485 from lukaszstolarczuk/merge-stable-v1.0.x-into-main
Merge stable v1.0.x into main
2 parents cc0565d + bade9a1 commit 0afa341

File tree

13 files changed

+161
-47
lines changed

13 files changed

+161
-47
lines changed

.github/workflows/pr_push.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,6 @@ jobs:
9999
uses: ./.github/workflows/reusable_compatibility.yml
100100
strategy:
101101
matrix:
102-
tag: ["v1.0.0"]
102+
tag: ["v1.0.1"]
103103
with:
104104
tag: ${{matrix.tag}}

.github/workflows/reusable_compatibility.yml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ on:
99
tag:
1010
description: Check backward compatibility with this tag
1111
type: string
12-
default: "v1.0.0"
12+
# While we're still compatible with v1.0.0, we implemented a fix in v1.0.1
13+
# to verify if the split operation is supported (in jemalloc pool).
14+
# Without bumping the tag we'd have to omit some tests.
15+
default: "v1.0.1"
1316

1417
permissions:
1518
contents: read
@@ -99,7 +102,7 @@ jobs:
99102
UMF_LOG: level:warning;flush:debug;output:stderr;pid:no
100103
LD_LIBRARY_PATH: ${{github.workspace}}/latest_version/build/lib/
101104
run: |
102-
ctest --verbose -E test_memoryProvider
105+
ctest --verbose -E "test_memoryProvider"
103106
test/test_memoryProvider --gtest_filter="-*Trace"
104107
105108
# Browse all folders in the examples directory, build them using the
@@ -226,7 +229,9 @@ jobs:
226229
UMF_LOG: level:warning;flush:debug;output:stderr;pid:no
227230
run: |
228231
cp ${{github.workspace}}/latest_version/build/bin/Debug/umf.dll ${{github.workspace}}/tag_version/build/bin/Debug/umf.dll
229-
ctest -C Debug --verbose -E test_memoryProvider
232+
ctest -C Debug --verbose -E "test_memoryProvider"
233+
$env:Path = "${{github.workspace}}/tag_version/build/bin/Debug;${{env.VCPKG_BIN_PATH}};$env:Path"
234+
test/Debug/test_memoryProvider.exe --gtest_filter="-*Trace"
230235
231236
# Browse all folders in the examples directory, build them using the
232237
# latest UMF version, and run them, excluding those in the exclude list.
@@ -368,7 +373,7 @@ jobs:
368373
UMF_LOG: level:warning;flush:debug;output:stderr;pid:no
369374
LD_LIBRARY_PATH: ${{github.workspace}}/latest_version/build/lib/
370375
run: |
371-
ctest --verbose -E test_memoryProvider
376+
ctest --verbose -E "test_memoryProvider"
372377
test/test_memoryProvider --gtest_filter="-*Trace"
373378
374379
# Browse all folders in the examples directory, build them using the

CMakeLists.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,14 @@ else()
203203
DEPENDS ${jemalloc_targ_SOURCE_DIR}/configure)
204204

205205
if(NOT UMF_QEMU_BUILD)
206-
set(MAKE_ARGUMENTS "-j$(nproc)")
206+
if(CMAKE_GENERATOR STREQUAL "Ninja")
207+
# While CMake is supposed to escape this in the generated build
208+
# files, for some reason, it doesn't do so here. Until it's fixed,
209+
# we just manually escape it for ninja.
210+
set(MAKE_ARGUMENTS "-j$$(nproc)")
211+
else()
212+
set(MAKE_ARGUMENTS "-j$(nproc)")
213+
endif()
207214
endif()
208215

209216
add_custom_command(

ChangeLog

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
Fri Aug 08 2025 Łukasz Stolarczuk <[email protected]>
2+
3+
* Version 1.0.1
4+
5+
This patch release contains following changes:
6+
- make topology_init faster (#1469)
7+
- verify if the provider supports the split operation (#1465)
8+
- fix build failure when building for jemalloc with ninja (#1474)
9+
110
Mon Jul 21 2025 Łukasz Stolarczuk <[email protected]>
211

312
* Version 1.0.0

src/libumf.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,11 @@ umf_result_t umfInit(void) {
9191
if (TRACKER) {
9292
LOG_DEBUG("UMF library initialized");
9393
}
94-
94+
#if !defined(UMF_NO_HWLOC)
95+
// some benchmarks uses multiple forks, and topology initialization is very slow
96+
// so if we initialize topology before the first fork, we can get significant performance gain.
97+
umfGetTopologyReduced();
98+
#endif
9599
return UMF_RESULT_SUCCESS;
96100
}
97101

src/memspaces/memspace_host_all.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ static umf_result_t umfMemspaceHostAllCreate(umf_memspace_handle_t *hMemspace) {
3535

3636
umf_result_t umf_ret = UMF_RESULT_SUCCESS;
3737

38-
hwloc_topology_t topology = umfGetTopology();
38+
hwloc_topology_t topology = umfGetTopologyReduced();
3939
if (!topology) {
4040
// TODO: What would be an approrpiate err?
4141
return UMF_RESULT_ERROR_UNKNOWN;

src/memtargets/memtarget_numa.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ static umf_result_t numa_get_capacity(void *memTarget, size_t *capacity) {
218218
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
219219
}
220220

221-
hwloc_topology_t topology = umfGetTopology();
221+
hwloc_topology_t topology = umfGetTopologyReduced();
222222
if (!topology) {
223223
return UMF_RESULT_ERROR_NOT_SUPPORTED;
224224
}

src/pool/pool_jemalloc.c

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <string.h>
1313

1414
#include "base_alloc_global.h"
15+
#include "memory_provider_internal.h"
16+
#include "provider_tracking.h"
1517
#include "utils_common.h"
1618
#include "utils_concurrency.h"
1719
#include "utils_log.h"
@@ -283,8 +285,15 @@ static bool arena_extent_split(extent_hooks_t *extent_hooks, void *addr,
283285

284286
jemalloc_memory_pool_t *pool = get_pool_by_arena_index(arena_ind);
285287
assert(pool);
286-
return umfMemoryProviderAllocationSplit(pool->provider, addr, size,
287-
size_a) != UMF_RESULT_SUCCESS;
288+
289+
umf_result_t ret =
290+
umfMemoryProviderAllocationSplit(pool->provider, addr, size, size_a);
291+
if (ret != UMF_RESULT_SUCCESS) {
292+
LOG_ERR("memory provider failed to split a memory region, while "
293+
"jemalloc requires that");
294+
}
295+
296+
return ret != UMF_RESULT_SUCCESS;
288297
}
289298

290299
// arena_extent_merge - an extent merge function conforms to the extent_merge_t type and optionally
@@ -435,11 +444,45 @@ static void *op_aligned_alloc(void *pool, size_t size, size_t alignment) {
435444
return ptr;
436445
}
437446

447+
// Verify if the memory provider supports the split() operation,
448+
// because jemalloc pool requires that.
449+
static umf_result_t verify_split(umf_memory_provider_handle_t provider) {
450+
// Retrieve the upstream memory provider
451+
umf_memory_provider_handle_t upstream_provider = NULL;
452+
umfTrackingMemoryProviderGetUpstreamProvider(
453+
umfMemoryProviderGetPriv(provider), &upstream_provider);
454+
455+
size_t page_size = 0;
456+
umf_result_t ret =
457+
umfMemoryProviderGetMinPageSize(upstream_provider, NULL, &page_size);
458+
if (ret != UMF_RESULT_SUCCESS) {
459+
return ret;
460+
}
461+
462+
size_t size = 2 * page_size; // use double the page size for the split test
463+
if (UMF_RESULT_ERROR_NOT_SUPPORTED ==
464+
umfMemoryProviderAllocationSplit(upstream_provider, (void *)size, size,
465+
page_size)) {
466+
LOG_ERR("memory provider does not support the split operation, while "
467+
"jemalloc pool requires that");
468+
return UMF_RESULT_ERROR_NOT_SUPPORTED;
469+
}
470+
471+
return UMF_RESULT_SUCCESS;
472+
}
473+
438474
static umf_result_t op_initialize(umf_memory_provider_handle_t provider,
439475
const void *params, void **out_pool) {
440476
assert(provider);
441477
assert(out_pool);
442478

479+
// Verify if the memory provider supports the split() operation,
480+
// because jemalloc pool requires that.
481+
umf_result_t ret = verify_split(provider);
482+
if (ret != UMF_RESULT_SUCCESS) {
483+
return ret;
484+
}
485+
443486
extent_hooks_t *pHooks = &arena_extent_hooks;
444487
size_t unsigned_size = sizeof(unsigned);
445488
int n_arenas_set_from_params = 0;

src/provider/provider_os_memory.c

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "ctl/ctl_internal.h"
2525
#include "libumf.h"
2626
#include "provider_os_memory_internal.h"
27+
#include "topology.h"
2728
#include "utils_assert.h"
2829
#include "utils_common.h"
2930
#include "utils_concurrency.h"
@@ -561,27 +562,19 @@ static umf_result_t os_initialize(const void *params, void **provider) {
561562
snprintf(os_provider->name, sizeof(os_provider->name), "%s",
562563
in_params->name);
563564

564-
int r = hwloc_topology_init(&os_provider->topo);
565-
if (r) {
566-
LOG_ERR("HWLOC topology init failed");
567-
ret = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
568-
goto err_free_os_provider;
569-
}
570-
571-
r = hwloc_topology_load(os_provider->topo);
572-
if (r) {
565+
os_provider->topo = umfGetTopologyReduced();
566+
if (!os_provider->topo) {
573567
os_store_last_native_error(UMF_OS_RESULT_ERROR_TOPO_DISCOVERY_FAILED,
574568
0);
575569
LOG_ERR("HWLOC topology discovery failed");
576570
ret = UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC;
577-
goto err_destroy_hwloc_topology;
578571
}
579572

580573
os_provider->fd_offset_map = critnib_new(NULL, NULL);
581574
if (!os_provider->fd_offset_map) {
582575
LOG_ERR("creating file descriptor offset map failed");
583576
ret = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
584-
goto err_destroy_hwloc_topology;
577+
goto err_free_os_provider;
585578
}
586579

587580
ret = translate_params(in_params, os_provider);
@@ -624,8 +617,6 @@ static umf_result_t os_initialize(const void *params, void **provider) {
624617
free_bitmaps(os_provider);
625618
err_destroy_critnib:
626619
critnib_delete(os_provider->fd_offset_map);
627-
err_destroy_hwloc_topology:
628-
hwloc_topology_destroy(os_provider->topo);
629620
err_free_os_provider:
630621
umf_ba_global_free(os_provider);
631622
return ret;
@@ -649,7 +640,7 @@ static umf_result_t os_finalize(void *provider) {
649640
if (os_provider->nodeset_str_buf) {
650641
umf_ba_global_free(os_provider->nodeset_str_buf);
651642
}
652-
hwloc_topology_destroy(os_provider->topo);
643+
653644
umf_ba_global_free(os_provider);
654645
return UMF_RESULT_SUCCESS;
655646
}

src/topology.c

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright (C) 2024 Intel Corporation
3+
* Copyright (C) 2024-2025 Intel Corporation
44
*
55
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
66
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -13,7 +13,9 @@
1313
#include "utils_log.h"
1414

1515
static hwloc_topology_t topology = NULL;
16+
static hwloc_topology_t topology_reduced = NULL;
1617
static UTIL_ONCE_FLAG topology_initialized = UTIL_ONCE_FLAG_INIT;
18+
static UTIL_ONCE_FLAG topology_reduced_initialized = UTIL_ONCE_FLAG_INIT;
1719

1820
void umfDestroyTopology(void) {
1921
if (topology) {
@@ -24,22 +26,55 @@ void umfDestroyTopology(void) {
2426
memcpy(&topology_initialized, &is_initialized,
2527
sizeof(topology_initialized));
2628
}
29+
if (topology_reduced) {
30+
hwloc_topology_destroy(topology_reduced);
31+
32+
// portable version of "topology_initialized = UTIL_ONCE_FLAG_INIT;"
33+
static UTIL_ONCE_FLAG is_initialized = UTIL_ONCE_FLAG_INIT;
34+
memcpy(&topology_reduced_initialized, &is_initialized,
35+
sizeof(topology_reduced_initialized));
36+
}
2737
}
2838

29-
static void umfCreateTopology(void) {
30-
if (hwloc_topology_init(&topology)) {
39+
static void umfCreateTopologyHelper(bool reduced,
40+
hwloc_topology_t *topology_ptr) {
41+
if (hwloc_topology_init(topology_ptr)) {
3142
LOG_ERR("Failed to initialize topology");
32-
topology = NULL;
43+
*topology_ptr = NULL;
3344
return;
3445
}
3546

36-
if (hwloc_topology_load(topology)) {
47+
if (reduced) {
48+
// Set the topology to only include NUMA nodes and memory
49+
// to improve performance of the topology load on large systems
50+
if (hwloc_topology_set_all_types_filter(*topology_ptr,
51+
HWLOC_TYPE_FILTER_KEEP_NONE)) {
52+
LOG_ERR("Failed to set topology filter");
53+
hwloc_topology_destroy(*topology_ptr);
54+
*topology_ptr = NULL;
55+
return;
56+
}
57+
}
58+
if (hwloc_topology_load(*topology_ptr)) {
3759
LOG_ERR("Failed to initialize topology");
38-
hwloc_topology_destroy(topology);
39-
topology = NULL;
60+
hwloc_topology_destroy(*topology_ptr);
61+
*topology_ptr = NULL;
4062
}
4163
}
4264

65+
static void umfCreateTopology(void) {
66+
umfCreateTopologyHelper(false, &topology);
67+
}
68+
69+
static void umfCreateTopologyReduced(void) {
70+
umfCreateTopologyHelper(true, &topology_reduced);
71+
}
72+
73+
hwloc_topology_t umfGetTopologyReduced(void) {
74+
utils_init_once(&topology_reduced_initialized, umfCreateTopologyReduced);
75+
return topology_reduced;
76+
}
77+
4378
hwloc_topology_t umfGetTopology(void) {
4479
utils_init_once(&topology_initialized, umfCreateTopology);
4580
return topology;

0 commit comments

Comments
 (0)