Re: [fpc-pascal] If vs case or something else?
Thank you Sven and Stefan for the advice and examples, I really appreciate it. I'll to some time tests with some sample programs and figure out which way to go with it. It seems at first glance that the array of procedures would be more complicated, but the more I think about it, the more I think it would actually be easier to manage and easier to follow than the insane list of if, then, else statements, and also easier to manage than a huge long case statement, I do have several other conditional statements within the big long if then else structure and sometime I mess up the entire thing by misplacing an end, or leaving one out... this would never be a problem with the array of procedures as the conditional statements inside the procedures would be well defined as they would not be mixed in with a huge list of if statements, and I might be able to combine many of the procedures and just pass them related arguments. It might also help organization with Units. Also thanks to Ched for the idea using a case statement on just the first character in a string then smaller case statements within that. I do have another situation where I needed to use string input and figure out what to do based on the string value and it seems this would save a lot of time. James ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] If vs case or something else?
I am not sure I follow. If switching on strings, or any sparse value set, you can use the balanced tree approach or better yet, a hash table. But when switching on a compact, limited set of integer values (as the case seems to be), I do not see how you can compete with constant time procedure table/array lookups. Stefan You can skip large blocks of tests coding like this Not as fast as a tree search balanced with probabilities (no answer to my question on the list afew days ago...), but probably ten time faster then what you proposed. Cheers, Ched' Le 06.07.2017 à 20:41, Stefan V. Pantazi a écrit : That is quite the case statement you have there. You may benefit greatly from re-analyzing and refactoring your programs by splitting them in multiple individual units, if possible. That should be perfectly possible if Dosomething();DoSomethingelse(); keep repeating across your 70+ switch cases. Anyway, here you go, you can try something like the attached. Good luck! Stefan On 07/06/2017 12:33 PM, James Richters wrote: I'm trying to optimize a console application ported over from Turbo Pascal with a huge set of if then else statements like this: Var TXT : String; If TXT = 'Thing1' then Begin Dosomething(); DoSomethingelse(); End else If TXT = 'AnotherThing' then Begin Dosomethinganotherway(); DoSomethingelsetoo(); End Else If TXT = 'Thing3' then Begin Dosomethingathirdtime(); DoSomethingelse3(); End else etc.. over 70 times... etc It works but it's hard to follow and not so fast. It has to run through this for every line of a file to see what's in the file and do the right things with it. So I'm thinking of undertaking a huge re-organization of it and I'm wondering what the best way would be to do it. I can use case statement with strings apparently now, but the thing is, I create this file myself in an earlier stage, so I do not need to create the file with strings at all, I could use some codes and do something like this: Const Thing1 = 1 Another_Thing = 2 Thing3 = 3 Var Codenum: Word; Case Codenum of Thing1: Begin DoSomethng() DoSomethingElse() End; Another_Thing: Begin ... etc ... I'm guessing that would be faster as I wouldn't have to keep evaluating all the strings for every condition. As I was searching for the best way to do this, I came across something about making an Array of Procedures, or something to that effect. Does anyone know how to do that, and are there performance advantages to doing that? It's going to take a bit of work to straighten all this out so it would be best if I just did it the best way instead of doing it one way then finding out it could have been better another way. Any other ideas on how to handle this? Any advice on this is greatly appreciated James ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] If vs case or something else?
Hi Stefan, You can skip large blocks of tests coding like this If Length(txt)>0 then case txt[1] of 'a': if txt='another' then ... else if txt='anum' then ...; 'b': if txt="bubble' then ... else if ... else ... end; Not as fast as a tree search balanced with probabilities (no answer to my question on the list afew days ago...), but probably ten time faster then what you proposed. Cheers, Ched' Le 06.07.2017 à 20:41, Stefan V. Pantazi a écrit : That is quite the case statement you have there. You may benefit greatly from re-analyzing and refactoring your programs by splitting them in multiple individual units, if possible. That should be perfectly possible if Dosomething();DoSomethingelse(); keep repeating across your 70+ switch cases. Anyway, here you go, you can try something like the attached. Good luck! Stefan On 07/06/2017 12:33 PM, James Richters wrote: I'm trying to optimize a console application ported over from Turbo Pascal with a huge set of if then else statements like this: Var TXT : String; If TXT = 'Thing1' then Begin Dosomething(); DoSomethingelse(); End else If TXT = 'AnotherThing' then Begin Dosomethinganotherway(); DoSomethingelsetoo(); End Else If TXT = 'Thing3' then Begin Dosomethingathirdtime(); DoSomethingelse3(); End else etc.. over 70 times... etc It works but it's hard to follow and not so fast. It has to run through this for every line of a file to see what's in the file and do the right things with it. So I'm thinking of undertaking a huge re-organization of it and I'm wondering what the best way would be to do it. I can use case statement with strings apparently now, but the thing is, I create this file myself in an earlier stage, so I do not need to create the file with strings at all, I could use some codes and do something like this: Const Thing1 = 1 Another_Thing = 2 Thing3 = 3 Var Codenum: Word; Case Codenum of Thing1: Begin DoSomethng() DoSomethingElse() End; Another_Thing: Begin ... etc ... I'm guessing that would be faster as I wouldn't have to keep evaluating all the strings for every condition. As I was searching for the best way to do this, I came across something about making an Array of Procedures, or something to that effect. Does anyone know how to do that, and are there performance advantages to doing that? It's going to take a bit of work to straighten all this out so it would be best if I just did it the best way instead of doing it one way then finding out it could have been better another way. Any other ideas on how to handle this? Any advice on this is greatly appreciated James ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] If vs case or something else?
That is quite the case statement you have there. You may benefit greatly from re-analyzing and refactoring your programs by splitting them in multiple individual units, if possible. That should be perfectly possible if Dosomething(); DoSomethingelse(); keep repeating across your 70+ switch cases. Anyway, here you go, you can try something like the attached. Good luck! Stefan On 07/06/2017 12:33 PM, James Richters wrote: I'm trying to optimize a console application ported over from Turbo Pascal with a huge set of if then else statements like this: Var TXT : String; If TXT = 'Thing1' then Begin Dosomething(); DoSomethingelse(); End else If TXT = 'AnotherThing' then Begin Dosomethinganotherway(); DoSomethingelsetoo(); End Else If TXT = 'Thing3' then Begin Dosomethingathirdtime(); DoSomethingelse3(); End else etc.. over 70 times... etc It works but it's hard to follow and not so fast. It has to run through this for every line of a file to see what's in the file and do the right things with it. So I'm thinking of undertaking a huge re-organization of it and I'm wondering what the best way would be to do it. I can use case statement with strings apparently now, but the thing is, I create this file myself in an earlier stage, so I do not need to create the file with strings at all, I could use some codes and do something like this: Const Thing1 = 1 Another_Thing = 2 Thing3 = 3 Var Codenum: Word; Case Codenum of Thing1: Begin DoSomethng() DoSomethingElse() End; Another_Thing: Begin ... etc ... I'm guessing that would be faster as I wouldn't have to keep evaluating all the strings for every condition. As I was searching for the best way to do this, I came across something about making an Array of Procedures, or something to that effect. Does anyone know how to do that, and are there performance advantages to doing that? It's going to take a bit of work to straighten all this out so it would be best if I just did it the best way instead of doing it one way then finding out it could have been better another way. Any other ideas on how to handle this? Any advice on this is greatly appreciated James ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ program fast_switch; uses sysutils, fast_switch_handler_unit;//implements case handlers const TEST_COUNT=100; function GetCodeNum():word; begin Result:=Random(MAX_HANDLER_IDX); end; var i:Integer; Codenum: Word; //or enum begin Randomize; for i:=0 to TEST_COUNT-1 do begin WriteLn('Test switching #',i); repeat codeNum:=GetCodeNum(); //execute procedure with index codeNum from PROC_TABLE if (Codenum>0) and (Codenum<=MAX_HANDLER_IDX) then PROC_TABLE[CodeNum]; Sleep(50); until codeNum=0; WriteLn('Done switching test #',i); end; WriteLn('Done switching test program.'); end. unit fast_switch_dosomething_unit; {$mode objfpc}{$H+} interface uses Classes, SysUtils; procedure Dosomething(); procedure DoSomethingelse(); procedure Dosomethinganotherway(); procedure DoSomethingelsetoo(); procedure Dosomethingathirdtime(); procedure DoSomethingelse3(); implementation procedure Dosomething(); begin WriteLn('Dosomething()'); end; procedure DoSomethingelse(); begin WriteLn('DoSomethingelse()'); end; procedure Dosomethinganotherway(); begin WriteLn('Dosomethinganotherway()'); end; procedure DoSomethingelsetoo(); begin WriteLn('DoSomethingelsetoo()'); end; procedure Dosomethingathirdtime(); begin WriteLn('Dosomethingathirdtime()'); end; procedure DoSomethingelse3(); begin WriteLn('DoSomethingelse3()'); end; end. unit fast_switch_handler_unit; {$mode objfpc}{$H+} interface uses fast_switch_dosomething_unit;//implements DoSomething* const MAX_HANDLER_IDX=3;// or 70 procedure Thing1_Handler(); procedure AnotherThing_Handler(); procedure Thing3_Handler(); const PROC_TABLE:array[1..MAX_HANDLER_IDX] of procedure=( @Thing1_Handler, @AnotherThing_Handler, @Thing3_Handler // ... //@Thing70_Handler ); implementation procedure Thing1_Handler(); Begin Dosomething(); DoSomethingelse(); End; procedure AnotherThing_Handler(); Begin Dosomethinganotherway(); DoSomethingelsetoo(); End; procedure Thing3_Handler(); Begin Dosomethingathirdtime(); DoSomethingelse3(); End; end. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] If vs case or something else?
On 06.07.2017 18:33, James Richters wrote: > I can use case statement with strings apparently now, but the thing is, I > create this file myself in an earlier stage, so I do not need to create the > file with strings at all, I could use some codes and do something like this: "case of String" is essentially the same as your chain of if-statements, the compiler doesn't do any real optimization there. > Const >Thing1 = 1 > Another_Thing = 2 > Thing3 = 3 > Var > Codenum: Word; > > Case Codenum of >Thing1: Begin > DoSomethng() > DoSomethingElse() >End; > Another_Thing: Begin > ... etc ... > > > I'm guessing that would be faster as I wouldn't have to keep evaluating all > the strings for every condition. As I was searching for the best way to do > this, I came across something about making an Array of Procedures, or > something to that effect. Does anyone know how to do that, and are there > performance advantages to doing that? It's going to take a bit of work to > straighten all this out so it would be best if I just did it the best way > instead of doing it one way then finding out it could have been better > another way. Any other ideas on how to handle this? > > Any advice on this is greatly appreciated If you aren't fixed on having to work on a string that would definitely be best as you could then use a enum or something like that and you a case statement. The compiler will try to pick a suitable implementation then (jumptable, linear search), depending on the amount of labels. Alternatively you can indeed use an array of procedures like this: === code begin === program tprocarray; procedure Proc1; begin Writeln('Proc1'); end; procedure Proc2; begin Writeln('Proc2'); end; const Procs: array[0..1] of TProcedure = ( @Proc1, @Proc2 ); var proc: Longint; begin proc := 1; Procs[proc](); end. === code end === Of course you can also use an enum as the array index: === code begin === {$scopedenums on} // just for demonstrations type TProcs = ( One, Two ); const Procs: array[TProcs] of TProcedure = ( @Proc1, @Proc2 ); var proc: TProcs; begin proc := TProcs.Two; Procs[proc](); end. === code end === The variant with the enum has the advantage that the compiler will complain about missing elements if you add one to the enum type. Though in both cases you should ensure that your index is in range. In case of many branches the variant with the array (any of the two variants) should be faster than the case one. Regards, Sven ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
[fpc-pascal] If vs case or something else?
I'm trying to optimize a console application ported over from Turbo Pascal with a huge set of if then else statements like this: Var TXT : String; If TXT = 'Thing1' then Begin Dosomething(); DoSomethingelse(); End else If TXT = 'AnotherThing' then Begin Dosomethinganotherway(); DoSomethingelsetoo(); End Else If TXT = 'Thing3' then Begin Dosomethingathirdtime(); DoSomethingelse3(); End else etc.. over 70 times... etc It works but it's hard to follow and not so fast. It has to run through this for every line of a file to see what's in the file and do the right things with it. So I'm thinking of undertaking a huge re-organization of it and I'm wondering what the best way would be to do it. I can use case statement with strings apparently now, but the thing is, I create this file myself in an earlier stage, so I do not need to create the file with strings at all, I could use some codes and do something like this: Const Thing1 = 1 Another_Thing = 2 Thing3 = 3 Var Codenum: Word; Case Codenum of Thing1: Begin DoSomethng() DoSomethingElse() End; Another_Thing: Begin ... etc ... I'm guessing that would be faster as I wouldn't have to keep evaluating all the strings for every condition. As I was searching for the best way to do this, I came across something about making an Array of Procedures, or something to that effect. Does anyone know how to do that, and are there performance advantages to doing that? It's going to take a bit of work to straighten all this out so it would be best if I just did it the best way instead of doing it one way then finding out it could have been better another way. Any other ideas on how to handle this? Any advice on this is greatly appreciated James ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal