diff --git a/mm.js b/mm.js index 3444ed6..875b392 100755 --- a/mm.js +++ b/mm.js @@ -42,20 +42,37 @@ const AGENT = "Meta Miner " + VERSION; // the multiplier is for supporting hashrate prints in different units // the nr benchmark prints is to make sure hashrate has stabilized before snapping the benchmark value const hashrate_regexes = [ - [1, 1, /\[[^\]]+\] speed 2.5s\/60s\/15m [\d\.]+ ([\d\.]+)\s/], // for old xmrig - [1, 1, /\[[^\]]+\] speed 10s\/60s\/15m [\d\.n/a]+ ([\d\.]+)\s/], // for new xmrig - [1, 1, /\s+miner\s+speed 10s\/60s\/15m [\d\.n/a]+ ([\d\.]+)\s/], // for xmrig v6+ - [1, 1, /Totals \(ALL\):\s+[\d\.]+\s+([1-9]\d*\.\d+|0\.[1-9]\d*)\s/], // xmr-stak - [1, 1, /Total Speed: ([\d\.]+) H\/s,/], // claymore - [1, 1, /\(Avr ([\d\.]+)H\/s\)/], // CryptoDredge - [1e3, 3, /Total[^:]+:\s*([\d\.]+)\s*kh\/s/], // TeamRedMiner variant 1 (kh/s) - [1, 3, /Total[^:]+:\s*([\d\.]+)\s*h\/s/], // TeamRedMiner variant 2 (h/s) - [1, 1, /Mining at\s+([\d\.]+) gps/], // tube4referenceMiner (use mode=rolling command line option) - [1, 1, /mining at\s+([\d\.]+) gps/], // SwapReferenceMiner (use mode=rolling command line option) - [1, 2, /Total\s+:\s+([\d\.]+) gps/], // MoneroVMiner - [1, 2, /([\d\.]+) G\/s/], // gminer - [1000000, 2, /([\d\.]+) MH\/s/], // gminer + [1, 1, /\[[^\]]+\] speed 2.5s\/60s\/15m [\d\.]+ ([\d\.]+)\s/, 'xmrig old'], + [1, 1, /\[[^\]]+\] speed 10s\/60s\/15m [\d\.n/a]+ ([\d\.]+)\s/, 'xmrig new'], + [1, 1, /\s+miner\s+speed 10s\/60s\/15m [\d\.n/a]+ ([\d\.]+)\s/, 'xmrig v6+'], + [1, 1, /Totals \(ALL\):\s+[\d\.]+\s+([1-9]\d*\.\d+|0\.[1-9]\d*)\s/, 'xmr-stak'], + [1, 1, /Total Speed: ([\d\.]+) H\/s,/, 'claymore'], + [1, 1, /\(Avr ([\d\.]+)H\/s\)/, 'CryptoDredge'], + [1e3, 3, /Total[^:]+:\s*([\d\.]+)\s*kh\/s/, 'TeamRedMiner variant 1 (kh/s)'], + [1, 3, /Total[^:]+:\s*([\d\.]+)\s*h\/s/, 'TeamRedMiner variant 2 (h/s)'], + [1, 1, /Mining at\s+([\d\.]+) gps/, 'tube4referenceMiner (use mode=rolling command line option)'], + [1, 1, /mining at\s+([\d\.]+) gps/, 'SwapReferenceMiner (use mode=rolling command line option)'], + [1, 2, /Total\s+:\s+([\d\.]+) gps/, 'MoneroVMiner'], + [1, 2, /^\|.*[^\d\.]([\d\.]+) G\/s.*\|$/, 'gminer (gh/s)'], + [1e6, 2, /^\|.*[^\d\.]([\d\.]+) M\/s.*\|$/, 'gminer (mh/s)'], + [1, 2, /^ethminer .* ([\d\.]+) h - /, 'ethminer (h/s)'], + [1e3, 2, /^ethminer .* ([\d\.]+) Kh - /, 'ethminer (kh/s)'], + [1e6, 2, /^ethminer .* ([\d\.]+) Mh - /, 'ethminer (mh/s)'], + [1e9, 2, /^ethminer .* ([\d\.]+) Gh - /, 'ethminer (gh/s)'], + [1, 2, /^GPU #\d+: .* - ([\d\.]+) H\/s/, 'T-Rex (h/s)'], + [1e3, 2, /^GPU #\d+: .* - ([\d\.]+) KH\/s/, 'T-Rex (kh/s)'], + [1e6, 2, /^GPU #\d+: .* - ([\d\.]+) MH\/s/, 'T-Rex (mh/s)'], + [1e9, 2, /^GPU #\d+: .* - ([\d\.]+) GH\/s/, 'T-Rex (gh/s)'], + [1, 2, /^Average speed \(30s\): ([\d\.]+) h\/s/, 'lolMiner (h/s)'], + [1e3, 2, /^Average speed \(30s\): ([\d\.]+) kh\/s/, 'lolMiner (kh/s)'], + [1e6, 2, /^Average speed \(30s\): ([\d\.]+) mh\/s/, 'lolMiner (mh/s)'], + [1e9, 2, /^Average speed \(30s\): ([\d\.]+) gh\/s/, 'lolMiner (gh/s)'], + [1, 2, /^Eth speed: ([\d\.]+) H\/s, shares:.*time:/, 'PhoenixMiner (h/s)'], + [1e3, 2, /^Eth speed: ([\d\.]+) KH\/s, shares:.*time:/, 'PhoenixMiner (kh/s)'], + [1e6, 2, /^Eth speed: ([\d\.]+) MH\/s, shares:.*time:/, 'PhoenixMiner (mh/s)'], + [1e9, 2, /^Eth speed: ([\d\.]+) GH\/s, shares:.*time:/, 'PhoenixMiner (gh/s)'], ]; +const hashrate_per_gpu = [] function algo_hashrate_factor(algo) { switch (algo) { @@ -452,10 +469,10 @@ function start_miner_raw(exe, args, out_cb) { let proc = child_process.spawn(exe, args, is_miner_stdin ? {stdio: ['inherit', 'pipe', 'pipe']} : {}); proc.stdout.on('data', (data) => { - if (out_cb) out_cb(`${data}`); + if (out_cb) out_cb(data.toString()); }); proc.stderr.on('data', (data) => { - if (out_cb) out_cb(`${data}`); + if (out_cb) out_cb(data.toString()); }); proc.on('close', (code) => { if (is_verbose_mode) { @@ -841,15 +858,15 @@ function do_miner_perf_runs(cb) { jsonrpc: "2.0", method: "mining.set_difficulty", params: [ - 1000000 + 10.24 ], }) + "\n" + JSON.stringify({ jsonrpc: "2.0", method: "mining.notify", params: [ "benchmark1", // job_id - "e79f0f63030bf691445c2b9d0266b24a9619e355194067f2ad2c73a8e0a26c65", // seed hash - "feb4243b885cd1af5337979f5d81849335cab197b4993e5c61ea4b43b43dbbc6", // hash + "ffaad0781cfec93fee66657ef8a9f132f422becba3626b5d936ad3cb1f8228d4", // seed hash + "a917c993b27e4a15c6ed3611bcaa7e5eee5c9b984053f6c1270032c0c4d6dc83", // hash true, ] }) + "\n"); @@ -900,27 +917,47 @@ function do_miner_perf_runs(cb) { }; let nr_prints_needed = -1; let nr_prints_found = 0; - miner_proc = start_miner(cmd, function(str) { - print_messages(str); - str = str.replace(/\x1b\[[0-9;]*m/g, ""); // remove all colors - for (let i in hashrate_regexes) { - const hashrate_regex = hashrate_regexes[i]; - const m = str.match(hashrate_regex[2]); - if (m) { - if (nr_prints_needed < 0) nr_prints_needed = hashrate_regex[1]; - const hashrate = parseFloat(m[1]) * hashrate_regex[0] * algo_hashrate_factor(algo); - if (++nr_prints_found >= nr_prints_needed) { - const algo_deps = bench_algo_deps(algo, hashrate); - for (let algo_dep in algo_deps) { - log("Setting performance for " + algo_dep + " algo to " + algo_deps[algo_dep]); - c.algo_perf[algo_dep] = algo_deps[algo_dep]; + let chunk_leftover = ''; + miner_proc = start_miner(cmd, function(chunk) { + chunk = [chunk_leftover, chunk].join('') + const buf_size = chunk.lastIndexOf('\n'); + chunk_leftover = chunk.slice(chunk, buf_size); + const eol = `\x1b[0m\n`; + let hashrate_prev = 0; + let line = 0; + processing: + for (let str of chunk.split('\n')) { + print_messages(`${line++}: ${str}${eol}`); + str = str.replace(/\x1b\[[0-9;]*m/g, ""); // remove all colors + for (let i in hashrate_regexes) { + const hashrate_regex = hashrate_regexes[i]; + const m = str.match(hashrate_regex[2]); + if (m) { + if (nr_prints_needed < 0) nr_prints_needed = hashrate_regex[1]; + const hashrate_raw = parseFloat(m[1]); + if (hashrate_raw > 0) { + const hashrate = hashrate_raw * hashrate_regex[0] * algo_hashrate_factor(algo); + const variance = hashrate_prev / hashrate; + const variance_good = (variance > 0.98 && variance < 1.02); + if (variance_good > 0.9 && ++nr_prints_found >= nr_prints_needed) { + const algo_deps = bench_algo_deps(algo, hashrate); + for (let algo_dep in algo_deps) { + log("Setting performance for " + algo_dep + " algo to " + algo_deps[algo_dep]); + c.algo_perf[algo_dep] = algo_deps[algo_dep]; + } + miner_proc.on('close', (code) => { clearTimeout(timeout); resolve(); }); + tree_kill(miner_proc.pid); + break processing; + } else { + let msg = "Read"; + if (!variance_good) { + msg = "Skip"; + } + log(msg + " performance for " + algo + " algo of " + hashrate + ", waiting for " + + (nr_prints_needed - nr_prints_found) + " more print(s)."); + } + hashrate_prev = hashrate } - miner_proc.on('close', (code) => { clearTimeout(timeout); resolve(); }); - tree_kill(miner_proc.pid); - break; - } else { - log("Read performance for " + algo + " algo to " + hashrate + ", waiting for " + - (nr_prints_needed - nr_prints_found) + " more print(s)."); } } }