My application creates many objects in memory based on file names (among other string data). I was hoping to optimize memory usage by keeping the path and file name separate, and then dividing the path between objects on the same path. I did not try to use the string pool or anything else, basically my objects are sorted, so if I have 10 objects with the same path, I want objects 2-10 to have their path “pointed” in the path of the object 1 (for example, object [2] = .Path of object [1] .Path);
I have a problem, but I do not believe that my objects actually share the link to the same line after I think I tell them (object [2] .Path = object [1]. Path assignment) .
When I perform an experiment with a string list and set all the values pointing to the first value in the list, I can see the “save memory” in action, but when I use objects, I absolutely do not see any changes, admittedly, I use the task manager (private working set) to view changes in memory usage.
Here is a contrived example, I hope this makes sense.
I have an object:
TfileObject=class(Tobject) FpathPart: string; FfilePart: string; end;
Now I create 1,000,000 object instances using a new line for each of them:
var x: integer; MyFilePath: string; fo: TfileObject; begin for x := 1 to 1000000 do begin // create a new string for every iteration of the loop MyFilePath:=ExtractFilePath(Application.ExeName); fo:=TfileObject.Create; fo.FpathPart:=MyFilePath; FobjectList.Add(fo); end; end;
Run this and the task manager says I'm using 68 MB of memory or something like that. (Note that if I allocated MyFilePath outside the loop, I will save memory due to one instance of the string, but this is a contrived example, and not really how it will happen in the application).
Now I want to "optimize" the use of my memory if all the objects have the same instance of the path string, since this is the same value:
var x: integer; start for x: = 1 for FobjectList.Count-1 do start TfileObject (FobjectList [x]) FpathPart: .. = TfileObject (FobjectList [0]) FpathPart; end; end;
Task Manager shows absurdly no changes.
However, if I do something like this with a TstringList:
var x: integer; begin for x := 1 to 1000000 do begin FstringList.Add(ExtractFilePath(Application.ExeName)); end; end;
Task Manager talks about 60 MB memory usage.
Now optimize with:
var x: integer; begin for x := 1 to FstringList.Count - 1 do FstringList[x]:=FstringList[0]; end;
Task Manager shows the reduction in memory usage that I expect is now 10 MB.
So, I seem to be able to use strings in a list of strings, but not in objects. I obviously missed something conceptually, in code or both!
I hope this makes sense, I really can see the ability to save memory using this technique, since I have many objects with lots of string data, the data is sorted differently, and I would like to be able to iterate over this data after loading it into memory and free some of this memory back, dividing the lines this way.
Thanks in advance for any help you can offer.
PS: I use Delphi 2007, but I just tested on Delphi 2010, and the results are the same, except that Delphi 2010 uses twice as much memory due to unicode strings ...