Re: [fpc-pascal] Re: UnicodeString comparison performance

2012-07-24 Thread Thomas Schatzl
HI,

On Mon, 2012-07-23 at 16:58 +0200, OBones wrote:
 Jonas Maebe wrote:
  On 23 Jul 2012, at 10:58, OBones wrote:
 
  leledumbo wrote:
  I look at the generated code and in the direct one there's additional
  overhead of decrementing the reference counter on each iteration.
  I see it too now (I forgot about the -a option).
  I can understand why there is a call to the decrementer outside the loop 
  when using the variable, but I don't understand why it pushes it 
  completely out of the loop. I mean, isn't there a reference count problem 
  here?
  Reference counted data types are returned by reference in a location passed 
  to the function by the caller. The compiler here passes the address of S to 
  the function, so that when assigning something to the function result 
  inside the function, S' reference count gets decreased.
 
  The fact that when the result is returned in a temp, this temp also gets 
  finalized on the caller side before the call is just a code generator 
  inefficiency. I've changed that in trunk.
 Thanks for the explanation and the fix.

 Because the finalization happened too early, those memory allocations 
 and deallocations were very costly and I found the direct code to be 30 
 times slower.
 Doing it this way has the advantage of being inherently thread safe, but 
 considering the performance penalty, I have moved to doing it this way:
 
 var
Buffer: array [0..1024*1024-1] of WideChar;
BufferLock: NativeInt;
 
 function GetSomeString(Index: Integer): UnicodeString;
 begin
while BufferLock  0 do
  Sleep(1);
 
InterlockedIncrement(BufferLock);
try
  CallToAnAPIThatWritesBackAWideString(@Buffer[0], Length(Buffer) - 1);
  Result := PWideChar(@Buffer[0]);
finally
  InterlockedDecrement(BufferLock);
end;
 end;
 
 This works, with an equivalent penalty on both methods and is threadsafe 
 (I believe).

This code is not thread safe at all. A thread switch after the while
loop and before the increment will not prevent progress on other
threads, so multiple threads can enter the critical section.

Use EnterCriticalSection/LeaveCriticalSection from the RTL if you need
that.

If you could somewhat decrease the size of your buffer to something
reasonable - do you really expect to translate a string with 1M chars? -
use the stack. Actually even a 2M data object on the stack might be
reasonable.

Further, in any case you'll need some code that works in all cases
anyway - what if your string does exceed 1M chars after all? I mean, on
a 1M string, heap allocation will probably be the least of your
performance worries.

This will completely avoid use of any synchronization primitive.

E.g.

function GetSomeString(index : integer) : UnicodeString;
const
  bufsize = 1024; // as you wish
var
  buffer : array[0..bufsize-1] of WideChar;
  pbuffer : PWideChar;
  islongstring : boolean;
  lengthofstring : integer;
begin
  lengthofstring := length(stringfromindex(integer));
  islongstring := lengthofstring  bufsize;
  if (islongstring) then
pbuffer := getmem(lengthofstring * sizeof(WideChar));
  else
pbuffer := @buffer;
  CallToAnAPIThatWritesBackAWideString(stringfromindex(integer),
pbuffer, lengthofstring);
  if (islongstring) then
freemem(pbuffer);
  result := pbuffer;
end;

You may want to improve the code further by e.g. checking whether the
memory allocation has been successful or not; or factor out the case
when the string is big into a separate method to improve readability.

Thomas


___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Re: UnicodeString comparison performance

2012-07-24 Thread OBones

Thomas Schatzl wrote:

This code is not thread safe at all. A thread switch after the while
loop and before the increment will not prevent progress on other
threads, so multiple threads can enter the critical section.
Well, yes, even if under Windows it's rare that a thread is preempted 
right in the middle of its execution. At least that's what my own 
experience has told me and why I'm calling Sleep in the while loop, so 
that the thread yields to other ones.



Use EnterCriticalSection/LeaveCriticalSection from the RTL if you need
that.
I did not because I thought that would be too slow, but it turns out 
it's not so yes, it's much better.



If you could somewhat decrease the size of your buffer to something
reasonable - do you really expect to translate a string with 1M chars? -
use the stack. Actually even a 2M data object on the stack might be
reasonable.
That's the highest value that the documentation of the API is giving, so 
I guess the API will respect its own publicized contract.



function GetSomeString(index : integer) : UnicodeString;
const
   bufsize = 1024; // as you wish
var
   buffer : array[0..bufsize-1] of WideChar;
   pbuffer : PWideChar;
   islongstring : boolean;
   lengthofstring : integer;
begin
   lengthofstring := length(stringfromindex(integer));
   islongstring := lengthofstring  bufsize;
   if (islongstring) then
 pbuffer := getmem(lengthofstring * sizeof(WideChar));
   else
 pbuffer := @buffer;
   CallToAnAPIThatWritesBackAWideString(stringfromindex(integer),
pbuffer, lengthofstring);
   if (islongstring) then
 freemem(pbuffer);
   result := pbuffer;
end;
Thanks for your example, but it implies that the string length is known 
before calling the API while this is not the case.
The API is given a buffer and a maximum length, a buffer into which it 
writes a zero terminated string. But the length of that string cannot be 
known beforehand, hence the reason why I wrote it that way.
Note also that having buffer local to the function is just as bad 
(performance wise) as setting the length of the result string.


In the end, many thanks for your suggestions, I'll go with the critical 
section as it is much safer.


Regards
Olivier
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Re: UnicodeString comparison performance

2012-07-24 Thread Sven Barth

Am 24.07.2012 13:21, schrieb OBones:

Thomas Schatzl wrote:

This code is not thread safe at all. A thread switch after the while
loop and before the increment will not prevent progress on other
threads, so multiple threads can enter the critical section.

Well, yes, even if under Windows it's rare that a thread is preempted
right in the middle of its execution. At least that's what my own
experience has told me and why I'm calling Sleep in the while loop, so
that the thread yields to other ones.


Windows will preempt a thread once it's time slice has run out or it 
yields it's execution. In the first case it does not matter whether the 
thread is inside some function execution, because the sheduler does not 
know about such a concept.


Regards,
Sven
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


[fpc-pascal] Dynamic messaging in Delphi

2012-07-24 Thread Ryan Joseph
I was asking on the Mac Pascal list if Delphi had any ways to invoke methods on 
objects which the class was unknown at compile time (like a class that invokes 
a user defined delegate commonly used in Cocoa Mac programming and I assume 
Delphi not knowing) and one user told me interfaces will work for this. Btw, 
I'm aware you can use strings to invoke methods with a single argument but I 
wanted something better since this has been a real drawback in Pascal for me in 
recent years.

The idea is Main.pas has a delegate class which implements IMyInterface and 
MyInterface.pas declares the interface and can invoke its methods using a 
generic delegate object (typed TObject). This is really typical of UI elements 
like a button that wants to tell a receiver an action occurred but doesn't know 
the class of the receiving object. Providing this example works it's sort of a 
workaround to multiple inheritence but I don't see that Pascal would be capable 
of this, i.e. simply type casting an object and forcing it to call a method 
that may or may not exist (I feel like I tried this before and got crashing).

He swears this works and no one else answered otherwise but I'm getting Error: 
Class or Object types TObject and IMyInterface are not related errors at 
the line shown below.

Any ideas? Thanks.



{$mode delphi}
{$interfaces corba}

unit MyInterface;
interface

type
IMyInterface = interface
procedure DoThis (value: integer);
end;

procedure InvokeDelegate (delegate: TObject);

implementation

procedure InvokeDelegate (delegate: TObject);
var
intfDelegate: IMyInterface;
begin
ERROR  intfDelegate := IMyInterface(delegate);
intfDelegate.DoThis(1);
end;

end.



{$mode delphi}
{$interfaces corba}

program Main;
uses
MyInterface;

type
TMyDelegate = class (TInterfacedObject, IMyDelegate)
procedure DoThis (value: integer);
end;

procedure TMyDelegate.DoThis (value: integer);
begin
writeln('did this ', value);
end;

var
delegate: TMyDelegate;
begin   
delegate := TMyDelegate.Create;
TestDelegate(delegate);
end.

Regards,
Ryan Joseph
thealchemistguild.com

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Dynamic messaging in Delphi

2012-07-24 Thread Luiz Americo Pereira Camara

Em 24/7/2012 11:13, Ryan Joseph escreveu:

I was asking on the Mac Pascal list if Delphi had any ways to invoke methods on 
objects which the class was unknown at compile time (like a class that invokes 
a user defined delegate commonly used in Cocoa Mac programming and I assume 
Delphi not knowing) and one user told me interfaces will work for this. Btw, 
I'm aware you can use strings to invoke methods with a single argument but I 
wanted something better since this has been a real drawback in Pascal for me in 
recent years.

The idea is Main.pas has a delegate class which implements IMyInterface and 
MyInterface.pas declares the interface and can invoke its methods using a 
generic delegate object (typed TObject). This is really typical of UI elements 
like a button that wants to tell a receiver an action occurred but doesn't know 
the class of the receiving object. Providing this example works it's sort of a 
workaround to multiple inheritence but I don't see that Pascal would be capable 
of this, i.e. simply type casting an object and forcing it to call a method 
that may or may not exist (I feel like I tried this before and got crashing).

He swears this works and no one else answered otherwise but I'm getting Error: Class or Object types 
TObject and IMyInterface are not related errors at the line shown below.


  if delegate.GetInterface(IMyInterface, intfDelegate) then
intfDelegate.DoThis

Luiz



Any ideas? Thanks.



{$mode delphi}
{$interfaces corba}

unit MyInterface;
interface

type
IMyInterface = interface
procedure DoThis (value: integer);
end;

procedure InvokeDelegate (delegate: TObject);

implementation

procedure InvokeDelegate (delegate: TObject);
var
intfDelegate: IMyInterface;
begin
ERROR   intfDelegate := IMyInterface(delegate);
intfDelegate.DoThis(1);
end;

end.



{$mode delphi}
{$interfaces corba}

program Main;
uses
MyInterface;

type
TMyDelegate = class (TInterfacedObject, IMyDelegate)
procedure DoThis (value: integer);
end;

procedure TMyDelegate.DoThis (value: integer);
begin
writeln('did this ', value);
end;

var
delegate: TMyDelegate;
begin   
delegate := TMyDelegate.Create;
TestDelegate(delegate);
end.

Regards,
Ryan Joseph
thealchemistguild.com

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal



___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Dynamic messaging in Delphi

2012-07-24 Thread Ryan Joseph
I never heard of this syntax, is it Delphi only? 

Trying this I got Error: Interface type IMyInterface has no valid GUID. What 
else do I need to do?

Thanks.

On Jul 24, 2012, at 4:26 PM, Luiz Americo Pereira Camara wrote:

  if delegate.GetInterface(IMyInterface, intfDelegate) then
intfDelegate.DoThis

Regards,
Ryan Joseph
thealchemistguild.com

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] Dynamic messaging in Delphi

2012-07-24 Thread Luiz Americo Pereira Camara

Em 24/7/2012 20:17, Ryan Joseph escreveu:

I never heard of this syntax, is it Delphi only?

Trying this I got Error: Interface type IMyInterface has no valid 
GUID. What else do I need to do?


The sintaxe i posted is for COM interfaces.

For CORBA interfaces do

  IMyInterface = interface
   ['myintf']
procedure DoThis (value: integer);
end;

if delegate.GetInterface('myintf', intfDelegate) then
   intfDelegate.DoThis


Luiz




Thanks.

On Jul 24, 2012, at 4:26 PM, Luiz Americo Pereira Camara wrote:


 if delegate.GetInterface(IMyInterface, intfDelegate) then
   intfDelegate.DoThis


Regards,
Ryan Joseph
thealchemistguild.com http://thealchemistguild.com



___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal