# Is there any document about the amount of memory occupied by the basic types of Motoko canister?

**URL:** <https://forum.dfinity.org/t/is-there-any-document-about-the-amount-of-memory-occupied-by-the-basic-types-of-motoko-canister/6442>\
**Category:** Developers\
**Created:** [August 13, 2021, 3:50am UTC](https://forum.dfinity.org/t/is-there-any-document-about-the-amount-of-memory-occupied-by-the-basic-types-of-motoko-canister/6442 "2021-08-13T03:50:58Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![flyq](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/flyq/32/3637_2.png) [@flyq](https://forum.dfinity.org/u/flyq)\
**Post date:** [August 13, 2021, 3:50am UTC](https://forum.dfinity.org/t/is-there-any-document-about-the-amount-of-memory-occupied-by-the-basic-types-of-motoko-canister/6442/1 "2021-08-13T03:50:58Z")

</div>

Is there any document about the amount of memory occupied by the basic types of Motoko canister?

such as a Nat8 array with n size, a principal, a enum, a HashMap and so on.

---

<div class="post-metadata">

**Author:** ![jzxchiang](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/jzxchiang/32/2592_2.png) [@jzxchiang](https://forum.dfinity.org/u/jzxchiang)\
**Post date:** [August 13, 2021, 5:12am UTC](https://forum.dfinity.org/t/is-there-any-document-about-the-amount-of-memory-occupied-by-the-basic-types-of-motoko-canister/6442/2 "2021-08-13T05:12:37Z")

</div>

In the world of canisters and cycles… every byte counts.

---

<div class="post-metadata">

**Author:** ![nomeata](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/nomeata/32/733_2.png) [@nomeata](https://forum.dfinity.org/u/nomeata)\
**Post date:** [August 13, 2021, 9:00am UTC](https://forum.dfinity.org/t/is-there-any-document-about-the-amount-of-memory-occupied-by-the-basic-types-of-motoko-canister/6442/3 "2021-08-13T09:00:47Z")

</div>

No, I don’t think such a document exists. The ASCII-art and comments in [motoko/compile.ml at master · dfinity/motoko · GitHub](https://github.com/dfinity/motoko/blob/master/src/codegen/compile.ml#L1287) is maybe the best place right now, but this is of course written with the compiler developer in mind. And there are a bunch of optimizations (e.g. small numbers are not stored as pointed-to objects, but “instead of” the pointer) that make such predictions harder.

To answer your concrete questions:

- A `[Nat8]` with _n_ elements will take _8+4×n_ bytes.
- A principal is represented the same way as a blog, so if it is _n_ bytes (binary representation, not the textual format), then up to _8+n+3_ bytes.
- An variant is 12 bytes (plus whatever is stored inside the tag). If it’s strictly an enum (i.e. only `()` stored inside), then the `()` is “free”.
- A hashmap is more complicated, but it’s not a basic type, so I’ll punt on that one 🙂

---

<div class="post-metadata">

**Author:** ![flyq](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/flyq/32/3637_2.png) [@flyq](https://forum.dfinity.org/u/flyq)\
**Post date:** [September 11, 2021, 7:17am UTC](https://forum.dfinity.org/t/is-there-any-document-about-the-amount-of-memory-occupied-by-the-basic-types-of-motoko-canister/6442/4 "2021-09-11T07:17:07Z")

</div>

Thanks for your great answer,

How about Nat32, Nat64, Nat, Int, Text, List, Option ?T, Char

---

<div class="post-metadata">

**Author:** ![nomeata](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/nomeata/32/733_2.png) [@nomeata](https://forum.dfinity.org/u/nomeata)\
**Post date:** [September 11, 2021, 8:03am UTC](https://forum.dfinity.org/t/is-there-any-document-about-the-amount-of-memory-occupied-by-the-basic-types-of-motoko-canister/6442/5 "2021-09-11T08:03:08Z")

</div>

- `Nat32`, `Char`: 8 bytes
- `Int64`: 12 bytes
- `Nat` and `Int`: “free” if smaller than 2^30, else at least 20 bytes, up to arbitrary sizes
- `Text` and `Blob`: up to 8+n+3 bytes.
- `opt`: “free” unless you deal with the value `?…?null`
- `List` is not a basic type. Probably 12\*n

Free means that it’s stored inside the containing data structure without extra allocation.

---

<div class="post-metadata">

**Author:** ![alexander](https://avatars.discourse-cdn.com/v4/letter/a/bc8723/32.png) [@alexander](https://forum.dfinity.org/u/alexander)\
**Post date:** [January 6, 2022, 2:08pm UTC](https://forum.dfinity.org/t/is-there-any-document-about-the-amount-of-memory-occupied-by-the-basic-types-of-motoko-canister/6442/6 "2022-01-06T14:08:29Z")

</div>

> [@nomeata](#):
>
> A `[Nat8]` with _n_ elements will take _8+4×n_ bytes.

Does this also apply to the RUST canister?

---

<div class="post-metadata">

**Author:** ![timo](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/timo/32/5543_2.png) [@timo](https://forum.dfinity.org/u/timo)\
**Post date:** [January 6, 2022, 5:25pm UTC](https://forum.dfinity.org/t/is-there-any-document-about-the-amount-of-memory-occupied-by-the-basic-types-of-motoko-canister/6442/7 "2022-01-06T17:25:16Z")

</div>

No, he’s talking about Motoko only.

Just curious: why does a Nat32 occupy 8 bytes?

---

<div class="post-metadata">

**Author:** ![nomeata](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/nomeata/32/733_2.png) [@nomeata](https://forum.dfinity.org/u/nomeata)\
**Post date:** [January 6, 2022, 6:29pm UTC](https://forum.dfinity.org/t/is-there-any-document-about-the-amount-of-memory-occupied-by-the-basic-types-of-motoko-canister/6442/8 "2022-01-06T18:29:57Z")

</div>

> [@timo](#):
>
> Just curious: why does a Nat32 occupy 8 bytes?

Every heap-allocated object has a 1-word (4-bytes) header, followed by the payload, which, in this case, is 4 bytes:

> <https://github.com/dfinity/motoko/blob/bd6580188dd7584bca87365767f5a153e2f0cd74/src/codegen/compile.ml#L1617-L1628>

---

<div class="post-metadata">

**Author:** ![alexander](https://avatars.discourse-cdn.com/v4/letter/a/bc8723/32.png) [@alexander](https://forum.dfinity.org/u/alexander)\
**Post date:** [January 6, 2022, 8:17pm UTC](https://forum.dfinity.org/t/is-there-any-document-about-the-amount-of-memory-occupied-by-the-basic-types-of-motoko-canister/6442/9 "2022-01-06T20:17:20Z")

</div>

Does it specific only for motoko compiled module? I mean if I build a module using rust what size whould be for byte array ?

---

<div class="post-metadata">

**Author:** ![skilesare](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/skilesare/32/5609_2.png) [@skilesare](https://forum.dfinity.org/u/skilesare)\
**Post date:** [July 12, 2025, 12:05am UTC](https://forum.dfinity.org/t/is-there-any-document-about-the-amount-of-memory-occupied-by-the-basic-types-of-motoko-canister/6442/10 "2025-07-12T00:05:58Z")

</div>

@luc-blaeser, @ggreif, @claudio

Can we get a 2025 breakdown of this? Is it different with 64 bit?

---

<div class="post-metadata">

**Author:** ![claudio](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/claudio/32/322_2.png) [@claudio](https://forum.dfinity.org/u/claudio)\
**Post date:** [July 15, 2025, 5:20pm UTC](https://forum.dfinity.org/t/is-there-any-document-about-the-amount-of-memory-occupied-by-the-basic-types-of-motoko-canister/6442/11 "2025-07-15T17:20:19Z")

</div>

It is different with 64 bit in the sense that the word size is now 64-bit, not 32-bit, so most values double in size. However, more values can be represented unboxed, without a heap indirection, which also saves space for smaller values.

In all gcs, small values less than the word size are encoded as unboxed words. Larger values that cannot fit in a word are heap allocated and represented by a tagged pointer (another word) to the heap location. The location on the heap contains a word sized tag to identify the type of the object (record, variant, text, blob, boxed (singed or unsigned) full-word, mutable array, immutable array, tuple). For an incremental GC like the 32-bit incremental gc or eop GC, each heap allocated block contains an additional forwarding pointer, used by the GC to move objects between memory partitions.

I’ll add it to our todo list to documents this more clearly, though it is an implementation details that changes (e.g. with the choice of GC).

With eop, the tags are actually more informative than with the 32-bit gc, and even unboxed values contain tags to disambiguate their types (for other reasons to do with last-resort upgrades via serialization). This info is not user accessible but used by the runtime system (and could be used fruitfully by a debugger)
