Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to identify the exact memory size of an ETS table?

Tags:

erlang

ets

Give an ETS table with data, the info/1 function returns various properties for the table, including a size value which is specific to the number of rows rather than the physical size.

Is there any way to calculate the amount of memory in bytes occupied by an ETS table ?

ets:new( mytable, [bag, named_table, compressed]),
ets:insert( mytable, { Key, Value } ),
....
ets:info ( mytable ).
like image 703
gextra Avatar asked Feb 23 '14 20:02

gextra


1 Answers

TL;DR:

ETS table allocated memory size in bytes:

ets:info(Table,memory) * erlang:system_info(wordsize).


To elaborate a bit, ets:info(Table,memory) gives you the words allocated to data in an ETS table (same for Mnesia. You can view al that info in the TV application. The same attribute for DETS tables is in bytes).

A word is nothing more than the 'natural' data unit of a particular CPU architecture. What that represents depends on your architecture: 32-bit or 64-bit (or use erlang:system_info(wordsize) to get the correct word size immediately)

  • On a 32-bit system, a word is 4 bytes (32 bits).
  • On a 64-bit system, a word is 8 bytes (64 bits).

Also note that a ETS table initially spans 768 words, to wich you must add the size of each element, 6 words + size of Erlang data. It's not really clear if those are the words "allocated to data" ets:info specifies.

Calculating the exact size is a bit of a hassle: ETS tables have their own independent memory management system, which is optimized and garbage collected, and can vary depending on table type (set, bag, duplicate_bag). As an experiment, an empty table returns, in my environment, 300 words "allocated to data". If I add 11 tuples, size increases to 366 words. No Idea to how those relate to the initial 768 words, or why the size only increases by 11*6 words, when it should have been 11*6 + 11*1 (11 atoms), according to definition.

Still, a naive estimate, taking the initial table size and the words allocated to data, for example 22086 words, results in 768*8 + 22.086*8 = 182.832 bytes (178.54 KiB).

Of course, the bigger the data, the less those "structural" words matter, so you could only use the "words allocated to data" number, returned by ets:info, to estimate your table's size in memory.


Edit: There are two other functions that let you audit ETS memory usage:

  • erlang:memory/1: erlang:memory(ets) returns the memory size, in bytes, allocated to ETS.
  • ets:i/0: an overview of all active ETS tables (a bit like viewing system tables in TV, but with type and memory data).

As a small test, an newly created empty table increased memory use with 312 words (2.44 KiB), a lot less than the 768 number in the manual (perhaps it's CPU architecture related, I have no idea), while ETS itself reported 299 words (2.33 KiB) allocated to the data.

That's only 13 words (104 bytes) of structural overhead away (or so it seems, it remains nebulous) from the increase erlang:memory/1 reported, so ets:info/2 is fairly accurate after all.

After the insertion of a simple tuple consisting of 2 atoms, erlang:memory/1 reported a 8 word memory allocation increase, just like the documentation said it would (new ETS record: 6 words + size of data - 2 in this case : 1 word per atom).

like image 151
Berzemus Avatar answered Nov 10 '22 11:11

Berzemus