If the memory you are simulating can fit into the ram of the workstation then using a fixed-size storage is the easiest to use. But as you have seen, signals are much more expensive compared to variables. This difference is related to the discrete event simulation model that VHDL is based on. A signal assignment schedules a transaction at a given point in time, but a variable assignment is strictly a sequential statement that execute in zero simulation time. The difference can be seen in the memory usage of the two different models. The results are obtained by running the example code below in Riviera PRO.
Memory allocation when using a signal for data storage:
Allocation: Simulator allocated 891567 kB (elbread=1023 elab2=890389 kernel=154 sdf=0)
Memory allocation when using a variable for data storage:
Allocation: Simulator allocated 39599 kB (elbread=1023 elab2=38421 kernel=154 sdf=0)
Example code
library ieee;
use ieee.std_logic_1164.all;
use std.env;
entity memtest is
end;
architecture sim of memtest is
signal clk : std_logic := '0';
signal we : std_logic;
signal writedata, q : integer;
signal addr : natural;
-- Uncomment or comment to switch between variable or signal for memory storage.
--signal mem : integer_vector(0 to 2 * 2048**2-1);
begin
clk <= not clk after 10 ns;
-----------------------------------
stimulus :
-----------------------------------
process
begin
for n in 0 to 100 loop
wait until falling_edge(clk);
we <= '1' ;
writedata <= n;
addr <= n;
end loop;
env.stop;
end process;
-----------------------------------
memory :
-----------------------------------
process ( clk )
-- Uncomment or comment to switch between variable or signal for memory storage.
variable mem : integer_vector(0 to 2 * 2048**2-1);
begin
if rising_edge(clk) then
q <= mem(addr);
if we = '1' then
-- Remember to modify assignment operator when switching data storage.
mem(addr) := writedata;
end if;
end if;
end process;
end;