Results 1 to 14 of 14

Thread: Global DTMs and you

  1. #1
    Join Date
    Sep 2009
    Posts
    580
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default Global DTMs and you

    Do you think it's a good idea to declare all my DTMs (6 of them) locally to save me the hassle of making sure they're there when I need it? or will it slow down the script a lot?
    I don't check this place often, sorry.

    Currently working on - Software Engineering degree. Thank you SRL for showing me the one true path

  2. #2
    Join Date
    Jan 2008
    Location
    NC, USA.
    Posts
    4,429
    Mentioned
    0 Post(s)
    Quoted
    4 Post(s)

    Default

    It will slow down the script a lot. I'd just create them when needed, and then free them.
    Quote Originally Posted by irc
    [00:55:29] < Guest3097> I lol at how BenLand100 has become noidea
    [01:07:40] <@BenLand100> i'm not noidea i'm
    [01:07:44] -!- BenLand100 is now known as BenLand42-
    [01:07:46] <@BenLand42-> shit
    [01:07:49] -!- BenLand42- is now known as BenLand420
    [01:07:50] <@BenLand420> YEA

  3. #3
    Join Date
    Sep 2006
    Location
    New Jersey, USA
    Posts
    5,347
    Mentioned
    1 Post(s)
    Quoted
    3 Post(s)

    Default

    It depends how often you use them.
    Interested in C# and Electrical Engineering? This might interest you.

  4. #4
    Join Date
    Sep 2009
    Posts
    580
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    I'll probably keep them global for testing purposes, and then make them local before I release script.
    I don't check this place often, sorry.

    Currently working on - Software Engineering degree. Thank you SRL for showing me the one true path

  5. #5
    Join Date
    May 2007
    Location
    knoxville
    Posts
    2,873
    Mentioned
    7 Post(s)
    Quoted
    70 Post(s)

    Default

    SCAR Code:
    function loaddtm(dtm: string):integer;
    begin
      case lowecase(dtm) of
        'dtm1' : result := DTMFromString('78DA63F4626260C8636440054C601226CAE80' +
           '6E4371250130EE4971350630FE4571250130AE41710501348847B' +
           '5C80FC7CFC6A0004E80581');
        'dtm2' : result := DTMFromString('78DA63F4626260C8636440054C601226CAE80' +
           '6E4371250130EE4971350630FE4571250130AE41710501348847B' +
           '5C80FC7CFC6A0004E80581');
      end;
    end;

    function isdtm(dtm : string):boolean;
    begin
      result := finddtm(x, y, loaddtm(dtm), blah blah blah);
      freedtm(loaddtm(dtm));
    end;

    begin
      if isdtm('dtm1') then writeln('yay :D');
    end;

    etc

    remember to free dtms
    <TViYH> i had a dream about you again awkwardsaw
    Malachi 2:3

  6. #6
    Join Date
    Sep 2006
    Location
    New Jersey, USA
    Posts
    5,347
    Mentioned
    1 Post(s)
    Quoted
    3 Post(s)

    Default

    Quote Originally Posted by Awkwardsaw View Post
    SCAR Code:
    function loaddtm(dtm: string):integer;
    begin
      case lowecase(dtm) of
        'dtm1' : result := DTMFromString('78DA63F4626260C8636440054C601226CAE80' +
           '6E4371250130EE4971350630FE4571250130AE41710501348847B' +
           '5C80FC7CFC6A0004E80581');
        'dtm2' : result := DTMFromString('78DA63F4626260C8636440054C601226CAE80' +
           '6E4371250130EE4971350630FE4571250130AE41710501348847B' +
           '5C80FC7CFC6A0004E80581');
      end;
    end;

    function isdtm(dtm : string):boolean;
    begin
      result := finddtm(x, y, loaddtm(dtm), blah blah blah);
      freedtm(loaddtm(dtm));
    end;

    begin
      if isdtm('dtm1') then writeln('yay :D');
    end;

    etc

    remember to free dtms
    That doesn't work.

    SCAR Code:
    program New;
    begin
      writeln(DTMFromString('78DA635CC2C8C0F0940105DCBD79094C3342F98C6540D67C5435FFFFFF475103003C23082A'));
      writeln(DTMFromString('78DA635CC2C8C0F0940105DCBD79094C3342F98C6540D67C5435FFFFFF475103003C23082A'));
    end.

    Even though they are the same DTM, they are loaded separately.

    If a dtm is used often, keep it global. If it is only used once in a while, then leave it local.

    It comes down to a memory/speed tradeoff.
    Global = more memory usage, more speed;
    Local = less memory usage, but slower.
    Interested in C# and Electrical Engineering? This might interest you.

  7. #7
    Join Date
    Sep 2009
    Posts
    580
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Sorry Smartz, but it'd work. In fact it looks like a great idea
    I don't check this place often, sorry.

    Currently working on - Software Engineering degree. Thank you SRL for showing me the one true path

  8. #8
    Join Date
    May 2007
    Location
    knoxville
    Posts
    2,873
    Mentioned
    7 Post(s)
    Quoted
    70 Post(s)

    Default

    Quote Originally Posted by Smartzkid View Post
    That doesn't work.

    SCAR Code:
    program New;
    begin
      writeln(DTMFromString('78DA635CC2C8C0F0940105DCBD79094C3342F98C6540D67C5435FFFFFF475103003C23082A'));
      writeln(DTMFromString('78DA635CC2C8C0F0940105DCBD79094C3342F98C6540D67C5435FFFFFF475103003C23082A'));
    end.

    Even though they are the same DTM, they are loaded separately.
    wat?
    <TViYH> i had a dream about you again awkwardsaw
    Malachi 2:3

  9. #9
    Join Date
    Sep 2006
    Location
    New Jersey, USA
    Posts
    5,347
    Mentioned
    1 Post(s)
    Quoted
    3 Post(s)

    Default

    The program I posted prints out the memory handle to each DTM. Notice that the two are different? This means each call to DTMFromString loads the DTM to a new place in memory, even though the data is the same.

    I can understand your confusion; while the code 'works', it is a memory leak:
    You load the DTM into memory pos 1, and search for it.
    Next, you load it into memory pos 2, and free it.

    The DTM in position 1 never gets freed.

    Luckily, a better solution is not far away:

    SCAR Code:
    function isdtm(dtm : string):boolean;
    var
      tmpdtm: integer;
    begin
      tmpdtm := loaddtm(dtm);
      result := finddtm(x, y, tmpdtm, blah blah blah);
      freedtm(tmpdtm);
    end;

    The problem now, though, is that you are allocating memory, filling it up with data, and then freeing it - every time you search for a DTM. Memory operations like this take a good amount of time, so if you are using a DTM often, you should consider making it global and keeping it in memory, which will boost your script's efficiency and lower your CPU usage.

    In addition, case statements in SCAR are very slow. They act as large if/else statements; thus, as your list of DTMs grows, so will the time it takes to load each one. This is an additional reason why you may want to keep some DTMs global.
    Last edited by Smartzkid; 01-30-2010 at 06:28 AM.
    Interested in C# and Electrical Engineering? This might interest you.

  10. #10
    Join Date
    Jan 2008
    Location
    Ontario, Canada
    Posts
    7,805
    Mentioned
    5 Post(s)
    Quoted
    3 Post(s)

    Default

    The best option, in my opinion would be using an array of boolean, set them to true as each dtm is set which is allocated by a constant in an array. Then in the script terminate procedure, have a for loop free every loaded dtm.

    I'd write some code but I'm on my iPod.

    E: oh and the dtms stored in a TIntegerArray associated to the same object. To be honest a record would work here too.
    Writing an SRL Member Application | [Updated] Pascal Scripting Statements
    My GitHub

    Progress Report:
    13:46 <@BenLand100> <SourceCode> @BenLand100: what you have just said shows you 
                        have serious physchological problems
    13:46 <@BenLand100> HE GETS IT!
    13:46 <@BenLand100> HE FINALLY GETS IT!!!!1

  11. #11
    Join Date
    May 2007
    Location
    knoxville
    Posts
    2,873
    Mentioned
    7 Post(s)
    Quoted
    70 Post(s)

    Default

    Quote Originally Posted by Smartzkid View Post
    The program I posted prints out the memory handle to each DTM. Notice that the two are different? This means each call to DTMFromString loads the DTM to a new place in memory, even though the data is the same.

    I can understand your confusion; while the code 'works', it is a memory leak:
    You load the DTM into memory pos 1, and search for it.
    Next, you load it into memory pos 2, and free it.

    The DTM in position 1 never gets freed.

    Luckily, a better solution is not far away:

    SCAR Code:
    function isdtm(dtm : string):boolean;
    var
      tmpdtm: integer;
    begin
      tmpdtm := loaddtm(dtm);
      result := finddtm(x, y, tmpdtm, blah blah blah);
      freedtm(tmpdtm);
    end;

    The problem now, though, is that you are allocating memory, filling it up with data, and then freeing it - every time you search for a DTM. Memory operations like this take a good amount of time, so if you are using a DTM often, you should consider making it global and keeping it in memory, which will boost your script's efficiency and lower your CPU usage.

    In addition, case statements in SCAR are very slow. They act as large if/else statements; thus, as your list of DTMs grows, so will the time it takes to load each one. This is an additional reason why you may want to keep some DTMs global.
    only one dtm is being called per function use, because of the case, how would both of them be called in memory?

    also, the case statements "slowness" isn't noticeable at all, even then a little "pause" might be better anyways
    <TViYH> i had a dream about you again awkwardsaw
    Malachi 2:3

  12. #12
    Join Date
    Jan 2007
    Posts
    8,876
    Mentioned
    123 Post(s)
    Quoted
    327 Post(s)

    Default

    Quote Originally Posted by Awkwardsaw View Post
    only one dtm is being called per function use, because of the case, how would both of them be called in memory?

    also, the case statements "slowness" isn't noticeable at all, even then a little "pause" might be better anyways
    Please do not take this the wrong way, but you should know this already.. :/

    Whenever you call DTMFromString (or BitmapFromString) the DTM (or Bitmap) is loaded into the memory. So if you call your function two times with the same parameter then SCAR will load two different DTMs into the memory, but with the same information (Better explained with bitmaps: Two different bitmaps, but with all the pixels exactly the same)

  13. #13
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    Quote Originally Posted by Nava2 View Post
    The best option, in my opinion would be using an array of boolean, set them to true as each dtm is set which is allocated by a constant in an array. Then in the script terminate procedure, have a for loop free every loaded dtm.

    I'd write some code but I'm on my iPod.

    E: oh and the dtms stored in a TIntegerArray associated to the same object. To be honest a record would work here too.
    Boolean arrays work wonders when used in the right situations.

  14. #14
    Join Date
    Sep 2006
    Location
    New Jersey, USA
    Posts
    5,347
    Mentioned
    1 Post(s)
    Quoted
    3 Post(s)

    Default

    Since a DTM handle is simply an integer corresponding to an index in an array, we cannot use a (dtm != 0) test as we would on a normal memory handle (the first DTM created will always be equal to 0, so it would never get freed). In addition, this test is useless without a wrapper function to free DTMs, because SCAR doesn't set handles to 0 when it frees the memory they point to.

    Even so, there are a few possible solutions:

    In a situation with only local DTMs, and no explicit calls to FreeDTM, this function will take care of freeing all DTMs. Thus, if called at the end of every procedure that uses DTMs, your memory will stay nice and clean.
    SCAR Code:
    procedure FreeAllDTMs;
    var
      i: integer;
    begin
      try
        repeat
          FreeDTM(i);
          inc(i);
        until(false)
      except end;
    end;

    For a situation requiring both global and local DTMs, the most desirable solution is a memory management system - something along the lines of what Nava described.

    Personally, I would create wrapper functions for DTMFromString and FreeDTM. These functions would add to and remove from an array of integers. This array could be inspected to glean two important pieces of information - the current number of DTMs allocated, and the handles of all current DTMs. Using this data, memory cleanup becomes quite trivial.
    A rough implementation of this idea is below.

    Mixter's bitmap debugging code operates on somewhat the same principal.

    In a perfect world, all DTMs would be loaded into a 'DTM Manager', which would store raw DTM data and a string identifier for each DTM. To use a DTM, one would call a function GetDTM(dtmName: String): integer; which would return the handle to a DTM. Inside the GetDTM function, statistical analysis would be applied over a period of time to determine exactly which DTMs ought to be kept in memory, and which ought to be freed. The DTMs that ended up being freed would be re-allocated when needed, and freed at the next call to this function. In reality, a system like this would not be hard to set up. Rather than running complicated statistics, one could simply designate whether or not to make a DTM stay allocated ('global') or be allocated on the fly ('local'). The rest is quite easy to implement.

    @Awkwardsaw: There is a big difference between inefficient code and wait statements. Inefficient code makes the processor do more work than it needs to, whereas wait statements defer processor cycles to another program. Inefficient code causes lag; wait statements prevent it.


    The code below is different than what many people are used to. Rather than freeing DTMs by reference to a specific handle, they are freed by order of creation. The concept is that you create your global DTMs at the beginning of the script, and whenever local DTMs are used, you clean up afterward with a call to DTMFreeRecent with the number of DTMs used in the current procedure. If you have no global DTMs, you can clean up after each procedure with a call to DTMFreeAll.

    SCAR Code:
    var
      xxDTMArray: Array of Integer;

    procedure DTMFreeRecent(quantity: integer);
    //Free the last q DTMs made
    var
      i, startIndex: integer;
    begin
      startIndex := High(xxDTMArray) - quantity;
      for i := 0 to quantity do
        FreeDTM(xxDTMArray[startIndex + i]);
      SetLength(xxDTMArray, startIndex);
    end;

    function DTMCreate(s: String): integer;
    //Create a DTM from input string s
    var
      size: integer;
    begin
      result := DTMFromString(s);
      size := Length(xxDTMArray);
      SetLength(xxDTMArray, size + 1);
      xxDTMArray[size] := result;
    end;

    function DTMQuantity: integer;
    //Get number of DTMs currently in use
    begin
      result := Length(xxDTMArray);
    end;

    procedure DTMFreeAll;
    //Free all DTMs
    var
      i: integer;
    begin
      for i := 0 to high(xxDTMArray) do
        FreeDTM(xxDTMArray[i]);
      SetLength(xxDTMArray, 0);
    end;
    Last edited by Smartzkid; 01-31-2010 at 07:20 AM.
    Interested in C# and Electrical Engineering? This might interest you.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •