Re: [fpc-pascal] If vs case or something else?

2017-07-07 Thread James Richters
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?

2017-07-06 Thread Stefan V. Pantazi
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?

2017-07-06 Thread Ched

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?

2017-07-06 Thread Stefan V. Pantazi
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?

2017-07-06 Thread Sven Barth via fpc-pascal
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?

2017-07-06 Thread James Richters
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