<?php

    $methods = array("method_diff_assoc", "method_diff_key", "method_sort");

    function make_array($size) {
        $array = array();
        for ($i = 0; $i < $size; $i++) {
            $array[$i] = $i + 1;
        }
        shuffle($array);
        srand((float)microtime() * 1000000);
        $pos =& rand(0, $size - 1);
        do {
            $val = rand(1, $size - 1);
        } while ($array[$pos] == $val);
        $array[$pos] = $val;
        return $array;
    }

    function method_diff_assoc($array) {
        $u = array_unique($array);
        $dup = array_diff_assoc($array, $u);
        return array_pop($dup);
    }

    function method_diff_key($array) {
        $u = array_unique($array);
        $dup = array_diff_key($array, $u);
        return array_pop($dup);
    }

    function method_sort($array) {
        sort($array);
        $prev = null;
        foreach ($array as $item) {
            if ($item === $prev) { return $item; }
            $prev = $item;
        }
    }

    function validate($iterations) {
        global $methods;
        for ($i = 0; $i < $iterations; $i++) {
            $a = make_array(1000);
            $check = null;
            foreach ($methods as $method_name) {
                $result = call_user_func($method_name, $a);
                if (!is_null($check) && $check !== $result) {
                    echo "Method $method_name returned $result instead of $check!\n";
                    return false;
                }
                $check = $result;
            }
        }
        return true;
    }

    function profile($method_name, $iterations) {
        $start = time();
        for ($i = 0; $i < $iterations; $i++) {
            $a = make_array(10000);
            call_user_func($method_name, $a);
        }
        return time() - $start;
    }

    if (validate(20)) {
        echo "Tests passed, all implementations seem to argee on results.\n";
    } else {
        echo "TESTS FAILED. FIX THE CODE FIRST.\n";
        exit(1);
    }
    $c = 50; // Increase at will, this value is low just for ideone.com
    foreach ($methods as $method_name) {
        printf("Trying %d iterations of method %s\n", $c, $method_name);
        printf("\t%s took: %0.2f seconds/iteration\n", $method_name, profile($method_name, $c) / $c);
    }

?>