Do not allow the m_transforming_liquid queue to increase until all RAM is consumed
authorCraig Robbins <kde.psych@gmail.com>
Wed, 17 Dec 2014 16:54:43 +0000 (02:54 +1000)
committerCraig Robbins <kde.psych@gmail.com>
Wed, 17 Dec 2014 17:32:19 +0000 (03:32 +1000)
minetest.conf.example
src/defaultsettings.cpp
src/map.cpp
src/map.h

index 7b8ab3692f2880f5c0075081fd4b62a3ec8365fa..7e5228bec30af959fc36403c3c3162b06e67800b 100644 (file)
 #new_style_water = false
 # Max liquids processed per step
 #liquid_loop_max = 10000
+# The time (in seconds) that the liquids queue may grow beyond processing
+# capacity until an attempt is made to decrease its size by dumping old queue items
+#liquid_queue_purge_time = 30
 # Update liquids every .. recommend for finite: 0.2
 #liquid_update = 1.0
 # Enable nice leaves; disable for speed
index 1ebf5dc49bc7dd34df1985ba391253abdea21246..5b83c26946cbc4e41dfd60375f79e70fcb14a8d0 100644 (file)
@@ -277,6 +277,7 @@ void set_default_settings(Settings *settings)
 
        //liquid stuff
        settings->setDefault("liquid_loop_max", "10000");
+       settings->setDefault("liquid_queue_purge_time", "30");
        settings->setDefault("liquid_update", "1.0");
 
        //mapgen stuff
index 009bc3d72e6c191aa483764f4ec250d2a4e3b256..10a6f62837a4e10cee146d6bbbaa84dd696dd918 100644 (file)
@@ -76,7 +76,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 Map::Map(std::ostream &dout, IGameDef *gamedef):
        m_dout(dout),
        m_gamedef(gamedef),
-       m_sector_cache(NULL)
+       m_sector_cache(NULL),
+       m_transforming_liquid_loop_count_multiplier(1.0f),
+       m_unprocessed_count(0),
+       m_inc_trending_up_start_time(0),
+       m_queue_size_timer_started(false)
 {
 }
 
@@ -1611,6 +1615,7 @@ s32 Map::transforming_liquid_size() {
 
 void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
 {
+
        INodeDefManager *nodemgr = m_gamedef->ndef();
 
        DSTACK(__FUNCTION_NAME);
@@ -1619,6 +1624,8 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
        u32 loopcount = 0;
        u32 initial_size = m_transforming_liquid.size();
 
+       u32 curr_time = getTime(PRECISION_MILLI);
+
        /*if(initial_size != 0)
                infostream<<"transformLiquids(): initial_size="<<initial_size<<std::endl;*/
 
@@ -1628,7 +1635,27 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
        // List of MapBlocks that will require a lighting update (due to lava)
        std::map<v3s16, MapBlock*> lighting_modified_blocks;
 
-       u16 loop_max = g_settings->getU16("liquid_loop_max");
+       u32 liquid_loop_max = g_settings->getS32("liquid_loop_max");
+       u32 loop_max = liquid_loop_max;
+
+//     std::cout << "transformLiquids(): loopmax initial="
+//                << loop_max * m_transforming_liquid_loop_count_multiplier;
+
+       // If liquid_loop_max is not keeping up with the queue size increase
+       // loop_max up to a maximum of liquid_loop_max * dedicated_server_step.
+       if (m_transforming_liquid.size() > loop_max * 2) {
+               // "Burst" mode
+               float server_step = g_settings->getFloat("dedicated_server_step");
+               if (m_transforming_liquid_loop_count_multiplier - 1.0 < server_step)
+                       m_transforming_liquid_loop_count_multiplier *= 1.0 + server_step / 10;
+       } else {
+               m_transforming_liquid_loop_count_multiplier = 1.0;
+       }
+
+       loop_max *= m_transforming_liquid_loop_count_multiplier;
+
+//     std::cout << " queue sz=" << m_transforming_liquid.size()
+//                << " loop_max=" << loop_max;
 
        while(m_transforming_liquid.size() != 0)
        {
@@ -1884,6 +1911,54 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
        while (must_reflow.size() > 0)
                m_transforming_liquid.push_back(must_reflow.pop_front());
        updateLighting(lighting_modified_blocks, modified_blocks);
+
+
+       /*
+        * Queue size limiting
+        */
+       u32 prev_unprocessed = m_unprocessed_count;
+       m_unprocessed_count = m_transforming_liquid.size();
+
+       // if unprocessed block count is decreasing or stable
+       if (m_unprocessed_count <= prev_unprocessed) {
+               m_queue_size_timer_started = false;
+       } else {
+               if (!m_queue_size_timer_started)
+                       m_inc_trending_up_start_time = curr_time;
+               m_queue_size_timer_started = true;
+       }
+
+       u16 time_until_purge = g_settings->getU16("liquid_queue_purge_time");
+       time_until_purge *= 1000;       // seconds -> milliseconds
+
+//     std::cout << " growing for: "
+//                << (m_queue_size_timer_started ? curr_time - m_inc_trend_up_start_time : 0)
+//                << "ms" << std::endl;
+
+       // Account for curr_time overflowing
+       if (m_queue_size_timer_started && m_inc_trending_up_start_time > curr_time)
+               m_queue_size_timer_started = false;
+
+       /* If the queue has been growing for more than liquid_queue_purge_time seconds
+        * and the number of unprocessed blocks is still > liquid_loop_max then we
+        * cannot keep up; dump the oldest blocks from the queue so that the queue
+        * has liquid_loop_max items in it
+        */
+       if (m_queue_size_timer_started
+                       && curr_time - m_inc_trending_up_start_time > time_until_purge
+                       && m_unprocessed_count > liquid_loop_max) {
+
+               size_t dump_qty = m_unprocessed_count - liquid_loop_max;
+
+               infostream << "transformLiquids(): DUMPING " << dump_qty
+                          << " blocks from the queue" << std::endl;
+
+               while (dump_qty--)
+                       m_transforming_liquid.pop_front();
+
+               m_queue_size_timer_started = false; // optimistically assume we can keep up now
+               m_unprocessed_count = m_transforming_liquid.size();
+       }
 }
 
 NodeMetadata *Map::getNodeMetadata(v3s16 p)
index c650e51b65090c7defd7febfccf12ad491b6c0cd..70082d664518955858b23bde116bee9901c3f472 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -366,6 +366,12 @@ protected:
 
        // Queued transforming water nodes
        UniqueQueue<v3s16> m_transforming_liquid;
+
+private:
+       f32 m_transforming_liquid_loop_count_multiplier;
+       u32 m_unprocessed_count;
+       u32 m_inc_trending_up_start_time; // milliseconds
+       bool m_queue_size_timer_started;
 };
 
 /*