読者です 読者をやめる 読者になる 読者になる

kkana's blog

新米コーダーの忘れそうなことメモ

大量のオブジェクトを処理するときに考えた事(4)(インスタンス化と処理速度について)

nature of code あたらしく覚えた! プログラミングのこと

前回大量のオブジェクトを処理するときに考えた事(3)(連結リストについて) - kkana's blogもうこれでいいかなぁと思っていたところ

「粒子ごとに距離を測って加える力を計算するところ(連結リストをwhile文で回しているところ)でnew演算子を使わないようにするともっとカクカクしなくなる」と教えてもらったので また考え直しました。

大量ものを回しているときにnew しない!

できたもの↓

See the Pen ぶつからないように動くビークル(3) by kanaparty (@kanaparty) on CodePen.

(処理が早くなったのをいいことにしっぽを生やしました)

具体的に書き換えたところは以下です。 コメントアウトしてあるところが自作のベクトルクラスを呼び出しているところ。 他の粒子との距離を測るところでは、xとyの座標がわかってさえすればいいので わざわざベクトルクラスをインスタンス化しなくても良かったのでした。

  separate() {
    //  var sum = new Vector(0, 0);
    var sumX = 0;
    var sumY = 0;
    var count = 0;

    // var targetVehicle = currentVehicle;
    var targetVehicle = vehicles.first;
    while (targetVehicle) {
      //  var diff = Vector.sub(this.vlocation, targetVehicle.vlocation);
      var diffx = this.vlocation.x - targetVehicle.vlocation.x;
      var diffy = this.vlocation.y - targetVehicle.vlocation.y;

      //  var distance = diff.mag();
      var distance = Math.sqrt(diffx * diffx + diffy * diffy);
      if (distance < this.separateRange && distance > 0) {
        //  diff.div(distance);
        var weighting = distance * 4;
        diffx = diffx / weighting;
        diffy = diffy / weighting;
        //  sum.add(diff);
        sumX += diffx;
        sumY += diffy;
        count++;
      }
      targetVehicle = targetVehicle.next;
    }
    if (count > 0) {
      // var steer = sum.sub(this.velocity);
      var steer = new Vector(sumX - this.velocity.x , sumY - this.velocity.y);
      this.acceleration.add(steer);
    }
  }

そんなに変わるのかな、と思って
new Vector()してるときとしていない時で粒子を2000個作って、 1フレームだけアニメーションさせて時間をはかった(おわりからループの始まりの時間を引いた)ところ、

  • newVectorしたとき
    138 146 140 139  146 130  147  138 143 132
    平均139.9

  • しないとき
    92 99 87 91 92 93 93 89 91 91
    平均91.8

と、こんなに差がでました!!

インスタンス化するとそのぶんメモリが確保される(しないと最初から一つの場所しか参照しない)ので
処理の速度に違いが出るんじゃないのかということでした(?)

他に高速化のためにできそうなこと

  • 一度計算した粒子間の距離をどこかに保存しておいて2重に計算しない
  • 最初に生成する粒子の量を決めておいて、マウスを押したら死んだ粒子を生き返らせて(プロパティをセットし直して)使う(新しくnewで粒子を生成しない)

他に粒子系の処理の高速化を考えるなら・・・flashの作品を読む

粒子系の処理は昔flashでよく取り組まれていて、すでにいろんな方法で高速化が試されているらしい 。 なのでもっと突っ込んで考えたかったら beautifl.net

こういうところを参考にするといいそうです。

とはいえ考えすぎるのもよくない

しかしそんなにカクカクしなくなったのかは・・・・正直あまりわかりませんでした。。 高速化に取り組むのはいいけど深掘りすればするほどやれることが出てくるので
そのときどきに応じた対応をしたほうがよさそう