Jump to content

Dalija Prasnikar

Members
  • Content Count

    1067
  • Joined

  • Last visited

  • Days Won

    91

Posts posted by Dalija Prasnikar


  1. 5 minutes ago, David Heffernan said:

    Imagine not being able to get your company's website up and running again after more than a week? What an absolute joke. I guess I'll go and find my old Delphi 6 printed language guide to look up the info I can't find online rn.

    It is coming online at times, but only for a short periods.


  2. On 1/27/2022 at 12:51 PM, Mark Williams said:

    I have made numerous small changes to the project in the last few weeks. I am now randomly getting errors when closing forms (including those which do not include TVirtualStringTree. The error arises from the  freeing if tree nodes. No clue in the error report as to which treeview. I have tried to replicate the error by repeating the same steps to no avail. It is quite random.

    If application worked correctly before the changes, then those code changes will be the cause of the issue, not the TreeView. I suggest going back through your changes history, finding out the last good version of your code. By comparing the code between good and bad version you can more easily pinpoint the real cause.


  3. 5 minutes ago, Kryvich said:

    The compiler should generate absolutely the same code for var and out parameters, both for the calling and for the called subroutines. The only difference will be in the warnings it issues:

    
    Warning                                            var parameter    out parameter   Where to show
    1. W1036 Variable might not have been initialized  yes              no              Calling routine
    2. The parameter must be initialized before use    no               yes             Called routine
    3. Return value of parameter might be undefined    no               yes             Called routine

    Warnings 2. and 3. should work in the same way as for the Return value of a function (W1035 Return value of function might be undefined). That is, all the necessary checks (W1035, W1036) are already in the compiler, Embarcadero only has to apply them to the parameters where necessary.

    I am usually all for warnings as they can help you detecting bad code and preventing bad code prevents bugs. But if there is a price to pay, if the warning makes too much noise, then such warning does more harm than good. Crappifying the code and losing the performance, just to catch few places where you turned off your brain before writing the code, is not an option for me. There are other tools that can catch such issues, compiler doesn't have to do everything.

     

    Having the same warning for all implies that we wouldn't have the ability to disable var parameter warning without impacting all other places. If var parameter warning would be a separate one, that would be acceptable..


  4. 19 minutes ago, aehimself said:

    As far as I'm aware Delphi is not initializing local variables and I also don't think we were that lucky for 15+ years that these variables were always reserved on a previously cleared memory area (therefore, pointing to nil).

    Yes, you were lucky. Uninitialized variable will contain whatever was previously written at that location. If you were lucky enough that value is zero, broken code would work. 

     

    19 minutes ago, aehimself said:

    Before you say anything, I know that this is a coding issue and was corrected quickly, I'm interested why it behaves differently; maybe some compiler differences...?

    Yes, there is a compiler difference one is 32bit compiler another is 64bit one. Pointer sizes are different. Memory layout will be different. 

     

    But, different compiler is besides the point. Working with uninitialized variables is undefined behavior. That means anything can happen even with the same compiler. 

    • Like 2

  5. On 1/27/2022 at 6:37 PM, Rollo62 said:

    I like to "share" global data by TMessage sometimes, which could completely decouple separate units.

    You only have to initialize a "global" module, sunscribing to its message,

    and then you can request global (or non-global) data by messaging from everywhere you want.

    TMessage from System.Messaging?

     

    On 1/27/2022 at 6:37 PM, Rollo62 said:

    You can implement thread-safetyness, imutability as you like.

    System.Messaging is not thread-safe so you cannot use it for anything thread related.


  6. Different languages have different set of features and also differ in implementations of those features.

     

    Properties in general are a tool that provides additional level of abstraction around encapsulation and enables future implementation changes while preserving stable public API.

     

    Some of the benefits are more visible in some languages than the others. For instance, if you have public field Name and you want to add some code around retrieving that field is easy to do in Delphi. You can rename field and move it to private section and declare public function Name to retrieve it. I Java, you cannot do such thing because calling method must include brackets. This requires refactoring all code that uses such field. If you want to add setter, you will break the code in any language.

     

    This is where using properties helps with encapsulation. They hide unnecessary implementation details and give implementing class to ability to change those without breaking user code. You can start with simple field backed property, which from performance aspect is no different than public field and you can add getters and setters as needed without breaking code. Without properties, you can also maintain stable API, but the cost is having getters and setters for everything and paying the price in performance. No matter how small it is, eventually it can add up. 

     

    Additionally, code with simple assignment is easier to read than setter method.

     

    There are some parts of general properties functionality that Delphi does not implement, like different access levels for reading and writing, or some additional ceremony when declaring properties, especially in interfaces. Some of those could be improved to make properties more flexible, but lacking them is poor argument against using properties. In situations where you really need some functionality properties don't provide, you can use other ways to achieve what you need, but not using properties everywhere else because you cannot do something in rare occasions is also not very convincing argument.

     

    Arguments around name refactoring are not very convincing either. They compare name refactoring, where there is a bit more renaming in declaration. Now, compare that single place where you need to make additional rename, to refactoring all code in case where you need to replace public fields with accessor methods. 

     

    When it comes to extra declaration code needed for properties with accessor methods comparing to only having accessor methods, think how much unnecessary getters and setter methods you need to write in cases where you could use field backed property declaration. 

     

    Overall using properties results with cleaner code and having more functionality than you can have with simple fields or just accessor methods. The little bit of ceremony around the declaration is price I am more than willing to pay, to get all other benefits.

    • Like 11

  7. procedure TForm2.Button1Click(Sender: TObject);
    begin
      Edit1.Text := inttostr(TChild.id)  { <= Calling the Child's property}
    end;

    When you use the above call, TChild.id calls static GetMasterID method. Because that method is static it does not have Self parameter passed, which in context of class methods represents class itself. 

     

    So when you are inside GetMasterID method, compiler no longer knows from which class you have called that method. It only knows the class where the method is implemented, in this case TMaster. And calling GetChildID will be interpreted as calling TMaster.GetChildID.

     

    If you remove abstract on TMaster.GetChildID and implement that function as regular virtual method, which returns different integer than TChild.GetChildID you will no longer have abstract exception, but you will get wrong results. 

     

    • Like 1

  8. 8 hours ago, David Schwartz said:

    This is a test jig and I've been juggling things around trying to see what the differences are. 

    Testing is one things, calling something that serves no purpose is another. 

     

    If the system is over stressed then pumping messages from UpdateLV will not make it run any faster. If the system is not stressed it will pump messages even without you forcing it, literally as soon as you exit UpdateLV method. If you have too many items on list view and UpdateLV is killing your overal performance, then you should modify that logic and instead of updating the whole list all the time update only item that is modified.

     

    Yes, you could see some differences in behavior with Application.ProcessMessages, but none that really matter. Just remove those.

    • Like 1

  9. 1 hour ago, FPiette said:

    GPX file have very simple structure but there are tens of thousands of nodes (Example of GPX file). Before changing my code, I would profile it to know if the slowness comes from the XML parser our from my own code which is fully class oriented with generic TObjectList. I suspect this is much slower in my case compared to records and pre-allocated dynamic arrays.

    Understandable. I would do the same.

     

    GPX format is ideal for SAX parser. Avoiding allocations of thousands of XML nodes would be my best bet for optimization. 

    • Like 1

  10. Unrelated to the profiling, there are other optimizations.

     

    First, SAX parsing is generally more performant than DOM parsing, especially when DOM is based on interfaces. If you don't need XML DOM, then building your business classes directly during parsing will be more efficient. But not all structures cane be equally easy parsed by SAX. 

    Next, IXmlDoc works on top of standard IDOM interfaces, so you have additional slowdown there. If you cannot use SAX, modifying code to work directly with IDOM interfaces might be a solution. Or using different DOM parser.

     


  11. 6 hours ago, David Schwartz said:

    FastMM is what I was referring to. I have not been able to get either of the two most recent V4 versions to work properly in Sidney. It works fine in Tokyo. I've brought it up here before, and apparently it's unique to my machine since nobody else seems to have a problem.

     

    I built a tool for it that parses out the log file and makes it super easy to figure out the likely source of the error. Most of the stuff in the log file is redundant, and it's mostly documenting side-effects of the error, not the error itself.

     

    Eg, failing to free the Objects in a stringlist throws a gazillion errors related to all of the orphaned objects, making it really hard to figure out that the problem was with the stringlist, which technically did nothing wrong. 

     

    Also, in some situations, I'll get tons of orphaned string literals showing up that baffle me why they're even there. I forgot to properly free something that had a bunch of strings in it, and I guess Unicode sometimes gets them from the heap when they're added to certain containers (?). It's all just noise!

     

    In most cases, it comes down to missing one single call to .Free somewhere before either replacing something or freeing the container.

    I cannot say whether something in logs changed, but as far as I can remember FastMM works in Sidney the same way it worked before. I don't have the Tokyo installed for comparison. And it shows the stack trace correctly so I can follow to the line where issue happened.

    Yes, I know that in more complex code it can be harder to figure out real culprit, but that has always been the case.


  12. 8 minutes ago, Attila Kovacs said:

    he has no problems with memory management, he even made it clear in just a couple of replies above so I have no idea what you trying to prove here

    I am talking about your comment to  @Wagner Landgraf where he mentioned memory management and you are saying this thread is not about memory management. 

     

    I am not trying to prove anything, just wanted to say that memory management is indirectly involved in this conversation, and Wagner didn't post in the wrong thread.

    • Like 1

  13. 32 minutes ago, Attila Kovacs said:

    So you are expecting and handling exceptions from the constructor but not expecting and not handling exceptions from any further method calls?

    Interesting.

    The way I am reading that is: if you pass parameters in constructor to initialize fields and you validate them there, raising exception if they are not valid, then you can avoid checking those fields when you are using them in other places because you know they cannot hold invalid values.

    • Thanks 1

  14. 2 minutes ago, Attila Kovacs said:

    @Dalija Prasnikar Hm, I really don't know what would I do on out of memory, never had to deal with that.

    Depends on the context.

    If you open some file for processing and it turns out to be a too large so processing it raises out of memory, you just clean up and tell to the user: "Sorry, your file is too large and you don't have enough memory." But after proper cleanup your application will be in fine condition to process some other smaller file. 

    On the other hand, there are situations where out of memory is not recoverable. You still may be able to show message to the user there is not enough memory, but you will just have to kill the application after that.

    • Like 2
    • Thanks 1

  15. 21 minutes ago, Lars Fosdal said:

    So, basically

    
    try
      var MyThing := TThing.Create;
      try
        MyThing.DoIt;
      finally
        MyThing.Free;
      end;
    except
      // deal with it
    end;
    
    // instead of
    
    var MyThing := TThing.Create;
    try
      try
        MyThing.DoIt;
      except
        // deal with it
      end;
    finally
      MyThing.Free;
    end;

    I prefer the latter since I can handle the problem in the context of which it occurs.

    IMO, exceptions that you let "bubble up the stack" become increasingly difficult (Edit: and expensive) to manage, since you are less and less aware of the exception context, the further out you get.

     

    If you want to handle the exception on site, then the second option is the wrong way to do it for several reasons. 

     

    Construction of an object can always fail because of OutOfMemory, so if you wanted to handle all exceptions at that point you have failed to do so. If you are fine to bubble up that exception further on and if except part (handling the exception) cannot raise exceptions, you don't need try..finally at all.

    • Like 2
×