Can I get a list of all currently-registered atoms?

I'm not sure if there's a way to do it on a live system, but if you can run it in a test environment you should be able to get a list via crash dump. The atom table is near the end of the crash dump format. You can create a crash dump via erlang:halt/1, but that will bring down the whole runtime system.


You can get hold of all atoms by using an undocumented feature of the external term format.

TL;DR: Paste the following line into the Erlang shell of your running node. Read on for explanation and a non-terse version of the code.

(fun F(N)->try binary_to_term(<<131,75,N:24>>) of A->[A]++F(N+1) catch error:badarg->[]end end)(0).

Elixir version by Ivar Vong:

for i <- 0..:erlang.system_info(:atom_count)-1, do: :erlang.binary_to_term(<<131,75,i::24>>)

An Erlang term encoded in the external term format starts with the byte 131, then a byte identifying the type, and then the actual data. I found that EEP-43 mentions all the possible types, including ATOM_INTERNAL_REF3 with type byte 75, which isn't mentioned in the official documentation of the external term format.

For ATOM_INTERNAL_REF3, the data is an index into the atom table, encoded as a 24-bit integer. We can easily create such a binary: <<131,75,N:24>>

For example, in my Erlang VM, false seems to be the zeroth atom in the atom table:

> binary_to_term(<<131,75,0:24>>).
false

There's no simple way to find the number of atoms currently in the atom table*, but we can keep increasing the number until we get a badarg error.

So this little module gives you a list of all atoms:

-module(all_atoms).

-export([all_atoms/0]).

atom_by_number(N) ->
    binary_to_term(<<131,75,N:24>>).

all_atoms() ->
    atoms_starting_at(0).

atoms_starting_at(N) ->
    try atom_by_number(N) of
        Atom ->
            [Atom] ++ atoms_starting_at(N + 1)
    catch
        error:badarg ->
            []
    end.

The output looks like:

> all_atoms:all_atoms().
[false,true,'_',nonode@nohost,'$end_of_table','','fun',
 infinity,timeout,normal,call,return,throw,error,exit,
 undefined,nocatch,undefined_function,undefined_lambda,
 'DOWN','UP','EXIT',aborted,abs_path,absoluteURI,ac,accessor,
 active,all|...]
> length(v(-1)).
9821

* In Erlang/OTP 20.0, you can call erlang:system_info(atom_count):

> length(all_atoms:all_atoms()) == erlang:system_info(atom_count).
true

Tags:

Erlang