impl/worker_thread, client/app: Smooth post() processing of tasks

This commit is contained in:
Perttu Ahola 2014-10-18 15:57:39 +03:00
parent 339a8225da
commit de2c956825
4 changed files with 53 additions and 12 deletions

View File

@ -8,7 +8,7 @@ local cereal = require("buildat/extension/cereal")
local dump = buildat.dump
local M = {}
local UPDATE_TIME_FRACTION = 0.20
local UPDATE_TIME_FRACTION = 0.10
--local LOD_DISTANCE = 140
--local LOD_DISTANCE = 100

View File

@ -49,3 +49,7 @@ Buildat TODO
- Allow connecting the input systems of multiple windows, which is simple
but less automatic and most people don't know how to get rid of window
borders
- A way for module reloading to interrupt world generation
- Maintain a global budget of background processing per frame so that
a long woxelworld:update and ThreadPool::run_post() will not be run on the
same frame

View File

@ -34,7 +34,7 @@
#include <FileSystem.h>
#include <PhysicsWorld.h>
#include <DebugRenderer.h>
//#include <Profiler.h>
#include <Profiler.h>
#pragma GCC diagnostic pop
extern "C" {
#include <lua.h>
@ -535,7 +535,11 @@ struct CApp: public App, public magic::Application
if(m_state)
m_state->update();
m_thread_pool->run_post();
{
magic::AutoProfileBlock profiler_block(
GetSubsystem<magic::Profiler>(), "Buildat|ThreadPool::post");
m_thread_pool->run_post();
}
}
void on_post_render_update(

View File

@ -4,6 +4,7 @@
#include "interface/mutex.h"
#include "interface/semaphore.h"
#include "core/log.h"
#include <c55/os.h>
#include <deque>
#ifdef _WIN32
#include "ports/windows_compat.h"
@ -127,16 +128,48 @@ struct CThreadPool: public ThreadPool
void run_post()
{
std::deque<up_<Task>> output_queue;
{
interface::MutexScope ms(m_mutex);
output_queue.swap(m_output_queue);
int64_t t1 = get_timeofday_us();
size_t queue_size = 0;
size_t post_count = 0;
for(;;){
// Pop an output task
up_<Task> task;
{
interface::MutexScope ms(m_mutex);
if(!m_output_queue.empty()){
queue_size = m_output_queue.size();
task = std::move(m_output_queue.front());
m_output_queue.pop_front();
}
}
if(!task)
break;
// run post() until too long has passed
bool done = false;
for(;;){
post_count++;
done = task->post();
// If done, take next output task
if(done)
break;
int64_t t2 = get_timeofday_us();
int64_t max_t = 2000;
if(queue_size > 4)
max_t += (queue_size - 4) * 5000;
if(t2 - t1 >= max_t)
break;
}
// If still not done, push task to back to front of queue and stop
// processing
if(!done){
interface::MutexScope ms(m_mutex);
m_output_queue.push_front(std::move(task));
break;
}
}
// TODO: Limit task->post() execution time per frame
for(auto &task : output_queue){
while(!task->post());
}
// Done with tasks; discard them
/*int64_t t2 = get_timeofday_us();
log_v(MODULE, "output post(): %ius (%zu calls; queue size: %zu)",
(int)(t2 - t1), post_count, queue_size);*/
}
};