Limit maximum memory use of string.inspect
#4939
lpil
started this conversation in
Ideas & suggestions
Replies: 1 comment 3 replies
-
Looks reasonable. I'm not sure |
Beta Was this translation helpful? Give feedback.
3 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
We have the
string.inspect
function which can turn any data into a Gleam-sync-like representation of that data. This may be useful for debugging and for error reporting with unknown data (such as data from FFI, OTP exits, inside the Erlang logger, etc).While it will detect reference cycles on JavaScript to avoid attempting to make a string of infinite size, there is no upper limit to how large the constructed string can be; It will convert the entire input data structure. With large values, or values that use a lot of duplicated data or static data (Erlang literal pool, JS static variables), this can result in very high memory usage, especially if
string.inspect
is being called frequently, such when logging a frequent error. This can cause performance problems or even crashes due to memory exhaustion.Elixir has a similar function,
Kernel.inspect
, and it has alimit
andprintable_limit
options that help with this by limiting how many elements to render per-collection.https://hexdocs.pm/elixir/1.12/Inspect.html
https://hexdocs.pm/elixir/1.12/Inspect.Opts.html
note: The
limit
option also applies to the depth that the function will descend into nested containers.I think it would be useful to have similar functionality for Gleam's
string.inspect
, to avoid accidental memory spikes.Proposal
Add a limit to the size of the output of
string.inspect
, limiting the size byte-size of the output rather than Elixir's limit on the number of elements in the data structure and byte size of strings. When the limit is reached we could either append...
and return the string.The advantage of this over an Elixir style depth limit is that the maximum size is more predictable, however there would be more situations in which values in the parent container that come after a large earlier sibling value would not be printed at all that in Elixir. I think this is an acceptable drawback as data this large is already impractical to read, we don't have reason to especially prioritise those higher-but-later values, and the programmer could raise the limit if they want those ones to be printed.
string.inspect
is used in a lot of code, with GitHub search returning 1,300 modules using it. To avoid a highly disruptive breaking API change we can add a second function that takes the limit as an argument.string.bounded_inspect
? Name TBD.string.inspect
would be implemented as a call to the other function with some default limit that is large enough to produce output is too big to practically read, but not so large that it enables memory use problems. It's OK for the output ofstring.inspect
to change like this as the output is not guaranteed to be stable.Beta Was this translation helpful? Give feedback.
All reactions