How can I quickly clear a record of simple types?
Asked Answered
H

5

31

I have a structure defined like this:

const
  MaxSignalRecords=255;
type
  TSignalRecord=record
   signal1  : integer;
   signal2  : integer;
   signal3  : integer;
   signal4  : integer;
   signal5  : integer;
   signal6  : integer;
   bsignal1 : Boolean;
   bsignal2 : Boolean;
   bsignal3 : Boolean;
   bsignal4 : Boolean;
   bsignal5 : Boolean;
   bsignal6 : Boolean;
  end;

TListSignals = Array[0..MaxSignalRecords-1] of TSignalRecord;

This structure is used to make thousands of calculations in an algorithm like this:

for i:=1 to 900000 do
begin
  CleartheList(MyList);
  DotheMath(MyList);
  DotheChart(MyList);
end;

I am looking for a fast way to initializate the values of my TListSignals to 0 and false.

Now I am using this :

procedure ClearListSignals(var ListSignals:TListSignals);
var
  i :Integer;
begin
  for i := 0 to MaxSignalRecords - 1 do
  with ListSignals[i] do
  begin
   signal1   :=0;
   signal2   :=0;
   signal3   :=0;
   signal4   :=0;
   signal5   :=0;
   signal6   :=0;
   bsignal1  :=false;
   bsignal2  :=false;
   bsignal3  :=false;
   bsignal4  :=false;
   bsignal5  :=false;
   bsignal6  :=false;
  end;
end;

How can I improve the performance of the ClearListSignals procedure?

Honshu answered 1/4, 2011 at 5:10 Comment(3)
see: #11066321Minded
see: #46764364Minded
see: #14176698Minded
S
32

you can use the ZeroMemory procedure located in the Windows unit.

var
  MyList : TListSignals;
begin
     ZeroMemory(@Mylist,SizeOf(MyList));
end;
Spooner answered 1/4, 2011 at 5:12 Comment(7)
So if I was to read the value of any ListSignals[i].signal1 this would equal 0? Nice way to avoid the initial assignments.Carmacarmack
@Altar the question and answer is only for a record of simple types.Spooner
i suppose answer from ZENsan is more correct. need to use Default and no hack with direct memory accessLakendra
@SolarWind, if the record contains strings have values, ZeroMemory will cause a memory leak. You can call Finalize() on the record first to deallocate the strings before calling ZeroMemory.Nigro
@dan-gph-Salvador shows no strings in his record so zeromemory works in this case.Minded
It would be nice if your answer will mention the "ugly" face of ZeroMemory :)Minded
Related: #14176698Minded
I
30

You should use the standard Delphi language function Default()!

const
  MaxSignalRecords = 255;

type
  TSignalRecord = record
    ...
    bsignal6 : Boolean;
  end;

var
  X: TSignalRecord
...
X := Default(TSignalRecord);
...

And no hack.. as suggested before..

Inelegancy answered 4/11, 2015 at 10:11 Comment(3)
Default() was introduced in Delphi 2009.Confocal
That seems to be the most elegant way. I think that if you have a constructor for a record it should zero the memory for you anyway, so that records work more like classes.Ping
Related: #14176698Minded
H
17
FillChar(ListSignals, SizeOf(ListSignals), 0);
Haemophilic answered 1/4, 2011 at 5:13 Comment(4)
ZeroMemory is just a wrapper around FillChar(,,0).Phenolic
ZeroMemory is an inline that uses FullChar, but ZeroMemory reads a lot betterBarbosa
FillChar is defined in System which makes it platform independant, ZeroMemory only works on Windows.Solan
FillChar works also with Laazarus and Free Pascal and on Mac OS X.Bateau
G
10

In addition to what was said about FillChar and ZeroMemory (which internally just calls FillChar anyway), you can reduce the size of your record by using bsignal: set of 1..6; instead of individual booleans which should speed up the clearing slightly.

Guerra answered 1/4, 2011 at 5:26 Comment(6)
+1 since it's a good idea. booleans will be aligned on 4 or 8 bytes boundaries, so it's like an awful waste of space, therefore speed in this case.Phenolic
Really, @A.Bouchez? I thought Booleans were aligned on 1-byte boundaries. Are you saying the total size of the record in the question is 48 instead of 30?Mastitis
Booleans will be aligned based on the compiler alignment switch, unless the record is packed. Also, RAM is pretty cheap these days so I would not worry too much about wasted space.Haemophilic
@Rob: You're right: use sizeof(TSignalRecord) and you'll get... 32, i.e. there will be 1-byte aligned. And the whole record size is then with packed record, you'll get sizeof(TSignalRecord)=30. With set of 1..6 you'll have sizeof(TSignalRecord)=28.Phenolic
The issue with wasted space is not the monetary cost of RAM but the speed implications that come with poor use of the cache. But it's not so relevant here because Boolean has an alignment of 1.Barbosa
Efficient cache use becomes very important now a days. The difference in latency between a L1 cache hit and going to main memory is by now in the same order of magnitude as the difference between main memory and having to go to disk.Guerra
C
4

You can use SecureZeroMemory

To avoid undesired effects of optimizing compilers, use the SecureZeroMemory function.

The SecureZeroMemory function fills a block of memory with zeros. It is designed to be a more secure version of ZeroMemory.

Use this function instead of ZeroMemory when you want to ensure that your data will be overwritten promptly, as the compiler can optimize a call to ZeroMemory by removing it entirely.

http://msdn.microsoft.com/en-us/library/aa366877%28v=vs.85%29.aspx

LE: here you have how to use it in Delphi if your version does not contain it:

Using SecureZeroMemory in Delphi

Cystolith answered 1/4, 2011 at 11:15 Comment(2)
SecureZeroMemory as its name implies, is a security feature. It's not intended for general purpose use. Optimising compilers only remove the call to ZeroMemory if it detects that the memory is not reused later - implying there's no point in clearing it. However, it's possible that the memory could contain a password, but is not reused later. Then you still want to ensure the password is cleared from memory lest it appear in memory dumps, or be accessible by a hacking attack. In OP's case, there is absolutely no need to use SecureZeroMemory. Though it is useful to be aware of the function.Unfolded
the question and answer is only for a record of simple typesCystolith

© 2022 - 2024 — McMap. All rights reserved.