Skip to content

emmalloc: Ask sbrk for aligned sizes#20759

Merged
kripken merged 4 commits intomainfrom
emmalloc.aligned-sbrk
Nov 21, 2023
Merged

emmalloc: Ask sbrk for aligned sizes#20759
kripken merged 4 commits intomainfrom
emmalloc.aligned-sbrk

Conversation

@kripken
Copy link
Member

@kripken kripken commented Nov 21, 2023

If we give it an unaligned size, then it will align it, and then memory will
seem non-contiguous. That is, if we sbrk 4 bytes from address 0 then it
returns 0 (the start of the allocation), and logically we reserved the range
0-4. Our next sbrk of any amount will return 8, because sbrk aligns up the
address to multiples of 8. So it seems like we have a region 0-4 and another
8-. Because of this emmalloc would generate separate root regions for
them, that is, they would not get merged because of the 4 bytes of dead
space in the middle.

With this PR, the amount of new regions created in
test_emmalloc_memvalidate_verbose goes from 1311 to 1234. I'm not sure
if it's worth testing that, as it would make updating the test difficult, and this
is such an internal detail of emmalloc.

Also add some verbose logging that helps debug this.

Noticed in #20704 (comment)

// it will not return contiguous regions, which leads to use creating more
// root regions below, inefficiently. (Note that we assume our alignment is
// identical to sbrk's, see the assumptions at the start of this file.)
numBytes = (size_t)ALIGN_UP(numBytes, MALLOC_ALIGNMENT);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the cast needed here? numBytes is already size_t.. and I imagine that MALLOC_ALIGNMENT is too, no?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cast is needed as the output of the macro is a pointer,

#define ALIGN_UP(ptr, alignment) ((uint8_t*)((((uintptr_t)(ptr)) + ((alignment)-1)) & ~((alignment)-1)))

@kripken
Copy link
Member Author

kripken commented Nov 21, 2023

This increases code size by a few bytes (the extra alignment enforcement), but it seems worth it to avoid possibly large amounts of wasted memory at runtime (or even infinite looping as found in #20704).

@kripken kripken merged commit 326600a into main Nov 21, 2023
@kripken kripken deleted the emmalloc.aligned-sbrk branch November 21, 2023 22:20
@juj
Copy link
Collaborator

juj commented Nov 27, 2023

Great fix 👍

br0nk pushed a commit to br0nk/emscripten that referenced this pull request Nov 29, 2023
If we give it an unaligned size, then it will align it, and then memory will
seem non-contiguous. That is, if we sbrk 4 bytes from address 0 then it
returns 0 (the start of the allocation), and logically we reserved the range
0-4. Our next sbrk of any amount will return 8, because sbrk aligns up the
address to multiples of 8. So it seems like we have a region 0-4 and another
8-. Because of this emmalloc would generate separate root regions for
them, that is, they would not get merged because of the 4 bytes of dead
space in the middle.

With this PR, the amount of new regions created in
test_emmalloc_memvalidate_verbose goes from 1311 to 1234. I'm not sure
if it's worth testing that, as it would make updating the test difficult, and this
is such an internal detail of emmalloc.

Also add some verbose logging that helps debug this.

Noticed in emscripten-core#20704 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants