Profile cover photo
Profile photo
Stefan Glienke
462 followers
462 followers
About
Posts

Post has attachment

Shouldn't the compiler be able to devirtualize the call in the interface trampoline methods it generates for IFoo? It knows that it can only point to TFoo.Test

See this code:

type
IFoo = interface
procedure Test;
end;

TAbstractFoo = class(TInterfacedObject)
procedure Test; virtual; abstract;
end;

TFoo = class(TAbstractFoo)
procedure Test; override;
end;

TSealedFoo = class sealed(TFoo, IFoo)
end;

procedure TFoo.Test;
begin
end;

var
foo: IFoo;
fooA: TAbstractFoo;
fooB: TFoo;
fooC: TSealedFoo;
begin
foo := TSealedFoo.Create;
foo.Test;

fooC := TSealedFoo.Create;
fooB := fooC;
fooA := fooC;
fooA.Test; // virtual call
fooB.Test; // virtual call
fooC.Test; // static call to TFoo.Test

When calling the interface method and inspecting the disassembly you can see that it does the virtual call in the compiler generated trampoline method (and on win32 also suffers from a defect described here: http://andy.jgknet.de/blog/2016/05/whats-wrong-with-virtual-methods-called-through-an-interface/)

I strongly believe that the compiler should devirtualize these calls when it is able to. Before anyone asks why would you do virtual methods behind interfaces: because sometimes you want to provide a base class that already implements the base behavior and you only need to override if you want specific behavior.

Especially since we don't have interface helpers / extension methods you might have a design where the interface offers a rich API which internally just redirects to other methods where maybe only one needs to be implemented. So you can make that method virtual abstract while all the other methods ultimately call this one - all already implemented in the base class.

Post has attachment

I wonder if anyone is bold enough to put his Delphi web application framework up for test since I don't see any in that list - I wonder how they would perform.

mORMot (+A. Bouchez), DMVC (+Daniele Teti), Mars (+Andrea Magni), RADServer (+Marco Cantù) - I guess there are more but those where the ones that came to my mind

https://www.techempower.com/benchmarks/

Post has attachment
Planning of a two day conference in early 2019 (spring of course) all about Spring4D - presumably in northern italy - just started.

Those of you that would like to attend please vote and/or comment.

#spring4dconf
-
votes visible to Public
45%
Yes, of course!
55%
Yes, but ...

Bogus W1036 ?

Documentation: http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Variables_(Delphi)

"If you do not explicitly initialize a global variable, the compiler initializes it to 0."

Code:

{$APPTYPE CONSOLE}

var
i: Integer;
begin
Writeln(i);
end.

[DCC Warning] Project1.dpr(6): W1036 Variable 'i' might not have been initialized

Is anyone using DUnitX to run unit tests on Linux?
I keep getting an AV (see https://github.com/VSoftTechnologies/DUnitX/issues/201)

DUnit just works.

Spring4D 1.2.1 release is getting close!

It does not only contain a lot of bugfixes and improvements but also some new features (and a few minor breaking changes, sorry! but don't be worried). More about those in detail soon or in the Releasenotes.txt

Please have a look at all those in the release/1.2.1 branch. This is basically beta testing for the upcoming release - let us know if there are any issues.

We have a new red-black tree implementation which is used by the new TSortedDictionary and TSortedSet. Using the tree internally they always keep the items in order as specified by the default or the passed comparer.

There are also the new TOrderedDictionary and TOrderedSet who remember the item insertion order (they internally are hash based just like the regular TDictionary and THashSet but additionally remember the key insertion order).

See this example code:

procedure PrintSet(const values: ISet<Integer>);
var
i: Integer;
begin
for i in values do
Write(i, ' ');
Writeln;
end;


begin
PrintSet(TCollections.CreateSet<Integer>([5, 4, 3, 2, 1]));
PrintSet(TCollections.CreateOrderedSet<Integer>([5, 4, 3, 2, 1]));
PrintSet(TCollections.CreateSortedSet<Integer>([5, 4, 3, 2, 1]));
end.

The order of the first is "random" (well, determined by the internal hash) but not really predictable.
The second will print 5 4 3 2 1 because it keeps the insertion order and the third will print 1 2 3 4 5 as it has the items sorted.

More about the Spring4D 1.2.1 release soon ;)

Since recently there was the discussion about the QuickSort implementation in Delphi suffering from the worst case performance and possible stack overflow I looked into IntroSort (see https://en.wikipedia.org/wiki/Introsort) and the Microsoft implementation (see http://blog.teamleadnet.com/2013/08/introsort-algorithm-in-net-45-internal.html)

Here is my current implementation - there might be some room of improvement (currently just testing with long array of Integer which performs approx 30% faster on random data) and only is a bit slower on reverse ordered input than the RTL implementation:

https://bitbucket.org/snippets/sglienke/64LG6b/introsort

Please let me know your feedback and improvement suggestions.

Drawing with ReactiveX: https://bitbucket.org/snippets/sglienke/BEXnM9

Yes, the classic approach would be way less code but you get the idea of how you can combine multiple event streams to achieve these things.

Still looking for ways to reduce the generic argument cluttering.

FWIW here is the same example in JS: https://codepen.io/HunorMarton/pen/mWVVXg

Links to the feature requests mentioned in the comments (please vote):
https://quality.embarcadero.com/browse/RSP-16763
https://quality.embarcadero.com/browse/RSP-10336
Wait while more posts are being loaded