Get the new [Wayback/Archive] Delphi Thread Safety Patterns eBook at a discount while it is hot:
Use Coupon Code: DTSPATT10 at checkout to get a $10 discount.
This promotional offer is valid through June 14.
Posted by jpluimers on 2022/06/01
Get the new [Wayback/Archive] Delphi Thread Safety Patterns eBook at a discount while it is hot:
Use Coupon Code: DTSPATT10 at checkout to get a $10 discount.
This promotional offer is valid through June 14.
Posted in Delphi, Development, Encoding, ISO-8859, ISO8859, Mojibake, Multi-Threading / Concurrency, Software Development, UTF-8, Windows-1252 | Leave a Comment »
Posted by jpluimers on 2022/05/18
Subtitle:
GetFullPathNamethread-unsafety because ofSetCurrentDirectoryisn’t, so derived functions (like DelphiGetDir/ChDir/TPath.GetFullPath, or .NETSystem.IO.Path.GetFullPath) are not thread-safe either (via The Old New Thing)
A while ago I got a big reminder because of [Wayback] What are these dire multithreading consequences that the GetFullPathName documentation is trying to warn me about? | The Old New Thing:
Posted in Delphi, Development, Pascal, Software Development, Turbo Pascal, Windows Development | Leave a Comment »
Posted by jpluimers on 2022/05/17
Earlier this year, [Wayback/Archive] Lars Fosdal posted a long thread about Embarcadero/IDERA software quality and one special person trying to offset the lack.
It is important not just because of his opinion, but also because Lars posts rarely about his Delphi opinion. He is the kind of guy quietly working with Delphi and doing a lot of community support.
When he posts, it is important and should be a signal to be picked up by Embarcadero/IDERA. Until now, not so much of that.
The first tweet was this:
Posted in Delphi, Development, Software Development | Leave a Comment »
Posted by jpluimers on 2022/01/26
When working with converging algorithms, sometimes floating code can become very slow. That is: orders of magnitude slower than you would expect.
A very interesting answer to [Wayback] c++ – Why does changing 0.1f to 0 slow down performance by 10x? – Stack Overflow.
I’ve only quoted a few bits, read the full question and answer for more background information.
Welcome to the world of denormalized floating-point! They can wreak havoc on performance!!!
Denormal (or subnormal) numbers are kind of a hack to get some extra values very close to zero out of the floating point representation. Operations on denormalized floating-point can be tens to hundreds of times slower than on normalized floating-point. This is because many processors can’t handle them directly and must trap and resolve them using microcode.
If you print out the numbers after 10,000 iterations, you will see that they have converged to different values depending on whether
0or0.1is used.
Basically, the convergence uses some values closer to zero than a normal floating point representation dan store, so a trick is used called “denormal numbers or denormalized numbers (now often called subnormal numbers)” as described in Denormal number – Wikipedia:
…
In a normal floating-point value, there are no leading zeros in the significand; rather, leading zeros are removed by adjusting the exponent (for example, the number 0.0123 would be written as 1.23 × 10−2). Denormal numbers are numbers where this representation would result in an exponent that is below the smallest representable exponent (the exponent usually having a limited range). Such numbers are represented using leading zeros in the significand.
…
Since a denormal number is a boundary case, many processors do not optimise for this.
–jeroen
Posted in .NET, Algorithms, ARM, Assembly Language, C, C#, C++, Delphi, Development, Software Development, x64, x86 | Leave a Comment »
Posted by jpluimers on 2022/01/19
Since uptimerobot has slowly moving free features, part of my family uses it to monitor uptime of their personal stuff, and I don’t want to pay for the free monitoring I do on Embarcadero infrastructure (I know that they have been phasing out older useful sites for ages, but even their main sites were down for 2 days about a year ago).
Yes, I know the competitiveness of [Wayback] Website monitoring – Wikipedia, and I’m glad Uptimerobot has been there for a relatively long time, but alas: for personal use…
The list of of the pricing pages of each site, containing a one line summary blurb if it was available:
Freshping FREE plan ✓ 50 URL checks ✓ 1-minute interval ✓ FREE Public status pages. Need more? Check out the enterprise plan.
50k API check runs / mo, 5k browser check runs / mo, 5 users, basic features
Basic, FREE, 10 Uptime Monitors, 5 Minute Tests
Free: 3 Checks, 5 minute min. monitoring interval, All check types, 3 days history max, 0 sms alerts, ∞ email alerts, SSH Only
Via [Wayback] 16 Best Online Services to Monitor Sites Uptime
–jeroen
Posted in *nix, Delphi, Development, Monitoring, Power User, Software Development | Leave a Comment »
Posted by jpluimers on 2022/01/12
I thought I had written about this a long time ago, as Math.SetRoundMode (and now System.Math.SetRoundMode) has been introduced since at least Delphi 2007. There are also related GetRoundMode and TFPURoundingMode.
Delphi 2009 also introduced TFPUPrecisionMode, GetPrecisionMode and SetPrecisionMode.
Delphi 2010 also introduced TFPUException, TFPUExceptionMask, TFPUPrecisionMode, TFPURoundingMode, ClearExceptions, GetExceptionMask, and SetExceptionMask.
Delphi XE2 introduced namespaces, so prepended the unit Math with the namespace System. to become unit System.Math. It also introduced $EXCESSPRECISION (for x64), GetMXCSR, SetMXCSR, ResetMXCSR, ClearFPUExceptions, TSSEException, TSSEExceptionMask, GetSSEExceptionMask, SetSSEExceptionMask, ClearSSEExceptions, TSSERoundingMode, GetSSERoundMode, SetSSERoundMode.
The documentation basically only had formatting changes. This is the most important part of SetRoundMode:
function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode;…
Call
SetRoundingModeto specify how the FPU handles rounding issues. The rounding mode can be any of the following values:
Value MeaningrmNearest Rounds to the closest value.rmDown Rounds toward negative infinity.rmUp Rounds toward positive infinity.rmTruncate Truncates the value, rounding positive numbers down and negative numbers up.
This is the most important bit of SetPrecisionMode:
function SetPrecisionMode(const Precision: TFPUPrecisionMode): TFPUPrecisionMode;…
Call
SetPrecisionModeto specify the level of precision that the FPU (floating-point unit) uses for floating-point calculations. The precision control mode can be any of the following values:
Value MeaningpmSingle single precisionpmReserved not usedpmDouble double precisionpmExtended extended precision
SetPrecisionModereturns the previous precision control mode.
Both are functions, so so they return the previous value which you can use to set it back later: this is important as it is a process wide. SetPrecisionMode documents this, but SetRoundMode does not!
Since SetRoundMode and SetPrecisionMode set the 8087 CW (and on XE2 and up SetMXCSR), it means all usual Set8087CW caveats apply: changing the global 8087 CW setting impacts all running code, which means that threads, DLLs (especially ones written in other languages), etc might malfunction. You can find some of the caveat effects on my bog by searching for [Wayback] Set8087CW site:wiert.me – Google Search.
If you want to avoid global side effects, you might try the solution in [Wayback] c# – What is the equivalent of Math.Round() with MidpointRounding.AwayFromZero in Delphi? – Stack Overflow by [Wayback] Andreas Rejbrand.
[Wayback/Archive.is] SSE Instruction Set (not sure why Embarcadero used this as reference material from their docwiki, but hey, Intel documentation is likely outdated):
SSE — MXCSR
The
MXCSRregister is a 32-bit register containing flags for control and status information regarding SSE instructions. As of SSE3, only bits 0-15 have been defined.
Pnemonic Bit Location Description FZ bit 15 Flush To Zero R+ bit 14 Round Positive R- bit 13 Round Negative RZ bits 13 and 14 Round To Zero RN bits 13 and 14 are 0 Round To Nearest PM bit 12 Precision Mask UM bit 11 Underflow Mask OM bit 10 Overflow Mask ZM bit 9 Divide By Zero Mask DM bit 8 Denormal Mask IM bit 7 Invalid Operation Mask DAZ bit 6 Denormals Are Zero PE bit 5 Precision Flag UE bit 4 Underflow Flag OE bit 3 Overflow Flag ZE bit 2 Divide By Zero Flag DE bit 1 Denormal Flag IE bit 0 Invalid Operation Flag
FZmode causes all underflowing operations to simply go to zero. This saves some processing time, but loses precision.The
R+,R-,RN, andRZrounding modes determine how the lowest bit is generated. Normally,RNis used.
PM,UM,MM,ZM,DM, andIMare masks that tell the processor to ignore the exceptions that happen, if they do. This keeps the program from having to deal with problems, but might cause invalid results.
DAZtells the CPU to force all Denormals to zero. A Denormal is a number that is so small that FPU can’t renormalize it due to limited exponent ranges. They’re just like normal numbers, but they take considerably longer to process. Note that not all processors supportDAZ.
PE,UE,ME,ZE,DE, andIEare the exception flags that are set if they happen, and aren’t unmasked. Programs can check these to see if something interesting happened. These bits are “sticky”, which means that once they’re set, they stay set forever until the program clears them. This means that the indicated exception could have happened several operations ago, but nobody bothered to clear it.
DAZwasn’t available in the first version of SSE. Since setting a reserved bit inMXCSRcauses a general protection fault, we need to be able to check the availability of this feature without causing problems. To do this, one needs to set up a 512-byte area of memory to save the SSE state to, usingfxsave, and then one needs to inspect bytes 28 through 31 for theMXCSR_MASKvalue. If bit 6 is set,DAZis supported, otherwise, it isn’t.
Architectures Software Developer’s Manual: Intel® 64 and IA-32 includes supporting processors programming environment and architecture.
[Wayback] Intel® 64 and IA-32 Architectures Developer’s Manual: Vol. 1
[Wayback]
Some of the documentation links (that regrettably do not explain what happens behind the scenes with the 8087 CW) are these:
System namespace got prepended, x64 support added and a rudimentary page [Wayback] Floating-Point Rounding Issues – RAD Studio XE2 added
$EXCESSPRECISIONTSSEPrecisionModeSetSSEPrecisionModeGetSSEPrecisionMode
–jeroen
Posted in Delphi, Development, Software Development | Leave a Comment »
Posted by jpluimers on 2022/01/06
Contrary to what many believe is that MySQL utf8 is not always full blown UTF-8 support, but actually utf8mb3, which has been deprecated for a while now.
Only utf8mb4 will give you full blown UTF-8 support.
This when someone reminded me of this in a Delphi application:
When I insert :joy: emoji into mysql varchar filed I got an error :
#22007 Incorrect string value: '\xF0\x9F\x98\x82' for column 'remarks' at row 1database charset is
utf8
Note that the :joy: emoji is 😂 and has Unicode code point U+1F602 which is outside the basic multilingual plane.
See:
- Kristian Köhntopp
»Where does PostgreSQL’s collation logic come from?
PostgreSQL relies on external libraries to order strings.
– libc, meaning the operating system locale facility (POSIX or Windows)
– icu, meaning the ICU project (if PostgreSQL was built with ICU support)«- MySQL does things differently:
MySQL binary data files are independent of the host operating system in byte order, number representation (as long as the host fulfils MySQLs basic requirements), collation and even time zone handling.- So MySQL implements collations internally, also to guarantee stability across OS updates.
If it didn’t, a libc update changing collations would mean you have to recreate a lot of indexes. Also, you would not be able to safely move data files from host to host.- MySQL also, for quite some time now, no longer updates its own charsets and collations internally, for the same reason.
So utf8 in MySQL is utf8mb3, the three byte variant of Unicode UTF-8 implementation that covers only the BMP (unicode up to U+FFFF).- When moving to fuller (multiplane) UTF-8 support, a new name was needed, and utf8mb4 was chosen.
So when you actually want modern utf8 in MySQL, you have to use utf8mb4, and now you know why.- utf8 is deprecated and will be upgraded to utf8mb4 in some future MySQL release. This will be a breaking upgrade, and I wonder if it will require dropping and recreating all indexes affected by the change.
That will be painful.- https://dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8mb3.html …
utf8mb3 page in the MySQL 8.0 manual, with deprecation notice.
What will change is the meaning of the alias utf8 (currently an alias for utf8mb3).
utf8mb3 Character Set (3-Byte UTF-8 Unicode Encoding)
utf8is an alias forutf8mb3; the character limit is implicit, rather than explicit in the name.NoteThe
utf8mb3character set is deprecated and you should expect it to be removed in a future MySQL release. Please useutf8mb4instead. Althoughutf8is currently an alias forutf8mb3, at some pointutf8is expected to become a reference toutf8mb4. To avoid ambiguity about the meaning ofutf8, consider specifyingutf8mb4explicitly for character set references instead ofutf8.
utf8mb4contrasts with theutf8mb3character set, which supports only BMP characters and uses a maximum of three bytes per character:
- For a BMP character,
utf8mb4andutf8mb3have identical storage characteristics: same code values, same encoding, same length.- For a supplementary character,
utf8mb4requires four bytes to store it, whereasutf8mb3cannot store the character at all. When convertingutf8mb3columns toutf8mb4, you need not worry about converting supplementary characters because there are none.
–jeroen
Posted in Conference Topics, Conferences, Database Development, Delphi, Development, Encoding, Event, MySQL, Software Development, UTF-8, UTF8 | Leave a Comment »
Posted by jpluimers on 2021/12/22
For my link archive, as I hardly see this (it happens in many Delphi versions and always has to do with missing/wrong DLLs), so always forget how to solve it.
Basically it is the same fix as for Fixing hg.exe “ImportError: DLL load failed: %1 is not a valid Win32 application.”:
If you get the below error when running hg.exe, then you are mixing a 64-bit Mercurial with 32-bit dependencies.
[Wayback] XE2 – “%1 is not a valid Win32 application” when installing a package – embarcadero.delphi.ide with entries by [Wayback] Remy Lebeau and [Wayback] Jeff Overcash:
I don't know what I did, but when trying to install a set of freshly built Delphi Win32 packages into the IDE, XE2 is giving me this error message now: {quote} Can't load package ... %1 is not a valid Win32 application. {quote}
a
> Often that is caused by the same named 32 and 64 bit run time packages > and the OS finding the 64 bit first when the IDE must load the 32 bit. If > that is the case check your path variable and make sure the 32 bit paths > appear first. That was the problem. The Windows PATH variable had a 64-bit folder in front of the 32-bit folder. Deleted the 64-bit files and the error went away. Noe I'm getting a new error: {quote} The program can't start because <RuntimePackage>.bpl is missing from your computer. Try reinstalling the program to fix this problem. {quote} But the "missing" package is in the same folder as the design-time package I am trying to install.
Since the design time location is known it is explicitely loaded, but the run time is implicitly loaded and follows the dll loading rules. Both are dynamically loaded. The reason you only see this the next time you restart the IDE is because the working directory changes to your project directory when you load a project so if the runtime is there it is found that way, but the next time you load the IDE the working directory starts in the bin directory.
I thought it was, but turns out the 32-bit output folder had been moved and the PATH was not updated accordingly. Fixed the PATH and now the packages install.
–jeroen
Posted in Delphi, Development, Software Development | Leave a Comment »