Search Unity

Question Profiling game: ParticleSystem.WaitForPreMapping taking 36.9% CPU. What is it?

Discussion in 'General Graphics' started by Jamez0r, May 23, 2020.

  1. Jamez0r

    Jamez0r

    Joined:
    Jul 29, 2019
    Posts:
    206


    The top highlighted line says ParticleSystem.WaitForPreMapping, and it is taking 36.9% CPU time. I googled ParticleSystem.WaitForPreMapping as well as ParticleSystem.ScheduleGeometryJobs and couldn't find any information.

    In the current scene the only particles that are active are a Rain particle effect (screenshot below). Probably around 300 or 400 active particles. There must be something weird going on to cause this 36.9% CPU usage, but without knowing what WaitForPreMapping is, I have no idea what to do.

    In case it matters, I'm using URP with the 2D Renderer. Unity 2019.3.7f1



    Would appreciate any help! Thanks a lot!
     
  2. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,285
    We try to predict how much GPU memory we need for particles for the current frame, so it’s ready ahead of time and there is no extra waiting.

    But if our prediction is too low, there can be a wait on one frame, and then we make a better guess on future frames.

    This only applies to some platforms/devices. On newer ones like metal and dx12 there is never a stall for this.

    Is it just happening on a single frame? As you are running at (approx) 100fps probably that’s why the wait appears so significant - there isn’t much other work going on to reduce the idle time.
     
  3. DaseinPhaos

    DaseinPhaos

    Joined:
    Nov 20, 2017
    Posts:
    7
    We are experiencing similar problems on Android with OpenGLES3, the stall happens constantly across multiple frames under our SRP renderloop, nested inside CullScriptable/ParticleSystem.ScheduleGeometryJobs. I wander is there a way to walkaround this on mobile platforms?

    An Unity issue tracker which might be relevant: https://issuetracker.unity3d.com/is...t-schedulegeometryjobs-takes-a-very-long-time
    Find it confusing that it was marked as "by design" without additional notes..
     
  4. DaseinPhaos

    DaseinPhaos

    Joined:
    Nov 20, 2017
    Posts:
    7
    ---

    Status update: since we don't have this problem on PC build, which uses different quality settings, we decide to switch the quality settings and see what happens.

    Turns out that by increasing Quality/Particle Raycast Budget from 4 to 64, we get a significant improvement: time spent on ParticleSystem.ScheduleGeometryJobs drops from 9.31ms to 0.04ms (99.57% drop), see the attached Profile Analyzer screenshot
     

    Attached Files:

    Last edited: Jun 13, 2020
    jhughes2112 likes this.
  5. Jamez0r

    Jamez0r

    Joined:
    Jul 29, 2019
    Posts:
    206
    [EDIT: Possible solution in my next Reply]

    Hey @richardkettlewell , thanks a lot for responding! Sorry that its taking me so long to reply, had a bunch of IRL stuff come up - but things are back to normal and I'm looking to get this thing figured out :)

    The ScheduleGeometryJobs is happening almost every frame (there may be a frame or two everyone once in a while where it doesn't happen, but it seems to be almost every frame). Here is a video - it shows the player standing in a field, and the only thing happening is the Rain particle effect:


    Notes that could be relevant:

    -I'm running the game in-editor and standalone on PC only. Video above is standalone on PC with attached profiler.

    -There are 2 particle effects for the rain - the 'raindrops' falling downward, and then a separate particle system for the little 'splashes' that appear randomly on the ground. The 'splashes' use collision detection so that they don't make a 'splash' on an areas that aren't solid ground (like off the edge of a cliff). Not sure if that is relevant or not. Even with both the raindrop and the splash particles disabled (aka no particles being rendered), the ScheduleGeometryJobs takes the same amount of CPU usage (30%-80%).

    -The weather in my game is a really important aspect of the visuals, so the rain particle effect needs to smoothly transition (tween) many of its Modules (number of raindrops, their speed, their size, etc). This snippet of code is how I change the Module settings:

    Code (CSharp):
    1. public void UpdateAllVariables() {
    2.  
    3.         //RAINDROPS
    4.         rainEmissionModule.rateOverTime = rainAmount;
    5.  
    6.         rainMainModule.startLifetime = new MinMaxCurve(rainLifetimeMin, rainLifetimeMax);
    7.  
    8.         rainMainModule.startSizeX = new MinMaxCurve(rainWidthScaleMin, rainWidthScaleMax);
    9.         rainMainModule.startSizeY = new MinMaxCurve(rainLengthScaleMin, rainLengthScaleMax);
    10.  
    11.         rainSizeOverLifetimeModule.size = new MinMaxCurve(1, rainSizeOverLifetimeCurve);
    12.  
    13.         rainVelocityModule.x = new MinMaxCurve(rainSpeedMinX, rainSpeedMaxX);
    14.         rainVelocityModule.y = new MinMaxCurve(-rainSpeedMinY, -rainSpeedMaxY);
    15.  
    16.         GradientAlphaKey[] newRainAlphaKeys = new GradientAlphaKey[] {
    17.             new GradientAlphaKey(0, 0.0f),
    18.             new GradientAlphaKey(rainOpacity * 0.73f, rainColorGradient.alphaKeys[1].time),
    19.             new GradientAlphaKey(rainOpacity, rainColorGradient.alphaKeys[2].time),
    20.             new GradientAlphaKey(rainOpacity, rainColorGradient.alphaKeys[3].time),
    21.             new GradientAlphaKey(rainOpacity * 0.73f, rainColorGradient.alphaKeys[4].time),
    22.             new GradientAlphaKey(0, 1.0f)};
    23.         rainColorGradient.SetKeys(rainColorGradient.colorKeys, newRainAlphaKeys);
    24.         rainColorOverLifetimeModule.color = rainColorGradient;
    25.  
    26.         //SPLATS
    27.         splatEmissionModule.rateOverTime = splatAmount;
    28.  
    29.         splatMainModule.startSizeX = new MinMaxCurve(splatWidthScaleMin, splatWidthScaleMax);
    30.         splatMainModule.startSizeY = new MinMaxCurve(splatLengthScaleMin, splatLengthScaleMax);
    31.  
    32.         GradientAlphaKey[] newSplatAlphaKeys = new GradientAlphaKey[] {
    33.             new GradientAlphaKey(splatOpacity, 0.0f),
    34.             new GradientAlphaKey(splatOpacity, splatColorGradient.alphaKeys[1].time),
    35.             new GradientAlphaKey(0, 1.0f)};
    36.         splatColorGradient.SetKeys(splatColorGradient.colorKeys, newSplatAlphaKeys);
    37.         splatColorOverLifetimeModule.color = splatColorGradient;
    38.  
    39.     }
    Those modules are updated every frame by my RainManager script. I'm not sure if they could be the cause of this issue, since I've been using that script for a couple months before this ScheduleGeometryJobs issue popped up. Also, even when disabling this RainManager script the ScheduleGeometryJobs takes the same high amount of CPU.

    -So just to re-iterate: Even with my custom RainManager script disabled AND the rain particle effects disabled, the ScheduleGeometryJobs CPU usage stays high.

    -Here is a screenshot of the profiler while running the game in-editor. The sections with the highest CPU milliseconds are where the ScheduleGeometryJobs is at around 80%, and the dips downward with the lower CPU milliseconds is where ScheduleGeometryJobs is at around 30%.




    Would be glad to provide any additional information, or try any ideas. I'm going to test out what @DaseinPhaos suggested (although I'm already running it on PC) and I'll respond here if it helps!

    (Side note: I know my CPU/GPU millisecond usage are roughly equal, but there is a major performance improvement I will be doing soon on the GPU side, so if I can do that AND fix this CPU usage I think I'll be in much better shape!)
     
    Last edited: Jun 13, 2020
  6. Jamez0r

    Jamez0r

    Joined:
    Jul 29, 2019
    Posts:
    206
    Wow, I just did the same thing (Particle Raycast Budget from 4 to 64) and the ScheduleGeometryJobs dropped down as well:



    Very nice, and thanks a lot for the info @DaseinPhaos ! I'm not sure what is going on behind the scenes here - I had the default Quality settings for the game set to Very Low (assuming it would be the baseline setup that would give me the highest FPS)... so it seems strange that increasing that Raycast Budget (which I would assume was set to a low number due to the Quality setting) actually made a framerate IMPROVEMENT. Strange, but super glad its helping!
     
  7. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,285
    This is super surprising to me too! I’d love a bug report with a minimal repro.. but I suspect this is one of those complex issues that requires a full project with all of its quirks.. that said, if either of you did want to report this as a bug (even with the full project) and mention me/this forum post, and reply here with the case number, I will try to understand what’s going on!
     
  8. jhughes2112

    jhughes2112

    Joined:
    Nov 20, 2014
    Posts:
    178
    Hey guys. I wanted to mention that I had the same apparent issue (ParticleSystem.ScheduleGeometryJobs steadily high) and realized that in my case, it did not matter what I set my Particle Raycast Budget to--mine was already 4096. I tried various values and changed quality settings and found it did not change anything. But what I did notice, however, is for whatever reason, it looks like geometry scheduling happens really early in the frame, and immediately prior is a Particles.Sync call. The profiler tries its best, but I suspect what we're really seeing is the CPU deadlocked waiting for vsync or the graphics pipe in general. In my case, the weird dip-spikes are places where my ONLY significant entry is a Gfx.WaitForPresentOnGfxThread, and on that frame, the time is exactly the same as what is normally on ScheduleGeometryJobs. I don't believe in coincidences. You can also just see from the graph, the time taken in my case is an astronomical 17ms, which is roughly the time required to hit the vsync for 30fps, since my frame is slower than 60fps. This is far from definitive, but while changing the particle budget might help some people, it's also a red herring for others.

    upload_2021-7-23_1-0-35.png
     
  9. Radiangames2

    Radiangames2

    Joined:
    Aug 22, 2012
    Posts:
    45
    I'm having the exact same issue, but the raycast budget is definitely not the problem (mine was 2048 already). Normally my game runs at 100+ FPS, but once I start moving a vehicle, the particles from the wheels cause the framerate to dip into the 40s. All the time is taken up in ParticleSystem.WaitForPremapping (20+ ms). There are maybe 200 particles on-screen, all generated from the same system.

    I'm either going to be trying to write a custom GPU-based particle system anyway (I want 100,000+ particles), or switch to URP/HDRP and use VFX graph instead. I'm assuming that doesn't have the same problem.
     
  10. DragonCoder

    DragonCoder

    Joined:
    Jul 3, 2015
    Posts:
    1,698
    To add a hint:
    Believe it or not, a restart of unity can magically fix this issue as well o_O
     
  11. zedz

    zedz

    Joined:
    Aug 31, 2013
    Posts:
    250
    After upgrading from 2021.2.3 -> 2022.2.20 I'm seeing a large slow down with particlesystem.waitforpremapping also.
    Increasing the Particle Raycast Budget doesn't help
    Luckily it seems this is only in the editor, a standalone build seems to run fast. Its a bit annoying though

    EDIT: Seems a reboot fixed it
    Oddly particlesystem.waitforpremapping now takes 0.00msec
     
    Last edited: May 25, 2023