优化代码物理

时间:2016-07-15 01:12:54

标签: ios swift performance sprite-kit

我一直在尝试优化代码以降低我的CPU使用率。我已经重写了这些功能几次无济于事,寻求一些帮助。

63%的时间花在球上......最多只有24个孩子。

   func totalMass() -> CGFloat {
    var ret : CGFloat = 0
    for ball in self.children as! [Ball] {
        ret += ball.mass
    }
    return ret
}

将近90%的时间用于if距离(食物......),可以有超过800件食物'一次。

func randomMove() {
        confidenceLevel = 0
        if let b = self.children.first as! Ball? {
            if b.physicsBody?.velocity == CGVector(dx: 0, dy: 0) {
                //print("a")
                self.move(randomPosition())
            } else if b.position.x + b.radius > 1950 || b.position.x - b.radius < -1950 {
                //print("here", b.position.x, b.radius)
                self.move(randomPosition())
            } else if b.position.y + b.radius > 1950 || b.position.y - b.radius < -1950 {
                //print("there")
                self.move(randomPosition())
            } else {
                // Keep moving
                let scene : GameScene = self.scene as! GameScene
                for food in scene.foodLayer.children as! [Food] {
                    if distance (food.position, p2: self.centerPosition()) < b.radius * 5 {
                        self.move(food.position)
                        return
                    }
                }
            }
        }
    }
在第三个IF声明之前

在结束花括号线}上花费的时间的100%

override func didSimulatePhysics() {

        world.enumerateChildNodesWithName("//ball*", usingBlock: {
            node, stop in
            let ball = node as! Ball
            ball.regulateSpeed()
            if let body = ball.physicsBody {
                if (body.velocity.speed() > 0.01) {
                    ball.zRotation = body.velocity.angle() - self.offset
                }
            }
        })

        if let p = currentPlayer {
            centerWorldOnPosition(p.centerPosition())
        } else if playerLayer.children.count > 0 {
            let p = playerLayer.children.first! as! Player
            centerWorldOnPosition(p.centerPosition())
        } else {
            centerWorldOnPosition(CGPoint(x: 0, y: 0))
        }
    }

2 个答案:

答案 0 :(得分:4)

你知道关于渔夫的老看见了吗? 给他一条鱼,喂他一天。 教他钓鱼,你喂他一辈子。

不要告诉你要修复什么,让我解释一下如何通过手动采样找到加速比。

让我们假设您的代码可以更快(可能)。如果你这样做,它会节省一些时间,比如20%。 这意味着您要优化的具体详细活动,无论它是什么,实际上都在执行至少 20%的时间。

可能会执行更大比例的时间,例如40%。 只是你的优化可能无法摆脱所有这些。 你可能只能摆脱一半,所以你只能净20%。

这意味着如果你随机停止它,并在那个时间点检查它正在做的所有事情以及为什么,那么你有40%的机会看到它做你想做的事情要优化,浪费的东西。

你怎么知道你看到的是什么,虽然浪费,但是有足够的时间来解决问题? 你知道,如果你看到第二时间。 看到一次的东西并没有告诉你太多 - 只需要非零时间, 但是你看到第二时间,你不知道它有多大,但你确实知道它不小。 在看到它两次之前采样的次数越少,它就越大。 Here are the statistics.

因此,如果它将节省20%,并且如果它在40%的时间内执行,那么在看到它之前需要多少个样本? 平均为2 / .4,即5个样本。 如果你取10个样品,你能看到多少次?四。 如果您采取10个样本,那么不会多次查看它的概率是多少? 4.5% 如果你拿20个样本,你会错过它的概率是多少?实际上为零。

所以这是手动采样的力量。 您可以看到程序正在做什么的精确细节以及它为什么这样做。 这是分析师不告诉你的。 他们采取了更多的样本,然后将它们拼凑成时间数字,这样你就可以看到所谓的“热门代码”了,但是你还在猜测你可以做些什么来修复它。 详细地手动检查少量样本,让所有程序员的智力理解每一个,告诉你完全

这就是为什么this post虽然与普遍的智慧相反,却有如此多的选票。 你可以获得更快的速度。

答案 1 :(得分:1)

以这种方式使用距离公式可能是一项昂贵的操作,如果你不需要实际距离,我建议你使用距离平方

func randomMove() {
        confidenceLevel = 0
        if let b = self.children.first as! Ball? {
            if b.physicsBody?.velocity == CGVector(dx: 0, dy: 0) {
                //print("a")
                self.move(randomPosition())
            } else if b.position.x + b.radius > 1950 || b.position.x - b.radius < -1950 {
                //print("here", b.position.x, b.radius)
                self.move(randomPosition())
            } else if b.position.y + b.radius > 1950 || b.position.y - b.radius < -1950 {
                //print("there")
                self.move(randomPosition())
            } else {
                // Keep moving
                let bRadiusSqr = b.radius * 5 * b.radius * 5
                let selfPosition = self.centerPosition()
                let scene : GameScene = self.scene as! GameScene
                var moved = false
                scene.foodLayer.children.forEach() {
                    food in
                    if(!moved)
                    {
                        let diffX = food.position.x - selfPosition.x
                        let diffY = food.position.y - selfPosition.y 
                        if diffX * diffX + diffY * diffY < bRadiusSqr  {
                            self.move(food.position)
                            moved = true
                        }
                    }
                }
            }
        }
    }

仔细检查每一种食物是一种不好的方法,而不是尝试一下:

func randomMove() {
        confidenceLevel = 0
        if let b = self.children.first as! Ball? {
            if b.physicsBody?.velocity == CGVector(dx: 0, dy: 0) {
                //print("a")
                self.move(randomPosition())
            } else if b.position.x + b.radius > 1950 || b.position.x - b.radius < -1950 {
                //print("here", b.position.x, b.radius)
                self.move(randomPosition())
            } else if b.position.y + b.radius > 1950 || b.position.y - b.radius < -1950 {
                //print("there")
                self.move(randomPosition())
            } else {
                // Keep moving
                let bRadiusSqr = b.radius * 5 * b.radius * 5
                let selfPosition = self.centerPosition()
                let scene : GameScene = self.scene as! GameScene
                let world : SKPhysicsWorld = scene.physicsWorld
                world.enumerateBodiesInRect(CGRectMake(selfPosition.x - b.radius, selfPosition.y - b.radius,bradius*2,bradius*2))
                {
                    body,stop in
                    guard let food = body.node as? Food else { return}                        
                    let diffX = food.position.x - selfPosition.x
                    let diffY = food.position.y - selfPosition.y 
                    if diffX * diffX + diffY * diffY < bRadiusSqr  {
                        self.move(food.position)
                        stop = true
                    }
                }
            }
        }
    }

不幸的是,我们的选择是在光线,点或矩形中获取物体,但是这将使我们所有的物理体都具有半径的盒子。我们之后使用距离公式以获得更好的准确性。