Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strings and high memory usage

Tags:

delphi

When I run this code in XE4, the application ends up using ~800 MB.

Why not closer to 100 MB ?

Using Ansistring instead of string makes no difference.

const
  N = 10000000; // 10 million
  M = 10;
var
  i,j: integer;
  s: string;
  X: array of string;
begin
  setlength(X,N);
  for i:= 1 to N do
  begin
    s:= '';
    for j:= 1 to M do s:= s+chr(65+random(25));
    X[i-1]:= s;
  end;
  showmessage('pause');
end;
like image 277
Uffe Kousgaard Avatar asked Jan 23 '14 14:01

Uffe Kousgaard


People also ask

How much memory do strings take up?

An empty String takes 40 bytes—enough memory to fit 20 Java characters.

Do strings take more memory than integers?

strings take up more memory, but the memory size is tiny... an integer takes up about 4 bytes for its actual data (some extra for memory pointers depending on how you store it, but string will have that same extra memory as well). A string takes up about a byte per letter (with a minimum of course as .

How do strings work in memory?

Strings are stored on the heap area in a separate memory location known as String Constant pool. String constant pool: It is a separate block of memory where all the String variables are held. String str1 = "Hello"; directly, then JVM creates a String object with the given value in a String constant pool.

Does list take more memory than string?

String[] and List<String> both taking same space in memory to store data. String[] - you need to have all information how much elements get stored in your memory, and it should be not minimum or not maximum space then required space.


2 Answers

A string of length 10 in XE4 uses 34 Bytes of memory (see DocWiki). 20 Bytes for the content, 2 Bytes for the #0 terminator and 12 bytes management data.

Each array entry is a pointer to that kind of memory. Thus those 10 million strings in the array end up using 380 MB (340 for the strings and 40 for the array items) of memory at minimum.

like image 184
Uwe Raabe Avatar answered Sep 27 '22 19:09

Uwe Raabe


Try this

const MaxString = 15; // you said so

type stringholder = record
  strict private 
     var Cell: string[ MaxString * SizeOf(Char) div SizeOf(AnsiChar) ];
     function GetUS: String; // in xe 4 that is a shortcut to UnicodeString actual type
     procedure SetUS(const US: string); 
  public
     property Value: string read GetUS write SetUS;
     class operator Implicit(const from: string): stringholder; inline;
     class operator Implicit(const from: stringholder): string; inline;
  end;

function stringholder.GetUS: String;
var i: integer;
begin
  i := Ord( Cell[0] );
  SetLength( Result, i div (SizeOf(Char) div SizeOf(AnsiChar)) );
  if i > 0 then
     Move( Cell[1], Result[1], i);
end;

procedure SetUS(const US: string);
var i: integer;
begin
  If US = '' then begin
     Cell := ''; // constant here, not US itself
     Exit;
  End;

  i := Length(US);
  If i > MaxString then raise EInvalidCast.Create('.....'+US);

  i := i * SizeOf(Char) div SizeOf(AnsiChar)
  Move( US[1], Cell[1], i );
  Cell(. 0 .) := AnsiChar(i);
end;

class operator stringholder.Implicit(const from: string): stringholder;
begin
  Result.Value := from;
end;

class operator stringholder.Implicit(const from: stringholder): string;
begin
  Result := from.Value;
end;


const
  N = 10000000; // 10 million
  M = 10;
var
  i,j: integer;
  s: string;
  X: array of stringholder;
begin
  setlength(X,N);
  for i:= 1 to N do
  begin
    s:= '';
    for j:= 1 to M do s:= s+chr(65+random(25));
    X(. i-1 .) := s;
  end;
  showmessage('pause');
end;
like image 39
Arioch 'The Avatar answered Sep 27 '22 20:09

Arioch 'The