Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2011-01

Status report for "class helpers"

51 messages · 10 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Sven Barth

Hello together!

I've decided to provide a little status report on the "class helper" feature that I'm currently implementing.

I found the time to put up a first version of a wiki page: http://wiki.freepascal.org/Class_helpers

Does someone know a good place to link this page from? Maybe something where other language/compiler features are referenced from or can be linked to in the future.

And yes, I plan to extend the "Code examples" list further. :D

Now what is my current status?
* class helper syntax is supported (including inheritance - which is a pseudo inheritance internally)
* calling methods that are provided by a class helper works
* only the last available class helper is used (regarding the search algorithm see below)
* enumerators provided by class helpers are used
* overloading methods of the extended class with the ones provided by the class helper does NOT work currently (I need to investigate how "overload" works at all ^^)
* in mode Delphi "override" and "virtual" are ignored (they are disallowed for mode ObjFPC), but as I remove their corresponding flags I might have a problem with the following example that compiles in newer Delphis (at least Delphi 2007 does not compile this, because of an incorrect implementation in the compiler):

==== source begin ====
type
   THelper1 = class helper for TObject
     procedure Foo; virtual;
   end;
   THelper2 = class helper(THelper1) for TObject
     procedure Foo; override;
   end;
==== source end ====

* I have experienced one time that Delphi chokes on properties. I'll need to investigate that further (one can define them, but Delphi does not seem to find them)
* I have yet to test whether the restriction "Create must be first statement in constructors" holds true (I've found a code sample that suggests its not true)
* I have yet to read about "class constructors" and whether they can be used (and how)

This basically sums up my status.

Regarding the algorithm I use to find the last available class helper (this is implemented in
compiler/symtable.pas/search_last_objectpascal_classhelper): Delphi uses the last class helper that is available in the current scope for method resolution (and the "parents" of that class helper). For this I walk the symtable stack and search for a def where is_objectpascal_classhelper returns "true". This can potentially lead to a bad runtime behavior if a project does not use any class helpers, but includes many units (the compiler is a good example of that). Do you (especially @Devs) think that this is a sufficient approach or should this be done another way? (Note: I have not yet profiled compiling the compiler once with that search enabled and once without)

Perhaps searching for class helpers should be made dependent on a modeswitch? E.g. "useclasshelpers"
That might lead to the potentially confusing behavior that a class helper is not even found in its own unit though, although I think that this would be a consequent behavior (the switch needs to be documented good enough though ^^).
This switch could be enabled by default in mode Delphi.

Also as Delphi searches a class helper based on the last available class helper instead of the last available method as Objective C categories do, I think that I don't need to generate that static symbols (done by create_class_helper_for_procdef in symdef.pas). Any objections for disabling that for Object Pascal class helpers again?

Two other questions regarding compiler internals:
Do I need to consider something regarding WPO? Or is all that done automatically by the compiler already (e.g. by me referencing the symbol of a class helper method)?

What is the difference between the "Message*" and "CGMessage*" procedures? Or asked differently: when should I use which?

Regards,
Sven

Reply by email

Florian Klaempfl
to Sven Barth
Sven Barth wrote
Do you (especially @Devs) think that this is a sufficient approach or should this be done another way? (Note: I have not yet profiled compiling the compiler once with that search enabled and once without)

Profile compiler compilation first, then we can decide what to do.

Show quoted text 7 lines
Perhaps searching for class helpers should be made dependent on a modeswitch? E.g. "useclasshelpers" That might lead to the potentially confusing behavior that a class helper is not even found in its own unit though, although I think that this would be a consequent behavior (the switch needs to be documented good enough though ^^).

I think this is too dangerous.

What is the difference between the "Message*" and "CGMessage*" procedures? Or asked differently: when should I use which?

During code generation, use CGMessage*

Reply by email

Sven Barth
to Florian Klaempfl
Florian Klaempfl wrote 7 lines
Am 29.01.2011 13:25, schrieb Sven Barth: > Do you (especially @Devs) think that this is a sufficient approach or > should this be done another way? (Note: I have not yet profiled > compiling the compiler once with that search enabled and once without) Profile compiler compilation first, then we can decide what to do.

Done. Differences are dramatic (at least on my Linux PC)

Used command:
time make cycle > /dev/null

Both variants use Revision 16834 of my branch, but variant two has the following change:

==== patch begin ====
Index: /mnt/media/subversion/fpc-classhelpers/compiler/symtable.pas =================================================================== --- /mnt/media/subversion/fpc-classhelpers/compiler/symtable.pas (Revision 16835)
+++ /mnt/media/subversion/fpc-classhelpers/compiler/symtable.pas (Arbeitskopie)
@@ -2138,12 +2138,12 @@

        begin
          { search for a class helper method first if this is an Object

Pascal
class }
- if is_class(classh) then
+ {if is_class(classh) then

            begin
result:=search_objectpascal_class_helper(classh,contextclassh,s,srsym,srsymtable);
              if result then
                exit;
-          end;
+          end;}
          orgclass:=classh;
          { in case this is a formal objcclass, first find the real

definition }
==== patch end ====

Results Variant 1:

Run 1:
real 5m18.444s
user 3m57.075s
sys 0m4.806s

Run 2:
real 5m5.727s
user 3m53.811s
sys 0m4.426s

Run 3:
real 5m5.094s
user 3m54.475s
sys 0m4.676s

Results Variant 2:

Run 1:
real 1m7.982s
user 0m46.024s
sys 0m4.390s

Run 2:
real 1m8.619s
user 0m46.104s
sys 0m4.513s

Run 3:
real 1m10.078s
user 0m46.290s
sys 0m4.333s

It seems rather obvious that my search algorithm isn't a good idea ^^

Show quoted text 10 lines
> > Perhaps searching for class helpers should be made dependent on a > modeswitch? E.g. "useclasshelpers" > That might lead to the potentially confusing behavior that a class > helper is not even found in its own unit though, although I think that > this would be a consequent behavior (the switch needs to be documented > good enough though ^^). I think this is too dangerous.

Would you please explain why you think so?

Show quoted text 5 lines
> > What is the difference between the "Message*" and "CGMessage*" > procedures? Or asked differently: when should I use which? During code generation, use CGMessage*

I hope to notice when I'm in code generation then ^^

Regards,
Sven

Reply by email

Paul Ishenin
to Sven Barth: Hello together! I've decided to provide a little status report on the "class helper"…
Sven Barth wrote
Does someone know a good place to link this page from? Maybe something where other language/compiler features are referenced from or can be linked to in the future.

http://wiki.freepascal.org/delphi_language_features_which_fpc_does_not_have http://wiki.freepascal.org/FPC_New_Features_Trunk

* I have yet to test whether the restriction "Create must be first statement in constructors" holds true (I've found a code sample that suggests its not true)

"If a class helper has a constructor the first statement in that constructor must be a call to the parameterless constructor." I think this is a copy-paste from some delphi .net or c# help where "parameterless constructor" has some special meaning.

Show quoted text 12 lines
Regarding the algorithm I use to find the last available class helper (this is implemented in compiler/symtable.pas/search_last_objectpascal_classhelper): Delphi uses the last class helper that is available in the current scope for method resolution (and the "parents" of that class helper). For this I walk the symtable stack and search for a def where is_objectpascal_classhelper returns "true". This can potentially lead to a bad runtime behavior if a project does not use any class helpers, but includes many units (the compiler is a good example of that). Do you (especially @Devs) think that this is a sufficient approach or should this be done another way? (Note: I have not yet profiled compiling the compiler once with that search enabled and once without)

Maybe to speedup the search we can mark the symtable with a flag that if it contains a class helper? Other flags can come in future - like has type definitions - to speedup type searches.

Show quoted text 7 lines
Perhaps searching for class helpers should be made dependent on a modeswitch? E.g. "useclasshelpers" That might lead to the potentially confusing behavior that a class helper is not even found in its own unit though, although I think that this would be a consequent behavior (the switch needs to be documented good enough though ^^). This switch could be enabled by default in mode Delphi.

objfpc also allows final methods and sealed classes so it needs class helpers too. Better to allow them for all modes which support classes I think.

Don't forget about record helpers. And I also noticed that in delphi class helpers and record helpers are synonims so you can define a class helper for a record and a record helper for a class - I think FPC should be more restrictive here.

Best regards,
Paul Ishenin

Reply by email

Paul Ishenin
to Sven Barth: Done. Differences are dramatic (at least on my Linux PC) Used command: time make cycle >…
Sven Barth wrote
Done. Differences are dramatic (at least on my Linux PC)

Try to add a set of flags to the symtable class. Store/Load it from/to ppu. When you add a def into check it if it is a class helper and add a flag if so. In you search algorithm test the flag first before the scaning of symtable.

I also noticed that you check only unit symtables. I don't know what if you add a class helper into a record/class/object type section?

Best regards,
Paul Ishenin

Reply by email

Paul Ishenin
to Paul Ishenin
Paul Ishenin wrote
I also noticed that you check only unit symtables. I don't know what if you add a class helper into a record/class/object type section?

This code works in delphi:

program Project42;
{$APPTYPE CONSOLE}
type
   TFoo = class
     class procedure DoSomething; static;
   type
     TFooHelper = class helper for TFoo
       class procedure HelpSomehow; static;
     end;
   end;

{ TFoo.TFooHelper }

class procedure TFoo.TFooHelper.HelpSomehow;
begin
   WriteLn('In Help somehow');
end;

{ TFoo }

class procedure TFoo.DoSomething;
begin
   WriteLn('In DoSomething');
end;
begin
   TFoo.DoSomething;
   TFoo.HelpSomehow;
end.

Best regards,
Paul Ishenin

Reply by email

Sven Barth
to Paul Ishenin: http://wiki.freepascal.org/delphi_language_features_which_fpc_does_not_have…
Paul Ishenin wrote 6 lines
29.01.2011 19:25, Sven Barth wrote: > Does someone know a good place to link this page from? Maybe something > where other language/compiler features are referenced from or can be > linked to in the future. http://wiki.freepascal.org/delphi_language_features_which_fpc_does_not_have http://wiki.freepascal.org/FPC_New_Features_Trunk

Ok, thanks.

Show quoted text 8 lines
> * I have yet to test whether the restriction "Create must be first > statement in constructors" holds true (I've found a code sample that > suggests its not true) "If a class helper has a constructor the first statement in that constructor must be a call to the parameterless constructor." I think this is a copy-paste from some delphi .net or c# help where "parameterless constructor" has some special meaning.

Could be.

Show quoted text 27 lines
> Regarding the algorithm I use to find the last available class helper > (this is implemented in > compiler/symtable.pas/search_last_objectpascal_classhelper): > Delphi uses the last class helper that is available in the current > scope for method resolution (and the "parents" of that class helper). > For this I walk the symtable stack and search for a def where > is_objectpascal_classhelper returns "true". This can potentially lead > to a bad runtime behavior if a project does not use any class helpers, > but includes many units (the compiler is a good example of that). > Do you (especially @Devs) think that this is a sufficient approach or > should this be done another way? (Note: I have not yet profiled > compiling the compiler once with that search enabled and once without) Maybe to speedup the search we can mark the symtable with a flag that if it contains a class helper? Other flags can come in future - like has type definitions - to speedup type searches. > Perhaps searching for class helpers should be made dependent on a > modeswitch? E.g. "useclasshelpers" > That might lead to the potentially confusing behavior that a class > helper is not even found in its own unit though, although I think that > this would be a consequent behavior (the switch needs to be documented > good enough though ^^). > This switch could be enabled by default in mode Delphi. objfpc also allows final methods and sealed classes so it needs class helpers too. Better to allow them for all modes which support classes I think.

I didn't say that ObjFPC should not be able to use class helpers. I only wanted to mention the possibility to make the search for class helpers optional in that mode. But your suggestion regarding a flag might make this idea obsolete.

Don't forget about record helpers. And I also noticed that in delphi class helpers and record helpers are synonims so you can define a class helper for a record and a record helper for a class - I think FPC should be more restrictive here.

At first I forgot them, but currently I think that I'll only finish class helpers for now as record helpers might prove a bit more complex: In normal classes most problems are taken care of because the extended class is the real parent of the class helper class. I don't have that inheritance in records though, so here one must approach that differently.

But I agree that FPC should be more strict regarding the separation of class helper <-> record helper.

Regards,
Sven

Reply by email

Sven Barth
to Paul Ishenin: Try to add a set of flags to the symtable class. Store/Load it from/to ppu. When you add…
Paul Ishenin wrote 7 lines
29.01.2011 23:31, Sven Barth wrote: > Done. Differences are dramatic (at least on my Linux PC) Try to add a set of flags to the symtable class. Store/Load it from/to ppu. When you add a def into check it if it is a class helper and add a flag if so. In you search algorithm test the flag first before the scaning of symtable.

Ok, I'll try that.

Regards,
Sven

Reply by email

Sven Barth
to Paul Ishenin: This code works in delphi: program Project42; {$APPTYPE CONSOLE} type TFoo = class class…
Paul Ishenin wrote 37 lines
29.01.2011 23:41, Paul Ishenin wrote: > I also noticed that you check only unit symtables. I don't know what > if you add a class helper into a record/class/object type section? This code works in delphi: program Project42; {$APPTYPE CONSOLE} type TFoo = class class procedure DoSomething; static; type TFooHelper = class helper for TFoo class procedure HelpSomehow; static; end; end; { TFoo.TFooHelper } class procedure TFoo.TFooHelper.HelpSomehow; begin WriteLn('In Help somehow'); end; { TFoo } class procedure TFoo.DoSomething; begin WriteLn('In DoSomething'); end; begin TFoo.DoSomething; TFoo.HelpSomehow; end.

This is one of those moments where I need to restrain myself to not swear for the whole world to hear...

*sigh*

Does the nested class helper adhere to visibility rules? E.g. if you make it "strict private" or "strict protected" does it still work? Or if you put the class in another unit and lower the visibility somewhere below public? (I can't test now, because I have Delphi only at work)

Regards,
Sven

Reply by email

Paul Ishenin
to Sven Barth
Sven Barth wrote
This is one of those moments where I need to restrain myself to not swear for the whole world to hear... *sigh*

I had the same feeling when I found that generics are stored as TFoo<,> in the delphy symtable and therefore it is possible to have TFoo, TFoo<T>, TFoo<T1,T2>, TFoo<T1,T2,T3> types in the same unit :)

Show quoted text 5 lines
Does the nested class helper adhere to visibility rules? E.g. if you make it "strict private" or "strict protected" does it still work? Or if you put the class in another unit and lower the visibility somewhere below public? (I can't test now, because I have Delphi only at work)

For some reason the visibility is completely ignored here. I can add a class helper to the strict private or even move it to another unit - it is always visible.

Best regards,
Paul Ishenin

Reply by email

Sven Barth
to Paul Ishenin
Paul Ishenin wrote 8 lines
29.01.2011 23:58, Sven Barth wrote: > This is one of those moments where I need to restrain myself to not > swear for the whole world to hear... > > *sigh* I had the same feeling when I found that generics are stored as TFoo<,> in the delphy symtable and therefore it is possible to have TFoo, TFoo<T>, TFoo<T1,T2>, TFoo<T1,T2,T3> types in the same unit :)

At least I'm not alone with that feeling. :P

Show quoted text 9 lines
> Does the nested class helper adhere to visibility rules? E.g. if you > make it "strict private" or "strict protected" does it still work? Or > if you put the class in another unit and lower the visibility > somewhere below public? (I can't test now, because I have Delphi only > at work) For some reason the visibility is completely ignored here. I can add a class helper to the strict private or even move it to another unit - it is always visible.

Thanks for testing.

So suggestions regarding implementation?
Ignore in mode Delphi as well and enforce visibility rules in mode ObjFPC?

Regards,
Sven

Reply by email

Sven Barth
to Paul Ishenin: http://wiki.freepascal.org/delphi_language_features_which_fpc_does_not_have…
Paul Ishenin wrote 6 lines
29.01.2011 19:25, Sven Barth wrote: > Does someone know a good place to link this page from? Maybe something > where other language/compiler features are referenced from or can be > linked to in the future. http://wiki.freepascal.org/delphi_language_features_which_fpc_does_not_have http://wiki.freepascal.org/FPC_New_Features_Trunk

Added a link to the first page. The second one is not yet a valid place. :P

Regards,
Sven

Reply by email

Sven Barth
to Paul Ishenin: Try to add a set of flags to the symtable class. Store/Load it from/to ppu. When you add…
Paul Ishenin wrote 7 lines
29.01.2011 23:31, Sven Barth wrote: > Done. Differences are dramatic (at least on my Linux PC) Try to add a set of flags to the symtable class. Store/Load it from/to ppu. When you add a def into check it if it is a class helper and add a flag if so. In you search algorithm test the flag first before the scaning of symtable.

Should I add the flag set to TSymtable or tstoredsymtable? (only the latter can write/save itself to ppu)

Regards,
Sven

Reply by email

Florian Klämpfl
to Paul Ishenin
Paul Ishenin wrote 5 lines
30.01.2011 0:50, Sven Barth wrote: > Should I add the flag set to TSymtable or tstoredsymtable? (only the > latter can write/save itself to ppu) I would add it to TSymTable.

I really wonder that symtables have no flag set yet. Please move b_needs_init_final to this flag set then as well.

Reply by email

Sven Barth
to Florian Klämpfl: I really wonder that symtables have no flag set yet. Please move b_needs_init_final to…
Florian Klämpfl wrote 9 lines
Am 29.01.2011 19:04, schrieb Paul Ishenin: > 30.01.2011 0:50, Sven Barth wrote: >> Should I add the flag set to TSymtable or tstoredsymtable? (only the >> latter can write/save itself to ppu) > > I would add it to TSymTable. I really wonder that symtables have no flag set yet. Please move b_needs_init_final to this flag set then as well.

Will do (once I know why the flag set does not seem to be stored at all...).

Regards,
Sven

Reply by email

Sven Barth
to Florian Klämpfl: Ok, you'll really swear as soon as people test their code with your implementation :)
Florian Klämpfl wrote 7 lines
Am 29.01.2011 17:58, schrieb Sven Barth: > > This is one of those moments where I need to restrain myself to not > swear for the whole world to hear... Ok, you'll really swear as soon as people test their code with your implementation :)

I have normally no problems with restraining myself, but seeing what Borland/CodeGear/Embarcadero allows in its language dialect...

Regards,
Sven

Reply by email

Jonas Maebe
to Sven Barth
Sven Barth wrote
I have normally no problems with restraining myself, but seeing what Borland/CodeGear/Embarcadero allows in its language dialect...

I would suggest to file bug reports with Embarcadero about this. Then you can also find out whether this is intentional, or whether they are bugs.

Jonas

Reply by email

Sven Barth
to Sven Barth: Done. Differences are dramatic (at least on my Linux PC) Used command: time make cycle >…
Sven Barth wrote 11 lines
On 29.01.2011 16:08, Florian Klaempfl wrote: > Am 29.01.2011 13:25, schrieb Sven Barth: >> Do you (especially @Devs) think that this is a sufficient approach or >> should this be done another way? (Note: I have not yet profiled >> compiling the compiler once with that search enabled and once without) > > Profile compiler compilation first, then we can decide what to do. > Done. Differences are dramatic (at least on my Linux PC)

[snip]

Show quoted text 36 lines
Results Variant 1: Run 1: real 5m18.444s user 3m57.075s sys 0m4.806s Run 2: real 5m5.727s user 3m53.811s sys 0m4.426s Run 3: real 5m5.094s user 3m54.475s sys 0m4.676s Results Variant 2: Run 1: real 1m7.982s user 0m46.024s sys 0m4.390s Run 2: real 1m8.619s user 0m46.104s sys 0m4.513s Run 3: real 1m10.078s user 0m46.290s sys 0m4.333s It seems rather obvious that my search algorithm isn't a good idea ^^

Ok, I have now implemented a set of flags in TSymtable of which one is set when the (global-,static-)symtable contains a class helper (I haven't refactored b_needs_init_final yet).

Here are the new results with the search for class helpers enabled (only two runs this time):

Run 1:
real 2m22.980s
user 0m47.140s
sys 0m4.333s

Run 2:
real 2m15.362s
user 0m47.274s
sys 0m4.140s

Regards,
Sven

Reply by email

Paul Ishenin
to Sven Barth
Sven Barth wrote 16 lines
Ok, I have now implemented a set of flags in TSymtable of which one is set when the (global-,static-)symtable contains a class helper (I haven't refactored b_needs_init_final yet). Here are the new results with the search for class helpers enabled (only two runs this time): Run 1: real 2m22.980s user 0m47.140s sys 0m4.333s Run 2: real 2m15.362s user 0m47.274s sys 0m4.140s

Imo it works much better now.

Best regards,
Paul Ishenin

Reply by email

Hans-Peter Diettrich
to Paul Ishenin: I had the same feeling when I found that generics are stored as TFoo<,> in the delphy…
For some reason the visibility is completely ignored here. I can add a class helper to the strict private or even move it to another unit - it is always visible.

IMO class helper methods always should become visible as part of the class, regardless of where they are declared.

From the Delphi wiki:

"You can define and associate multiple helpers with a single type. However, only zero or one helper applies in any specific location in source code. The helper defined in the nearest scope will apply. Class or record helper scope is determined in the normal Delphi fashion (for example, right to left in the unit's uses clause)."

I.e. a single Helper reference (field) in the class definition is sufficient. This field cannot be persistent, instead it has to be initialized for every use case: whenever a helper is found in the compiled unit, or in one of its used units, it overwrites the Helper reference. Adding the helper elements to the class STB is not a valid solution, because another helper can become active at any time, during compilation.

The ancestors of the Helper class must be searched as well.

Also:

"Note that the class helper function MyFunc is called, because the class helper takes precedence over the actual class type."

That's bad, because this disallows to treat the helper like an ancestor, accessible in all derived classes :-(

Interesting questions:

1) Unit A defines an class helper for TFoo, then uses in the implementation section unit B, which also defines an helper for TFoo. According to the above rules the helper in A should become inaccessible and useless then.

2) Similarly multiple class helpers can be defined in the implementation section, which are used in the immediately following code, until the next helper declaration.

3) What about derived classes? Since derived classes are compiled independently, they never will use a reintroduced method in an class helper.

4) When class helpers are evaluated at compile time, according to the static object types (like properties are), then they could be handled just like the well known typecast hack:

type TMyFoo = class(TFoo)
<helper methods>

   end;

with following casts of every TFoo reference into TMyFoo. But TFoo derived types must be handled in the same way, so that I see no way around an extended search inside the TFoo STB.

5) What's the meaning of the "ancestor list"? IMO interfaces cannot be added by an class helper, and multiple inheritance is quite unlikely. Will the ancestor list allow to override interface *implementations*?

DoDi

Reply by email

Sven Barth
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote 27 lines
Paul Ishenin schrieb: > For some reason the visibility is completely ignored here. I can add a > class helper to the strict private or even move it to another unit - > it is always visible. IMO class helper methods always should become visible as part of the class, regardless of where they are declared. From the Delphi wiki: "You can define and associate multiple helpers with a single type. However, only zero or one helper applies in any specific location in source code. The helper defined in the nearest scope will apply. Class or record helper scope is determined in the normal Delphi fashion (for example, right to left in the unit's uses clause)." I.e. a single Helper reference (field) in the class definition is sufficient. This field cannot be persistent, instead it has to be initialized for every use case: whenever a helper is found in the compiled unit, or in one of its used units, it overwrites the Helper reference. Adding the helper elements to the class STB is not a valid solution, because another helper can become active at any time, during compilation. The ancestors of the Helper class must be searched as well.

Sorry, I don't understand what you want to tell here.

I personally expect a class helper that is defined inside a private section of a class not to be available in another unit like I can't access a field or another type defined in there as well.

Show quoted text 9 lines
Also: "Note that the class helper function MyFunc is called, because the class helper takes precedence over the actual class type." That's bad, because this disallows to treat the helper like an ancestor, accessible in all derived classes :-(

If you want to have a class helper available in a derived class there is only one way to do this:

==== source begin ====
type
   TFoo = class
   end;
   TFooHelper = class helper for TFoo
   end; // this helper only applies to variables of type TFoo
   TBar = class(TFoo)
   end; // No methods of TFooHelper are available for variables of this type

TBarHelper = class helper(TFooHelper) for TBar

   end; // now all methods of TFooHelper (that aren't overriden by

TBarHelper) are available for all variables of type TBar as well ==== source end ====

Show quoted text 7 lines
Interesting questions: 1) Unit A defines an class helper for TFoo, then uses in the implementation section unit B, which also defines an helper for TFoo. According to the above rules the helper in A should become inaccessible and useless then.

This is indeed something that I need to test. And I hope that Delphi behaves the way you described (because that would be the consistent behavior)

2) Similarly multiple class helpers can be defined in the implementation section, which are used in the immediately following code, until the next helper declaration.

Needs to be tested as well, but I hope so.

3) What about derived classes? Since derived classes are compiled independently, they never will use a reintroduced method in an class helper.

This is correct. The following does not work in Delphi:

==== source begin ====
type
   TStringsHelper = class helper for TStrings
     procedure Test;
   end;
var
   s: TStringList;
begin
   s.Test; // this won't work
   TStrings(s).Test // but this does
end;
==== source end ====
Show quoted text 12 lines
4) When class helpers are evaluated at compile time, according to the static object types (like properties are), then they could be handled just like the well known typecast hack: type TMyFoo = class(TFoo) <helper methods> end; with following casts of every TFoo reference into TMyFoo. But TFoo derived types must be handled in the same way, so that I see no way around an extended search inside the TFoo STB.

Technically class helpers ARE classes that derive from the extended class (here: TFoo). But there are no casts of TFoo references. When searching for a symbol in a class the last class helper in scope for that class is searched first and then the symbol is searched in the class itself.

5) What's the meaning of the "ancestor list"? IMO interfaces cannot be added by an class helper, and multiple inheritance is quite unlikely. Will the ancestor list allow to override interface *implementations*?

I don't know how you come to interfaces now. But basically from the outside class helpers seem to support multiple inheritance, but technically they don't. It works like this:

* the extended class is the real parent of the class helper class
* if the class helper has a parent ( e.g. class helper(TFooHelper) for TFoo ) this parent is referenced in a mostly unimportant "helperparent" field of tobjectdef and only used when searching for a symbol. At the end the pseudo parent of a class helper tells the compiler to search the symbol table of that class helper as well.

Regards,
Sven

Reply by email

Sven Barth
to Paul Ishenin: Imo it works much better now. Paul Ishenin
Paul Ishenin wrote 19 lines
30.01.2011 5:22, Sven Barth wrote: > Ok, I have now implemented a set of flags in TSymtable of which one is > set when the (global-,static-)symtable contains a class helper (I > haven't refactored b_needs_init_final yet). > > Here are the new results with the search for class helpers enabled > (only two runs this time): > > Run 1: > real 2m22.980s > user 0m47.140s > sys 0m4.333s > > Run 2: > real 2m15.362s > user 0m47.274s > sys 0m4.140s Imo it works much better now.

Only one minute slower in the complete run instead of four. I let you guys decide whether this is good enough ^^

How often is the compiler compiled completly during a make cycle?

Regards,
Sven

Reply by email

Paul Ishenin
to Sven Barth
Sven Barth wrote
Imo it works much better now. Only one minute slower in the complete run instead of four. I let you guys decide whether this is good enough ^^

2m22.980s -
2m15.362s =
0m7.xxxs - were is a minute?

How often is the compiler compiled completly during a make cycle?

3 times.

Best regards,
Paul Ishenin

Reply by email

Sven Barth
to Paul Ishenin
Paul Ishenin wrote 8 lines
30.01.2011 15:45, Sven Barth wrote: > Imo it works much better now. > > Only one minute slower in the complete run instead of four. I let you > guys decide whether this is good enough ^^ 2m22.980s - 2m15.362s = 0m7.xxxs - were is a minute?

That was two runs of the same compiler. I've run it twice, to be sure that the workload of the PC doesn't influence the result to much.

The timing of the compiler without class helper search is the one in the older mail:

Show quoted text 17 lines
Run 1: real 1m7.982s user 0m46.024s sys 0m4.390s Run 2: real 1m8.619s user 0m46.104s sys 0m4.513s Run 3: real 1m10.078s user 0m46.290s sys 0m4.333s > How often is the compiler compiled completly during a make cycle? 3 times.

The first run is done by the starting compiler, right (2.4.2 in my case)? So this would mean that roughly half a minute is added by the 2.5.1 compilers using the class helper search (I'll need to verify this assumption of course).

Regards,
Sven

Reply by email

Sven Barth
to Sven Barth: [snip] Ok, I have now implemented a set of flags in TSymtable of which one is set when…
Sven Barth wrote
Ok, I have now implemented a set of flags in TSymtable of which one is set when the (global-,static-)symtable contains a class helper (I haven't refactored b_needs_init_final yet).

I have commited the changes now as well (I was too tired yesterday), so please fell free to critize them (especially the ones in ppudump) as I need to build on on these changes regarding b_needs_init_final (or should this wait until everything is merged back to trunk?).

Regards,
Sven

Reply by email

Paul Ishenin
to Sven Barth
Sven Barth wrote
I have commited the changes now as well (I was too tired yesterday), so please fell free to critize them (especially the ones in ppudump) as I need to build on on these changes regarding b_needs_init_final (or should this wait until everything is merged back to trunk?).

b_needs_init_final should wait I think.

Best regards,
Paul Ishenin

Reply by email

Sven Barth
to Paul Ishenin
Paul Ishenin wrote
30.01.2011 16:22, Sven Barth wrote: > I have commited the changes now as well (I was too tired yesterday), > so please fell free to critize them (especially the ones in ppudump). Why do you need ibsymtableoptions ?

tstoredsymtable stores only definitions and symbols in its own entries, so I felt that its more save to add a new entry instead of having a set floating around in the nirvana of the ppu.
Also this can be extended later e.g. for Delphi attributes where everything seems to be able to carry an attribute (I've seen a variable with an attribute already, though I don't know whether this example really works/compiles).

And the real reason why I added it: I had problems when I only stored the set (the "more save" from above), but this could be related to the missing "inherited ppuwrite" call in tabstractlocaldef (which I discovered after I had added the entry).

Regards,
Sven

Reply by email

Jonas Maebe
to Sven Barth: Only one minute slower in the complete run instead of four. I let you guys decide whether…
Sven Barth wrote
Only one minute slower in the complete run instead of four. I let you guys decide whether this is good enough ^^

It's still a lot of overhead.

An alternative solution could be to add a hashtable (tfphaslist) to tmodule whose entries are hashed on the qualified class names (unit$classname, since different units can contain classes with the same name). The value of such an entry would a tfpobjectlist of class helpers, with the last entry the one that is actually used. This list has to be updated whenever a symtablestack.push/pop is performed (you would probably have to wrap those calls, since the symtablestack itself is a fairly low level thing and I don't think it is supposed to know anything about tobjectdefs).

The reason for having a list of class helpers rather than only the current class helper, is because you would also have to remove class helpers again when its symtable is removed from the symtable stack, and this way you wouldn't have to search all previous symtables on the stack to see whether they also contained a class helper (simply remove all class helpers from the list whose owner=symtablestack.top).

Of course, this won't be free either since you have to scan all pushed symtables for class helpers, and when popping them you have to go through all hashtable items to remove the appropriate ones. I don't know whether overall it will be faster or slower than your current approach.

The reason the hashtable would have to be kept per module rather than simply adding the list of class helpers in scope to the tabstractrecorddef of the relevant record/class, is that in the latter case you would get into trouble whenever you switch from parsing one unit to another (which happens a lot while parsing uses-clauses). The reason is that you would have to save/restore the current class helpers in scope for every abstractrecorddef that has been loaded whenever you switched units.

Jonas

PS: the fact that you can have classes with the same name in different units is something that requires special handling in any case. In Objective-C, there is a global class name space (so all classes with the same name are the same class according to the run time), but you probably need different class helper name mangling in the case of Object Pascal to prevent false collisions.

Reply by email

Florian Klämpfl
to Sven Barth: Only one minute slower in the complete run instead of four. I let you guys decide whether…
Sven Barth wrote 22 lines
On 30.01.2011 04:30, Paul Ishenin wrote: > 30.01.2011 5:22, Sven Barth wrote: >> Ok, I have now implemented a set of flags in TSymtable of which one is >> set when the (global-,static-)symtable contains a class helper (I >> haven't refactored b_needs_init_final yet). >> >> Here are the new results with the search for class helpers enabled >> (only two runs this time): >> >> Run 1: >> real 2m22.980s >> user 0m47.140s >> sys 0m4.333s >> >> Run 2: >> real 2m15.362s >> user 0m47.274s >> sys 0m4.140s > > Imo it works much better now. Only one minute slower in the complete run instead of four.

Now I understand the timings :) Actually two times slower, right?

I let you guys decide whether this is good enough ^^

Actually I think anything about a ten percent slower compiler will people make cry ... And as far as I understand, for projects with a lot of units it will be even worse, right?

How often is the compiler compiled completly during a make cycle?

2-4 times iirc.

Reply by email

Sven Barth
to Florian Klämpfl
Florian Klämpfl wrote 26 lines
Am 30.01.2011 09:45, schrieb Sven Barth: > On 30.01.2011 04:30, Paul Ishenin wrote: >> 30.01.2011 5:22, Sven Barth wrote: >>> Ok, I have now implemented a set of flags in TSymtable of which one is >>> set when the (global-,static-)symtable contains a class helper (I >>> haven't refactored b_needs_init_final yet). >>> >>> Here are the new results with the search for class helpers enabled >>> (only two runs this time): >>> >>> Run 1: >>> real 2m22.980s >>> user 0m47.140s >>> sys 0m4.333s >>> >>> Run 2: >>> real 2m15.362s >>> user 0m47.274s >>> sys 0m4.140s >> >> Imo it works much better now. > > Only one minute slower in the complete run instead of four. Now I understand the timings :) Actually two times slower, right?

I was a bit bad with explaining my profile results ^^

The complete "make cycle" is two times slower, yes.

Show quoted text 7 lines
> I let you > guys decide whether this is good enough ^^ Actually I think anything about a ten percent slower compiler will people make cry ... And as far as I understand, for projects with a lot of units it will be even worse, right?

A huge number of units is not the main cause. The main problem is many units included in the uses clause. A project could have thousand units, but if every unit only used two or three you might not even notice much (a very hypothetic scenario, but to show you where the problem is). That's why I used the compiler as a testcase (though Lazarus might be a good candidate as well...)

Regards,
Sven

Reply by email

Sven Barth
to Jonas Maebe: It's still a lot of overhead. An alternative solution could be to add a hashtable…
Jonas Maebe wrote 7 lines
On 30 Jan 2011, at 09:45, Sven Barth wrote: > Only one minute slower in the complete run instead of four. I let you guys decide whether this is good enough ^^ It's still a lot of overhead.

Yes and that's why I'm thankful for every suggestion I can get (like your one).

Show quoted text 6 lines
An alternative solution could be to add a hashtable (tfphaslist) to tmodule whose entries are hashed on the qualified class names (unit$classname, since different units can contain classes with the same name). The value of such an entry would a tfpobjectlist of class helpers, with the last entry the one that is actually used. This list has to be updated whenever a symtablestack.push/pop is performed (you would probably have to wrap those calls, since the symtablestack itself is a fairly low level thing and I don't think it is supposed to know anything about tobjectdefs). The reason for having a list of class helpers rather than only the current class helper, is because you would also have to remove class helpers again when its symtable is removed from the symtable stack, and this way you wouldn't have to search all previous symtables on the stack to see whether they also contained a class helper (simply remove all class helpers from the list whose owner=symtablestack.top). Of course, this won't be free either since you have to scan all pushed symtables for class helpers, and when popping them you have to go through all hashtable items to remove the appropriate ones. I don't know whether overall it will be faster or slower than your current approach.

The need to scan all pushed symtables can be reduced by keeping the flag I introduced and using it for this purpose.

The reason the hashtable would have to be kept per module rather than simply adding the list of class helpers in scope to the tabstractrecorddef of the relevant record/class, is that in the latter case you would get into trouble whenever you switch from parsing one unit to another (which happens a lot while parsing uses-clauses). The reason is that you would have to save/restore the current class helpers in scope for every abstractrecorddef that has been loaded whenever you switched units.

Thank you for your suggestion. I'll try to implement this to see whether it helps.

PS: the fact that you can have classes with the same name in different units is something that requires special handling in any case. In Objective-C, there is a global class name space (so all classes with the same name are the same class according to the run time), but you probably need different class helper name mangling in the case of Object Pascal to prevent false collisions.

While I understand the difference between namespaces in case of Objective-C and Object Pascal, I don't understand why I should pay attention to the mangling of class helpers. I might be missing a small puzzle piece here, so would you please explain this?

Regards,
Sven

Reply by email

Paul Ishenin
to Sven Barth: Only one minute slower in the complete run instead of four. I let you guys decide whether…
Sven Barth wrote
Only one minute slower in the complete run instead of four. I let you guys decide whether this is good enough ^^ How often is the compiler compiled completly during a make cycle?

I still see an ability to optimize your implementation.

       procedure update_unit_symtable_options;
          var
            st: tsymtable;
          begin
            st:=owner;
            while not(st.symtabletype in [globalsymtable,staticsymtable]) do
              st:=st.defowner.owner;
            if objecttype in [odt_classhelper,odt_objccategory] then
              include(st.tableoptions,sto_has_classhelper);
          end;

remove "if objecttype in [odt_classhelper,odt_objccategory] then" from this routine to outside - so you will not need to scan owners in the loop for all object types.

Best regards,
Paul Ishenin

Reply by email

Florian Klämpfl
to Martin Schreiber
Martin Schreiber wrote 8 lines
On Sunday, 30. January 2011 12.13:21 Florian Klämpfl wrote: > > Actually I think anything about a ten percent slower compiler will > people make cry ... And as far as I understand, for projects with a lot > of units it will be even worse, right? > I cry if FPC doesn't compile at least ten percent *faster* than the previous release...

Sven, see ;)?

Reply by email

Jonas Maebe
to Martin Schreiber: I cry if FPC doesn't compile at least ten percent *faster* than the previous release...…
Martin Schreiber wrote
I cry if FPC doesn't compile at least ten percent *faster* than the previous release...

At least on Mac OS X/i386, we are pretty close to that currently as far as compiling the compiler with itself is concerned:

* Compiling it with 2.4.2:
user 0m7.663s
sys 0m0.545s

user 0m7.540s
sys 0m0.535s

user 0m7.527s
sys 0m0.532s

* Compiling it with 2.5.1:

user 0m6.972s
sys 0m0.451s

user 0m6.967s
sys 0m0.456s

user 0m6.966s
sys 0m0.456s

The reason I'm specifically mentioning the used platform is that there's one new Mac OS X/i386-specific optimization in 2.5.1 (more efficient PIC trampolines, and PIC is enabled by default on that platform), although I cannot imagine that it would be completely (or even largely) responsible for an 8% speedup.

Jonas

Reply by email

Sven Barth
to Florian Klämpfl: Sven, see ;)?
Florian Klämpfl wrote 11 lines
Am 30.01.2011 12:37, schrieb Martin Schreiber: > On Sunday, 30. January 2011 12.13:21 Florian Klämpfl wrote: >> >> Actually I think anything about a ten percent slower compiler will >> people make cry ... And as far as I understand, for projects with a lot >> of units it will be even worse, right? >> > I cry if FPC doesn't compile at least ten percent *faster* than the previous > release... Sven, see ;)?

Indeed... :)

Regards,
Sven

Reply by email

Sven Barth
to Paul Ishenin: I still see an ability to optimize your implementation. procedure…
Paul Ishenin wrote 21 lines
30.01.2011 15:45, Sven Barth wrote: > Only one minute slower in the complete run instead of four. I let you > guys decide whether this is good enough ^^ > > How often is the compiler compiled completly during a make cycle? I still see an ability to optimize your implementation. procedure update_unit_symtable_options; var st: tsymtable; begin st:=owner; while not(st.symtabletype in [globalsymtable,staticsymtable]) do st:=st.defowner.owner; if objecttype in [odt_classhelper,odt_objccategory] then include(st.tableoptions,sto_has_classhelper); end; remove "if objecttype in [odt_classhelper,odt_objccategory] then" from this routine to outside - so you will not need to scan owners in the loop for all object types.

Sorry, but I don't understand your intention here. The if-clause is only run after the global- or staticsymtable this class belongs to is reached. Or do you mean something completly different?

Regards,
Sven

Reply by email

Marco van de Voort
to Sven Barth: Indeed... :) Sven

In our previous episode, Sven Barth said:

Show quoted text 11 lines
>>> >>> Actually I think anything about a ten percent slower compiler will >>> people make cry ... And as far as I understand, for projects with a lot >>> of units it will be even worse, right? >>> >> I cry if FPC doesn't compile at least ten percent *faster* than the previous >> release... > > Sven, see ;)? Indeed... :)

Don't forget to keep a reign on memory too :-)

Reply by email

Paul Ishenin
to Sven Barth: Sorry, but I don't understand your intention here. The if-clause is only run after the…
Sven Barth wrote 18 lines
> > procedure update_unit_symtable_options; > var > st: tsymtable; > begin > st:=owner; > while not(st.symtabletype in [globalsymtable,staticsymtable]) do > st:=st.defowner.owner; > if objecttype in [odt_classhelper,odt_objccategory] then > include(st.tableoptions,sto_has_classhelper); > end; > > remove "if objecttype in [odt_classhelper,odt_objccategory] then" from > this routine to outside - so you will not need to scan owners in the > loop for all object types. I still see an ability to optimize your implementation. Sorry, but I don't understand your intention here.
procedure update_unit_symtable_options;
var
st: tsymtable;
begin
st:=owner;
while not(st.symtabletype in [globalsymtable,staticsymtable]) do
st:=st.defowner.owner;
include(st.tableoptions,sto_has_classhelper);
end;
if objecttype in [odt_classhelper,odt_objccategory] then
    update_unit_symtable_options;

This will work faster because loop and the function call will run not for all object types.

Best regards,
Paul Ishenin

Reply by email

Sven Barth
to Paul Ishenin
Paul Ishenin wrote 34 lines
30.01.2011 19:41, Sven Barth wrote: >> >> procedure update_unit_symtable_options; >> var >> st: tsymtable; >> begin >> st:=owner; >> while not(st.symtabletype in [globalsymtable,staticsymtable]) do >> st:=st.defowner.owner; >> if objecttype in [odt_classhelper,odt_objccategory] then >> include(st.tableoptions,sto_has_classhelper); >> end; >> >> remove "if objecttype in [odt_classhelper,odt_objccategory] then" from >> this routine to outside - so you will not need to scan owners in the >> loop for all object types. > I still see an ability to optimize your implementation. > > Sorry, but I don't understand your intention here. procedure update_unit_symtable_options; var st: tsymtable; begin st:=owner; while not(st.symtabletype in [globalsymtable,staticsymtable]) do st:=st.defowner.owner; include(st.tableoptions,sto_has_classhelper); end; if objecttype in [odt_classhelper,odt_objccategory] then update_unit_symtable_options; This will work faster because loop and the function call will run not for all object types.

Now I understand. Thanks for clarification.

I've done that change.

Timings without that change:

Run 1:

real 1m3.461s
user 0m45.957s
sys 0m4.590s

Run 2:

real 1m10.777s
user 0m46.204s
sys 0m4.696s

Run 3:

real 1m11.596s
user 0m46.690s
sys 0m4.406s

Timings with that change:

Run 1:

real 1m8.919s
user 0m46.597s
sys 0m4.166s

Run 2:

real 1m9.359s
user 0m46.524s
sys 0m4.380s

Run 3:

real 1m8.342s
user 0m46.294s
sys 0m4.490s

Doesn't change much. For comparison timings without the search for class helpers (if-clause in symtable.pas/searchsym_in_class disabled):

Run 1:

real 1m5.040s
user 0m46.050s
sys 0m4.163s

Run 2:

real 1m4.008s
user 0m45.784s
sys 0m4.343s

Run 3:

real 1m6.074s
user 0m45.714s
sys 0m4.546s

It seems that I should have rerun the profiling without class helper search as well after I added the flag yesterday...

I'll nevertheless try to implement Jonas' suggestion to see whether this improves timing a bit more (and maybe the flags can be used to optimize the speed for other types of searches a bit more, like Paul suggested :D )

Regards,
Sven

Reply by email

Paul Ishenin
to Sven Barth
Sven Barth wrote 15 lines
Timings without that change: Run 1: real 1m3.461s user 0m45.957s sys 0m4.590s Timings with that change: Run 1: real 1m8.919s user 0m46.597s sys 0m4.166s

But previously you gave 2 minutes values.

Best regards,
Paul Ishenin

Reply by email

Hans-Peter Diettrich
to Sven Barth: Sorry, I don't understand what you want to tell here. I personally expect a class helper…
Sorry, I don't understand what you want to tell here.

Sorry2, I'll retry.

I personally expect a class helper that is defined inside a private section of a class not to be available in another unit like I can't access a field or another type defined in there as well.

Delphi allows for *at most* one active class helper, determined by the unit search order, just like every other ambiguous identifier is resolved. If you don't want an class helper used in other units, simply move it to the implementation section.

Hiding an class helper in a private section of a class IMO is not the right way, and the result may be compiler specific.

If you want to have a class helper available in a derived class there is only one way to do this:

[...]

Okay, now I understand the use of one ancestor, but still not the use of a list of ancestors.

Show quoted text 20 lines
> 3) What about derived classes? Since derived classes are compiled > independently, they never will use a reintroduced method in an class > helper. > This is correct. The following does not work in Delphi: ==== source begin ==== type TStringsHelper = class helper for TStrings procedure Test; end; var s: TStringList; begin s.Test; // this won't work TStrings(s).Test // but this does end; ==== source end ====

This looks very much like my #4.

Show quoted text 18 lines
> 4) When class helpers are evaluated at compile time, according to the > static object types (like properties are), then they could be handled > just like the well known typecast hack: > > type TMyFoo = class(TFoo) > <helper methods> > end; > > with following casts of every TFoo reference into TMyFoo. > But TFoo derived types must be handled in the same way, so that I see no > way around an extended search inside the TFoo STB. > Technically class helpers ARE classes that derive from the extended class (here: TFoo). But there are no casts of TFoo references. When searching for a symbol in a class the last class helper in scope for that class is searched first and then the symbol is searched in the class itself.

Then one possible implementation could hide the extended class (TFoo), and use the helper class STB instead. This were the implementation of an implicit type cast. The symtable stack has to be built or modified accordingly, so that searching continues in the proper class ancestors.

Show quoted text 5 lines
> 5) What's the meaning of the "ancestor list"? IMO interfaces cannot be > added by an class helper, and multiple inheritance is quite unlikely. > Will the ancestor list allow to override interface *implementations*? I don't know how you come to interfaces now.

This is the normal use of a *list* of ancestors. The first ancestor denotes the parent class, all others denote interfaces.

Show quoted text 10 lines
But basically from the outside class helpers seem to support multiple inheritance, but technically they don't. It works like this: * the extended class is the real parent of the class helper class * if the class helper has a parent ( e.g. class helper(TFooHelper) for TFoo ) this parent is referenced in a mostly unimportant "helperparent" field of tobjectdef and only used when searching for a symbol. At the end the pseudo parent of a class helper tells the compiler to search the symbol table of that class helper as well.

See above.

I'd push the extended class onto the symtable stack, then the class helper parents, and finally the class helper itself, and use that stack whenever a reference to a class with a helper class is encounterd.

DoDi

Reply by email

Hans-Peter Diettrich
to Jonas Maebe: It's still a lot of overhead. An alternative solution could be to add a hashtable…
Show quoted text 9 lines
An alternative solution could be to add a hashtable (tfphaslist) to tmodule whose entries are hashed on the qualified class names (unit$classname, since different units can contain classes with the same name). The value of such an entry would a tfpobjectlist of class helpers, with the last entry the one that is actually used. This list has to be updated whenever a symtablestack.push/pop is performed (you would probably have to wrap those calls, since the symtablestack itself is a fairly low level thing and I don't think it is supposed to know anything about tobjectdefs).

IIRC a class symtable is pushed onto the symtable stack, whenever a qualifier is encountered (e.g. "TFoo."). Regardless of the implementation, this makes the symbol search start in TFoo and continue in its ancestors, before the remainder of the stack is searched. It should be possible to extend that mechanism, adding eventual class helpers to the search order.

Removal of such a qualified scope, with all contained ancestors, also must have been implemented already, and should not deserve much changing.

Show quoted text 5 lines
Of course, this won't be free either since you have to scan all pushed symtables for class helpers, and when popping them you have to go through all hashtable items to remove the appropriate ones. I don't know whether overall it will be faster or slower than your current approach.

Is the hashtable *really* rebuilt with every push and pop of another symtable? It would be much easier to have a hashtable per symtable, that deserves no further modifications. When all hashtables use the same hash algorithm, a hash value must be computed only once, and then can be used for lookup in every STB on the stack.

DoDi

Reply by email

Thaddy
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote 10 lines
Jonas Maebe schrieb: Is the hashtable *really* rebuilt with every push and pop of another symtable? It would be much easier to have a hashtable per symtable, that deserves no further modifications. When all hashtables use the same hash algorithm, a hash value must be computed only once, and then can be used for lookup in every STB on the stack. DoDi

CRC's are also hashes. isn't that used?

Reply by email

Burkhard Carstens
to Paul Ishenin: But previously you gave 2 minutes values. Paul Ishenin
Paul Ishenin wrote 19 lines
31.01.2011 0:26, Sven Barth wrote: > Timings without that change: > > Run 1: > > real 1m3.461s > user 0m45.957s > sys 0m4.590s > > Timings with that change: > > Run 1: > > real 1m8.919s > user 0m46.597s > sys 0m4.166s But previously you gave 2 minutes values.

AFAIK, the "real" time is pretty meaningless. It just says how much time passed between prg start and prg end.
The "user" time is the interesting one. It says how much processor time the prg used actually doing something instead of waiting to be sheduled by the OS. That's why a multithreaded app on a multi-core can have higher user time than real time.

regards
Burkhard

Reply by email

Sven Barth
to Paul Ishenin: But previously you gave 2 minutes values. Paul Ishenin
Paul Ishenin wrote 18 lines
31.01.2011 0:26, Sven Barth wrote: > Timings without that change: > > Run 1: > > real 1m3.461s > user 0m45.957s > sys 0m4.590s > > Timings with that change: > > Run 1: > > real 1m8.919s > user 0m46.597s > sys 0m4.166s But previously you gave 2 minutes values.

Yes, I found that strange as well and that's why I rerun the timings without the search for class helpers Burkhard said the "real" value seems to be highly load dependant while the "user" one might be the one we should care about...

And regarding this there aren't that much changes... I might rerun the complete tests with the usage of the symbol table flag disabled and see what's the difference.

Regards,
Sven

Reply by email

Sven Barth
to Florian Klämpfl: I really wonder that symtables have no flag set yet. Please move b_needs_init_final to…
Florian Klämpfl wrote 7 lines
Am 29.01.2011 19:04, schrieb Paul Ishenin: > 30.01.2011 0:50, Sven Barth wrote: >> Should I add the flag set to TSymtable or tstoredsymtable? (only the >> latter can write/save itself to ppu) > I would add it to TSymTable. I really wonder that symtables have no flag set yet. Please move b_needs_init_final to this flag set then as well.

Better late than never: done in 24523 ;)

Regards,
Sven

Reply by email