Оптимизация — Можно ли оптимизировать скорость PHP CRC-рутины?

Эта процедура возвращает 0, если CRC 30 первых байтов равен значению crc (EBU) в последних двух байтах. На моем сервере сценарий немного медленный, поэтому я хочу знать, можно ли оптимизировать эту процедуру.

Если я намеренно позволю сбою на 86500 строках 32-байтовых данных, моя программа завершится через 2,2 секунды, если я откомментирую «Первое возвращение». Он заканчивается через 4,4 секунды, если я отменяю комментарии о втором возвращении, и через 5,8 секунды, если я отменяю комментарии о третьем возвращении. Думаю, было бы хорошо пропустить распаковку, но все мои попытки провалились.

Сама CRC-рутина была найдена в сети. Спасибо тому, кто написал это!

function crc($datax)
{
//return 1; // First return
global $row;
$data = unpack('C*', $datax); // unpack seems to start with index 1...
//return 1; // Second return
$crc = 0xFFFF;
for ($i = 1; $i < 31; $i++) {
$x = (($crc >> 8) ^  $data[$i] ) & 0xFF;
$x ^= $x >> 4;
$crc = (($crc << 8) ^ ($x << 12) ^ ($x << 5) ^ $x);
}
//return 1; // Third return
return ( (~$crc & 0xFFFF ) - $data[31] * 256 - $data[32] );
}

и данные поступают из

$fib = fread($fp, 32);
if ( crc16( $fib ) == 0 ) {
; // process data...
}

Спасибо!

0

Решение

Вы можете использовать табличный подход, который немного быстрее. Это приводит вас к цели вашего ~$crc & 0xFFFF, Вычтенные значения после этого не являются частью фактического CRC.

$crc16epc_table = array(
0x1e0f, 0x0e2e, 0x3e4d, 0x2e6c, 0x5e8b, 0x4eaa, 0x7ec9, 0x6ee8,
0x9f07, 0x8f26, 0xbf45, 0xaf64, 0xdf83, 0xcfa2, 0xffc1, 0xefe0,
0x0c3e, 0x1c1f, 0x2c7c, 0x3c5d, 0x4cba, 0x5c9b, 0x6cf8, 0x7cd9,
0x8d36, 0x9d17, 0xad74, 0xbd55, 0xcdb2, 0xdd93, 0xedf0, 0xfdd1,
0x3a6d, 0x2a4c, 0x1a2f, 0x0a0e, 0x7ae9, 0x6ac8, 0x5aab, 0x4a8a,
0xbb65, 0xab44, 0x9b27, 0x8b06, 0xfbe1, 0xebc0, 0xdba3, 0xcb82,
0x285c, 0x387d, 0x081e, 0x183f, 0x68d8, 0x78f9, 0x489a, 0x58bb,
0xa954, 0xb975, 0x8916, 0x9937, 0xe9d0, 0xf9f1, 0xc992, 0xd9b3,
0x56cb, 0x46ea, 0x7689, 0x66a8, 0x164f, 0x066e, 0x360d, 0x262c,
0xd7c3, 0xc7e2, 0xf781, 0xe7a0, 0x9747, 0x8766, 0xb705, 0xa724,
0x44fa, 0x54db, 0x64b8, 0x7499, 0x047e, 0x145f, 0x243c, 0x341d,
0xc5f2, 0xd5d3, 0xe5b0, 0xf591, 0x8576, 0x9557, 0xa534, 0xb515,
0x72a9, 0x6288, 0x52eb, 0x42ca, 0x322d, 0x220c, 0x126f, 0x024e,
0xf3a1, 0xe380, 0xd3e3, 0xc3c2, 0xb325, 0xa304, 0x9367, 0x8346,
0x6098, 0x70b9, 0x40da, 0x50fb, 0x201c, 0x303d, 0x005e, 0x107f,
0xe190, 0xf1b1, 0xc1d2, 0xd1f3, 0xa114, 0xb135, 0x8156, 0x9177,
0x8f87, 0x9fa6, 0xafc5, 0xbfe4, 0xcf03, 0xdf22, 0xef41, 0xff60,
0x0e8f, 0x1eae, 0x2ecd, 0x3eec, 0x4e0b, 0x5e2a, 0x6e49, 0x7e68,
0x9db6, 0x8d97, 0xbdf4, 0xadd5, 0xdd32, 0xcd13, 0xfd70, 0xed51,
0x1cbe, 0x0c9f, 0x3cfc, 0x2cdd, 0x5c3a, 0x4c1b, 0x7c78, 0x6c59,
0xabe5, 0xbbc4, 0x8ba7, 0x9b86, 0xeb61, 0xfb40, 0xcb23, 0xdb02,
0x2aed, 0x3acc, 0x0aaf, 0x1a8e, 0x6a69, 0x7a48, 0x4a2b, 0x5a0a,
0xb9d4, 0xa9f5, 0x9996, 0x89b7, 0xf950, 0xe971, 0xd912, 0xc933,
0x38dc, 0x28fd, 0x189e, 0x08bf, 0x7858, 0x6879, 0x581a, 0x483b,
0xc743, 0xd762, 0xe701, 0xf720, 0x87c7, 0x97e6, 0xa785, 0xb7a4,
0x464b, 0x566a, 0x6609, 0x7628, 0x06cf, 0x16ee, 0x268d, 0x36ac,
0xd572, 0xc553, 0xf530, 0xe511, 0x95f6, 0x85d7, 0xb5b4, 0xa595,
0x547a, 0x445b, 0x7438, 0x6419, 0x14fe, 0x04df, 0x34bc, 0x249d,
0xe321, 0xf300, 0xc363, 0xd342, 0xa3a5, 0xb384, 0x83e7, 0x93c6,
0x6229, 0x7208, 0x426b, 0x524a, 0x22ad, 0x328c, 0x02ef, 0x12ce,
0xf110, 0xe131, 0xd152, 0xc173, 0xb194, 0xa1b5, 0x91d6, 0x81f7,
0x7018, 0x6039, 0x505a, 0x407b, 0x309c, 0x20bd, 0x10de, 0x00ff
);

function crc16epc($string)
{
$bytes = unpack("C*", $string);
$crc = 0;
foreach ($bytes as $next)
$crc = ($crc << 8) ^ $GLOBALS['crc16epc_table'][(($crc >> 8) ^ $next) & 0xff];
return $crc & 0xffff;
}
0

Другие решения

Других решений пока нет …