Delphi XE2-64bit: bottleneck in trigonometric functions?
The 64bit introduced SSE2 maths, replacing the silicon-based implementations of the FPU by software.
(more…)
Tips, Hints and Documentation Posts for SamplingProfiler and other Delphi Tools
The 64bit introduced SSE2 maths, replacing the silicon-based implementations of the FPU by software.
(more…)
Click the image below for a little real-time verlet integration animation.
I’ve recently been adding DWScript snippets to Rosetta Code, using them as unit tests as well.
Quite a few of Rosetta Code’s tasks consist in mathematical tasks, and I was wondering, how many math tests do you really need?
…or why you can’t hide under the complexity carpet 😉
As uncovered in previous episodes, one of the keys behind TMonitor performance issues is that it allocates a dynamic block of memory for its locking purposes, and when those blocks end up allocated on the same CPU cache line, the two TMonitor on the same cache line will end up fighting for the cache line, resulting in a drastic drop of performance and thread contention. The technical term for that behavior is false sharing.
(more…)
Last episode in the TMonitor saga. In the previous episode, Chris Rolliston posted a more complete test case, for which he got surprising results (including that a Critical Section approach wouldn’t scale with the thread count). Starting from his code I initially also got similar surprising results.
edit: apparently the “crash” part of the TMonitor issues have been acknowledged by the powers that be, and a hotfix could be on the way, though it points back to QC 78415, an issue reported in 2009, ouch. Guess those 4 bytes per instance haven’t seen much use…
(more…)
Primoz Gabrijelcic recently reported a possible bug with TMonitor, in the more advanced side of TMonitor.
However, when experimenting with it for DWS, I bumped on issues in the basic usage scenarios too, and reverted to using critical sections. It seems that as of Delphi XE, short of a patch, TMonitor is just a waste of 4 bytes per object instance.
(more…)
A while back, I posted of FireFox 4 JavaScript engine running around Delphi when it came to floating point performance on the Mandebrot set, since then, Chrome got updated to version 11, and further raised the bar by beating FireFox by about 20% in that benchmark. That’s no mean feat: current generation JavaScript engines run not just faster than Delphi, but also .Net and a slew of other compilers, native or not, when it comes to floating point. Only state of the art native compiler still resist.
The figures for Delphi 64 are still unknown, but it’ll face a challenge merely matching the floating point performance of JavaScript, and if the VCL’s TCanvas hasn’t been revamped from the ground up, chances are that out of the box, Delphi 64 won’t be able to beat the HTML5 Canvas on performance (not to mention in features, where HTML5 Canvas is also leading by a few miles).
In Unicode Delphi, post-Delphi 2009, there are two ways of making case-insensitive string comparisons, CompareText, which only does case-insensitivity in the ASCII range (non-accentuated characters), and the judiciously misnommed AnsiCompareText, which works on the whole Unicode range by calling into the Windows API.
Objects memory management in Delphi Web Script is automatic, and you never have to worry about releasing objects in a script if you don’t want to. However, there are elements of manual memory management in DWS which provide greater control, and allow to enforce correctness of object-lifetime.
For instance, in DWS you can avoid the issue that is present in traditional GC-based environments, where references to long obsolete objects can still live in memory, and can still be invoked without triggering exceptions.
Up to and including version 2.2, the garbage collection is implemented in DWS through reference-counting (based on Delphi’s interfaces), and supplemented by a special garbage collector which is responsible for handling and cleaning up object dependency cycles.
If you have no particular memory constraints or requirements, you can thus safely create objects in DWS and not worry about their release. The special cycles GC means DWS isn’t vulnerable like Delphi’s interfaces-based reference-counting is.
With DWS 2.2, destructors are being brought back in a meaningful way, i.e you can manually destroy an object that is still referenced, and the object will then acquire a special “destroyed” status. Any attempt to access a destroyed object’s fields, or invoke a destroyed object’s methods will trigger an exception.
Beyond controlled release, this mechanism can be used to make sure that an object, even if incorrectly kept around, can’t be used anymore without an exception happening.
Note that unlike in Delphi, to guarantee the correctness of the “destroyed” status, a destroyed object that is still referenced will still use some memory, for as long as it is referenced. However, that object’s Delphi-side objects and memory can have been freed, as well as the object’s memory used to store the object’s fields.
When debugging, it is possible to iterate over all script objects (via the program’s execution object), including all the “destroyed” objects which are being kept because of “dangling” references.
Objects that have not been manually destroyed, and are still referenced by the time EndProgram is executed will be cleaned up without having their destructor invoked. This covers the cases where the script execution has been completed (end of code reached), has been aborted Delphi-side, via an execution timeout, or terminated because of an unhandled exception.
The destructors are not invoked because when EndProgram is triggered, the script is no longer supposed to be running in a any way or form: the stack has been torn-down, and cross-object references become meaningless as the clean up forcibly proceeds.
For external objects exposed through TdwsUnit, you will get an OnCleanup event, which allows you to release your Delphi-side objects, though in OnCleanup you have to be aware that the script has already been terminated, so you shouldn’t Call script functions, or rely on other script objects still existing or being valid.
A useful, yet not very prominent class of DWScript is TdwsSymbolDictionary. It provides a reference of all symbols mentioned in your script, where they are declared, where they are used, etc. It is optionally filled up when you compile a script with the coSymbolDictionary compile option, and can be accessed from a compiler program object or interface.
It can be used for multiple purposes, centered around IDE features and auditing. Here are a few usage scenarios.
The most basic use of TdwsSymbolDictionary is probably to figure out which symbol is under the cursor or the mouse in your code editor. You can then use the symbol to provide relevant contextual help (either from your help file, or auto-generated from the script, such as a list of parameters for a function, of fields for a class, etc.) or look up the dictionary once more, and provide information about where it’s declared, implemented, used or forwarded. That positional information can also be used to offer navigation shortcuts between declaration and implementation, or to any of the symbol’s occurrences in the source.
The TSymbolDictionary can be used it to figure out what is currently being typed, by identifying the symbol at the cursor, or the last recognized symbol in the code being entered. From that point on, you can generate a list of contextual variables, methods, fields, etc. that can be used to fill up an auto-completion drop down.
Once you have a symbol pinpointed, either by name or through one of its occurrences in the source, you have access to all the places it’s occurring in the code. A trivial use of such a list is for a rename refactoring: as the list of symbol positions is already sorted by source file, line and column, you merely have to walk the list backwards and replace occurrences in your sources files.
You can also team up TdwsSymbolDictionary with other information sources to implement more complex refactorings. For instance alongside TdwsSourceContextMap (which is also provided in a compiled program), you can implement “extract method” (or its variants, “pull up” & “push down”).
The symbol dictionary can be a convenient starting place for symbol-related audits and diagnostics. All audits that relate to the amount of times a symbol is used (or not) being the most trivial.
Another straightforward usage is when you have naming conventions for fields, variables, classes etc. and/or to enforce case consistency. The later can be handled in your IDE in a similar fashion as a rename refactoring, except you only replace in suReference and suImplementation symbol positions, and it is harmless enough you can do it in a background task without requiring user interaction.
You can also use it to diagnose code issues, for instance such patterns:
someObject.someProperty[stuff].otherProperty.function.method(1); someObject.someProperty[stuff].otherProperty.function.method(2); someObject.someProperty[stuff].otherProperty.function.method(3);
can be heuristically detected (either as “too many member symbols on the same line” or “member symbol repeated too much in nearby lines”), and the attention brought to the hot-spots so the code can be simplified and cleaned up.