#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2013
    Posts
    15
    Rep Power
    0

    Numerous Questions About Delphi


    I've had a good look around, but finding definitive answers to these questions is a pain. So I've come here Let's see how we do.

    1. Do I need to free created string lists, or other objects every time? Take the following console application code:

    list:=Tstringlist.create

    ---- do something

    list.free

    [Note: I know TRY clause is usually used, but I have omitted it]


    Now... let's say our console app ends immediately after "do something" . Is there really any point in freeing the list or other object? I assume when an app dies, all memory is returned?

    2.

    Why does my memory usage double when saving a stringlist? Up to the end of the application, the stringlist's memory usage is correct, but when "savetofile" is used, suddenly the memory of my application doubles (presumably, the stringlist is being duplicated in memory). Is this normal, is it a problem, or is windows task manager just crap at reporting memory usage?

    3.

    When dealing with strings. Let's look at a function, where s is a string const input.

    Result:= s;

    In this line, can I assume NO copying is actually going on? That Result is just pointing to the address of s?

    4.

    When using ordinary string var

    s:string;

    as opposed to short string

    s:string[10]

    What are the advantages? If s becomes 10 characters long in both, why is it preferable to set its maximum length with [10]?

    5.

    Is there a faster method of counting chars in a string than this:

    Code:
    function CharCount(const s:ansistring;
                                        const c:ansichar):longint;
    var
    i: longint;
    begin
    result:=0;
    
      for i:=1 to length(s) do
        if s[i]=c then
        inc(result);
    
    end;
    In other words, is there some trick or algorithm that can improve on this? [including assembly]

    =============

    If I come up with any more queries, I'll post them here. Any help really appreciated.
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2008
    Posts
    350
    Rep Power
    7
    1. Do I need to free created string lists, or other objects every time?
    The short answer is Yes. The lifetime of the object obviously depends on the needs of the application, so you don't have to create and free the object in the same method as your example. You can, for example create an object in your form's OnCreate and free it in the OnDestroy Events. Just remember that if you need the object to live thought out the lifetime of your application, then it needs to be declared in the form's Type Declaration.

    Is there really any point in freeing the list or other object? I assume when an app dies, all memory is returned?

    While your last statement is correct (all memory is returned), if your code creates the object works with it, creates another, works with it etc. Or you create many different objects and never free any of them. Then you are leaking memory, and given enough time, your application will crash, which is definately a problem for your users.

    2. Why does my memory usage double when saving a stringlist? Up to the end of the application, the stringlist's memory usage is correct, but when "savetofile" is used, suddenly the memory of my application doubles (presumably, the stringlist is being duplicated in memory). Is this normal, is it a problem, or is windows task manager just crap at reporting memory usage?

    Well without seeing the code, no way to know if something unusual is happening, but windows task manager is definately not the right application judge memory usage.

    3. When dealing with strings. Let's look at a function, where s is a string const input.

    See here for a good explanation of Delphi Strings.

    4. When using ordinary string var ...

    The declaration

    S: String[10]; is no longer considered correct. Use

    S: String; Delphi's memory manager will manage the strings size.

    5. Is there a faster method of counting chars in a string than this:

    Well for strings that aren't too long you could use this:

    function CharCount(const: SearchString: String; const SearchTerm: String): Integer;
    begin
    Result := Length(SearchString)-Length(StringReplace(SearchString, '', SearchTerm, [rfReplaceAll, rfIgnoreCase])) div Length(SearchTerm);
    end;

    Slightly different that what you had, it allows you to count the occurrances of a string rather than just a character, althouth it works just fine if the search term is one character.
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2013
    Posts
    15
    Rep Power
    0
    Two things there:

    The question I asked was, do I need to free objects when the application is definitely going to end? If it is terminating immediately and the objects won't be used again, they are being freed anyway?

    Also

    Your example to count occurrences is bound to be pretty slow. I am looking for a very clever implementation. As fast as possible, or an understanding of HOW to make it faster, particularly with assembly if needed.

    Finally

    Can you recommend a good program for finding the true memory usage of the app? Or a way to do this inside my code.

    Thanks for your reply
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2008
    Posts
    350
    Rep Power
    7
    So actually, I thought I answered the first question. Yes, the OS will reclaim the memory, so if your program is just creating an object, uses it, then ends, then no you don't have to free it.

    The caveat though is that I just wouldn't recommend it. Far too many of my utilities that I've written have been modified, grown in scope over time, and what was a simple application becomes the basis for a far larger program. Why have something like this lurking in your program when all it takes is adding a simple Object.Free?

    Your example to count occurrences is bound to be pretty slow
    That's why I stated that it would not be appropriate to use the function with longer strings.

    If the problem with counting the occurrences of a substring in a string is locking up your application while it runs (if that's why you want a "clever" implementation), I'd suggest you do it in a thread, and pass the value back to the main thread via a message. Just let me know if you want help creating such a thread.

    As far as monitoring memory usage, you'll just have to google it. I haven't used one, so I can't recommend one to you.
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2013
    Posts
    15
    Rep Power
    0
    Well, I know for a fact that these are never being reused. The application is now complete and any modifications will be before the end. If I wasn't sure I wouldn't do it. I just don't like seeing five .free at the end of my code when they aren't necessary. Plus I don't need to mess about with TRY FINALLY. I can skip that step entirely, and focus on just exceptions with my code.

    --------------

    The reason I want to see how much faster that function can be made is purely that it would educate me on better methods in all functions of that nature. It's purely for my own education. I don't need to know about threading or otherwise, just any tricks that can make the algorithm itself faster. Be it assembly or otherwise. If it can't be made any faster, then I accept that. But there are usually ways to speed things up.

    edit

    Code:
    uses psapi;
    
    function CurrentProcessMemory: Cardinal;
    var
      MemCounters: TProcessMemoryCounters;
    begin
      MemCounters.cb := SizeOf(MemCounters);
      if GetProcessMemoryInfo(GetCurrentProcess,
          @MemCounters,
          SizeOf(MemCounters)) then
        Result := MemCounters.WorkingSetSize
      else
        RaiseLastOSError;
    end;
    Also, I used that to check memory usage. Seems that windows task manager was showing it wrong. There doesn't seem to be any change in memory usage.
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Jan 2006
    Location
    Carlsbad, CA
    Posts
    2,057
    Rep Power
    383
    A couple of comments.
    1. I would NEVER recommend using bad programming practices like ignoring Free and Try..Finally, especially where they have zero benefit to the program. Eventually bad habits will trip you up.

    2. You will usually find that Delphi's internal functions work at least as fast as anything you concoct, so unless you are experiencing a real performance issue I would not waste time on it. The best solution is usually revising your coding logic rather than function implementation. I also understand from other comments that the compiler is now so smart that it often creates better assembly code than you will hand craft.
  12. #7
  13. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2013
    Posts
    15
    Rep Power
    0
    Delphi's find replace was woeful. Even my own code was way faster... don't trust the rest after that :P

    Also it is your choice to use unneeded and unnecessary code, but I won't
  14. #8
  15. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2013
    Posts
    15
    Rep Power
    0
    Understanding PAnsiChar

    Okay, I am wondering if this might be a more efficient way of going abut things:

    original code:
    Code:
    function CharCount(const s: ansistring;
                       const c: ansichar):Longint;
    var
      i: longint;
    begin
    result:=0;
      for i:=1 to length(s) do
        if s[i]=c then
        inc(result);
    end;
    new
    Code:
    function CharCount(const s: ansistring;
                       const c: ansichar):Longint;
    var
    ps: pansichar;
    
    begin
    result:=0;
    ps:=@s[1];
    
      While ps^<>#0 do
      begin
        if ps^=c then
        inc(result);
      inc(ps);
      end;
    
    end;
    Shouldn't this be faster? Normal strings are terminated by nulls in delphi I believe?

    If this isn't faster or is a wrong use of pansichar, can someone explain a situation where pointers are more efficient with an example?
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Jan 2006
    Location
    Carlsbad, CA
    Posts
    2,057
    Rep Power
    383
    Why don't you just try it and tell us?

    Although I doubt that there will be any meaningful difference.
  18. #10
  19. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2013
    Posts
    15
    Rep Power
    0
    I don't know, that's why I'm asking. I don't understand the true benefits of pointers and I need to, because according to what I have read, they can be used to significantly speed up code. The tasks I am using are cpu heavy and time consuming, so anything I can squeeze out, I have to.
  20. #11
  21. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2013
    Posts
    15
    Rep Power
    0
    Well, the pointer version above was significantly slower in tests. Which I don't get.
    So if anyone knows why, and can explain where pointers can make code more efficient, let me know

IMN logo majestic logo threadwatch logo seochat tools logo