Posts: 66
Threads: 14
Joined: Jul 2025
Reputation:
0
20-02-2026, 04:00 PM
(This post was last modified: 20-02-2026, 04:00 PM by Qriva0.)
Hi, I noticed huge overhead coming from scheduling jobs and I have got several questions.
First of all I am aware that pushing many large job structs is slow and waking up threads is not free, however I did not expect such a big performance difference.
You can see profiler snapshot of obi simulation scheduling, single frame has 20 substeps and for testing purposes I added callback with job handle to schedule custom job (small blue bottom column).
Observations:
1. Each following substep is longer. For example the first call takes ~0.01ms, while the last one is ~0.1ms. This is huge difference, especially for jobs like particle collision where most of update is taken by them (0.4ms single substep!).
2. Using ScheduleByRef helps a bit, but I think for my custom jobs it's maybe 20% and what is more important I can't see wh huge job structs like friction can take small fraction of frame, while scheduling my job takes several times more time even if it's smaller.
3. I expected that changing Parallel to IJobFor would give me huge boost because it does not need to wake up everything, but it's not true.
4. Calling JobHandle.ScheduleBatchedJobs(); does not change anything, or I can't see visible difference.
In short I fail to see what exactly is causing that and on top of that Iam worried about obi8 - if I write custom constraint I guess it will be the same, so writing like 2-3 custom scripts going to kill the frame rate.
Posts: 6,712
Threads: 28
Joined: Jun 2017
Reputation:
435
Obi Owner:
20-02-2026, 10:55 PM
(This post was last modified: 20-02-2026, 11:50 PM by josemendez.)
Hi!
Scheduling jobs shouldn’t be anywhere as costly as 0.1 ms per job. Not sure why you mention friction constraints as an example of a “huge” job struct: it’s quite small, only a handful of NativeArrays are passed, which consist of just 2 integers each (memory address and count). That’s hardly enough data copying to even show up in the profiler.
Make sure to disable the jobs debugger though: enabling it will result exactly in the behavior you’re getting - scheduling jobs gets slower the more jobs you schedule in a frame, specially with long dependency chains. Everything will be considerably slower overall with debugging enabled.
Kind regards
Posts: 66
Threads: 14
Joined: Jul 2025
Reputation:
0
(20-02-2026, 10:55 PM)josemendez Wrote: Hi!
Scheduling jobs shouldn’t be anywhere as costly as 0.1 ms per job. Not sure why you mention friction constraints as an example of a “huge” job struct: it’s quite small, only a handful of NativeArrays are passed, which consist of just 2 integers each (memory address and count). That’s hardly enough data copying to even show up in the profiler.
Make sure to disable the jobs debugger though: enabling it will result exactly in the behavior you’re getting - scheduling jobs gets slower the more jobs you schedule in a frame, specially with long dependency chains. Everything will be considerably slower overall with debugging enabled.
Kind regards
Well, "huge" is relative term, I mean that my job struct is not even half as big as this one, but took way longer to schedule:
In any case you are right, disabling debugger removed stacked overhead, shame there is no button in editor and I need script for that.
Thanks!
Additional question - I noticed before that particle collision job is completed instantly and blocks main thread for very long time, is it possible to avoid this?
I see comment about fluid particles, but I don't use them, so is it possible to modify this code in some easy way to avoid this sync point?
Code: if (simulateWhenInvisible || isVisible)
{
simulationHandle = implementation.CollisionDetection(simulationHandle, simulatedTime);
simulationHandle?.Complete(); // complete here, since several jobs need fluidParticles.Length. TODO: use deferred jobs.
}
Posts: 6,712
Threads: 28
Joined: Jun 2017
Reputation:
435
Obi Owner:
23-02-2026, 01:00 PM
(This post was last modified: 23-02-2026, 01:02 PM by josemendez.)
(23-02-2026, 12:05 PM)Qriva0 Wrote: Well, "huge" is relative term, I mean that my job struct is not even half as big as this one, but took way longer to schedule:
That's 22 arrays and a few integers/floats, which totals around a bit more than 176 bytes (22*2*4 bytes), let's say 200. Copying 200 bytes is basically instant, should not even show up in a profiler. If your job is copying around larger structs (even if it looks smaller code-wise) then it will be slower to schedule. Note that schedule overhead also depends on other factors, not just struct size.
(23-02-2026, 12:05 PM)Qriva0 Wrote: In any case you are right, disabling debugger removed stacked overhead, shame there is no button in editor and I need script for that.
There's a button for this: you can find it in either Jobs->Jobs debugger or in Preferences->Jobs->Enable Jobs Debugger.
If you want to measure performance in editor, you should leave it disabled. See "Performance" of the Burst backend in Obi's manual:
https://obi.virtualmethodstudio.com/manu...kends.html
(23-02-2026, 12:05 PM)Qriva0 Wrote: Additional question - I noticed before that particle collision job is completed instantly and blocks main thread for very long time, is it possible to avoid this?
Not currently, since other jobs depend on it (including, but not limited to fluids). For Obi 8 I'm aiming to remove all Complete() calls mid-step.
kind regards,
Posts: 66
Threads: 14
Joined: Jul 2025
Reputation:
0
(23-02-2026, 01:00 PM)josemendez Wrote: That's 22 arrays and a few integers/floats, which totals around a bit more than 176 bytes (22*2*4 bytes), let's say 200. Copying 200 bytes is basically instant, should not even show up in a profiler. If your job is copying around larger structs (even if it looks smaller code-wise) then it will be slower to schedule. Note that schedule overhead also depends on other factors, not just struct size.
Yes, there are other factors and this what I tried to find out. Just for reference my struct below.
Obviously with debugger disabled this difference is not so huge, but still it's interesting what factors cause those gaps.
Code: [ReadOnly] public NativeArray<int> indices;
[NativeDisableParallelForRestriction] public NativeArray<float4> positions;
[WriteOnly] public NativeArray<float4> endPositions;
[NativeDisableParallelForRestriction] public NativeArray<quaternion> orientations;
[NativeDisableParallelForRestriction] public NativeArray<float> invMasses;
[WriteOnly] public NativeArray<float4> deltas;
public int2 constrainedRange;
public float segmentLength;
public float oOffset;
public float dt;
[ReadOnly, NativeDisableParallelForRestriction] public NativeArray<int> targetIndices;
public float targetTotalLength;
public int targetCount;
(23-02-2026, 01:00 PM)josemendez Wrote: There's a button for this: you can find it in either Jobs->Jobs debugger or in Preferences->Jobs->Enable Jobs Debugger. I think Jobs->Jobs debugger is available only with entities package, but prefereces works, thanks!
(23-02-2026, 01:00 PM)josemendez Wrote: Not currently, since other jobs depend on it (including, but not limited to fluids). For Obi 8 I'm aiming to remove all Complete() calls mid-step. Got it, great!
Thank you, have a great day!
|