Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by balabuev

  1. balabuev

    TTreeNode leak when VCL styles are active

    Actually, I even do not remember, what we discussed here
  2. balabuev

    Calling inherited in Destroy

    Given the simple code: type TMyClass = class end; procedure P; begin var obj := TMyClass.Create; obj.Free; end; Try to count, how many function calls (and especially virtual calls) are performed here. And after that, it's become clear that additional "inherited" call in destructor changes almost nothing.
  3. balabuev

    Delphi 11 High DPI designer

    This manual DPI handling issue will exist forever, and no good solution will be found. Even if the IDE itself will handle some portion of the problem, there will be always bugfull components. And so on, and so on... Only switching the whole UI library to logical points will really help.
  4. balabuev

    RAD Studio 11 Alexandria is now available

    What I want to say, is that icons and overal look is really awesome 😍. As well as the splash screen. This is the first time when splash screen produce "wow effect", I think, since Delphi 4.
  5. Why? I claimed that it uses same amount of fields like conventional hash table with heap allocated entries - and that's true. There is an array of indices - called "buckets", and yes, this is the main table array, which is analogous to array of pointers to entries (nothing "pretty compact"). There is the "next" field in each entry. So, the waste of space is roundly the same. The levels of indirections - are the same and even worse. You also ignored the fact that all entries are preallocated - thus even more waste of space. All entries are stored continuously in a single array - better cache locality - yes, but I've not talked about this. Overall, this topic is a big question. In real app we have a higly unpredictable sequence of memory accesses, because an app is really a big mess (graph) of heap allocated objects, and hash map access code is mixed with accesses of data from the other objects. And moreover, since hashmap has O(1) average access performance, you do not typically access more than a single entry at a time. So, speaking more generally, cache locality in OOP language is more a task for memory manager. And overall it importance for real code is imho exaggerated.
  6. The question is in overall size. If the size is not too big, which is again - typical, then the table with "unnecessary memory indirections" will work faster, because the logic here is simpler. A table, which inlines everything, must also pay its own price to prevent "wasting space by storing pointers" by introducing additional fields, doing bit manipulation and more array element accesses. But, such a table also wastes space because of lower "load factor", and for yet empty slots when SizeOf(Value) > SizeOf(Pointer). Some well known examples: - Java HashMap and Hashtable - heap allocated entries. Well, they have almost no choice, because Java has no structs. The only way to inline is to keep several parallel arrays. - C# Dictionary<K, V> - kind of tricky code, which preallocates all entries in a separate array, and then uses a kind of tiny embedded memory manager to provide entries from this array. As a result it stores two separate arrays (same waste of space) and indexes instead of direct pointers (waste of space; slower). Since all entries are preallocated, then it becomes even more waste of space when SizeOf(Value) > SizeOf(Pointer).
  7. All this is true when working with tiny things, like, for example, mapping int to int. But, in more usual case, like string keys, the effect is shadowed by string handling overhead and the fact that strings themselves are heap allocated.
  8. I suspected you will say this. But, anyway, in real life we use a lot of heap allocated stuff, like objects or strings, so I think there will be no big difference.
  9. I tried to keep the code reasonably simple. Yes, sure, some improvements are possible. Instead of objects we can at least use records for map items with New/Dispose (or even better, with GetMem/FreeMem), as @Stefan Glienke mentioned before (if I've understood right). We can also go futher and try to minimize heap allocations, or use some sort of map item pool, etc. We also can use some initial capacity as you propose. But, this will complicate the demo code, thus, hiding the main idea, which it tries to show. Moreover, map filling is not critical for this particular test. We measure only search speed.
  10. Does anyone know which tool Embarcadero uses itself to generate source code documentation (reference)?
  11. balabuev

    Documentation creation tool

    All this is very funny, but the question remains open. We are searching for appropriate source code documentation tool (except Documentation Insight, which we already know about), which is not outdated, and preferably allows to keep documentation separately from the code.
  12. This is the key line. Now let's think, where this strange "-32000" numbers may araise at all. I'm sure 99.9% that the numbers are received from a Windows API function call, such as GetWindowRect (or similar) in minimized window state (IsIconic(Handle) = True). Simple experiment proves it: procedure TForm1.Timer1Timer(Sender: TObject); var wr: TRect; begin if WindowState = TWindowState.wsMinimized then begin GetWindowRect(Handle, wr); OutputDebugString(PChar(wr.Left.ToString + ', ' + wr.Top.ToString)); end; end; So: With "-32000" left and top values the window is not, of course, within the area of your monitor 1, but this monitor becomes the closest one to the window.
  13. Handling of maximized form state is bugfull even without multi-monitor setup, and even without VCL Styles. Use the following code with a simple memo on a form: procedure TForm1.FormResize(Sender: TObject); begin Memo1.Lines.Add(Width.ToString + ', ' + Height.ToString + ', ' + IsIconic(Handle).ToString); end; Run the project and maximize the form. Minimize the form using taskbar app button. Maximize it back using taskbar app button. You will see that during minimize/maximize steps two OnResize events are fired with different Width/Height values. This was not the case in early Delphi versions, like Delphi 7; this was introduced later along with the Application.MainFormOnTaskbar feature. I'm sure that all such issues are related, and the problem is that they forget to check for IsIconic() whenever appropriate.
  14. I can confirm the issue with the configuration similar to yours: Monitor 1 - 100% (primary) Monitor 2 - 125% App's main form is shown on the primary monitor (1). The bug happens if monitors are related like this (monitor 2 has negative X coordinates in its area) The bug does not happen if monitors are related like this:
  15. Well, several posts above, @vfbb (topic starter) mentioned TEdit as an exmple "to clarify the problem", which is obviously uses text rendering.
  16. Not fully agree. You still has to rely on OS text rendering features. Which are themselfs depend on ICU. So, your own ICU can be not well consistent with OS's one, which is used for rendering.
  17. The official APIs in Windows to deal with Unicode stuff - is Uniscribe. It allows to decode Unicode related information from a Utf16 string. Including the sequence of glyphs for rendering. But, what you will do with them? Because, every glyph is denoted as a number, without any meaningfull value; and you can only pass this sequence to ExtTextOut. Also, Uniscribe provides supporting attributes to Unicode codepoints, such as: whether it's a wrod start (for Ctrl+Left/Right navigation) whether it's a word end a valid caret positions (some codepoints are not valid caret positions) should the codepoint be deleted as a group with neightboord codepoints etc. All rules are complex and different from each other. There no simple way to move editor caret and select the text in Unicode enabled text editor. I suggest the following old and great tutorial (an attempt to create the editor with Unicode support) http://www.catch22.net/tuts/neatpad/introduction-uniscribe#
  18. balabuev

    caFree & ,Free??

    As recently has been mentioned in another thread, it's only safe if the code inside try/finally do not occasionally (or indirectly) call Application.ProcessMessages after ShowModal: MyForm := TMyForm.Create(...); try MyForm.ShowModal; Application.ProcessMessages; // Or SomeAnotherForm.ShowModal, etc. finally MyForm.Free; end; In this case the form may be freed via CM_RELEASE, and then - freed the second time via the code in finally block.
  19. balabuev

    Creating sub nodes with debugger visualizer

    Also, I've noticed that the strings are different in code editor drop-down and in local variables view: String in code editor drop-down seems to be more complete (like it should be returned from GetReplacementValue). While the string in local variables view seems to be already processed by IDE.
  20. balabuev

    Creating sub nodes with debugger visualizer

    Never tried it myself, but I suspect that you just need to return a string with specific format. Such as "(3, 5, 7)" to show value as array with child elements. Or like "(PropA: 3; PropB: 5)" to show as object with child properties. I may be wrong, of course. Do you looked at the source code of TDebuggerListHelperVisualizer.GetReplacementValue?
  21. This happens (and always was the case) with the following settings:
  22. balabuev

    Delphi WAT of the day

    Task completed:
  23. balabuev

    Object Inspector issue in 10.4.2??

    Then, I don't know, sorry.
  24. balabuev

    Object Inspector issue in 10.4.2??

    Try to uninstall third-party stuff. Like Cnpack/Gexperts... Also your object instector looks strange. I have no horizontal lines:
  25. balabuev

    Object Inspector issue in 10.4.2??

    Non-standard property editors are installed. More technically (if anyone interested) this happens when a property editor implements ICustomPropertyDrawing interface but does not implement more recently introduced ICustomPropertyDrawing80 interface.