3f032156c8
Like yesterday's change to run CPU-parent child tasks serially in thread, this reduces peak memory usage by improving the temporaly locality of the bitmaps we create. E.g. Let's say we start with tasks A B C and D Queue: [ A B C D ] Running A creates A' and A", which depend on a bitmap created by A. Queue: [ B C D A' A" * ] That bitmap now needs sit around in RAM while B C and D run pointlessly and can only be destroyed at *. If instead we do this and push dependent child tasks to the front of the queue, the queue and bitmap lifetime looks like this: Queue: [ A' A" * B C D ] This is much, much worse in practice because the queue is often several thousand tasks long. 100s of megs of bitmaps can pile up for 10s of seconds pointlessly. To make this work we add addNext() to SkThreadPool and its cousin DMTaskRunner. I also took the opportunity to swap head and tail in the threadpool implementation so it matches the comments and intuition better: we always pop the head, add() puts it at the tail, addNext() at the head. Before Debug: 49s, 1403352k peak Release: 16s, 2064008k peak After Debug: 49s, 1234788k peak Release: 15s, 1903424k peak BUG=skia:2478 R=bsalomon@google.com, borenet@google.com, mtklein@google.com Author: mtklein@chromium.org Review URL: https://codereview.chromium.org/263803003 git-svn-id: http://skia.googlecode.com/svn/trunk@14506 2bbb7eff-a529-9590-31e7-b0007b416f81
74 lines
1.7 KiB
C++
74 lines
1.7 KiB
C++
#ifndef DMTask_DEFINED
|
|
#define DMTask_DEFINED
|
|
|
|
#include "DMReporter.h"
|
|
#include "DMGpuSupport.h"
|
|
#include "SkRunnable.h"
|
|
#include "SkTime.h"
|
|
|
|
// DM will run() these tasks on one of two threadpools.
|
|
// Subclasses can call fail() to mark this task as failed, or make any number of spawnChild() calls
|
|
// to kick off dependent tasks.
|
|
//
|
|
// Tasks delete themselves when run.
|
|
|
|
namespace DM {
|
|
|
|
class TaskRunner;
|
|
|
|
class CpuTask;
|
|
|
|
class Task {
|
|
public:
|
|
virtual bool shouldSkip() const = 0;
|
|
virtual SkString name() const = 0;
|
|
|
|
// Returns the number of parents above this task.
|
|
// Top-level tasks return 0, their children 1, and so on.
|
|
int depth() const { return fDepth; }
|
|
|
|
protected:
|
|
Task(Reporter* reporter, TaskRunner* taskRunner);
|
|
Task(const Task& parent);
|
|
virtual ~Task() {}
|
|
|
|
void start();
|
|
void fail(const char* msg = NULL);
|
|
void finish();
|
|
|
|
void spawnChildNext(CpuTask* task); // For now we don't allow GPU child tasks.
|
|
|
|
private:
|
|
Reporter* fReporter; // Unowned.
|
|
TaskRunner* fTaskRunner; // Unowned.
|
|
int fDepth;
|
|
SkMSec fStart;
|
|
};
|
|
|
|
class CpuTask : public Task, public SkRunnable {
|
|
public:
|
|
CpuTask(Reporter* reporter, TaskRunner* taskRunner);
|
|
CpuTask(const Task& parent);
|
|
virtual ~CpuTask() {}
|
|
|
|
void run() SK_OVERRIDE;
|
|
virtual void draw() = 0;
|
|
|
|
void spawnChild(CpuTask* task);
|
|
};
|
|
|
|
class GpuTask : public Task, public SkTRunnable<GrContextFactory> {
|
|
public:
|
|
GpuTask(Reporter* reporter, TaskRunner* taskRunner);
|
|
virtual ~GpuTask() {}
|
|
|
|
void run(GrContextFactory&) SK_OVERRIDE;
|
|
virtual void draw(GrContextFactory*) = 0;
|
|
|
|
void spawnChild(CpuTask* task);
|
|
};
|
|
|
|
} // namespace DM
|
|
|
|
#endif // DMTask_DEFINED
|