Improve JobSystem, especially under contention

- only signal waitAndRelease() when the corresponding job finishes and
only if there is waitAndRelease() active -- instead of signaling 
every time a job ends.

- don't surrender time slice when attempting to steal a job and it fails
as long as some queue has jobs.

- check that we have to wait, because taking the lock

- add a benchmark

This change more than doubles the amount of jobs we can handle per
second (~965,000 jobs/s on Pixel3)
This commit is contained in:
Mathias Agopian
2018-12-14 14:57:57 -08:00
committed by Mathias Agopian
parent d6de2bf426
commit cfb9c03226
4 changed files with 111 additions and 17 deletions

View File

@@ -70,7 +70,8 @@ public:
uint16_t parent; // 2 | 2
std::atomic<uint16_t> runningJobCount = { 1 }; // 2 | 2
mutable std::atomic<uint16_t> refCount = { 1 }; // 2 | 2
// 6 | 2 (padding)
std::atomic_bool hasWaiter = { false }; // 1 | 1
// 5 | 1 (padding)
// 64 | 64
};
@@ -97,6 +98,8 @@ public:
Job* setMasterJob(Job* job) noexcept { return mMasterJob = job; }
Job* create(Job* parent, JobFunc func) noexcept;
// NOTE: All methods below must be called from the same thread and that thread must be
// owned by JobSystem's thread pool.
@@ -342,9 +345,8 @@ private:
void incRef(Job const* job) noexcept;
void decRef(Job const* job) noexcept;
Job* create(Job* parent, JobFunc func) noexcept;
Job* allocateJob() noexcept;
JobSystem::ThreadState& getStateToStealFrom(JobSystem::ThreadState& state) noexcept;
JobSystem::ThreadState* getStateToStealFrom(JobSystem::ThreadState& state) noexcept;
bool hasJobCompleted(Job const* job) noexcept;
void requestExit() noexcept;