Marsil 4 Posted November 29, 2023 (edited) Hello, Any differences between declaring an inline variable inside a loop and declaring it before the loop? I know that declaring an inline variable inside a loop limits its scope which is a good thing, but any difference in term of performance, memory allocation, extra work,...especially in big loops, or anything I don't know about? Many thanks! Outside loop var FileRec : TSearchRec; while not StopSearch do begin ... GetData (FileRec); UseData; ... end; Inside loop while not StopSearch do begin ... var FileRec : TSearchRec; GetData (FileRec); UseData; ... end; Edited November 29, 2023 by Marsil Share this post Link to post
Marsil 4 Posted November 29, 2023 Thanks for the quick reply! I used to declare inline variables of simple types inside the loop, but this time it's a record of type TSearchRec, and I wondered if that was going to degrade performance. I guess that goes for other structured types too. Share this post Link to post
Stano 143 Posted November 29, 2023 It doesn't matter what type of variable. The reason for this is the unnecessary repeated creation of the variable. We know that we only need to create it once. 1 Share this post Link to post
Marsil 4 Posted November 29, 2023 Thanks again, so a rule of thumb is never to declare inline variables inside a loop Share this post Link to post
EugeneK 19 Posted November 29, 2023 I always declare it inside the loop if it is not used outside. Declaring it outside may lead to hard to find bugs. 1 1 Share this post Link to post
Marsil 4 Posted November 29, 2023 Just now, EugeneK said: I always declare it inside the loop if it is not used outside. Declaring it outside may lead to hard to find bugs. That was one of my thoughts too!, Limiting scope is good, but we cannot get all good things at once can we? Share this post Link to post
FPiette 383 Posted November 29, 2023 You may either measure the time for both way of doing it, of look at the assembly code generated. 4 Share this post Link to post
Marsil 4 Posted November 29, 2023 1 hour ago, FPiette said: You may either measure the time for both way of doing it, of look at the assembly code generated. Yes I'm planning to do that but I thought I may get more useful insights by asking first. What I know now is that an inline variable is allocated at the point of declaration, not at the start of the block where it is declared. If I am not mistaken. Share this post Link to post
Marsil 4 Posted November 29, 2023 (edited) Just ran a quick test (I'm not sure if it is a very good test) : // Before loop var FileRec : TSearchRec; var Stopwatch := TStopwatch.StartNew; for var i := 1 to 100000000 do begin FileRec.Name := 'Test'; end; Log (Stopwatch.ElapsedMilliseconds); // logs 205 // Inside loop var Stopwatch := TStopwatch.StartNew; for var i := 1 to 100000000 do begin var FileRec : TSearchRec; FileRec.Name := 'Test'; end; Log (Stopwatch.ElapsedMilliseconds); // logs 3129 (more than 15x) But when changing the inline variable type to Integer declare before loop timings: 161 161 161 161 161 declare Inside loop timings: 161 160 160 161 160 Increasing loop to 100 million times: before 1624 inside 1617 for a loop of millions times this is really negligible difference, nothing at all. So declaring simple types inside a loop may be the better choice after all?? Edited November 29, 2023 by Marsil 2 Share this post Link to post
Marsil 4 Posted November 29, 2023 (edited) Running a more realistic loop count of 100,000 times: TSearchRec var declared before loop : 0 ms inside loop: 3 ms 3 ms difference each 100,000 loop is a very small price to pay in exchange of encapsulation earned by limiting scope?? what do you think? Edited November 29, 2023 by Marsil Share this post Link to post
Anders Melander 1783 Posted November 29, 2023 6 hours ago, Stano said: Always before the loop. Beware of unqualified statements involving always and never. Unless the advice is to never put pineapple on pizza. That one is just a fundamental law of nature. 6 hours ago, Marsil said: Any differences between declaring an inline variable inside a loop and declaring it before the loop? As you've discovered it depends on the type of the variable. Local variables are declared on the stack and such doesn't involve the heap (i.e. the memory manager). Allocating a variable on the stack is basically free of cost. However, managed types need initialization and that initialization can be costly. TSearchRec contains a string and is therefore a managed type (i.e. slow). Integer is not a managed type (i.e. fast). Additionally, managed types are wrapped in an implicit try..finally block to ensure that they're also finalized. The help probably has more info on this. If you want to limit the scope just put a begin...end around the whole thing: begin var FileRec : TSearchRec; while not StopSearch do begin ... GetData (FileRec); UseData; ... end; end; Apart from that, in this particular case, you are touching the file system so the performance of inside vs outside will be dwarfed by that. 4 hours ago, Marsil said: Yes I'm planning to do that but I thought I may get more useful insights by asking first. ...and so the lesson here is: You don't get more useful insight by asking first. 5 Share this post Link to post
Marsil 4 Posted November 30, 2023 1 hour ago, Anders Melander said: If you want to limit the scope just put a begin...end around the whole thing I put a like for this hint! 2 hours ago, Anders Melander said: ...and so the lesson here is: You don't get more useful insight by asking first. On the contrary I did get some useful information from this question and probably more coming Share this post Link to post
Stano 143 Posted November 30, 2023 9 hours ago, Anders Melander said: 16 hours ago, Stano said: Always before the loop. Beware of unqualified statements involving always and never. Unless the advice is to never put pineapple on pizza. That one is just a fundamental law of nature. I agree. I'll keep an eye on it. I really am a layman. I was basing it on the PAL help. I have no other knowledge of it. Share this post Link to post
A.M. Hoornweg 144 Posted December 5, 2023 On 11/29/2023 at 4:55 PM, Marsil said: while not StopSearch do begin ... var FileRec : TSearchRec; GetData (FileRec); UseData; ... end; tSearchrec is a record that contains a managed type (the file name is a string). When managed types go out of scope, the code generated by the compiler checks if they are no longer in use and that any heap memory they occupy is freed properly. That costs time. On 11/29/2023 at 4:55 PM, Marsil said: Share this post Link to post
David Heffernan 2345 Posted December 5, 2023 Nobody seems yet to have wondered whether the potential for behaviour change is important. This is an ill posed question with no possible answer because we don't know any detail. So much heat, so little light. Share this post Link to post