crush: move two crush tests over

CrushWrapper handles map manipulation, crush.cc tests the placement.

Signed-off-by: Sage Weil <sage@redhat.com>
This commit is contained in:
Sage Weil 2015-01-15 21:10:31 -08:00
parent ddb91b2f8f
commit 7372ac7ae5
2 changed files with 159 additions and 160 deletions

View File

@ -68,166 +68,6 @@ TEST(CrushWrapper, get_immediate_parent) {
delete c;
}
TEST(CrushWrapper, straw_zero) {
// zero weight items should have no effect on placement.
CrushWrapper *c = new CrushWrapper;
const int ROOT_TYPE = 1;
c->set_type_name(ROOT_TYPE, "root");
const int OSD_TYPE = 0;
c->set_type_name(OSD_TYPE, "osd");
int n = 5;
int items[n], weights[n];
for (int i=0; i <n; ++i) {
items[i] = i;
weights[i] = 0x10000 * (n-i-1);
}
c->set_max_devices(n);
string root_name0("root0");
int root0;
EXPECT_EQ(0, c->add_bucket(0, CRUSH_BUCKET_STRAW, CRUSH_HASH_RJENKINS1,
ROOT_TYPE, n, items, weights, &root0));
EXPECT_EQ(0, c->set_item_name(root0, root_name0));
string name0("rule0");
int ruleset0 = c->add_simple_ruleset(name0, root_name0, "osd",
"firstn", pg_pool_t::TYPE_REPLICATED);
EXPECT_EQ(0, ruleset0);
string root_name1("root1");
int root1;
EXPECT_EQ(0, c->add_bucket(0, CRUSH_BUCKET_STRAW, CRUSH_HASH_RJENKINS1,
ROOT_TYPE, n-1, items, weights, &root1));
EXPECT_EQ(0, c->set_item_name(root1, root_name1));
string name1("rule1");
int ruleset1 = c->add_simple_ruleset(name1, root_name1, "osd",
"firstn", pg_pool_t::TYPE_REPLICATED);
EXPECT_EQ(1, ruleset1);
vector<unsigned> reweight(n, 0x10000);
for (int i=0; i<10000; ++i) {
vector<int> out0, out1;
c->do_rule(ruleset0, i, out0, 1, reweight);
ASSERT_EQ(1u, out0.size());
c->do_rule(ruleset1, i, out1, 1, reweight);
ASSERT_EQ(1u, out1.size());
ASSERT_EQ(out0[0], out1[0]);
//cout << i << "\t" << out0 << "\t" << out1 << std::endl;
}
}
TEST(CrushWrapper, straw_same) {
// items with the same weight should map about the same as items
// with very similar weights.
//
// give the 0 vector a paired stair pattern, with dup weights. note
// that the original straw flaw does not appear when there are 2 of
// the initial weight, but it does when there is just 1.
//
// give the 1 vector a similar stair pattern, but make the same
// steps weights slightly different (no dups). this works.
//
// compare the result and verify that the resulting mapping is
// almost identical.
CrushWrapper *c = new CrushWrapper;
const int ROOT_TYPE = 1;
c->set_type_name(ROOT_TYPE, "root");
const int OSD_TYPE = 0;
c->set_type_name(OSD_TYPE, "osd");
int n = 10;
int items[n], weights[n];
for (int i=0; i <n; ++i) {
items[i] = i;
weights[i] = 0x10000 * ((i+1)/2 + 1);
}
c->set_max_devices(n);
string root_name0("root0");
int root0;
EXPECT_EQ(0, c->add_bucket(0, CRUSH_BUCKET_STRAW, CRUSH_HASH_RJENKINS1,
ROOT_TYPE, n, items, weights, &root0));
EXPECT_EQ(0, c->set_item_name(root0, root_name0));
string name0("rule0");
int ruleset0 = c->add_simple_ruleset(name0, root_name0, "osd",
"firstn", pg_pool_t::TYPE_REPLICATED);
EXPECT_EQ(0, ruleset0);
for (int i=0; i <n; ++i) {
items[i] = i;
weights[i] = 0x10000 * ((i+1)/2 + 1) + (i%2)*100;
}
string root_name1("root1");
int root1;
EXPECT_EQ(0, c->add_bucket(0, CRUSH_BUCKET_STRAW, CRUSH_HASH_RJENKINS1,
ROOT_TYPE, n, items, weights, &root1));
EXPECT_EQ(0, c->set_item_name(root1, root_name1));
string name1("rule1");
int ruleset1 = c->add_simple_ruleset(name1, root_name1, "osd",
"firstn", pg_pool_t::TYPE_REPLICATED);
EXPECT_EQ(1, ruleset1);
if (0) {
crush_bucket_straw *sb0 = reinterpret_cast<crush_bucket_straw*>(c->get_crush_map()->buckets[-1-root0]);
crush_bucket_straw *sb1 = reinterpret_cast<crush_bucket_straw*>(c->get_crush_map()->buckets[-1-root1]);
for (int i=0; i<n; ++i) {
cout << i
<< "\t" << sb0->item_weights[i]
<< "\t" << sb1->item_weights[i]
<< "\t"
<< "\t" << sb0->straws[i]
<< "\t" << sb1->straws[i]
<< std::endl;
}
}
if (0) {
JSONFormatter jf(true);
jf.open_object_section("crush");
c->dump(&jf);
jf.close_section();
jf.flush(cout);
}
vector<int> sum0(n, 0), sum1(n, 0);
vector<unsigned> reweight(n, 0x10000);
int different = 0;
int max = 100000;
for (int i=0; i<max; ++i) {
vector<int> out0, out1;
c->do_rule(ruleset0, i, out0, 1, reweight);
ASSERT_EQ(1u, out0.size());
c->do_rule(ruleset1, i, out1, 1, reweight);
ASSERT_EQ(1u, out1.size());
sum0[out0[0]]++;
sum1[out1[0]]++;
if (out0[0] != out1[0])
different++;
}
for (int i=0; i<n; ++i) {
cout << i
<< "\t" << ((double)weights[i] / (double)weights[0])
<< "\t" << sum0[i] << "\t" << ((double)sum0[i]/(double)sum0[0])
<< "\t" << sum1[i] << "\t" << ((double)sum1[i]/(double)sum1[0])
<< std::endl;
}
double ratio = ((double)different / (double)max);
cout << different << " of " << max << " = "
<< ratio
<< " different" << std::endl;
ASSERT_LT(ratio, .001);
}
TEST(CrushWrapper, move_bucket) {
CrushWrapper *c = new CrushWrapper;

View File

@ -17,6 +17,7 @@
#include "global/global_context.h"
#include "crush/CrushWrapper.h"
#include "osd/osd_types.h"
#include <set>
@ -250,7 +251,165 @@ TEST(CRUSH, indep_out_progressive) {
delete c;
}
TEST(CrushWrapper, straw_zero) {
// zero weight items should have no effect on placement.
CrushWrapper *c = new CrushWrapper;
const int ROOT_TYPE = 1;
c->set_type_name(ROOT_TYPE, "root");
const int OSD_TYPE = 0;
c->set_type_name(OSD_TYPE, "osd");
int n = 5;
int items[n], weights[n];
for (int i=0; i <n; ++i) {
items[i] = i;
weights[i] = 0x10000 * (n-i-1);
}
c->set_max_devices(n);
string root_name0("root0");
int root0;
EXPECT_EQ(0, c->add_bucket(0, CRUSH_BUCKET_STRAW, CRUSH_HASH_RJENKINS1,
ROOT_TYPE, n, items, weights, &root0));
EXPECT_EQ(0, c->set_item_name(root0, root_name0));
string name0("rule0");
int ruleset0 = c->add_simple_ruleset(name0, root_name0, "osd",
"firstn", pg_pool_t::TYPE_REPLICATED);
EXPECT_EQ(0, ruleset0);
string root_name1("root1");
int root1;
EXPECT_EQ(0, c->add_bucket(0, CRUSH_BUCKET_STRAW, CRUSH_HASH_RJENKINS1,
ROOT_TYPE, n-1, items, weights, &root1));
EXPECT_EQ(0, c->set_item_name(root1, root_name1));
string name1("rule1");
int ruleset1 = c->add_simple_ruleset(name1, root_name1, "osd",
"firstn", pg_pool_t::TYPE_REPLICATED);
EXPECT_EQ(1, ruleset1);
vector<unsigned> reweight(n, 0x10000);
for (int i=0; i<10000; ++i) {
vector<int> out0, out1;
c->do_rule(ruleset0, i, out0, 1, reweight);
ASSERT_EQ(1u, out0.size());
c->do_rule(ruleset1, i, out1, 1, reweight);
ASSERT_EQ(1u, out1.size());
ASSERT_EQ(out0[0], out1[0]);
//cout << i << "\t" << out0 << "\t" << out1 << std::endl;
}
}
TEST(CrushWrapper, straw_same) {
// items with the same weight should map about the same as items
// with very similar weights.
//
// give the 0 vector a paired stair pattern, with dup weights. note
// that the original straw flaw does not appear when there are 2 of
// the initial weight, but it does when there is just 1.
//
// give the 1 vector a similar stair pattern, but make the same
// steps weights slightly different (no dups). this works.
//
// compare the result and verify that the resulting mapping is
// almost identical.
CrushWrapper *c = new CrushWrapper;
const int ROOT_TYPE = 1;
c->set_type_name(ROOT_TYPE, "root");
const int OSD_TYPE = 0;
c->set_type_name(OSD_TYPE, "osd");
int n = 10;
int items[n], weights[n];
for (int i=0; i <n; ++i) {
items[i] = i;
weights[i] = 0x10000 * ((i+1)/2 + 1);
}
c->set_max_devices(n);
string root_name0("root0");
int root0;
EXPECT_EQ(0, c->add_bucket(0, CRUSH_BUCKET_STRAW, CRUSH_HASH_RJENKINS1,
ROOT_TYPE, n, items, weights, &root0));
EXPECT_EQ(0, c->set_item_name(root0, root_name0));
string name0("rule0");
int ruleset0 = c->add_simple_ruleset(name0, root_name0, "osd",
"firstn", pg_pool_t::TYPE_REPLICATED);
EXPECT_EQ(0, ruleset0);
for (int i=0; i <n; ++i) {
items[i] = i;
weights[i] = 0x10000 * ((i+1)/2 + 1) + (i%2)*100;
}
string root_name1("root1");
int root1;
EXPECT_EQ(0, c->add_bucket(0, CRUSH_BUCKET_STRAW, CRUSH_HASH_RJENKINS1,
ROOT_TYPE, n, items, weights, &root1));
EXPECT_EQ(0, c->set_item_name(root1, root_name1));
string name1("rule1");
int ruleset1 = c->add_simple_ruleset(name1, root_name1, "osd",
"firstn", pg_pool_t::TYPE_REPLICATED);
EXPECT_EQ(1, ruleset1);
if (0) {
crush_bucket_straw *sb0 = reinterpret_cast<crush_bucket_straw*>(c->get_crush_map()->buckets[-1-root0]);
crush_bucket_straw *sb1 = reinterpret_cast<crush_bucket_straw*>(c->get_crush_map()->buckets[-1-root1]);
for (int i=0; i<n; ++i) {
cout << i
<< "\t" << sb0->item_weights[i]
<< "\t" << sb1->item_weights[i]
<< "\t"
<< "\t" << sb0->straws[i]
<< "\t" << sb1->straws[i]
<< std::endl;
}
}
if (0) {
JSONFormatter jf(true);
jf.open_object_section("crush");
c->dump(&jf);
jf.close_section();
jf.flush(cout);
}
vector<int> sum0(n, 0), sum1(n, 0);
vector<unsigned> reweight(n, 0x10000);
int different = 0;
int max = 100000;
for (int i=0; i<max; ++i) {
vector<int> out0, out1;
c->do_rule(ruleset0, i, out0, 1, reweight);
ASSERT_EQ(1u, out0.size());
c->do_rule(ruleset1, i, out1, 1, reweight);
ASSERT_EQ(1u, out1.size());
sum0[out0[0]]++;
sum1[out1[0]]++;
if (out0[0] != out1[0])
different++;
}
for (int i=0; i<n; ++i) {
cout << i
<< "\t" << ((double)weights[i] / (double)weights[0])
<< "\t" << sum0[i] << "\t" << ((double)sum0[i]/(double)sum0[0])
<< "\t" << sum1[i] << "\t" << ((double)sum1[i]/(double)sum1[0])
<< std::endl;
}
double ratio = ((double)different / (double)max);
cout << different << " of " << max << " = "
<< ratio
<< " different" << std::endl;
ASSERT_LT(ratio, .001);
}
int main(int argc, char **argv) {