Skip to content

libexpr: use allocBytes() to allocate StringData#14584

Merged
Ericson2314 merged 2 commits intoNixOS:masterfrom
Radvendii:allocbytes-stringdata
Nov 23, 2025
Merged

libexpr: use allocBytes() to allocate StringData#14584
Ericson2314 merged 2 commits intoNixOS:masterfrom
Radvendii:allocbytes-stringdata

Conversation

@Radvendii
Copy link
Contributor

Motivation

EvalMemory::allocBytes() allows us to easily change how memory is allocated throughout the program. I have been using it to put all allocations in a bump allocator so I can more easily track memory leaks.

One problem is that this has to change the c bindings. I don't know how much of an issue this is as I haven't worked on the c bindings much until now.

Context


Add 👍 to pull requests you find important.

The Nix maintainer team uses a GitHub project board to schedule and track reviews.

@Radvendii Radvendii requested a review from edolstra as a code owner November 17, 2025 21:07
@github-actions github-actions bot added new-cli Relating to the "nix" command c api Nix as a C library with a stable interface labels Nov 17, 2025
@Radvendii Radvendii force-pushed the allocbytes-stringdata branch from 403b9af to 26fa5af Compare November 17, 2025 21:25
Copy link
Member

@Ericson2314 Ericson2314 left a comment

Choose a reason for hiding this comment

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

Looks good, just should update the C API first and let Robert know.

As far as I can tell, this is an unavoidable breaking change of the C API.

CC @roberth

@Radvendii
Copy link
Contributor Author

To expand on what @Ericson2314 said, we discussed it in the meeting and we can anticipate that a similar change will be necessary for all the c api functions that create Values (eventually, when values themselves are stored in managed memory), so we should make those changes all now, and split it off into a separate PR. I'll try to get to that later this week.

Radvendii added a commit to Radvendii/nix that referenced this pull request Nov 19, 2025
We will need this argument in the future as we put things in managed
memory. see NixOS#14584 for an example.
@Radvendii Radvendii force-pushed the allocbytes-stringdata branch from 26fa5af to f27b283 Compare November 21, 2025 17:41
@Radvendii
Copy link
Contributor Author

As discussed in #14592, we don't actually need to change the C API for this (and shouldn't). When we're done with managed heap changes, maybe we should come out with an API v2, but in the meantime we can work around it for now.

This does come with some costs for the C API:

  • nix_value is now 16 bytes on top of the 16 bytes for a nix::Value (it stores a Value * and EvalMemory *)
  • We've added a layer of indirection to every nix_value access
  • When we call functions with an array of arguments, we have to create a new array with the other type of pointer.

CC: @roberth @Ericson2314

@Radvendii Radvendii force-pushed the allocbytes-stringdata branch from f27b283 to 0e9ef38 Compare November 21, 2025 17:44
@roberth
Copy link
Member

roberth commented Nov 21, 2025

some costs for the C API

This is usually insignificant. The number of values interacted with is generally not terribly big compared to the whole evaluation. For instance, something like nix build .#foo only needs to touch a handful of values that are returned to the CLI, whereas most values are intermediate results that are not affected by this.
It'd be a different story when, say, builtins.derivation were implemented through the C API, but I don't assume C API consumers operate at that scale.
If they do, I'd welcome their contributions, and a reasonable migration would be:

  1. provide alternative functions that don't make use of the extra field
  2. deprecate the old functions
  3. wait for the latest Nix version without the new functions to go EOL
  4. remove the old functions and the field

I see nix_init_string needs it. Any other functions?
The PR is ok, but perhaps we could do (1) so that we don't sit on the tech debt for too long.

@Radvendii
Copy link
Contributor Author

Currently nix_init_string is the only one that needs it and didn't already have access, but when we get to putting Values in managed memory and referencing them by index, we'll need EvalMemory anywhere that we access a Value.

My concern with (1) is that it's not 100% clear what the interface should look like when we're done with more of the changes. I'd rather redesign it once when we're more sure what the constraints are going to be, rather than to redesign a bit now and then realise it needs even more redesign a later.

But that's a tradeoff. If you think it's better to do the intermediate redesign now I'll defer to you.

this is a painful change. we should really add EvalState or EvalMemory
as an argument to various functions as we need it, but because we want
to preserve the stablity API, we hack it in as a field of nix_value.
@Radvendii Radvendii force-pushed the allocbytes-stringdata branch from 0e9ef38 to 7cd3252 Compare November 21, 2025 20:26
@roberth
Copy link
Member

roberth commented Nov 21, 2025

Got it. Can be done later, no problem.

@Ericson2314 Ericson2314 added this pull request to the merge queue Nov 23, 2025
Merged via the queue into NixOS:master with commit 327e8ba Nov 23, 2025
16 checks passed
@edolstra edolstra mentioned this pull request Dec 9, 2025
avidal added a commit to avidal/nix-plugins that referenced this pull request Jan 28, 2026
In NixOS/nix#14584 mkString was changed to require an `EvalMemory`, part of a larger effort to centralize memory allocation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c api Nix as a C library with a stable interface new-cli Relating to the "nix" command

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants