[C++] Monitoring execution time of LUA scripts and avoiding freezes

Discussion in 'Programming & Scripting' started by Stellow, Sep 23, 2016.

  1. Stellow

    Stellow C++/C#/PHP/LUA

    Joined:
    Oct 23, 2008
    Messages:
    997
    Likes Received:
    115
    Best Answers:
    0
    Hello guys, for months I was facing some problem with one of my client's server, on which it would simply freezes without any abomination on bandwidth. I knew that I had peeks on main memory, but still could not locate what was causing it. Was it some distro configuration that I have implemented on the past? Or some LUA functions? Well, turns out, with an advice from @Xikini I could monitor LUA function execution time and locate the error.

    This is a simply implementation, but it turns out, I could easily see LUA functions taking up to 1000+ms on its execution time, not to much, but if consider it blocks the current thread, it turns out a lot.

    For the geeks, I did the implementation using really basic structure, I did not want to globally instantiate a object to take care of the logging, because it would result in more functions calls and complexity. It would be better, but I did not want to mess up much with the code structure; I have opted for a simply class that would start counting, and on its destructor, did the real work in case time was overwhelmed. Could I maybe used some heap memory and pointers to avoid the extra memory on functions calls? hmm.. yes, but also, that would result in bad performance if not implemented correctly, nor keeping up with the memory layout itself.

    Please feel free to criticize on how this basic implementation is set up, and maybe we can workout together on something more attractive.

    Script.

    On baseevent.h (because all the other LUA scripts functions are inheritanced from it) I created a class:

    Code (Text):
    1.  
    2. #include "database.h"
    3.  
    4. class EventLog
    5. {
    6. public:
    7.     EventLog(std::string eventName) : _function(eventName), _time(OTSYS_TIME()), _eventName("") {}
    8.     void setName(std::string name) {_eventName = name;};
    9.     ~EventLog()
    10.     {
    11.         int64_t totalTime = OTSYS_TIME() - _time;
    12.         if (totalTime > 50) // 50 ms
    13.         {
    14.             std::cout << _function << " execution time:" << totalTime << " ms. Logging..." << std::endl;
    15.            
    16.             Database* db = Database::instance();
    17.             DBInsert stmt(db);
    18.             stmt.setQuery("INSERT INTO `event_log` (function, time_ms, event_name) VALUES ");
    19.             DBQuery query;
    20.             query << "'" << _function << "'" << ", " << totalTime << ", " << "'" << _eventName << "'";
    21.             stmt.addRow(query.str());
    22.             stmt.execute();
    23.         }
    24.     }
    25.    
    26. private:
    27.     std::string _function;
    28.     std::string _eventName;
    29.     int64_t _time;
    30. };
    Then, to log onLogout script for example, I simply call the function, set up few parameters, and let the destructor take care of it.

    Code (Text):
    1. bool CreatureEvent::executeOnLogout(Player* player)  
    2. //onLogout(cid)
    3. ...
    4.  EventLog event("onLogout");
    5.  event.setName(m_eventName);

    It results something like this:

    [​IMG]
     
    Joe Rod and milbradt like this.
  2. Xikini

    Xikini Titan Kingdoms

    Joined:
    Nov 17, 2010
    Messages:
    3,036
    Likes Received:
    1,553
    Best Answers:
    35
    Cool. :p
    But to be fair it was MatheusMkalo that made the function I linked you to. :rolleyes:
     
    tokenzz likes this.
  3. Mkalo

    Mkalo ボーカロイド Support Team

    Joined:
    Jun 1, 2011
    Messages:
    1,117
    Likes Received:
    878
    Best Answers:
    53
    I would store a good amount of logs in a buffer before getting them to the database, or even better, not use database at all and output it to a file. (That if you intend to keep this running on production)
     
  4. Stellow

    Stellow C++/C#/PHP/LUA

    Joined:
    Oct 23, 2008
    Messages:
    997
    Likes Received:
    115
    Best Answers:
    0
    What about if the server crash?
     
  5. Mkalo

    Mkalo ボーカロイド Support Team

    Joined:
    Jun 1, 2011
    Messages:
    1,117
    Likes Received:
    878
    Best Answers:
    53
    That's why I said the file was better :x
     
  6. RetroCore

    RetroCore New Member

    Joined:
    Jun 26, 2016
    Messages:
    10
    Likes Received:
    1
    Best Answers:
    0
    You can also save it 2 times.

    First time when it starts (you can easly find potential crash issue)

    Second time when it ends.
     
  7. Stellow

    Stellow C++/C#/PHP/LUA

    Joined:
    Oct 23, 2008
    Messages:
    997
    Likes Received:
    115
    Best Answers:
    0
    Well.. if server crash, and the file is open, can compromise the information on the file.
     

Share This Page

Loading...