In the hopes of finding more performance I thought I would see how Delphi is doing these days. I installed 11.3 and installed the cge packages and configured as per instructions.
Build proceeds and I fix various things to make them work for either compiler. But it is stopping in terrain.fs.inc because it doesn’t know what LineEnding is. I see this is #13#10 defined in syswinh.inc for fpc. I was hoping to just have to fix my code to work with Delphi. My cge version should be quite recent.
( I already don’t like busy monolithic huge window with many panes interface).
CGE fully compiles and works with Delphi, we auto-test it (for Delphi 11.3 and 10.2) and I regularly test manually (with 12.0). With community version too.
I seems you encounter this because terrain.fs.inc is in your project now, you copied it from CGE, according to one of past threads?
To solve it, add CastleUtils unit to the uses clause of the code that includes terrain.fs.inc. This defines LineEnding = SLineBreak, so Delphi will know LineEnding.
Alternatively, search/replace LineEnding → SLineBreak in your code. I emphasize that the files included in CGE, in particular terrain.fs.inc, should require zero modifications (submit a bug otherwise). This replacement should be done for include file in your project.
What should I do with the {$mode ObjFPC}{$H+} that fpc puts at the beginning of each file? Does this really matter? I commented it out and it still compiles fine on fpc.
I am having to deal with Delphi code I have from the old days. That is unencouraging. Embarcadero seems to have lost various divmod variations. +1 for FPC!
Argh. Delphi doesn’t support using dynamic methods as property functions?! Forcing me to make a bunch of methods virtual, making my memory footprint for the class huge. +10 for FPC.
We actually recommend to remove it – because it’s not necessary. Both Lazarus project settings, and Castle Game Engine default settings (hardcoded in CGE build tools) already specify options to FPC to say to use ObjFpc mode ({$mode ObjFPC}) and AnsiStrings ({$H+}).
So, yeah, you can just remove it. CGE examples also don’t use this.
Wow, that was a disappointing waste of time. Delphi pulls off 4fps in debug mode and 6fps in release mode compared to FPC getting more like 30fps in debug and 40fps in release. I don’t understand how it could be so bad. Delphi used to be fast. Do they cripple the community version somehow? fpc ftw.
Can you think of why Delphi performance would be so poor? Surely fpc isn’t an order of magnitude better?
The difference comes from FPC “ObjFpc mode” having a bit different idea how to deal with procedular variables. FPC “ObjFpc mode” says that in order to take an address of a procedular variable, you must use @. So e.g. you have to write
procedure Txxx.ButtonClick(Sender: TObject);
begin
end;
procedure ....;
begin
OnClick := @ButtonClick;
end;
It will not compile without @.
This is helpful to make some expressions unambiguous. E.g. what does it mean if OnMyEvent = MyFunction then ..., when events are defined as function: Integer → does this compare assigned events, or calls them? It gets even more complicated when the function returns the address of another function (like function: TNotifyEvent). In FPC ObjFpc mode, such expressions are simple to understand, because “without @, you cannot take address of a procedure, so the above calls the MyFunction”.
On the other hand, Delphi decided that ButtonClick, without @ is already a valid “address of ButtonClick”. In effect, only this compiles:
procedure ....;
begin
OnClick := ButtonClick;
end;
and trying to write OnClick := @ButtonClick; in Delphi will make an error, since you try to take an address of the address of ButtonClick, so it’s an address of temp variable, not useful.
From what I know, the advantage of “Delphi syntax” is just brevity. You can forget about @, and most expressions are obvious to the compiler, i.e. it can tell when you want to call a function, and when to take a function address.
What to do?
In CGE code and examples, we decided to just “live with it” and write {$ifdef fpc}@{$endif} everywhere needed. We like the extra clarity that comes from FPC ObjFpc requiring @. Also, many FPC / Lazarus users are most used to ObjFpc mode, since it’s the default mode set up in new Lazarus projects, so we abide to it. So we write
But for simplicity, we decided to assume “when CGE is compiled with FPC, we know it is compiled in FPC ObjFpc mode, since we set it ourselves in both command-line and by castleconf.inc”.
You can also choose a different approach: use “Delphi mode” with FPC. To do this, put -Mdelphi in compiler options in CastleEngineManifest.xml (Lazarus project settings also have a setting to change mode). See " 6.11. Compiler options and paths" in CastleEngineManifest.xml - Syntax and Examples | Manual | Castle Game Engine , we explicitly show there and discuss using -Mdelphi.
Then you have more consistent code between FPC and Delphi.
Hm, this is actually weird and doesn’t match my experience. When I measured, with CGE examples, the speed of everything was just equal between FPC and Delphi.
So the things we do on CPU, in Pascal, had mostly the same speed. And in many cases the Pascal code speed didn’t even matter so much (optimization of game engine is often “to deliver data in an efficient way to GPU”, and then you delegate most of “heavy lifting” to GPU; this is not always easy/done, but it is our goal, see also " 3.4. Optimize smartly: profile, optimize where it matters (and not where it doesn’t), think about smarter algorithms and moving CPU work to GPU to get big benefits" on Coding Conventions | Manual | Castle Game Engine ).
I don’t know why do you observe such big difference FPC vs Delphi speed. I wouldn’t be very surprised if, depending on particular application, one of them is better than other e.g. by 1.5x … (though that’s already larger difference than my experience tells me usually happens) but 10x is crazy If you’ll find out, please write here → I’m very curious.
I have narrowed down my performance issue. If I don’t start my work threads, it stays fast. The work threads ‘play life’ with a static array of singles and don’t do any file io, memory allocation, or do anything to collide with the main thread. Even if I comment out where the main thread updates a mesh with this data, it stays slow. It is as if the work threads are running in the main thread, even though the thread object knows it is not issingleprocessor. It doesn’t seem like you have to do anything special to enable threading in delphi?
No, you don’t need to do anything to activate threading in Delphi.
And modern Delphi even has a bit more feature-rich threading API, from what I know. I attended a workshop about threads in Delphi last year (during conference in Salamanca ), led by Primož Gabrijelčič, very smart person, knows everything about threads (author of OmniThreadLibrary). He showed a lot of cool features in Delphi about threads, only a subset of them implemented in FPC.
So, it does seem weird if Delphi’s threads seem “crippled in performance” for you.
It seems like Set8087CW($133F); was the solution to getting the floating point math in the work threads to not kill the main thread, but I am still not seeing enough performance to warrant switching to Delphi from FPC as I had hoped. No magic bullets.
That wasn’t actually the solution. I haven’t found a solution. I was getting the same performance because fpc had built that ‘success’, not Delphi. It bothers me to wonder why it seems like my simple thread floating point math is killing the main thread on Delphi. Just lots of single compares and addition between -100 and 100. I will just stick with fpc which runs so smooth and doesn’t try to remind you to pay Embarcadero all the time. At least all my stuff builds for Delphi now too.