Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

erlang:system_info - add snifs to the spec #9010

Closed
wants to merge 1 commit into from

Conversation

ilya-klyuchnikov
Copy link
Contributor

(Found with eqWAlizer when type-checking an internal project - erlang:system_info(snifs) was flagged)
snifs implementation: 091c65e

Copy link
Contributor

github-actions bot commented Oct 31, 2024

CT Test Results

    3 files    141 suites   49m 19s ⏱️
1 596 tests 1 547 ✅ 49 💤 0 ❌
2 305 runs  2 236 ✅ 69 💤 0 ❌

Results for commit a8c5fc7.

♻️ This comment has been updated with latest results.

To speed up review, make sure that you have read Contributing to Erlang/OTP and that all checks pass.

See the TESTING and DEVELOPMENT HowTo guides for details about how to run test locally.

Artifacts

// Erlang/OTP Github Action Bot

@garazdawi
Copy link
Contributor

snifs is an internal undocumented argument to system_info. If you need it for something, it should also be documented and testcases added to make sure that it works.

Do you have a usecase for this?

@potatosalad
Copy link
Contributor

@garazdawi We use this for listing and tracing any loaded BIF (or NIF) functions currently loaded into the BEAM (or for identifying them by cross-referencing). Is there another approved way for us to fetch the list of MFA from bif_table?

@IngelaAndin IngelaAndin added the team:VM Assigned to OTP team VM label Nov 4, 2024
@garazdawi
Copy link
Contributor

No, there is no other way to get that information. I'm a bit hesitant to expose this as I think it exposes something that is very internal to erts and something that we want to be able to change without caring for backwards compatability.

What information is it that you are after really? Whether a function is implemented using native code? Or is it specifically if it is implemented as a snif?

@potatosalad
Copy link
Contributor

What information is it that you are after really? Whether a function is implemented using native code?

Yes, I believe so, the code is part of a call profiler that effectively does this:

SystemMFAs = erlang:system_info(snifs),
lists:filtermap(fun(MFA = {_M, _F, _A}) ->
    case erlang:trace_info(MFA, call_time) of
        {call_time, List} when is_list(List) ->
            {true, collect(List)};
        _ ->
            false
    end
end, SystemMFAs).

Versus everything else:

OtherMFAs = lists:flatten([[{M, F, A} || {F, A} <- M:module_info(functions)] || {M, _} <- code:all_loaded()]),
% same as above...

Or is it specifically if it is implemented as a snif?

I'm not sure what a snif is exactly, isn't it just an entry in the bif_table, which would include all BIFs, but not any static NIFs, right?

@garazdawi
Copy link
Contributor

I'm not sure what a snif is exactly, isn't it just an entry in the bif_table, which would include all BIFs, but not any static NIFs, right?

We like to say snif (static native implemented function), as what exactly a BIF is varies a bit depending on who you ask. Our reference manual says one thing, while the erlang spec another. I'm not sure that the difference matters all that much.

Anyway... I think what I was asking with this questions:

Or is it specifically if it is implemented as a snif?

was whether you want to know which function are implemeneted using native code (be they normal NIFs or sNIFs), or if it is specifically the functions part of erts that you want? I'm wondering if it would not make more sense to update module_info to contain an attribute describing which function are actually native functions, or something like that.

@potatosalad
Copy link
Contributor

Oh, gotcha, I think if we had some other way to determine if a specific MFA is a BIF, NIF, SNIF, or whichever, that would also work.

Either as part of the module_info or if there was an erlang:function_native(M, F, A) or similar.

It would also be useful if this was possible for internal, non-exported functions.

It looks like all of the snifs are exported:

1> [MFA || MFA = {M, F, A} <- lists:usort(erlang:system_info(snifs)), not erlang:function_exported(M, F, A)].
[]

However, many modules have non-exported NIF, like in zlib:

-export([open/0]).
-nifs([open_nif/0]).

-doc "Opens a zlib stream.".
-spec open() -> zstream().
open() ->
    open_nif().
open_nif() ->
    erlang:nif_error(undef).

Particularly before erlang:load_nif/2 has been called on a module, I wonder what zlib:open_nif/0 would be reported as?

@garazdawi
Copy link
Contributor

I think I would like the API to be a new item to module_info/1 called native_functions that returns details about which functions (exported and local) are currently backed by native code. If a user wants to know which functions could potentially be backed to native code, then that can be figured out by parsing the AST and looking for the -nifs attribute.

@garazdawi
Copy link
Contributor

We would be happy to accept a PR that implements something similar to the API I suggested above to get this information. We may work on it ourselves, but probably not in the close future. I've created #9072 to track the feature.

@garazdawi garazdawi closed this Nov 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
team:VM Assigned to OTP team VM
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants