Fix pg_size changing from 3 to 2
parent
5473d5b4a2
commit
08e467270a
|
@ -140,20 +140,20 @@ function make_int_pgs(weights, pg_count, round_robin)
|
||||||
return int_pgs;
|
return int_pgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
function calc_intersect_weights(pg_size, pg_count, prev_weights, all_pgs)
|
function calc_intersect_weights(old_pg_size, pg_size, pg_count, prev_weights, all_pgs, ordered)
|
||||||
{
|
{
|
||||||
const move_weights = {};
|
const move_weights = {};
|
||||||
if ((1 << pg_size) < pg_count)
|
if ((1 << old_pg_size) < pg_count)
|
||||||
{
|
{
|
||||||
const intersect = {};
|
const intersect = {};
|
||||||
for (const pg_name in prev_weights)
|
for (const pg_name in prev_weights)
|
||||||
{
|
{
|
||||||
const pg = pg_name.substr(3).split(/_/);
|
const pg = pg_name.substr(3).split(/_/);
|
||||||
for (let omit = 1; omit < (1 << pg_size); omit++)
|
for (let omit = 1; omit < (1 << old_pg_size); omit++)
|
||||||
{
|
{
|
||||||
let pg_omit = [ ...pg ];
|
let pg_omit = [ ...pg ];
|
||||||
let intersect_count = pg_size;
|
let intersect_count = old_pg_size;
|
||||||
for (let i = 0; i < pg_size; i++)
|
for (let i = 0; i < old_pg_size; i++)
|
||||||
{
|
{
|
||||||
if (omit & (1 << i))
|
if (omit & (1 << i))
|
||||||
{
|
{
|
||||||
|
@ -161,6 +161,8 @@ function calc_intersect_weights(pg_size, pg_count, prev_weights, all_pgs)
|
||||||
intersect_count--;
|
intersect_count--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!ordered)
|
||||||
|
pg_omit = pg_omit.filter(n => n).sort();
|
||||||
pg_omit = pg_omit.join(':');
|
pg_omit = pg_omit.join(':');
|
||||||
intersect[pg_omit] = Math.max(intersect[pg_omit] || 0, intersect_count);
|
intersect[pg_omit] = Math.max(intersect[pg_omit] || 0, intersect_count);
|
||||||
}
|
}
|
||||||
|
@ -174,10 +176,10 @@ function calc_intersect_weights(pg_size, pg_count, prev_weights, all_pgs)
|
||||||
for (let i = 0; i < pg_size; i++)
|
for (let i = 0; i < pg_size; i++)
|
||||||
{
|
{
|
||||||
if (omit & (1 << i))
|
if (omit & (1 << i))
|
||||||
{
|
|
||||||
pg_omit[i] = '';
|
pg_omit[i] = '';
|
||||||
}
|
}
|
||||||
}
|
if (!ordered)
|
||||||
|
pg_omit = pg_omit.filter(n => n).sort();
|
||||||
pg_omit = pg_omit.join(':');
|
pg_omit = pg_omit.join(':');
|
||||||
max_int = Math.max(max_int, intersect[pg_omit] || 0);
|
max_int = Math.max(max_int, intersect[pg_omit] || 0);
|
||||||
}
|
}
|
||||||
|
@ -186,15 +188,18 @@ function calc_intersect_weights(pg_size, pg_count, prev_weights, all_pgs)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const prev_pg_hashed = Object.keys(prev_weights).map(pg_name => pg_name.substr(3).split(/_/).reduce((a, c) => { a[c] = 1; return a; }, {}));
|
const prev_pg_hashed = Object.keys(prev_weights).map(pg_name => pg_name
|
||||||
|
.substr(3).split(/_/).reduce((a, c, i) => { a[c] = i+1; return a; }, {}));
|
||||||
for (const pg of all_pgs)
|
for (const pg of all_pgs)
|
||||||
{
|
{
|
||||||
if (!prev_weights['pg_'+pg.join('_')])
|
if (!prev_weights['pg_'+pg.join('_')])
|
||||||
{
|
{
|
||||||
let max_int = 0;
|
let max_int = 0;
|
||||||
for (const prev_hash in prev_pg_hashed)
|
for (const prev_hash of prev_pg_hashed)
|
||||||
{
|
{
|
||||||
const intersect_count = pg.reduce((a, osd) => a + (prev_hash[osd] ? 1 : 0), 0);
|
const intersect_count = ordered
|
||||||
|
? pg.reduce((a, osd, i) => a + (prev_hash[osd] == 1+i ? 1 : 0), 0)
|
||||||
|
: pg.reduce((a, osd, i) => a + (prev_hash[osd] ? 1 : 0), 0);
|
||||||
if (max_int < intersect_count)
|
if (max_int < intersect_count)
|
||||||
{
|
{
|
||||||
max_int = intersect_count;
|
max_int = intersect_count;
|
||||||
|
@ -243,7 +248,7 @@ function add_valid_previous(osd_tree, prev_weights, all_pgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to minimize data movement
|
// Try to minimize data movement
|
||||||
async function optimize_change({ prev_pgs: prev_int_pgs, osd_tree, pg_size = 3, pg_minsize = 2, max_combinations = 10000, parity_space = 1 })
|
async function optimize_change({ prev_pgs: prev_int_pgs, osd_tree, pg_size = 3, pg_minsize = 2, max_combinations = 10000, parity_space = 1, ordered = false })
|
||||||
{
|
{
|
||||||
if (!osd_tree)
|
if (!osd_tree)
|
||||||
{
|
{
|
||||||
|
@ -266,9 +271,13 @@ async function optimize_change({ prev_pgs: prev_int_pgs, osd_tree, pg_size = 3,
|
||||||
prev_pg_per_osd[osd].push([ pg_name, (i >= pg_minsize ? parity_space : 1) ]);
|
prev_pg_per_osd[osd].push([ pg_name, (i >= pg_minsize ? parity_space : 1) ]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const old_pg_size = prev_int_pgs[0].length;
|
||||||
// Get all combinations
|
// Get all combinations
|
||||||
let all_pgs = random_combinations(osd_tree, pg_size, max_combinations, parity_space > 1);
|
let all_pgs = random_combinations(osd_tree, pg_size, max_combinations, parity_space > 1);
|
||||||
|
if (old_pg_size == pg_size)
|
||||||
|
{
|
||||||
add_valid_previous(osd_tree, prev_weights, all_pgs);
|
add_valid_previous(osd_tree, prev_weights, all_pgs);
|
||||||
|
}
|
||||||
all_pgs = Object.values(all_pgs);
|
all_pgs = Object.values(all_pgs);
|
||||||
const pg_per_osd = {};
|
const pg_per_osd = {};
|
||||||
for (const pg of all_pgs)
|
for (const pg of all_pgs)
|
||||||
|
@ -282,7 +291,7 @@ async function optimize_change({ prev_pgs: prev_int_pgs, osd_tree, pg_size = 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Penalize PGs based on their similarity to old PGs
|
// Penalize PGs based on their similarity to old PGs
|
||||||
const move_weights = calc_intersect_weights(pg_size, pg_count, prev_weights, all_pgs);
|
const move_weights = calc_intersect_weights(old_pg_size, pg_size, pg_count, prev_weights, all_pgs, ordered);
|
||||||
// Calculate total weight - old PG weights
|
// Calculate total weight - old PG weights
|
||||||
const all_pg_names = all_pgs.map(pg => 'pg_'+pg.join('_'));
|
const all_pg_names = all_pgs.map(pg => 'pg_'+pg.join('_'));
|
||||||
const all_pgs_hash = all_pg_names.reduce((a, c) => { a[c] = true; return a; }, {});
|
const all_pgs_hash = all_pg_names.reduce((a, c) => { a[c] = true; return a; }, {});
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright (c) Vitaliy Filippov, 2019+
|
||||||
|
// License: VNPL-1.1 (see README.md for details)
|
||||||
|
|
||||||
|
const LPOptimizer = require('./lp-optimizer.js');
|
||||||
|
|
||||||
|
const osd_tree = {
|
||||||
|
100: { 1: 1 },
|
||||||
|
200: { 2: 1 },
|
||||||
|
300: { 3: 1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
async function run()
|
||||||
|
{
|
||||||
|
let res;
|
||||||
|
console.log('16 PGs, size=3');
|
||||||
|
res = await LPOptimizer.optimize_initial({ osd_tree, pg_size: 3, pg_count: 16 });
|
||||||
|
LPOptimizer.print_change_stats(res, false);
|
||||||
|
console.log('\nChanging size to 2');
|
||||||
|
res = await LPOptimizer.optimize_change({ prev_pgs: res.int_pgs, osd_tree, pg_size: 2 });
|
||||||
|
LPOptimizer.print_change_stats(res, false);
|
||||||
|
if (res.space < 3*14/16)
|
||||||
|
{
|
||||||
|
throw new Error('Redistribution failed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run().catch(console.error);
|
Loading…
Reference in New Issue