mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[yul-phaser] ProgramBasedMetric: Add the ability to use ProgramCache
This commit is contained in:
parent
8b443627e2
commit
259f738f17
@ -76,15 +76,16 @@ protected:
|
|||||||
Chromosome m_chromosome{vector<string>{UnusedPruner::name, EquivalentFunctionCombiner::name}};
|
Chromosome m_chromosome{vector<string>{UnusedPruner::name, EquivalentFunctionCombiner::name}};
|
||||||
Program m_program = get<Program>(Program::load(m_sourceStream));
|
Program m_program = get<Program>(Program::load(m_sourceStream));
|
||||||
Program m_optimisedProgram = optimisedProgram(m_program);
|
Program m_optimisedProgram = optimisedProgram(m_program);
|
||||||
|
shared_ptr<ProgramCache> m_programCache = make_shared<ProgramCache>(m_program);
|
||||||
};
|
};
|
||||||
|
|
||||||
class FitnessMetricCombinationFixture: public ProgramBasedMetricFixture
|
class FitnessMetricCombinationFixture: public ProgramBasedMetricFixture
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
vector<shared_ptr<FitnessMetric>> m_simpleMetrics = {
|
vector<shared_ptr<FitnessMetric>> m_simpleMetrics = {
|
||||||
make_shared<ProgramSize>(m_program, 1),
|
make_shared<ProgramSize>(m_program, nullptr, 1),
|
||||||
make_shared<ProgramSize>(m_program, 2),
|
make_shared<ProgramSize>(m_program, nullptr, 2),
|
||||||
make_shared<ProgramSize>(m_program, 3),
|
make_shared<ProgramSize>(m_program, nullptr, 3),
|
||||||
};
|
};
|
||||||
vector<size_t> m_fitness = {
|
vector<size_t> m_fitness = {
|
||||||
m_simpleMetrics[0]->evaluate(m_chromosome),
|
m_simpleMetrics[0]->evaluate(m_chromosome),
|
||||||
@ -97,31 +98,66 @@ BOOST_AUTO_TEST_SUITE(Phaser)
|
|||||||
BOOST_AUTO_TEST_SUITE(FitnessMetricsTest)
|
BOOST_AUTO_TEST_SUITE(FitnessMetricsTest)
|
||||||
BOOST_AUTO_TEST_SUITE(ProgramBasedMetricTest)
|
BOOST_AUTO_TEST_SUITE(ProgramBasedMetricTest)
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(optimisedProgram_should_return_optimised_program, ProgramBasedMetricFixture)
|
BOOST_FIXTURE_TEST_CASE(optimisedProgram_should_return_optimised_program_even_if_cache_not_available, ProgramBasedMetricFixture)
|
||||||
{
|
{
|
||||||
string code = toString(DummyProgramBasedMetric(m_program).optimisedProgram(m_chromosome));
|
string code = toString(DummyProgramBasedMetric(m_program, nullptr).optimisedProgram(m_chromosome));
|
||||||
|
|
||||||
BOOST_TEST(code != toString(m_program));
|
BOOST_TEST(code != toString(m_program));
|
||||||
BOOST_TEST(code == toString(m_optimisedProgram));
|
BOOST_TEST(code == toString(m_optimisedProgram));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(optimisedProgram_should_use_cache_if_available, ProgramBasedMetricFixture)
|
||||||
|
{
|
||||||
|
string code = toString(DummyProgramBasedMetric(nullopt, m_programCache).optimisedProgram(m_chromosome));
|
||||||
|
|
||||||
|
BOOST_TEST(code != toString(m_program));
|
||||||
|
BOOST_TEST(code == toString(m_optimisedProgram));
|
||||||
|
BOOST_TEST(m_programCache->size() == m_chromosome.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(optimisedProgramNoCache_should_return_optimised_program_even_if_cache_not_available, ProgramBasedMetricFixture)
|
||||||
|
{
|
||||||
|
string code = toString(DummyProgramBasedMetric(m_program, nullptr).optimisedProgramNoCache(m_chromosome));
|
||||||
|
|
||||||
|
BOOST_TEST(code != toString(m_program));
|
||||||
|
BOOST_TEST(code == toString(m_optimisedProgram));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(optimisedProgramNoCache_should_not_use_cache_even_if_available, ProgramBasedMetricFixture)
|
||||||
|
{
|
||||||
|
string code = toString(DummyProgramBasedMetric(nullopt, m_programCache).optimisedProgramNoCache(m_chromosome));
|
||||||
|
|
||||||
|
BOOST_TEST(code != toString(m_program));
|
||||||
|
BOOST_TEST(code == toString(m_optimisedProgram));
|
||||||
|
BOOST_TEST(m_programCache->size() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
BOOST_AUTO_TEST_SUITE(ProgramSizeTest)
|
BOOST_AUTO_TEST_SUITE(ProgramSizeTest)
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(evaluate_should_compute_size_of_the_optimised_program, ProgramBasedMetricFixture)
|
BOOST_FIXTURE_TEST_CASE(evaluate_should_compute_size_of_the_optimised_program, ProgramBasedMetricFixture)
|
||||||
{
|
{
|
||||||
size_t fitness = ProgramSize(m_program).evaluate(m_chromosome);
|
size_t fitness = ProgramSize(m_program, nullptr).evaluate(m_chromosome);
|
||||||
|
|
||||||
BOOST_TEST(fitness != m_program.codeSize());
|
BOOST_TEST(fitness != m_program.codeSize());
|
||||||
BOOST_TEST(fitness == m_optimisedProgram.codeSize());
|
BOOST_TEST(fitness == m_optimisedProgram.codeSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(evaluate_should_be_able_to_use_program_cache_if_available, ProgramBasedMetricFixture)
|
||||||
|
{
|
||||||
|
size_t fitness = ProgramSize(nullopt, m_programCache).evaluate(m_chromosome);
|
||||||
|
|
||||||
|
BOOST_TEST(fitness != m_program.codeSize());
|
||||||
|
BOOST_TEST(fitness == m_optimisedProgram.codeSize());
|
||||||
|
BOOST_TEST(m_programCache->size() == m_chromosome.length());
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(evaluate_should_repeat_the_optimisation_specified_number_of_times, ProgramBasedMetricFixture)
|
BOOST_FIXTURE_TEST_CASE(evaluate_should_repeat_the_optimisation_specified_number_of_times, ProgramBasedMetricFixture)
|
||||||
{
|
{
|
||||||
Program const& programOptimisedOnce = m_optimisedProgram;
|
Program const& programOptimisedOnce = m_optimisedProgram;
|
||||||
Program programOptimisedTwice = optimisedProgram(programOptimisedOnce);
|
Program programOptimisedTwice = optimisedProgram(programOptimisedOnce);
|
||||||
|
|
||||||
ProgramSize metric(m_program, 2);
|
ProgramSize metric(m_program, nullptr, 2);
|
||||||
size_t fitness = metric.evaluate(m_chromosome);
|
size_t fitness = metric.evaluate(m_chromosome);
|
||||||
|
|
||||||
BOOST_TEST(fitness != m_program.codeSize());
|
BOOST_TEST(fitness != m_program.codeSize());
|
||||||
@ -131,7 +167,7 @@ BOOST_FIXTURE_TEST_CASE(evaluate_should_repeat_the_optimisation_specified_number
|
|||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(evaluate_should_not_optimise_if_number_of_repetitions_is_zero, ProgramBasedMetricFixture)
|
BOOST_FIXTURE_TEST_CASE(evaluate_should_not_optimise_if_number_of_repetitions_is_zero, ProgramBasedMetricFixture)
|
||||||
{
|
{
|
||||||
ProgramSize metric(m_program, 0);
|
ProgramSize metric(m_program, nullptr, 0);
|
||||||
size_t fitness = metric.evaluate(m_chromosome);
|
size_t fitness = metric.evaluate(m_chromosome);
|
||||||
|
|
||||||
BOOST_TEST(fitness == m_program.codeSize());
|
BOOST_TEST(fitness == m_program.codeSize());
|
||||||
@ -143,7 +179,13 @@ BOOST_AUTO_TEST_SUITE(RelativeProgramSizeTest)
|
|||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(evaluate_should_compute_the_size_ratio_between_optimised_program_and_original_program, ProgramBasedMetricFixture)
|
BOOST_FIXTURE_TEST_CASE(evaluate_should_compute_the_size_ratio_between_optimised_program_and_original_program, ProgramBasedMetricFixture)
|
||||||
{
|
{
|
||||||
BOOST_TEST(RelativeProgramSize(m_program, 3).evaluate(m_chromosome) == round(1000.0 * m_optimisedProgram.codeSize() / m_program.codeSize()));
|
BOOST_TEST(RelativeProgramSize(m_program, nullptr, 3).evaluate(m_chromosome) == round(1000.0 * m_optimisedProgram.codeSize() / m_program.codeSize()));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(evaluate_should_be_able_to_use_program_cache_if_available, ProgramBasedMetricFixture)
|
||||||
|
{
|
||||||
|
BOOST_TEST(RelativeProgramSize(nullopt, m_programCache, 3).evaluate(m_chromosome) == round(1000.0 * m_optimisedProgram.codeSize() / m_program.codeSize()));
|
||||||
|
BOOST_TEST(m_programCache->size() == m_chromosome.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(evaluate_should_repeat_the_optimisation_specified_number_of_times, ProgramBasedMetricFixture)
|
BOOST_FIXTURE_TEST_CASE(evaluate_should_repeat_the_optimisation_specified_number_of_times, ProgramBasedMetricFixture)
|
||||||
@ -151,17 +193,17 @@ BOOST_FIXTURE_TEST_CASE(evaluate_should_repeat_the_optimisation_specified_number
|
|||||||
Program const& programOptimisedOnce = m_optimisedProgram;
|
Program const& programOptimisedOnce = m_optimisedProgram;
|
||||||
Program programOptimisedTwice = optimisedProgram(programOptimisedOnce);
|
Program programOptimisedTwice = optimisedProgram(programOptimisedOnce);
|
||||||
|
|
||||||
RelativeProgramSize metric(m_program, 3, 2);
|
RelativeProgramSize metric(m_program, nullptr, 3, 2);
|
||||||
size_t fitness = metric.evaluate(m_chromosome);
|
size_t fitness = metric.evaluate(m_chromosome);
|
||||||
|
|
||||||
BOOST_TEST(fitness != 1000);
|
BOOST_TEST(fitness != 1000);
|
||||||
BOOST_TEST(fitness != RelativeProgramSize(programOptimisedTwice, 3, 1).evaluate(m_chromosome));
|
BOOST_TEST(fitness != RelativeProgramSize(programOptimisedTwice, nullptr, 3, 1).evaluate(m_chromosome));
|
||||||
BOOST_TEST(fitness == round(1000.0 * programOptimisedTwice.codeSize() / m_program.codeSize()));
|
BOOST_TEST(fitness == round(1000.0 * programOptimisedTwice.codeSize() / m_program.codeSize()));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(evaluate_should_return_one_if_number_of_repetitions_is_zero, ProgramBasedMetricFixture)
|
BOOST_FIXTURE_TEST_CASE(evaluate_should_return_one_if_number_of_repetitions_is_zero, ProgramBasedMetricFixture)
|
||||||
{
|
{
|
||||||
RelativeProgramSize metric(m_program, 3, 0);
|
RelativeProgramSize metric(m_program, nullptr, 3, 0);
|
||||||
|
|
||||||
BOOST_TEST(metric.evaluate(m_chromosome) == 1000);
|
BOOST_TEST(metric.evaluate(m_chromosome) == 1000);
|
||||||
}
|
}
|
||||||
@ -171,7 +213,7 @@ BOOST_FIXTURE_TEST_CASE(evaluate_should_return_one_if_the_original_program_size_
|
|||||||
CharStream sourceStream = CharStream("{}", "");
|
CharStream sourceStream = CharStream("{}", "");
|
||||||
Program program = get<Program>(Program::load(sourceStream));
|
Program program = get<Program>(Program::load(sourceStream));
|
||||||
|
|
||||||
RelativeProgramSize metric(program, 3);
|
RelativeProgramSize metric(program, nullptr, 3);
|
||||||
|
|
||||||
BOOST_TEST(metric.evaluate(m_chromosome) == 1000);
|
BOOST_TEST(metric.evaluate(m_chromosome) == 1000);
|
||||||
BOOST_TEST(metric.evaluate(Chromosome("")) == 1000);
|
BOOST_TEST(metric.evaluate(Chromosome("")) == 1000);
|
||||||
@ -181,11 +223,11 @@ BOOST_FIXTURE_TEST_CASE(evaluate_should_return_one_if_the_original_program_size_
|
|||||||
BOOST_FIXTURE_TEST_CASE(evaluate_should_multiply_the_result_by_scaling_factor, ProgramBasedMetricFixture)
|
BOOST_FIXTURE_TEST_CASE(evaluate_should_multiply_the_result_by_scaling_factor, ProgramBasedMetricFixture)
|
||||||
{
|
{
|
||||||
double sizeRatio = static_cast<double>(m_optimisedProgram.codeSize()) / m_program.codeSize();
|
double sizeRatio = static_cast<double>(m_optimisedProgram.codeSize()) / m_program.codeSize();
|
||||||
BOOST_TEST(RelativeProgramSize(m_program, 0).evaluate(m_chromosome) == round(1.0 * sizeRatio));
|
BOOST_TEST(RelativeProgramSize(m_program, nullptr, 0).evaluate(m_chromosome) == round(1.0 * sizeRatio));
|
||||||
BOOST_TEST(RelativeProgramSize(m_program, 1).evaluate(m_chromosome) == round(10.0 * sizeRatio));
|
BOOST_TEST(RelativeProgramSize(m_program, nullptr, 1).evaluate(m_chromosome) == round(10.0 * sizeRatio));
|
||||||
BOOST_TEST(RelativeProgramSize(m_program, 2).evaluate(m_chromosome) == round(100.0 * sizeRatio));
|
BOOST_TEST(RelativeProgramSize(m_program, nullptr, 2).evaluate(m_chromosome) == round(100.0 * sizeRatio));
|
||||||
BOOST_TEST(RelativeProgramSize(m_program, 3).evaluate(m_chromosome) == round(1000.0 * sizeRatio));
|
BOOST_TEST(RelativeProgramSize(m_program, nullptr, 3).evaluate(m_chromosome) == round(1000.0 * sizeRatio));
|
||||||
BOOST_TEST(RelativeProgramSize(m_program, 4).evaluate(m_chromosome) == round(10000.0 * sizeRatio));
|
BOOST_TEST(RelativeProgramSize(m_program, nullptr, 4).evaluate(m_chromosome) == round(10000.0 * sizeRatio));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
@ -17,14 +17,36 @@
|
|||||||
|
|
||||||
#include <tools/yulPhaser/FitnessMetrics.h>
|
#include <tools/yulPhaser/FitnessMetrics.h>
|
||||||
|
|
||||||
|
#include <libsolutil/CommonIO.h>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
using namespace solidity::util;
|
||||||
using namespace solidity::phaser;
|
using namespace solidity::phaser;
|
||||||
|
|
||||||
Program ProgramBasedMetric::optimisedProgram(Chromosome const& _chromosome) const
|
Program const& ProgramBasedMetric::program() const
|
||||||
{
|
{
|
||||||
Program programCopy = m_program;
|
if (m_programCache == nullptr)
|
||||||
|
return m_program.value();
|
||||||
|
else
|
||||||
|
return m_programCache->program();
|
||||||
|
}
|
||||||
|
|
||||||
|
Program ProgramBasedMetric::optimisedProgram(Chromosome const& _chromosome)
|
||||||
|
{
|
||||||
|
if (m_programCache == nullptr)
|
||||||
|
return optimisedProgramNoCache(_chromosome);
|
||||||
|
|
||||||
|
return m_programCache->optimiseProgram(
|
||||||
|
toString(_chromosome),
|
||||||
|
m_repetitionCount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Program ProgramBasedMetric::optimisedProgramNoCache(Chromosome const& _chromosome) const
|
||||||
|
{
|
||||||
|
Program programCopy = program();
|
||||||
for (size_t i = 0; i < m_repetitionCount; ++i)
|
for (size_t i = 0; i < m_repetitionCount; ++i)
|
||||||
programCopy.optimise(_chromosome.optimisationSteps());
|
programCopy.optimise(_chromosome.optimisationSteps());
|
||||||
|
|
||||||
|
@ -22,8 +22,10 @@
|
|||||||
|
|
||||||
#include <tools/yulPhaser/Chromosome.h>
|
#include <tools/yulPhaser/Chromosome.h>
|
||||||
#include <tools/yulPhaser/Program.h>
|
#include <tools/yulPhaser/Program.h>
|
||||||
|
#include <tools/yulPhaser/ProgramCache.h>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace solidity::phaser
|
namespace solidity::phaser
|
||||||
{
|
{
|
||||||
@ -50,7 +52,7 @@ public:
|
|||||||
* Abstract base class for fitness metrics that return values based on program size.
|
* Abstract base class for fitness metrics that return values based on program size.
|
||||||
*
|
*
|
||||||
* The class provides utilities for optimising programs according to the information stored in
|
* The class provides utilities for optimising programs according to the information stored in
|
||||||
* chromosomes.
|
* chromosomes. Allows using @a ProgramCache.
|
||||||
*
|
*
|
||||||
* It can also store weights for the @a CodeSize metric. It does not do anything with
|
* It can also store weights for the @a CodeSize metric. It does not do anything with
|
||||||
* them because it does not actually compute the code size but they are readily available for use
|
* them because it does not actually compute the code size but they are readily available for use
|
||||||
@ -60,19 +62,27 @@ class ProgramBasedMetric: public FitnessMetric
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ProgramBasedMetric(
|
explicit ProgramBasedMetric(
|
||||||
Program _program,
|
std::optional<Program> _program,
|
||||||
|
std::shared_ptr<ProgramCache> _programCache,
|
||||||
size_t _repetitionCount = 1
|
size_t _repetitionCount = 1
|
||||||
):
|
):
|
||||||
m_program(std::move(_program)),
|
m_program(std::move(_program)),
|
||||||
m_repetitionCount(_repetitionCount) {}
|
m_programCache(std::move(_programCache)),
|
||||||
|
m_repetitionCount(_repetitionCount)
|
||||||
|
{
|
||||||
|
assert(m_program.has_value() == (m_programCache == nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
Program const& program() const { return m_program; }
|
Program const& program() const;
|
||||||
|
ProgramCache const* programCache() const { return m_programCache.get(); }
|
||||||
size_t repetitionCount() const { return m_repetitionCount; }
|
size_t repetitionCount() const { return m_repetitionCount; }
|
||||||
|
|
||||||
Program optimisedProgram(Chromosome const& _chromosome) const;
|
Program optimisedProgram(Chromosome const& _chromosome);
|
||||||
|
Program optimisedProgramNoCache(Chromosome const& _chromosome) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Program m_program;
|
std::optional<Program> m_program;
|
||||||
|
std::shared_ptr<ProgramCache> m_programCache;
|
||||||
size_t m_repetitionCount;
|
size_t m_repetitionCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -98,11 +108,12 @@ class RelativeProgramSize: public ProgramBasedMetric
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit RelativeProgramSize(
|
explicit RelativeProgramSize(
|
||||||
Program _program,
|
std::optional<Program> _program,
|
||||||
|
std::shared_ptr<ProgramCache> _programCache,
|
||||||
size_t _fixedPointPrecision,
|
size_t _fixedPointPrecision,
|
||||||
size_t _repetitionCount = 1
|
size_t _repetitionCount = 1
|
||||||
):
|
):
|
||||||
ProgramBasedMetric(std::move(_program), _repetitionCount),
|
ProgramBasedMetric(std::move(_program), std::move(_programCache), _repetitionCount),
|
||||||
m_fixedPointPrecision(_fixedPointPrecision) {}
|
m_fixedPointPrecision(_fixedPointPrecision) {}
|
||||||
|
|
||||||
size_t fixedPointPrecision() const { return m_fixedPointPrecision; }
|
size_t fixedPointPrecision() const { return m_fixedPointPrecision; }
|
||||||
|
@ -171,6 +171,7 @@ unique_ptr<FitnessMetric> FitnessMetricFactory::build(
|
|||||||
for (Program& program: _programs)
|
for (Program& program: _programs)
|
||||||
metrics.push_back(make_unique<ProgramSize>(
|
metrics.push_back(make_unique<ProgramSize>(
|
||||||
move(program),
|
move(program),
|
||||||
|
nullptr,
|
||||||
_options.chromosomeRepetitions
|
_options.chromosomeRepetitions
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -181,6 +182,7 @@ unique_ptr<FitnessMetric> FitnessMetricFactory::build(
|
|||||||
for (Program& program: _programs)
|
for (Program& program: _programs)
|
||||||
metrics.push_back(make_unique<RelativeProgramSize>(
|
metrics.push_back(make_unique<RelativeProgramSize>(
|
||||||
move(program),
|
move(program),
|
||||||
|
nullptr,
|
||||||
_options.relativeMetricScale,
|
_options.relativeMetricScale,
|
||||||
_options.chromosomeRepetitions
|
_options.chromosomeRepetitions
|
||||||
));
|
));
|
||||||
|
Loading…
Reference in New Issue
Block a user