PHP - помочь повысить эффективность этого генератора URL-адреса в стиле YouTube - PullRequest
2 голосов
/ 06 декабря 2009

После некоторых поисков я нашел этот генератор URL-адресов в стиле youtube с шифрованием, чтобы скрыть оригинальный идентификатор ... однако я надеюсь повысить эффективность, так как он будет часто использоваться. Пока я улучшил это на 20% ... может кто-нибудь помочь мне улучшить это больше.

Это оригинал:

function alphaID($in, $to_num = false, $pad_up = false, $passKey = null)
{
    $index = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    if ($passKey !== null) {
        // Although this function's purpose is to just make the
        // ID short - and not so much secure,
        // with this patch by Simon Franz (http://blog.snaky.org/)
        // you can optionally supply a password to make it harder
        // to calculate the corresponding numeric ID

        for ($n = 0; $n<strlen($index); $n++) {
            $i[] = substr( $index,$n ,1);
        }

        $passhash = hash('sha256',$passKey);
        $passhash = (strlen($passhash) < strlen($index))
            ? hash('sha512',$passKey)
            : $passhash;

        for ($n=0; $n < strlen($index); $n++) {
            $p[] = substr($passhash, $n ,1);
        }

        array_multisort($p, SORT_DESC, $i);
        $index = implode($i);
    }

    $base = strlen($index);

    if ($to_num) {
        // Digital number <<-- alphabet letter code
        $in = strrev($in);
        $out = 0;
        $len = strlen($in) - 1;
        for ($t = 0; $t <= $len; $t++) {
            $bcpow = bcpow($base, $len - $t);
            $out = $out + strpos($index, substr($in, $t, 1)) * $bcpow;
        }

        if (is_numeric($pad_up)) {
            $pad_up--;
            if ($pad_up > 0) {
                $out -= pow($base, $pad_up);
            }
        }
    } else {
        // Digital number -->> alphabet letter code
        if (is_numeric($pad_up)) {
            $pad_up--;
            if ($pad_up > 0) {
                $in += pow($base, $pad_up);
            }
        }

        $out = "";
        for ($t = floor(log10($in) / log10($base)); $t >= 0; $t--) {
            $a = floor($in / bcpow($base, $t));
            $out = $out . substr($index, $a, 1);
            $in = $in - ($a * bcpow($base, $t));
        }
        $out = strrev($out); // reverse
    }

    return $out;
}

Вот мой модифицированный код:

function alphaID($in, $to_num = false, $pad_up = false, $passKey = null)
{
    $index = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $i = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');
    if ($passKey !== null) {
        // Although this function's purpose is to just make the
        // ID short - and not so much secure,
        // with this patch by Simon Franz (http://blog.snaky.org/)
        // you can optionally supply a password to make it harder
        // to calculate the corresponding numeric ID
       $len = strlen($index); 


        $passhash = hash('sha256',$passKey);
        $passhash = (strlen($passhash) < $len)
            ? hash('sha512',$passKey)
            : $passhash;

        for ($n=0; $n < $len; $n++) {
            $p[] = substr($passhash, $n ,1);
        }

        array_multisort($p, SORT_DESC, $i);
        $index = implode($i);
    }

    $base = strlen($index);

    if ($to_num) {
        // Digital number <<-- alphabet letter code
        $in = strrev($in);
        $out = 0;
        $len = strlen($in) - 1;
        for ($t = 0; $t <= $len; $t++) {
            $bcpow = bcpow($base, $len - $t);
            $out = $out + strpos($index, substr($in, $t, 1)) * $bcpow;
        }

        if (is_numeric($pad_up)) {
            $pad_up--;
            if ($pad_up > 0) {
                $out -= pow($base, $pad_up);
            }
        }
    } else {
        // Digital number -->> alphabet letter code
        if (is_numeric($pad_up)) {
            $pad_up--;
            if ($pad_up > 0) {
                $in += pow($base, $pad_up);
            }
        }

        $out = "";
        for ($t = floor(log10($in) / log10($base)); $t >= 0; $t--) {
            $a = floor($in / bcpow($base, $t));
            $out = $out . substr($index, $a, 1);
            $in = $in - ($a * bcpow($base, $t));
        }
        $out = strrev($out); // reverse
    }

    return $out;
}

Как вы можете заметить, никаких существенных различий, только я удалил strlen из цикла for, сохранил его в переменной и предварительно вычислил массив для индекса (немного неуклюжий ... но именно генерация массива составляла основная часть вычислений).

Кредит причитается: вот информация об авторах: * @author Кевин ван Зонневельд * @author Саймон Франц * @copyright 2008 Кевин ван Зонневельд (кевин точка ванзонневельд точка сеть) * @license www dot open source dot org / licenses / bsd-license dot php Новая лицензия BSD * @version SVN: выпуск: $ Id: alphaID.inc.php 344 2009-06-10 17: 43: 59Z кевин $ * @ link Кевин Дот Ванзонневельд Дот Сетка

Я не могу опубликовать URL-адрес, так как у меня низкая репутация: S

Ответы [ 3 ]

5 голосов
/ 06 декабря 2009

Я сделал несколько небольших оптимизаций, чтобы убрать лишние циклы ЦП тут и там. В основном это такие вещи, как ненужные назначения, дополнительные сравнения и т. Д. Кроме того, строки можно рассматривать как массивы, поэтому я тоже поработал с ними:

function alphaID($in, $to_num = false, $pad_up = false, $passKey = null)
{
    static $passcache;
    if(empty($passcache))
        $passcache = array();

    $index = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $i = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');
    if (!empty($passKey)) {
        // Although this function's purpose is to just make the
        // ID short - and not so much secure,
        // with this patch by Simon Franz (http://blog.snaky.org/)
        // you can optionally supply a password to make it harder
        // to calculate the corresponding numeric ID

        if(isset($passcache[$passKey]))
            $index = $passcache[$passKey];
        else {
            if(strlen($passhash = hash('sha256',$passKey)) < strlen($index))
                $passhash = hash('sha512',$passKey);

            $p = str_split($passhash);

            array_multisort($p, SORT_DESC, $i);
            $index = implode($i);
            $passcache = $index;
        }
    }

    $base = strlen($index);

    if ($to_num) {
        // Digital number <<-- alphabet letter code
        $in = strrev($in);
        $out = 0;
        $len = strlen($in) - 1;
        for ($t = 0; $t <= $len; $t++) {
            $bcpow = bcpow($base, $len - $t);
            $out += strpos($index, $in[$t]) * $bcpow;
        }

        if (is_numeric($pad_up)) {
            $pad_up--;
            if ($pad_up > 0) {
                $out -= pow($base, $pad_up);
            }
        }
    } else {
        // Digital number -->> alphabet letter code
        if (is_numeric($pad_up)) {
            $pad_up--;
            if ($pad_up > 0) {
                $in += pow($base, $pad_up);
            }
        }

        $out = "";
        for ($t = floor(log10($in) / log10($base)); $t >= 0; $t--) {
            $bcp = bcpow($base, $t);
            $a = floor($in / $bcp);
            $out .= $index[$a];
            $in -= $a *  $bcp;
        }
        $out = strrev($out); // reverse
    }

    return $out;
}

Редактировать: я обновил, чтобы включить кэш. Попробуйте сейчас!

0 голосов
/ 06 декабря 2009

Я думаю, что вы должны просто создать индекс и использовать его для всего сайта .. позвольте мне объяснить, почему ...

Хеширование и все, что выше '$ base = strlen ($ index);' просто для генерации индекса ... вам нужно будет использовать тот же $ passkey для декодирования URL. Поскольку у вас нет возможности узнать, какой пароль использовался, вам придется сделать его широко распространенным. Это означало бы, что каждый вызов для генерации URL будет использовать один и тот же ключ доступа и, следовательно, генерировать один и тот же индекс.

И так ... Я бы вырезал код, генерирующий индексы, сгенерировал бы уникальный индекс и сохранил бы его в переменной '$ index'.

0 голосов
/ 06 декабря 2009

Похоже, вы хорошо поработали, избавившись от лишних вызовов.

Похоже, что есть пара вызовов bcpow ($ base, $ t), которые можно уменьшить до одного ...

$out = "";
for ($t = floor(log10($in) / log10($base)); $t >= 0; $t--) {
    $newbase = bcpow($base, $t);
    $a = floor($in / $newbase);
    $out = $out . substr($index, $a, 1);
    $in = $in - ($a * $newbase);
}
$out = strrev($out); // reverse

Вы, вероятно, не заметите разницу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...