120 lines
3.5 KiB
JavaScript
120 lines
3.5 KiB
JavaScript
#!/usr/bin/nodejs
|
|
// "Stupid" gossip algorithm simulation tool
|
|
|
|
const gossip = 4; // how many nodes to gossip with every tick
|
|
const msgcap = 9; // how many nodes to gossip about every tick
|
|
const total = 1000; // total nodes
|
|
const total_updated = 1000; // total nodes to update if testing update. if 0 then test joining
|
|
const initial_nodes = 5; // initial nodes in sync to test joining (when total_updated == 0)
|
|
|
|
function test()
|
|
{
|
|
let messages_sent = 0;
|
|
let tick = 1;
|
|
const known = {};
|
|
const lists = {};
|
|
const listsv2 = {};
|
|
for (let i = 1; i <= total; i++)
|
|
{
|
|
known[i] = {};
|
|
lists[i] = [];
|
|
for (let j = 1; j <= (total_updated ? total : initial_nodes); j++)
|
|
{
|
|
known[i][j] = 1; // meta version 1
|
|
lists[i].push(j);
|
|
}
|
|
listsv2[i] = [];
|
|
}
|
|
let cmp_lists;
|
|
let cmp_n;
|
|
if (total_updated)
|
|
{
|
|
// We want to update <total_updated> nodes metadata to version 2
|
|
for (let i = 1; i <= total_updated; i++)
|
|
{
|
|
known[i][i] = 2;
|
|
listsv2[i].push(i);
|
|
}
|
|
cmp_lists = listsv2;
|
|
cmp_n = total_updated;
|
|
}
|
|
else
|
|
{
|
|
// We want <total-initial_nodes> to join <initial_nodes>
|
|
for (let i = 1; i <= initial_nodes; i++)
|
|
{
|
|
if (!known[i][i])
|
|
{
|
|
known[i][i] = 1;
|
|
lists[i].push(i);
|
|
}
|
|
for (let alive = initial_nodes+1; alive <= total; alive++)
|
|
{
|
|
if (!known[i][alive])
|
|
{
|
|
known[i][alive] = true;
|
|
lists[i].push(alive);
|
|
}
|
|
}
|
|
}
|
|
cmp_lists = lists;
|
|
cmp_n = total;
|
|
}
|
|
let in_sync = 0;
|
|
for (let i = 1; i <= total; i++)
|
|
{
|
|
if (cmp_lists[i].length == cmp_n)
|
|
{
|
|
in_sync++;
|
|
}
|
|
}
|
|
let avg_known = 0;
|
|
while (in_sync < total)
|
|
{
|
|
console.log('tick '+tick+': '+in_sync+' in sync, avg '+avg_known);
|
|
for (let i = 1; i <= total; i++)
|
|
{
|
|
const known_i = lists[i];
|
|
const send_to = [];
|
|
for (let j = 0; j < gossip; j++)
|
|
{
|
|
send_to.push(known_i[0|(Math.random()*known_i.length)]);
|
|
}
|
|
const send_what = [];
|
|
for (let j = 0; j < msgcap; j++)
|
|
{
|
|
// FIXME: Exclude duplicates, exclude <send_to>
|
|
send_what.push(known_i[0|(Math.random()*known_i.length)]);
|
|
}
|
|
for (const alive of send_what)
|
|
{
|
|
for (const to of send_to)
|
|
{
|
|
if (!known[to][alive] || known[i][alive] > known[to][alive])
|
|
{
|
|
known[to][alive] = known[i][alive];
|
|
cmp_lists[to].push(alive);
|
|
if (cmp_lists[to].length == cmp_n)
|
|
{
|
|
console.log('node '+to+': tick '+tick);
|
|
in_sync++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
messages_sent += send_what.length*send_to.length;
|
|
}
|
|
avg_known = 0;
|
|
for (let i = 1; i <= total; i++)
|
|
{
|
|
avg_known += cmp_lists[i].length;
|
|
}
|
|
avg_known /= total;
|
|
tick++;
|
|
}
|
|
console.log('tick '+tick+': '+in_sync+' in sync, avg '+avg_known);
|
|
console.log(messages_sent+' messages sent');
|
|
}
|
|
|
|
test();
|