1
0
This commit is contained in:
2022-09-21 14:01:45 +02:00
parent 0a30f39eb4
commit cfee4d93d0
349 changed files with 4 additions and 4 deletions

View File

@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace CondorcetPHP\Condorcet\Benchmarks;
use CondorcetPHP\Condorcet\Election;
use PhpBench\Attributes as Bench;
ini_set('memory_limit', '51200M');
class AddVotesBench
{
protected Election $election;
#[Bench\OutputTimeUnit('seconds')]
#[Bench\Warmup(1)]
#[Bench\Iterations(3)]
#[Bench\Revs(1)]
public function benchVotesWithManyCandidates(): void
{
$randomizer = new \Random\Randomizer(new \Random\Engine\Xoshiro256StarStar('CondorcetReproductibleRandomSeed'));
$this->election = $election = new Election;
$candidates = [];
for ($i=0; $i < 100; $i++) {
$candidates[] = $election->addCandidate();
}
for ($i = 0; $i < 1_000; $i++) {
$oneVote = $randomizer->shuffleArray($candidates);
$election->addVote($oneVote);
}
}
}

View File

@ -0,0 +1,45 @@
# v4.0-beta1 Branch
* AMD Ryzen 9 5900X
PHPBench (1.2.5)
with PHP version 8.1.6, xdebug ❌, opcache ✔ (with JIT Tracing)
```php
#[Bench\Warmup(1)]
#[Bench\Iterations(3)]
#[Bench\Revs(1)]
```
# v4.0-beta1 Branch
Subjects: 1, Assertions: 0, Failures: 0, Errors: 0
+------+---------------+------------------------------+-----+------+-------------+----------+--------------+----------------+
| iter | benchmark | subject | set | revs | mem_peak | time_avg | comp_z_value | comp_deviation |
+------+---------------+------------------------------+-----+------+-------------+----------+--------------+----------------+
| 0 | AddVotesBench | benchVotesWithManyCandidates | | 1 | 59,269,648b | 0.714s | -1.14σ | -0.10% |
| 1 | AddVotesBench | benchVotesWithManyCandidates | | 1 | 58,871,856b | 0.715s | -0.16σ | -0.01% |
| 2 | AddVotesBench | benchVotesWithManyCandidates | | 1 | 58,871,856b | 0.716s | +1.30σ | +0.12% |
+------+---------------+------------------------------+-----+------+-------------+----------+--------------+----------------+
# v3.3.3
Subjects: 1, Assertions: 0, Failures: 0, Errors: 0
+------+---------------+------------------------------+-----+------+-------------+----------+--------------+----------------+
| iter | benchmark | subject | set | revs | mem_peak | time_avg | comp_z_value | comp_deviation |
+------+---------------+------------------------------+-----+------+-------------+----------+--------------+----------------+
| 0 | AddVotesBench | benchVotesWithManyCandidates | | 1 | 59,029,584b | 18.906s | -1.00σ | -0.69% |
| 1 | AddVotesBench | benchVotesWithManyCandidates | | 1 | 59,029,504b | 18.990s | -0.36σ | -0.25% |
| 2 | AddVotesBench | benchVotesWithManyCandidates | | 1 | 59,030,016b | 19.218s | +1.36σ | +0.94% |
+------+---------------+------------------------------+-----+------+-------------+----------+--------------+----------------+
# v3.2
+------+---------------+------------------------------+-----+------+--------------+----------+--------------+----------------+
| iter | benchmark | subject | set | revs | mem_peak | time_avg | comp_z_value | comp_deviation |
+------+---------------+------------------------------+-----+------+--------------+----------+--------------+----------------+
| 0 | AddVotesBench | benchVotesWithManyCandidates | | 1 | 117,355,360b | 18.869s | +0.96σ | +0.84% |
| 1 | AddVotesBench | benchVotesWithManyCandidates | | 1 | 117,023,280b | 18.488s | -1.38σ | -1.20% |
| 2 | AddVotesBench | benchVotesWithManyCandidates | | 1 | 117,023,280b | 18.780s | +0.42σ | +0.36% |
+------+---------------+------------------------------+-----+------+--------------+----------+--------------+----------------+

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,61 @@
# Conclusion
When the garbage collector is actively used, there is no significant difference (memory used). If not, the implementation of weak references is much more economic.
# v3.2 Branch
## Time Centric
```
Subjects: 1, Assertions: 0, Failures: 0, Errors: 0
+------+---------------------+----------------------+-----+------+-------------+---------------+--------------+----------------+
| iter | benchmark | subject | set | revs | mem_peak | time_avg | comp_z_value | comp_deviation |
+------+---------------------+----------------------+-----+------+-------------+---------------+--------------+----------------+
| 0 | IntensiveUsageBench | benchSimpleManyVotes | | 10 | 27,103,632b | 258,943.200μs | -0.10σ | -0.05% |
| 1 | IntensiveUsageBench | benchSimpleManyVotes | | 10 | 27,103,632b | 257,405.200μs | -1.24σ | -0.65% |
| 2 | IntensiveUsageBench | benchSimpleManyVotes | | 10 | 27,103,632b | 261,179.300μs | +1.55σ | +0.81% |
| 3 | IntensiveUsageBench | benchSimpleManyVotes | | 10 | 27,103,632b | 258,782.800μs | -0.22σ | -0.11% |
+------+---------------------+----------------------+-----+------+-------------+---------------+--------------+----------------+
```
## Memory Centric
```
Subjects: 1, Assertions: 0, Failures: 0, Errors: 0
+------+---------------------+----------------------+-----+------+------------+-----------------+--------------+----------------+
| iter | benchmark | subject | set | revs | mem_peak | time_avg | comp_z_value | comp_deviation |
+------+---------------------+----------------------+-----+------+------------+-----------------+--------------+----------------+
| 0 | IntensiveUsageBench | benchSimpleManyVotes | | 10 | 6,883,080b | 2,605,364.000μs | -0.60σ | -0.42% |
| 1 | IntensiveUsageBench | benchSimpleManyVotes | | 10 | 6,883,080b | 2,591,650.000μs | -1.33σ | -0.95% |
| 2 | IntensiveUsageBench | benchSimpleManyVotes | | 10 | 6,883,080b | 2,633,507.000μs | +0.92σ | +0.65% |
| 3 | IntensiveUsageBench | benchSimpleManyVotes | | 10 | 6,883,080b | 2,635,192.000μs | +1.01σ | +0.72% |
+------+---------------------+----------------------+-----+------+------------+-----------------+--------------+----------------+
```
# v3.3 Branch
## Time Centric
```
Subjects: 1, Assertions: 0, Failures: 0, Errors: 0
+------+---------------------+----------------------+-----+------+------------+---------------+--------------+----------------+
| iter | benchmark | subject | set | revs | mem_peak | time_avg | comp_z_value | comp_deviation |
+------+---------------------+----------------------+-----+------+------------+---------------+--------------+----------------+
| 0 | IntensiveUsageBench | benchSimpleManyVotes | | 10 | 7,045,952b | 279,167.000μs | -0.30σ | -0.12% |
| 1 | IntensiveUsageBench | benchSimpleManyVotes | | 10 | 7,045,952b | 281,010.000μs | +1.30σ | +0.54% |
| 2 | IntensiveUsageBench | benchSimpleManyVotes | | 10 | 7,045,952b | 280,016.000μs | +0.43σ | +0.18% |
| 3 | IntensiveUsageBench | benchSimpleManyVotes | | 10 | 7,045,952b | 277,863.500μs | -1.43σ | -0.59% |
+------+---------------------+----------------------+-----+------+------------+---------------+--------------+----------------+
```
## Memory Centric
```
Subjects: 1, Assertions: 0, Failures: 0, Errors: 0
+------+---------------------+----------------------+-----+------+------------+-----------------+--------------+----------------+
| iter | benchmark | subject | set | revs | mem_peak | time_avg | comp_z_value | comp_deviation |
+------+---------------------+----------------------+-----+------+------------+-----------------+--------------+----------------+
| 0 | IntensiveUsageBench | benchSimpleManyVotes | | 10 | 7,041,560b | 2,847,455.000μs | +1.37σ | +0.80% |
| 1 | IntensiveUsageBench | benchSimpleManyVotes | | 10 | 7,041,560b | 2,801,896.000μs | -1.40σ | -0.81% |
| 2 | IntensiveUsageBench | benchSimpleManyVotes | | 10 | 7,041,560b | 2,829,893.000μs | +0.30σ | +0.18% |
| 3 | IntensiveUsageBench | benchSimpleManyVotes | | 10 | 7,041,560b | 2,820,355.000μs | -0.28σ | -0.16% |
+------+---------------------+----------------------+-----+------+------------+-----------------+--------------+----------------+
```

View File

@ -0,0 +1,39 @@
## Instructions
``` composer require --dev phpbench/phpbench ```
### Simple Suite
#### Time Centric
``` ./vendor/bin/phpbench run Benchmarks/SimpleUsageBench.php --report=default ```
#### Memory Centric
``` ./vendor/bin/phpbench run Benchmarks/SimpleUsageBench.php --report=default --executor=memory_centric_microtime ```
### Intensive Suite
#### Time Centric
``` ./vendor/bin/phpbench run Benchmarks/IntensiveUsageBench.php --report=default ```
#### Memory Centric
``` ./vendor/bin/phpbench run Benchmarks/IntensiveUsageBench.php --report=default --executor=memory_centric_microtime ```
### Run Specifics developement benchmarks
#### Pairwise Optimisation on Update (between commits)
``` ./vendor/bin/phpbench run Benchmarks/PairwiseUpdateOptimizationBench.php --report=default --executor=memory_centric_microtime ```
#### Pairwse and addVote performance related to election number of candidates
``` ./vendor/bin/phpbench run Benchmarks/PairwiseNumberOfCandidatesBench.php --report=default ```
#### Methods speed test by Candidates numbers
``` ./vendor/bin/phpbench run Benchmarks/MethodsNonProportionalBench.php --report=aggregate ```
``` ./vendor/bin/phpbench run Benchmarks/MethodsProportionalBench.php --report=aggregate ```
#### Add Votes (1000 votes with 100 candidates)
``` ./vendor/bin/phpbench run Benchmarks/AddVotesBench.php --report=default ```
#### Kemeny-Young Speed & Memory Test
``` ./vendor/bin/phpbench run Benchmarks/KemenyYoungBench.php --report=default --executor=memory_centric_microtime ```

View File

@ -0,0 +1,67 @@
<?php
declare(strict_types=1);
namespace CondorcetPHP\Condorcet\Benchmarks;
use CondorcetPHP\Condorcet\{Condorcet, Election};
use PhpBench\Attributes as Bench;
class IntensiveUsageBench
{
#[Bench\Warmup(3)]
#[Bench\Iterations(5)]
#[Bench\Revs(10)]
#[Bench\OutputTimeUnit('milliseconds')]
public function benchSimpleManyVotes(): void
{
$election = new Election;
$election->allowsVoteWeight(true);
$election->setNumberOfSeats(2);
$election->parseCandidates('A;B;C;D;E;F');
$election->parseVotes('
Ultimate Question of Life || A>B>C ^42 * 42
C=A>B ^2 * 200
B>C
E > B > C > A ^80 *50
F > B > G > H > A* 250
D = B = E > F ^6 * 48
');
$election->getCondorcetWinner();
$election->getCondorcetLoser();
foreach (Condorcet::getAuthMethods() as $method) {
$election->getResult($method);
}
$election->setImplicitRanking(false);
foreach (Condorcet::getAuthMethods() as $method) {
$election->getResult($method);
}
$election->allowsVoteWeight(false);
foreach (Condorcet::getAuthMethods() as $method) {
$election->getResult($method);
}
$election->parseVotes('
Ultimate Question of Life || C>B>A ^42 * 42
C=A=B ^2 * 200
B>C
A > C >E ^80 *50
G > B > H > F* 250
C = B = E > A ^6 * 48
');
foreach (Condorcet::getAuthMethods() as $method) {
$election->getResult($method);
}
$votes = $election->getVotesListAsString();
}
}

View File

@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace CondorcetPHP\Condorcet\Benchmarks;
use CondorcetPHP\Condorcet\Algo\Methods\KemenyYoung\KemenyYoung;
use CondorcetPHP\Condorcet\Election;
use PhpBench\Attributes as Bench;
ini_set('memory_limit', '51200M');
// Must use --executor=memory_centric_microtime
class KemenyYoungBench
{
public function __construct()
{
KemenyYoung::$MaxCandidates = 10;
}
public function provideCandidatesCount(): \Generator
{
for ($i = 1; $i <= 10; $i++) {
yield $i => ['candidatesCount' => $i];
}
}
#[Bench\ParamProviders(['provideCandidatesCount'])]
#[Bench\OutputTimeUnit('milliseconds')]
#[Bench\Warmup(1)]
#[Bench\Iterations(3)]
#[Bench\Revs(4)]
public function benchKemenyYoung(array $params): void
{
$election = new Election;
for ($i = 0; $i < $params['candidatesCount']; $i++) {
$candidates[] = $election->addCandidate();
}
$election->addVote($candidates);
$result = $election->getResult('KemenyYoung');
}
}

View File

@ -0,0 +1,89 @@
<?php
declare(strict_types=1);
namespace CondorcetPHP\Condorcet\Benchmarks;
use CondorcetPHP\Condorcet\Algo\Methods\KemenyYoung\KemenyYoung;
use CondorcetPHP\Condorcet\Algo\Methods\RankedPairs\RankedPairs_Core;
use CondorcetPHP\Condorcet\Algo\StatsVerbosity;
use CondorcetPHP\Condorcet\{Condorcet, Election};
use CondorcetPHP\Condorcet\Throwable\MethodLimitReachedException;
use PhpBench\Attributes as Bench;
ini_set('memory_limit', '51200M');
class MethodsNonProportionalBench
{
public bool $IS_A_PROPORTIONAL_BENCH = false;
public array $numberOfCandidates = [3, 5, 6, 7, 8, 9, 10, 11, 20, 30, 40, 50, 60, 70, 80, 90, 100];
protected Election $election;
public function __construct()
{
RankedPairs_Core::$MaxCandidates = null;
KemenyYoung::$MaxCandidates = 11;
}
protected function buildElection(int $numberOfCandidates, int $numberOfVotes): void
{
$randomizer = new \Random\Randomizer(new \Random\Engine\Xoshiro256StarStar('CondorcetReproductibleRandomSeed'));
$this->election = $election = new Election;
$this->election->setNumberOfSeats(max(1, (int) ($numberOfCandidates / 3)));
$this->election->setStatsVerbosity(StatsVerbosity::STD);
$candidates = [];
for ($i=0; $i < $numberOfCandidates; $i++) {
$candidates[] = $election->addCandidate();
}
for ($i = 0; $i < $numberOfVotes; $i++) {
$oneVote = $randomizer->shuffleArray($candidates);
$election->addVote($oneVote);
}
}
public function provideMethods(): \Generator
{
foreach (Condorcet::getAuthMethods() as $method) {
$class = Condorcet::getMethodClass($method);
if ($class::IS_PROPORTIONAL === $this->IS_A_PROPORTIONAL_BENCH) {
yield $method => ['method' => $method];
}
}
}
public function provideNumberOfCandidates(): \Generator
{
foreach ($this->numberOfCandidates as $n) {
yield $n => ['numberOfCandidates' => $n];
}
}
public function setUp(array $params): void
{
$this->buildElection($params['numberOfCandidates'], 1_000);
}
#[Bench\OutputTimeUnit('seconds')]
#[Bench\ParamProviders(['provideMethods', 'provideNumberOfCandidates'])]
#[Bench\BeforeMethods('setUp')]
#[Bench\Warmup(1)]
#[Bench\Iterations(3)]
#[Bench\Revs(1)]
public function benchByCandidates(array $params): void
{
try {
$result = $this->election->getResult($params['method']);
} catch (MethodLimitReachedException $e) {
}
$this->election->cleanupCalculator();
}
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace CondorcetPHP\Condorcet\Benchmarks;
use CondorcetPHP\Condorcet\Algo\Methods\STV\CPO_STV;
ini_set('memory_limit', '51200M');
class MethodsProportionalBench extends MethodsNonProportionalBench
{
public bool $IS_A_PROPORTIONAL_BENCH = true;
public array $numberOfCandidates = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 40, 50, 60, 70, 80, 90, 100];
public function __construct()
{
CPO_STV::$MaxOutcomeComparisons = 200_000;
}
}

View File

@ -0,0 +1,69 @@
<?php
declare(strict_types=1);
namespace CondorcetPHP\Condorcet\Benchmarks;
use CondorcetPHP\Condorcet\Algo\Methods\RankedPairs\RankedPairs_Core;
use CondorcetPHP\Condorcet\Election;
use PhpBench\Attributes as Bench;
ini_set('memory_limit', '51200M');
class PairwiseNumberOfCandidatesBench
{
public array $numberOfCandidates = [3, 5, 7, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
public array $numberOfVotes = [10, 100, 1000, 10000];
protected Election $election;
public function __construct()
{
RankedPairs_Core::$MaxCandidates = null;
}
protected function buildElection(int $numberOfCandidates, int $numberOfVotes): void
{
$randomizer = new \Random\Randomizer(new \Random\Engine\Xoshiro256StarStar('CondorcetReproductibleRandomSeed'));
$this->election = $election = new Election;
$this->election->setNumberOfSeats((int) ($numberOfCandidates / 3));
$candidates = [];
for ($i=0; $i < $numberOfCandidates; $i++) {
$candidates[] = $election->addCandidate();
}
for ($i = 0; $i < $numberOfVotes; $i++) {
$oneVote = $randomizer->shuffleArray($candidates);
$election->addVote($oneVote);
}
}
public function provideNumberOfCandidates(): \Generator
{
foreach ($this->numberOfCandidates as $n) {
yield $n => ['numberOfCandidates' => $n];
}
}
public function provideNumberOfVotes(): \Generator
{
foreach ($this->numberOfVotes as $n) {
yield $n => ['numberOfVotes' => $n];
}
}
#[Bench\OutputTimeUnit('seconds')]
#[Bench\ParamProviders(['provideNumberOfCandidates', 'provideNumberOfVotes'])]
#[Bench\Warmup(0)]
#[Bench\Iterations(1)]
#[Bench\Revs(1)]
public function benchByCandidates(array $params): void
{
$this->buildElection($params['numberOfCandidates'], $params['numberOfVotes']);
}
}

View File

@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace CondorcetPHP\Condorcet\Benchmarks;
use CondorcetPHP\Condorcet\Election;
use PhpBench\Attributes as Bench;
class PairwiseUpdateOptimizationBench
{
#[Bench\Warmup(1)]
#[Bench\Iterations(2)]
#[Bench\Revs(4)]
public function benchPairwiseOptimization(): void
{
$election = new Election;
$election->parseCandidates('A;B;C;D;E;F;G');
$election->parseVotes('
E > B > C > A > G * 2500
F > B > G > H > A * 2500
H > B > G > E > A * 2500
A = B = C > D > E = F > G * 2500
G = E = C > F > A * 2500
C > D = G > A > B * 2500
');
$election->getWinner();
$vote = $election->addVote('A>B>C');
$election->removeVote($vote);
$vote->setRanking('C>B>A');
$election->getWinner();
}
}

View File

@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace CondorcetPHP\Condorcet\Benchmarks;
use CondorcetPHP\Condorcet\{Condorcet, Election};
use PhpBench\Attributes as Bench;
class SimpleUsageBench
{
#[Bench\Warmup(1)]
#[Bench\Iterations(10)]
#[Bench\Revs(10)]
#[Bench\OutputTimeUnit('milliseconds')]
public function benchSimpleManyVotes(): void
{
$election = new Election;
$election->allowsVoteWeight(true);
$election->parseCandidates('A;B;C;D;E;F');
$election->parseVotes('
Ultimate Question of Life || A>B>C ^42 * 42
C=A>B ^2 * 250
B>C
E > B > C > A ^80 *257
F > B > G > H > A* 250
D = B = E > F ^6 * 100
B>F=A>C * 100
');
$winner = $election->getCondorcetWinner();
$loser = $election->getCondorcetLoser();
$result = [];
foreach (Condorcet::getAuthMethods() as $method) {
$result[] = $election->getResult($method);
}
}
}