Jump to content

Attila Kovacs

Members
  • Content Count

    1936
  • Joined

  • Last visited

  • Days Won

    25

Everything posted by Attila Kovacs

  1. Attila Kovacs

    TMemoryStream.Write

    @Alexander Sviridenkov Those implicit try/except blocks are really slow, you are right. These OoOE compliant codes are not so spectacular but they could sum up. I took a random example from htutils.pas, "AnsiStartsWith" and changed the early exit against "if (ls > lt) and (lt > 0) then .. else ...", as this is the most likely to happen and this is the path which will be predicted and I can measure around 5.5% faster code with a long "s" and a long "start" parameter. But I really needed long parameters + many many runs to be able to measure anything.
  2. Attila Kovacs

    TMemoryStream.Write

    As this is a nested proc, the generated code has no multiple exit points. Actually it's a very clean and straightforward asm, so no gain with your changes, rather a tick slower as you assigning the result twice. My original change however was shocking for me, same code, its parts in different order, 6.25% faster.
  3. Attila Kovacs

    TMemoryStream.Write

    Ok, here is a real-world example. In the code from https://quality.embarcadero.com/browse/RSP-29731 the original nested proc was: function IsBreak(AChar: PChar; ALineBreakPos: integer = 1): boolean; begin P2 := AChar; if AChar^ = #0 then Exit(True); Result := AChar^ = LineBreak[ALineBreakPos]; if Result and (ALineBreakPos < LineBreakLen) then Result := Result and IsBreak(AChar + 1, ALineBreakPos + 1); end; after changing it to: function IsBreak(AChar: PChar; ALineBreakPos: integer = 1): boolean; begin P2 := AChar; if AChar^ <> #0 then begin Result := AChar^ = LineBreak[ALineBreakPos]; if Result and (ALineBreakPos < LineBreakLen) then Result := Result and IsBreak(AChar + 1, ALineBreakPos + 1); end else Result := True; end; the time for reading an 50MB file with 227000 lines went from around 320ms to 300ms down, whereas the 2 codegens are the same except the conditional jump and that the "Exit(true)" is on the bottom (Result:=True). This must be OoOE, isn't it? It's impressive.
  4. Attila Kovacs

    TMemoryStream.Write

    @Mahdi Safsafi No, this was my question 🙂 "As a general rule, most if not all Intel CPUs assume forward branches are not taken the first time they see them. See Godbolt’s work." After reading the articles again, I would say, "forward branches are not taken the first time" means, no conditional forward jumps are taken by the predictor for the first time. Am I right?
  5. Attila Kovacs

    TMemoryStream.Write

    @Mahdi Safsafi I see thx. Which one is the forward branch again? The if or the else section? I'm not sure here anymore.
  6. Attila Kovacs

    TMemoryStream.Write

    @Mahdi Safsafi Thx for your explanation through the example with source code, really nice. I was curious how the prediction works and found that "As a general rule, most if not all Intel CPUs assume forward branches are not taken the first time they see them. See Godbolt’s work." and "Forward branches dominate backward branches by about 4 to 1 (whether conditional or not). About 60% of the forward conditional branches are taken, while approximately 85% of the backward conditional branches are taken (because of the prevalence of program loops). Just knowing this data about average code behavior, we could optimize our architecture for the common cases. A "Static Predictor" can just look at the offset (distance forward or backward from current PC) for conditional branches as soon as the instruction is decoded. Backward branches will be predicted to be taken, since that is the most common case. The accuracy of the static predictor will depend on the type of code being executed, as well as the coding style used by the programmer. These statistics were derived from the SPEC suite of benchmarks, and many PC software workloads will favor slightly different static behavior." However I did not found anything about "first time they see them", in what inertia system are they considered as "first seen". This means, we can tell that at the first "if" in the example above, the prediction is "not to take the else case". Not sure what happens on the next call to the method though,
  7. Attila Kovacs

    TMemoryStream.Write

    @Kas Ob. Ah, I see, what you were referring to. But this was/should be the case even without knowing any implementation detail of the CPU. At least for me. Yes, considering this, an early exit could screw the cpu's o-of-order algo. Interesting.
  8. Attila Kovacs

    TMemoryStream.Write

    @Kas Ob. Nice, this quote about Intel and their work. Now, how does an early exit vs. an "if then begin end;" differ, as the Delphi compiler, as far I have seen until now, does not multiply the return code but results in jumps to the end. Only the condition changes, true/false.
  9. Attila Kovacs

    TMemoryStream.Write

    And how do you measure the out-of-order-execution's algorithm's power consumption? Isn't it possible that for saving some cycles in the code, this algo in the cpu has to consume a bit more energy?
  10. Attila Kovacs

    TMemoryStream.Write

    if (FPosition >= 0) and (Count >= 0) then also translates to if not ((FPosition >= 0) and (Count >= 0)) then goto @exitpoint; so I can't see any performance hit on Exit(). Also, I can't see any sense for any optimization in this method. Do you really need to save 1-2 CPU cycles in a stream operation? Strange.
  11. While refactoring is still not perfect and does not work every time, I could improve it with turning off "View references before refactoring".
  12. I can remember the post on G+ by Stefan about the bloated .dcu's and the affected linking time, but this is the first time I see a "workaround".
  13. TArray<TItem> is TArray<T>, TArray is a class.
  14. Attila Kovacs

    MSSQL Update Freezes

    http://docwiki.embarcadero.com/RADStudio/Rio/en/Managing_Transactions_(FireDAC) btw, what is the connection's transactioncount in the original "defect" code right before the update?
  15. Attila Kovacs

    MSSQL Update Freezes

    you have to end the transaction either with commit or with rollback, so rollback comes into the except block
  16. Attila Kovacs

    ParnassusCoreEditor.dll AccessViolation

    There was a thread about it here how to rename the dlls, AFAIR @Uwe Raabe knows best.
  17. Attila Kovacs

    Konopka KSVC and Bookmarks now available for Syndey

    I'd be surprised if there was more changes than the compiler directives in the .inc file.
  18. Attila Kovacs

    Converting project from Delphi 2006 to Delphi 10.2

    it also copies all the 64 chars so the truncate trick is still needed SetString(PaperName, p, 64); PaperName := PChar(PaperName);
  19. Attila Kovacs

    Converting project from Delphi 2006 to Delphi 10.2

    @Anders Melander Wouldn't be a SetString() nicer?
  20. Attila Kovacs

    Converting project from Delphi 2006 to Delphi 10.2

    use DeviceCapabilities() instead of DeviceCapabilitiesA(), then you will also find examples
  21. Attila Kovacs

    Convert to Property

    How can I convert multiple fields to properties? It always converts the only one from the current line, where the cursor is positioned.
  22. Attila Kovacs

    Convert to Property

    @Uwe Raabe I see, I don't have this panel on the left, I'll just roll my own to work with selection. Thx anyway.
  23. Attila Kovacs

    Convert to Property

    @Lars Fosdal I mean MMX Code Explorer. MMX->Conversion-> Convert to property In the dialog title is "Field(s)" but I can't get it to work with multiple fields.
  24. Is that anywhere documented that RTTI is screwd up/missing on types declared in a console app's dpr? Maybe every kind of dpr. brr
Ă—