j4mie / paris

A lightweight Active Record implementation for PHP5, built on top of Idiorm.
http://j4mie.github.com/idiormandparis/
995 stars 131 forks source link

Slowness on save after find_many #61

Closed michaelward82 closed 11 years ago

michaelward82 commented 11 years ago

I have the following code in a script. The intention is to retrospectively hash all of the passwords in a user table.

namespace {

    # Autoload composer included libraries
    require 'vendor/autoload.php';

    ORM::configure('mysql:host=127.0.0.1;dbname=dbname');
    ORM::configure('username', 'user');
    ORM::configure('password', 'password');

    // User class
    class User extends Model
    {
    }

    function getUnhashedPasswordUsers($limit = 1000)
    {
        $nullPasswordValue = hex2bin('000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000');

        $users = Model::factory('User')
            ->where('password_hash', $nullPasswordValue)
            ->limit($limit)
            ->find_many();

        return $users;
    }

    function hashPasswords()
    {
        $users = getUnhashedPasswordUsers(1);

        if (count($users) > 0) {
            foreach ($users as $user) {
                $hash = password_hash($user->password, PASSWORD_DEFAULT);

                echo $user->password . " = $hash\n";

                $user->password_hash = $hash;
                $user->save();

                return true;
            }
        } else {
            return false;
        }
    }

    $notDoneHashing = true;
    while ($notDoneHashing) {
        $notDoneHashing = hashPasswords();
    }

    echo "finished";
}

The problem I have is that the more results the query returns, the more the script slows down on each iteration of the foreach loop.

The user query seems to run quickly enough, the slowdown appears to occur on save.

Is the entire set being saved on each iteration, or is there another explanation for the slowdown?

Lapayo commented 11 years ago

Maybe you should move the return true out of the foreach loop? :D It looks like you fetch 1000 rows, only edit the first, fetch the next 1000 rows, and so on.

michaelward82 commented 11 years ago

So obvious... Thanks!