code size and performance optimizations (#472)

* Clean-up EntityManager a bit

- use tsl::robin_set instead of std::set (which should have been unordered::set
  anyways).

- getListeners() now returns a vector which avoids to traverse a set twice.
  Turns out that copying the set wasn't as efficient as I thought.

* Improve jobsystem a bit

We recently added a job reference counting mechanism, but we were a bit
too aggressive about taking/release references.

Also make the API more complete by adding explicit retain/release,
which is needed to allow several threads to wait on the same job.

Also improve futex code by inlining it.
This commit is contained in:
Mathias Agopian
2018-11-12 14:11:31 -08:00
committed by GitHub
parent 3407302954
commit bc3aee118a
13 changed files with 207 additions and 172 deletions

View File

@@ -216,39 +216,78 @@ public:
return job;
}
// Add job to this thread's execution queue.
// Current thread must be owned by JobSystem's thread pool. See adopt().
/*
* Jobs are normally finished automatically, this can be used to cancel a job before it is run.
*
* Never use this once a flavor of run() has been called.
*/
void cancel(Job*& job) noexcept;
/*
* Adds a reference to a Job.
*
* This allows the caller to waitAndRelease() on this job from multiple threads.
* Use runAndWait() if waiting from multiple threads is not needed.
*
* This job MUST BE waited on with waitAndRelease(), or released with release().
*/
Job* retain(Job* job) noexcept;
/*
* Releases a reference from a Job obtained with runAndRetain() or a call to retain().
*
* The job can't be used after this call.
*/
void release(Job*& job) noexcept;
void release(Job*&& job) noexcept {
Job* p = job;
release(p);
}
/*
* Add job to this thread's execution queue. It's reference will drop automatically.
* Current thread must be owned by JobSystem's thread pool. See adopt().
*
* The job can't be used after this call.
*/
enum runFlags { DONT_SIGNAL = 0x1 };
void run(Job*& job, uint32_t flags = 0) noexcept;
// This version allow a call such as run(createJob(...));
void run(Job*&& job, uint32_t flags = 0) noexcept {
void run(Job*&& job, uint32_t flags = 0) noexcept { // allows run(createJob(...));
Job* p = job;
run(p);
}
// run a job and keep a reference to it. This job MUST BE waited on with wait().
/*
* Add job to this thread's execution queue and and keep a reference to it.
* Current thread must be owned by JobSystem's thread pool. See adopt().
*
* This job MUST BE waited on with wait(), or released with release().
*/
Job* runAndRetain(Job* job, uint32_t flags = 0) noexcept;
// Wait on a job and destroys it. The job must first be obtained from runAndRetain().
// Current thread must be owned by JobSystem's thread pool. See adopt().
void wait(Job*& job) noexcept;
/*
* Wait on a job and destroys it.
* Current thread must be owned by JobSystem's thread pool. See adopt().
*
* The job must first be obtained from runAndRetain() or retain().
* The job can't be used after this call.
*/
void waitAndRelease(Job*& job) noexcept;
void runAndWait(Job*& job) noexcept {
runAndRetain(job);
wait(job);
}
// This version allow a call such as runAndWait(createJob(...));
void runAndWait(Job*&& job) noexcept {
/*
* Runs and wait for a job. This is equivalent to calling
* runAndRetain(job);
* wait(job);
*
* The job can't be used after this call.
*/
void runAndWait(Job*& job) noexcept;
void runAndWait(Job*&& job) noexcept { // allows runAndWait(createJob(...));
Job* p = job;
runAndWait(p);
}
// jobs are normally finished automatically, this can be used to cancel a job
// before it is run.
void finish(Job* job) noexcept;
// for debugging
friend utils::io::ostream& operator << (utils::io::ostream& out, JobSystem const& js);
@@ -297,18 +336,6 @@ private:
uint32_t mask;
};
class Pin {
JobSystem& js;
Job const* job;
public:
Pin(JobSystem& js, Job const* job) noexcept : js(js), job(job) {
js.incRef(job);
}
~Pin() noexcept {
js.decRef(job);
}
};
static_assert(sizeof(ThreadState) % CACHELINE_SIZE == 0,
"ThreadState doesn't align to a cache line");
@@ -327,6 +354,7 @@ private:
void loop(ThreadState* threadState) noexcept;
bool execute(JobSystem::ThreadState& state) noexcept;
void finish(Job* job) noexcept;
void put(WorkQueue& workQueue, Job* job) noexcept {
size_t index = job - mJobStorageBase;