perf(agc): keep adjacent ranges one import serves as one region of the cached address space
A V# spanning two registered ranges dissolved the shared space into the build's own regions (about 10k regions copied, sorted and looked up per build in Killing Floor 3), although the import covering the run binds it in place. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uzy15wqYTt6iWyxYXEzUWo
This commit is contained in:
parent
ea2bbefb2b
commit
6bf9ab86ff
|
|
@ -2257,6 +2257,20 @@ void GuestBufferMemory::AcquireRegistered() {
|
|||
publish = false;
|
||||
spaces.unpublished.fetch_add(1, std::memory_order_relaxed);
|
||||
} else {
|
||||
std::size_t kept = 0;
|
||||
for (std::size_t index = 0; index < regions.size(); ++index) {
|
||||
auto& region = regions[index];
|
||||
if (kept != 0) {
|
||||
auto& previous = regions[kept - 1];
|
||||
if (region.direct != nullptr && previous.direct == region.direct && previous.end == region.begin && previous.writable == region.writable && region.mirror == nullptr && previous.mirror == nullptr && !region.sparse && !previous.sparse && region.end <= region.direct->base + region.direct->bytes) {
|
||||
previous.end = region.end;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (kept != index) regions[kept] = std::move(region);
|
||||
++kept;
|
||||
}
|
||||
regions.erase(regions.begin() + static_cast<std::ptrdiff_t>(kept), regions.end());
|
||||
for (const auto& region : regions) {
|
||||
if (region.direct != nullptr || region.mirror != nullptr) ranges.push_back(addressRange(region));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,6 +175,42 @@ void failedImportRemapTests(const Context& context, const BdaTestAccess& access)
|
|||
::operator delete(block, std::align_val_t{piece});
|
||||
}
|
||||
|
||||
void spaceImportRunTests(const Context& context) {
|
||||
constexpr std::size_t piece = 65536;
|
||||
void* block = ::operator new(2 * piece, std::align_val_t{piece});
|
||||
const auto first = reinterpret_cast<std::uintptr_t>(block);
|
||||
std::memset(block, 0x3c, 2 * piece);
|
||||
auto importing = context;
|
||||
importing.hostImportAlignment = piece;
|
||||
const auto change = [&](std::uint8_t* range, bool add) {
|
||||
auto* mutation = GuestAllocations::GuestAllocationsBegin_nid_postfix();
|
||||
if (add) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, range, piece, true, false, true);
|
||||
else GuestAllocations::GuestAllocationsRemove_nid_postfix(mutation, range);
|
||||
GuestAllocations::GuestAllocationsEnd_nid_postfix(mutation);
|
||||
};
|
||||
auto* guest = static_cast<std::uint8_t*>(block);
|
||||
change(guest, true);
|
||||
change(guest + piece, true);
|
||||
for (int build = 0; build < 2; ++build) {
|
||||
const auto before = AddressSpaceCounters();
|
||||
GuestBufferMemory leased(importing);
|
||||
leased.AcquireRegistered();
|
||||
leased.AddReadable(first + piece - 256, 512);
|
||||
leased.Upload(true);
|
||||
std::uint32_t adjustment = 0;
|
||||
const auto view = leased.Descriptor(first + piece - 256, 512, adjustment);
|
||||
Require(view.buffer != VK_NULL_HANDLE && view.range == 512 + adjustment, "a V# across one import's ranges has no descriptor");
|
||||
const auto ranges = leased.AddressRanges();
|
||||
Require(std::any_of(ranges.begin(), ranges.end(), [&](const auto& range) { return range.begin <= first && first + 2 * piece <= range.end; }), "one import's adjacent ranges are not one BDA table entry");
|
||||
leased.WriteBack();
|
||||
const auto after = AddressSpaceCounters();
|
||||
if (after.enabled && build == 1) Require(after.hits == before.hits + 1 && after.dissolvedOverlap == before.dissolvedOverlap, "a V# across one import's ranges dissolved the cached address space");
|
||||
}
|
||||
change(guest, false);
|
||||
change(guest + piece, false);
|
||||
::operator delete(block, std::align_val_t{piece});
|
||||
}
|
||||
|
||||
void importWindowTests(const Context& context) {
|
||||
constexpr std::size_t piece = 65536;
|
||||
constexpr std::size_t window = 2 * piece;
|
||||
|
|
@ -1202,6 +1238,7 @@ void RunBdaResourceTests(const Context& context, const BdaTestAccess& access) {
|
|||
importCrossingTests(context, access);
|
||||
importSpanTests(context);
|
||||
failedImportRemapTests(context, access);
|
||||
spaceImportRunTests(context);
|
||||
importWindowTests(context);
|
||||
heapMirrorTests(context, access);
|
||||
importedHeapMirrorTests(context, access);
|
||||
|
|
|
|||
Loading…
Reference in New Issue