-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Show task performance #445
base: master
Are you sure you want to change the base?
Changes from all commits
5acf1f5
ad1aa46
af2962b
ae11566
ce26e55
93a9d04
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -633,6 +633,7 @@ pub const ChunkMesh = struct { | |
.isStillNeeded = @ptrCast(&isStillNeeded), | ||
.run = @ptrCast(&run), | ||
.clean = @ptrCast(&clean), | ||
.taskType = .lighting, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also I just noticed you have three .lighting tasks, but they do completely different things. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It wouldn't be hard to change. Is there a better classification? I literally just classified it based on my impressions of the performance problems. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would just put the LightRefreshTaks and the LightMapLoadTask under .misc, they shouldn't take much performance. |
||
}; | ||
|
||
pub fn scheduleAndDecreaseRefCount(mesh: *ChunkMesh) void { | ||
|
@@ -1237,4 +1238,4 @@ pub const ChunkMesh = struct { | |
chunkList.append(self.chunkAllocation.start); | ||
transparentQuadsDrawn += self.culledSortingCount; | ||
} | ||
}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -985,6 +985,12 @@ pub fn BlockingMaxHeap(comptime T: type) type { | |
} | ||
|
||
pub const ThreadPool = struct { | ||
pub const TaskType = enum(usize) { | ||
chunkgen, | ||
lighting, | ||
misc, | ||
taskTypes, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of having a C-style enum length field, I think it would be better to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sometimes I wonder if Zig devs have a naming scheme. |
||
}; | ||
const Task = struct { | ||
cachedPriority: f32, | ||
self: *anyopaque, | ||
|
@@ -999,6 +1005,23 @@ pub const ThreadPool = struct { | |
isStillNeeded: *const fn(*anyopaque, milliTime: i64) bool, | ||
run: *const fn(*anyopaque) void, | ||
clean: *const fn(*anyopaque) void, | ||
taskType: TaskType = .misc, | ||
}; | ||
pub const Performance = struct { | ||
mutex: std.Thread.Mutex = .{}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this would be a great place to use atomics with monotonic ordering instead of locking. |
||
tasks: [@intFromEnum(TaskType.taskTypes)]u32 = {}, | ||
utime: [@intFromEnum(TaskType.taskTypes)]i64 = {}, | ||
|
||
fn clear(self: *Performance) void { | ||
for(0..@intFromEnum(TaskType.taskTypes)) |i| { | ||
self.tasks[i] = 0; | ||
self.utime[i] = 0; | ||
} | ||
} | ||
|
||
fn init(self: Performance) void { | ||
self.clear(); | ||
} | ||
}; | ||
const refreshTime: u32 = 100; // The time after which all priorities get refreshed in milliseconds. | ||
|
||
|
@@ -1007,11 +1030,14 @@ pub const ThreadPool = struct { | |
loadList: *BlockingMaxHeap(Task), | ||
allocator: NeverFailingAllocator, | ||
|
||
performance: *Performance, | ||
|
||
pub fn init(allocator: NeverFailingAllocator, threadCount: usize) ThreadPool { | ||
const self = ThreadPool { | ||
.threads = allocator.alloc(std.Thread, threadCount), | ||
.currentTasks = allocator.alloc(Atomic(?*const VTable), threadCount), | ||
.loadList = BlockingMaxHeap(Task).init(allocator), | ||
.performance = allocator.create(Performance), | ||
.allocator = allocator, | ||
}; | ||
for(self.threads, 0..) |*thread, i| { | ||
|
@@ -1062,6 +1088,15 @@ pub const ThreadPool = struct { | |
} | ||
} | ||
|
||
pub fn getPerformance(self: ThreadPool) Performance { | ||
self.performance.mutex.lock(); | ||
defer { | ||
self.performance.clear(); | ||
self.performance.mutex.unlock(); | ||
} | ||
return self.performance.*; | ||
} | ||
|
||
fn run(self: ThreadPool, id: usize) void { | ||
// In case any of the tasks wants to allocate memory: | ||
var sta = StackAllocator.init(main.globalAllocator, 1 << 23); | ||
|
@@ -1073,7 +1108,14 @@ pub const ThreadPool = struct { | |
{ | ||
const task = self.loadList.extractMax() catch break; | ||
self.currentTasks[id].store(task.vtable, .monotonic); | ||
const start = std.time.microTimestamp(); | ||
task.vtable.run(task.self); | ||
const end = std.time.microTimestamp(); | ||
const taskType = @intFromEnum(task.vtable.taskType); | ||
self.performance.mutex.lock(); | ||
self.performance.tasks[taskType] += 1; | ||
self.performance.utime[taskType] += end - start; | ||
self.performance.mutex.unlock(); | ||
self.currentTasks[id].store(null, .monotonic); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just use
@tagName
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To separate source code and rendering options. Suppose we added localization?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debug info does not need to be translated, since it shouldn't be used by the majority of players.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose that will be a secondary concern after we get any localization in place.