Infestation:PlaceBlobs causing massive slowdown [prolife]

SwatinemSwatinem Join Date: 2012-10-29 Member: 164362Members
When I was playing today on *tram*, I noticed than whenever i was near shipping/observation, my frames halved. From the usual 50-60 fps, it went to ~20fps.
When I left the area (back to hub), the frames returned to normal.

So I did a quick profile: <a href="http://cloud-2.steampowered.com/ugc/577849604472451369/B54EB906A9747018D408BE9BB4C696E7711B6A57/" target="_blank">http://cloud-2.steampowered.com/ugc/577849...C696E7711B6A57/</a>

So the „dynamic“ in Infestation means the blobs are generated on the fly, most noticeable when you are comm or when you respawn.
If I’m reading the profile correctly, the Infestation seems to be generated on every frame, slowing the game to a crawl. It also seems to do a GC directly in Infestation:PlaceBlob, for whatever reason.

I should have probably done a second profile screen as well, as only half of the GameClient:Update time is visible on screen :/ Don’t know what else is going on there...

Will try to come up with a better profile once I hit this bug a second time.

Comments

  • douchebagatrondouchebagatron Custom member title Join Date: 2003-12-20 Member: 24581Members, Constellation, Reinforced - Shadow
    edited December 2012
    taking a quick look at the code in PlaceBlobs, i see this:

    <!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->        // Get a uniformly distributed point the circle
            local x, z
            repeat
                x = random(-maxRand, maxRand)
                z = random(-maxRand, maxRand)
            until x * x + z * z < maxRand * maxRand<!--c2--></div><!--ec2-->

    which is pretty dang scary actually, since in theory this could hold up indefinitely. I understand the intention (to keep it within the radius of the cyst) but it shouldn't be done as a bunch of attempts until it's within the circle, it should be done using something like this:

    <!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->        local x, z, t, r
            t=2*pi*random(0,1)
            r=random(minRadius,maxRadius)
            x=r*cos(t)
            y=r*sin(t)<!--c2--></div><!--ec2-->

    this will give you a random point in the circle in one calculation, instead of in somewhere between 1 and infinite calculations.

    not sure how Lua does sin and cosign though. those can potentially be intensive to calculate if you're doing something like a taylor series. In the past I've used just a value index to look up the potential values of sin and cosign and it worked out fairly well. I'm sure NS2 would have a well established way for calculating sin and cosign exactly, but it might also be worth it to have a less precise but faster version for scenarios like this.

    a slightly different take is <a href="http://stackoverflow.com/questions/5837572/generate-a-random-point-within-a-circle-uniformly" target="_blank">here</a> that should give a uniform randomization, as I believe mine will be more concentracted at the center by making the following tweak:

    <!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->        local x, z, t, r, u
            t=2*pi*random(0,1)
            u=random(minRadius,maxRadius)+random(minRadius,maxRadius)
            if u>maxRadius then r=u-(maxRadius*2) else r=u
            x=r*cos(t)
            y=r*sin(t)<!--c2--></div><!--ec2-->
  • SwatinemSwatinem Join Date: 2012-10-29 Member: 164362Members
    Heh, that really is some ugly piece of code.
    Still does not explain why it usually runs without problems but why it was triggered a lot more in this particular situation.
  • SwatinemSwatinem Join Date: 2012-10-29 Member: 164362Members
    <a href="http://cloud-2.steampowered.com/ugc/577849604513206799/2B33502559805BC1DE665965083B71F518BC1CF1/" target="_blank">http://cloud-2.steampowered.com/ugc/577849...3B71F518BC1CF1/</a> <- Well I’m seeing a lot of such slowdowns lately.
    And not those „i go into the room and its slow for a frame“ but constant slowdowns when I’m in a certain area.

    20ms combined is waaay too high just for infestation. I’m also wondering why it causes such long GC pauses.
  • SwatinemSwatinem Join Date: 2012-10-29 Member: 164362Members
    <a href="http://cloud-2.steampowered.com/ugc/578976070515714949/CB729B47E22A8FDE907747644728CA906747FB71/" target="_blank">http://cloud-2.steampowered.com/ugc/578976...28CA906747FB71/</a>
    <a href="http://cloud-2.steampowered.com/ugc/578976070515724945/804212EBBCDEE12A255F444E8267F52ECC7C5086/" target="_blank">http://cloud-2.steampowered.com/ugc/578976...67F52ECC7C5086/</a>

    PlaceBlob is really slow, but also UpdateBlobAnimation is slow. Both add up 18-19ms (including gc).
    This is half of the total frame time. Thats really not acceptable :(
  • carlgmcarlgm Join Date: 2004-08-26 Member: 30907Members, Constellation
    Has anyone tried 6john example change to see how much of a difference it makes?
  • SwatinemSwatinem Join Date: 2012-10-29 Member: 164362Members
    I haven’t tried the different “random point in circle” function, but I have rather added a few more profiler hooks which show that the PlaceBlobs itself might not be that bad (while I’m sure that a potentially infinite loop needs to be fixed).

    The problem seems to be in GetBlobPlacement <a href="http://cloud.steampowered.com/ugc/578976070551536872/3EF5730977E5324B1D22B8E635E7553F449DC0F2/" target="_blank">http://cloud.steampowered.com/ugc/57897607...E7553F449DC0F2/</a>
    So, here I have high CreateModelArrays numbers: <a href="http://cloud.steampowered.com/ugc/578976070551528321/39ED2B5A7B92107F7D7F2F654B69A61FC1A1FB2F/" target="_blank">http://cloud.steampowered.com/ugc/57897607...69A61FC1A1FB2F/</a>
    High minimap drawing numbers: <a href="http://cloud-2.steampowered.com/ugc/578976070551539234/A3DFC5F2D129A6EB673657763F92A0A2C82C9985/" target="_blank">http://cloud-2.steampowered.com/ugc/578976...92A0A2C82C9985/</a>

    The console commands “debugblobs” and “debuginfest” are also nice to play around with, but with “debuginfest”, the fps goes down to below 1fps, haha.
    -> <a href="http://cloud.steampowered.com/ugc/578976070551512100/14F9A0F207E5AC7043EC1490B92A88B052E0FF10/" target="_blank">http://cloud.steampowered.com/ugc/57897607...2A88B052E0FF10/</a>


    So, in conclusion:

    We have
    <!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->    // Maximum number of blobs to generate in a frame
        _numBlobsToGenerate = 100
    […]
            numBlobGens = math.min(_numBlobsToGenerate, self.numBlobsToGenerate)
            self:PlaceBlobs(numBlobGens)
    […]
        local numBlobTries = numBlobGens * 3

        for j = 1, numBlobTries do
    […]
            local position, normal = GetBlobPlacement(x, z, xRadius, hostCoords)
            
            if position then
    […]
                numBlobs = numBlobs + 1
                
                if numBlobs == numBlobGens then
                    break<!--c2--></div><!--ec2-->

    Well this is quite complex code, but I kind of get the problem here:

    The code (tries to) generate 100 blobs per frame.
    For each blob, it *tries* 3 different random placements, hence the number of calls for GetBlobPlacement is maxed at 300.
    The problem is that the placement might be invalid (I guess it has to do with level geometry?) and it does not place a blob at all and the same thing continues the next frame.
    I think thats why I saw a constant slowdown when I roam around specific areas of a map. Seems like GetBlobPlacement returns an invalid position, and the code retries placement over and over again every single frame, leading to a constant slowdown.


    Reading the GetBlobPlacement code further, a correct placement would need 4 TraceRay traces for a correct placement (and anything from 1-3 for an invalid placement). On the supplied screenshot, we have 535 TraceRay calls for 300 GetBlobPlacement calls, which is a rather poor hit rate.


    This whole “get a random point, check if it can be placed on the level geometry, otherwise keep trying” concept seems to be quite bad.

    Why not do the following:
    * get the simplified level geometry that should be infested
    * place blobs *on that geometry* instead of at a random point which does not touch the geometry at all.


    Also regarding the minimap:
    Why not use *one* texture for infestation overlay.
    When the infestation changes, this texture is refreshed, otherwise it does not need to be. That texture can also be composited in such a way that the blips do not go over the edge of the minimap.
    For the marines, that texture would be masked using a “line of sight” texture.
    I think that would look better and perform better than the current method of drawing hundreds of blips on the minimap.


    It would be awesome to get some feedback from the devs regarding this stuff?
  • douchebagatrondouchebagatron Custom member title Join Date: 2003-12-20 Member: 24581Members, Constellation, Reinforced - Shadow
    I contacted Sewlek pointing him to this thread for more details on getting the change in the actual game. not in there yet though.
Sign In or Register to comment.