BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

How to make IndexOf(Object) faster and still OO-ish?

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi OO design
View previous topic :: View next topic  
Author Message
Ivo Bauer
Guest





PostPosted: Sat May 19, 2007 8:21 pm    Post subject: How to make IndexOf(Object) faster and still OO-ish? Reply with quote



Hi,

Background: Delphi for Win32. I have my own implementation of what can
be called an "aspect concept" or "event pattern" in dotNET, IOW a
variation of observer pattern (thanks to Joanna Carter, Peter Morris
and others for providing a valuable feedback on this some time ago).

The current implementation of the subject (event broadcaster) class
holds a list of items, where each item holds a reference to the event
class type and reference to the instance of list of observers (event
interceptors) that are interested in this particular event class type.

type
TEventDescriptorClass = class of TEventDescriptor;
TEventDescriptor = class end;

TInterceptorList = class(TList)
...
end;

TRegisteredEvent = class
...
public
property Class: TEventDescriptorClass read FClass;
property List: TInterceptorList read FList;
end;

TEventBroadcaster = class { = subject }
private
FRegisteredEvents: TList; { of TRegisteredEvent }
public
...
procedure BeginInterceptEvent(AInterceptor:
TBaseEventInterceptor; AClass: TEventDescriptorClass);
procedure BroadcastEvent(ADescriptor: TEventDescriptor);
procedure EndInterceptEvent(AInterceptor: TBaseEventInterceptor;
AClass: TEventDescriptorClass);
end;

Now, when there are many registered event classes and interceptors
observing those events, the observer registration/unregistration and
mainly event broadcasting gets slower due to inefficient
implementation of TList.IndexOf() method that is used to locate a
specific item in the list.

I need to make this faster but don't want to diverge from OO rules.
I'm thinking about turning both registered event list and interceptor
lists into TStringList (with sorting and duplicate checking turned
on), that would also store a references (a pointer to something) as
string hashes of original memory addresses they are pointing to and
use them for faster searching (instead of direct memory addresses like
before):

function HashPointer(APointer: Pointer): string;
begin
Result := Format('%p', [APointer]);
end;

Registering a new event class reference along with the instance of
interceptor list would be done like this:

FRegisteredEvents.AddObject(HashPointer(Pointer(AClass)),
LEventInterceptors);

Registering a new interceptor for already registered event would be
done this way (LEventInterceptors is a TStringList instance retrieved
from a given item of registered event list):

LEventInterceptors.AddObject(HashPointer(Pointer(AInterceptor)),
AInterceptor);

Considering what has been written above, the searching for a specific
registered event (and hence also for its associated list of
interceptors) can be re-written like this:

function TEventBroadcaster.IndexOfRegisteredEvent(AClass:
TEventDescriptorClass): Integer;
begin
Result := FRegisteredEvents.IndexOf(HashPointer(Pointer(AClass)));
end;

What do you think about these modifications? What do others use to
speed up the execution time of TList.IndexOf() method?

Thanks in advance for your feedback.


--
Ivo Bauer [OZM Research]
Back to top
Thomas Mueller
Guest





PostPosted: Sat May 19, 2007 10:48 pm    Post subject: Re: How to make IndexOf(Object) faster and still OO-ish? Reply with quote



Hi Ivo,

Ivo Bauer wrote:

Quote:
Now, when there are many registered event classes and interceptors
observing those events, the observer registration/unregistration and
mainly event broadcasting gets slower due to inefficient
implementation of TList.IndexOf() method that is used to locate a
specific item in the list.

I need to make this faster but don't want to diverge from OO rules.
I'm thinking about turning both registered event list and interceptor
lists into TStringList (with sorting and duplicate checking turned
on), that would also store a references (a pointer to something) as
string hashes of original memory addresses they are pointing to and
use them for faster searching (instead of direct memory addresses like
before):

Hm, why not just sort the existing TList?

MfG
twm
Back to top
Ivo Bauer
Guest





PostPosted: Sat May 19, 2007 11:52 pm    Post subject: Re: How to make IndexOf(Object) faster and still OO-ish? Reply with quote



Thomas Mueller napsal(a):
Quote:
Hm, why not just sort the existing TList?

I know TList can be sorted but it is the binary search what's missing
there. This is why I have been thinking about TStringList because I
don't want to develop (and test) this stuff unless it is absolutely
necessary. Does it make any sense?


--
Ivo Bauer [OZM Research]
Back to top
Thomas Mueller
Guest





PostPosted: Sun May 20, 2007 7:05 pm    Post subject: Re: How to make IndexOf(Object) faster and still OO-ish? Reply with quote

Hi,

Ivo Bauer wrote:

Quote:
Hm, why not just sort the existing TList?

I know TList can be sorted but it is the binary search what's missing
there. This is why I have been thinking about TStringList because I
don't want to develop (and test) this stuff unless it is absolutely
necessary. Does it make any sense?

OK, why not use one of the many sortable TList classes that are available?
E.g. the one that is part of my dzTemplates library:

http://www.dummzeuch.de/delphi/dztemplates/english.html

"dzSortedListTemplate / dzSortedObjectListTemplate is based on
dzListTemplate and adds a sort order to it. It introduces methods for
comparing two items and searching for them with a binary search algorithm.
A Duplicates property like the one in TStringList determines what to do
with duplicate items."

MfG
twm
Back to top
Ivo Bauer
Guest





PostPosted: Mon May 21, 2007 10:25 pm    Post subject: Re: How to make IndexOf(Object) faster and still OO-ish? Reply with quote

Hi Thomas,

Quote:
OK, why not use one of the many sortable TList classes that are available?

Such as? :-)

Quote:
E.g. the one that is part of my dzTemplates library:
http://www.dummzeuch.de/delphi/dztemplates/english.html

Thanks for the link. I will take a closer look at it.


--
Ivo Bauer [OZM Research]
Back to top
Charles McAllister
Guest





PostPosted: Mon May 21, 2007 10:53 pm    Post subject: Re: How to make IndexOf(Object) faster and still OO-ish? Reply with quote

FWIW, i use this code to search within a sorted list...

unit uFind;

interface

type
IFindable = interface
['{364D3ED9-800C-427D-9F3A-BCFCE8111604}']
function Count: Integer;
function FindCompare(Index: Integer): Integer;
end;

function Find(const AFindable: IFindable; out AIndex: Integer; AFindFirst: Boolean): Boolean;

implementation

function Find(const AFindable: IFindable; out AIndex: Integer; AFindFirst: Boolean): Boolean;
var
L, H, I, C: Integer;
begin
Result := False;
L := 0;
H := AFindable.Count - 1;
while L <= H do
begin
I := (L + H) shr 1;
C := AFindable.FindCompare(I);
if C < 0 then
L := I + 1
else
begin
H := I - 1;
if C = 0 then
begin
Result := True;
//if Duplicates <> dupAccept then L := I;
end;
end;
end;
if AFindFirst then
while (L > 0) and (AFindable.FindCompare(L - 1) = 0) do
Dec(L);
AIndex := L;
end;

....

so for instance, your class would support the IFindable interface like so...

type
TMyList = class(TInterfacedObject, IFindable)
protected
function FindCompare(Index: Integer): Integer;
public
function IndexOf(): Integer;
end;

....

function TMyList.IndexOf(): Integer;
begin
//first, store params in private fields

Find(Self, Result, True);
end;

function TMyList.FindCompare(Index: Integer): Integer;
begin
//Result := 0, 1, or -1 depending on list data and params from IndexOf
end;

....

I use a similar interface for QuickSorting, if you want to see that i can post it as well.
Back to top
Charles McAllister
Guest





PostPosted: Tue May 22, 2007 2:12 am    Post subject: Re: How to make IndexOf(Object) faster and still OO-ish? Reply with quote

Charles McAllister wrote:
Quote:
function TMyList.IndexOf(): Integer;
begin
//first, store params in private fields

Find(Self, Result, True);
end;


sorry should be...
if not Find() then
Result := -1;
Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi OO design All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.