-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from exussum12/addFFI
FFI Support
- Loading branch information
Showing
13 changed files
with
315 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,53 @@ | ||
A pure PHP implementation of [xxhash](https://github.com/Cyan4973/xxHash) | ||
|
||
Currently only working for the 32 bit version. | ||
Currently only working for the 32 bit version. (Pre PHP 7.4). 32 and 64 bit version both work with PHP 7.4 | ||
|
||
If speed is important use the php extension instead | ||
If speed is important use the FFI versions (PHP 7.4+) | ||
|
||
XXHash is a fast hash designed for file integrity checking. Passwords should not be hashed with this, please use Argon2 or BCrypt. | ||
|
||
# Installing | ||
|
||
Ideally use composer | ||
With composer | ||
|
||
composer require exussum12/xxhash | ||
|
||
Alternatively require the single file (making sure the path is correct) | ||
|
||
require 'xxhash/V32.php'; | ||
|
||
# Hashing input | ||
|
||
xxhash has a seed, this is 0 by default. To make a new instance of xxhash run | ||
|
||
use exussum12\xxhash\V32; | ||
$seed = 0; | ||
$hash = new V32($seed); | ||
|
||
Then to hash input, run | ||
|
||
$hash->hash('string'); ## to hasha string | ||
$hash->hash('string'); ## to hash a string | ||
|
||
or | ||
|
||
$file = fopen('path/to/file.ext', 'r'); | ||
$hash->hashStream($file); # for a stream (better for large files) | ||
|
||
The library can be called statically also, however this removes the ability to change the seed. The default see of 0 will be used | ||
|
||
V32::hash('string'); ## to hasha string | ||
V32::hash('string'); ## to hash a string | ||
$file = fopen('path/to/file.ext', 'r'); | ||
V32::hashStream($file); # for a stream (better for large files) | ||
|
||
Static functions should in general be avoided so the first method is the preferred method to use. | ||
Static functions should in general be avoided, so the first method is the preferred method to use. | ||
|
||
## FFI | ||
Since PHP 7.4 FFI allows PHP to call the native C client. This is much faster, and the preferred way if your running PHP 7.4 | ||
|
||
### Speed Comparison | ||
This is hashing a 320mb file using the stream method. | ||
The time is the time take (smaller is better) | ||
|
||
|Method |Time | Peak Memory | | ||
|-------------|------|-------------| | ||
|xxHash Binary| 0.081| 1604kb| | ||
|FFI | 0.194| 27616kb| | ||
|Pure PHP |49.218| 27844kb| | ||
|
||
Memory measured using `/usr/bin/time -v` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<?php | ||
namespace exussum12\xxhash\Ffi; | ||
|
||
use FFI; | ||
use exussum12\xxhash\Hash; | ||
|
||
/** | ||
* Class V64 | ||
* This uses the FFI extension which should be much faster than native. | ||
* @see https://github.com/Cyan4973/xxHash/wiki/xxHash-specification-(draft) | ||
*/ | ||
abstract class Base implements Hash | ||
{ | ||
protected int $seed; | ||
protected FFI $ffi; | ||
|
||
//functions from below | ||
protected string $hash = ''; | ||
protected string $createState = ''; | ||
protected string $reset = ''; | ||
protected string $update = ''; | ||
protected string $digest = ''; | ||
protected string $freeState = ''; | ||
|
||
public function hash(string $input): string | ||
{ | ||
if (!isset($this)) { | ||
$hash = new static(); | ||
return $hash->hash($input); | ||
} | ||
|
||
return dechex($this->ffi->{$this->hash}($input, strlen($input), $this->seed)); | ||
} | ||
|
||
public function hashStream($input): string | ||
{ | ||
if (!isset($this)) { | ||
$hash = new static(); | ||
return $hash->hashStream($input); | ||
} | ||
|
||
$state = $this->ffi->{$this->createState}(); | ||
$this->ffi->{$this->reset}($state, $this->seed); | ||
|
||
while (!feof($input)) { | ||
$buffer = fread($input, 8192); | ||
$this->ffi->{$this->update}($state, $buffer, strlen($buffer)); | ||
} | ||
|
||
$hash = dechex($this->ffi->{$this->digest}($state)); | ||
|
||
$this->ffi->{$this->freeState}($state); | ||
return $hash; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
typedef uint32_t XXH32_hash_t; | ||
typedef struct XXH32_state_s XXH32_state_t; | ||
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; | ||
XXH32_hash_t XXH32( | ||
const void* input, | ||
size_t length, | ||
XXH32_hash_t seed | ||
); | ||
void XXH32_update( | ||
XXH32_state_t* state, | ||
const void* input, | ||
size_t len | ||
); | ||
XXH32_state_t* XXH32_createState(); | ||
void XXH32_reset(XXH32_state_t*, XXH32_hash_t); | ||
XXH32_hash_t XXH32_digest(XXH32_state_t*); | ||
XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
typedef uint64_t XXH64_hash_t; | ||
typedef struct XXH64_state_s XXH64_state_t; | ||
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; | ||
XXH64_hash_t XXH64( | ||
const void* input, | ||
size_t length, | ||
XXH64_hash_t seed | ||
); | ||
void XXH64_update( | ||
XXH64_state_t* state, | ||
const void* input, | ||
size_t len | ||
); | ||
XXH64_state_t* XXH64_createState(); | ||
void XXH64_reset(XXH64_state_t*, XXH64_hash_t); | ||
XXH64_hash_t XXH64_digest(XXH64_state_t*); | ||
XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
namespace exussum12\xxhash\Ffi; | ||
|
||
use FFI; | ||
|
||
/** | ||
* Class V32 | ||
* This uses the FFI extension which should be much faster than native. | ||
* @see https://github.com/Cyan4973/xxHash/wiki/xxHash-specification-(draft) | ||
*/ | ||
final class V32 extends Base | ||
{ | ||
protected string $hash = 'XXH32'; | ||
protected string $createState = 'XXH32_createState'; | ||
protected string $reset = 'XXH32_reset'; | ||
protected string $update = 'XXH32_update'; | ||
protected string $digest = 'XXH32_digest'; | ||
protected string $freeState = 'XXH32_digest'; | ||
|
||
public function __construct(int $seed = 0) | ||
{ | ||
$this->seed = $seed; | ||
$this->ffi = FFI::cdef( | ||
file_get_contents(__DIR__ . '/Headers/XXH32.h'), | ||
__DIR__ . '/libxxhash.so.0.7.4' | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
namespace exussum12\xxhash\Ffi; | ||
|
||
use FFI; | ||
|
||
/** | ||
* Class V64 | ||
* This uses the FFI extension which should be much faster than native. | ||
* @see https://github.com/Cyan4973/xxHash/wiki/xxHash-specification-(draft) | ||
*/ | ||
final class V64 extends Base | ||
{ | ||
protected string $hash = 'XXH64'; | ||
protected string $createState = 'XXH64_createState'; | ||
protected string $reset = 'XXH64_reset'; | ||
protected string $update = 'XXH64_update'; | ||
protected string $digest = 'XXH64_digest'; | ||
protected string $freeState = 'XXH64_digest'; | ||
|
||
public function __construct(int $seed = 0) | ||
{ | ||
$this->seed = $seed; | ||
$this->ffi = FFI::cdef( | ||
file_get_contents(__DIR__ . '/Headers/XXH64.h'), | ||
__DIR__ . '/libxxhash.so.0.7.4' | ||
); | ||
} | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?php | ||
|
||
namespace exussum12\xxhash; | ||
|
||
interface Hash | ||
{ | ||
public function hash(string $input): string; | ||
|
||
public function hashStream($input): string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
<?php | ||
namespace exussum12\xxhash\tests; | ||
|
||
use PHPUnit\Framework\TestCase; | ||
use exussum12\xxhash\Ffi\V64; | ||
|
||
class FFIH64HashTest extends TestCase | ||
{ | ||
protected V64 $hash; | ||
|
||
public function setUp() | ||
{ | ||
$this->hash = new V64(0); | ||
} | ||
public function testSingleByte() | ||
{ | ||
$this->assertSame( | ||
'4fdcca5ddb678139', | ||
$this->hash->hash('test') | ||
); | ||
} | ||
|
||
public function testLeftOverBytes() | ||
{ | ||
$this->assertSame( | ||
'b8f97d6e4b71ad0', | ||
$this->hash->hash('test1') | ||
); | ||
} | ||
|
||
public function test16Byes() | ||
{ | ||
$this->assertSame( | ||
'539eee07e4f72744', | ||
$this->hash->hash('testtesttesttest') | ||
); | ||
} | ||
|
||
public function test17Byes() | ||
{ | ||
$this->assertSame( | ||
'bbcf707044ae361a', | ||
$this->hash->hash('testtesttesttest1') | ||
); | ||
} | ||
|
||
public function testDifferntSeed() | ||
{ | ||
$hash = new V64(3); | ||
|
||
$this->assertSame( | ||
'4e75e829de9fa9dd', | ||
$hash->hash('test') | ||
); | ||
} | ||
public function testStaticCall() | ||
{ | ||
$this->assertSame( | ||
'4fdcca5ddb678139', | ||
V64::hash('test') | ||
); | ||
} | ||
} |
Oops, something went wrong.