RandomX is intended to be run efficiently on a general-purpose CPU. The virtual machine (VM) which runs RandomX code attempts to simulate a generic CPU using the following set of components:
RandomX uses a 4 GiB read-only dataset. The dataset is constructed using a combination of the [Argon2d](https://en.wikipedia.org/wiki/Argon2) hashing function, [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) encryption/decryption and a random permutation. The dataset is regenerated every ~34 hours.
RandomX uses a simple low-level language (instruction set), which was designed so that any random bitstring forms a valid program. Each RandomX instruction has a length of 128 bits.
Proof-of-concept implementation is written in C++.
```
> bin/randomx --help
Usage: bin/randomx [OPTIONS]
Supported options:
--help shows this message
--compiled use x86-64 JIT-compiled VM (default: interpreted VM)
--lightClient use 'light-client' mode (default: full dataset mode)
--softAes use software AES (default: x86 AES-NI)
--threads T use T threads (default: 1)
--nonces N run N nonces (default: 1000)
--genAsm generate x86 asm code for nonce N
```
Two RandomX virtual machines are implemented:
### Interpreted VM
The interpreted VM is the reference implementation, which aims for maximum portability.
The VM has been tested for correctness on the following platforms:
* Linux: x86-64, ARMv7 (32-bit), ARMv8 (64-bit)
* Windows: x86, x86-64
* MacOS: x86-64
The interpreted VM supports two modes: "full dataset" mode, which requires more than 4 GiB of virtual memory, and a "light-client" mode, which requires about 64 MiB of memory, but runs significantly slower because dataset blocks are created on the fly rather than simply fetched from memory.
Software AES implementation is available for CPUs which don't support [AES-NI](https://en.wikipedia.org/wiki/AES_instruction_set).
The following table lists the performance for Intel Core i5-3230M (Ivy Bridge) CPU using a single core on Windows 64-bit, compiled with Visual Studio 2017:
|mode|required memory|AES|initialization time [s]|performance [programs/s]|
A JIT compiler is available for x86-64 CPUs. This implementation shows the approximate performance that can be achieved using optimized mining software. The JIT compiler generates generic x86-64 code without any architecture-specific optimizations. Only "full dataset" mode is supported.
For optimal performance, an x86-64 CPU needs:
* 32 KiB of L1 instruction cache per thread
* 16 KiB of L1 data cache per thread
* 240 KiB of L2 cache (exclusive) per thread
The following table lists the performance of AMD Ryzen 7 1700 (clock fixed at 3350 MHz, 1.05 Vcore, dual channel DDR4 2400 MHz) on Linux 64-bit (compiled with GCC 5.4.0).
Power consumption was measured for the whole system using a wall socket wattmeter (±1W). Table lists difference over idle power consumption. [Prime95](https://en.wikipedia.org/wiki/Prime95#Use_for_stress_testing) (small/in-place FFT) and [Cryptonight V2](https://github.com/monero-project/monero/pull/4218) power consumption are listed for comparison.
||threads|initialization time [s]|performance [programs/s]|power [W]
\* [blake2b](https://en.wikipedia.org/wiki/BLAKE_%28hash_function%29#BLAKE2) is a cryptographic hash function, [t1ha2](https://github.com/leo-yuriev/t1ha) is a fast hashing function.
The above steps can be chained multiple times to prevent mining strategies that search for programs with particular properties (for example, without division).