diff --git a/README.md b/README.md index febd3ffb..336915e8 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ **GUN** is an _ecosystem_ of tools that let you build tomorrow's dApps, today. -Decentralized alternatives to [Reddit](https://notabug.io/), [YouTube](https://d.tube/), [Wikipedia](https://news.ycombinator.com/item?id=17685682), etc. are already pushing terabytes of daily P2P traffic on GUN. We are a [friendly community](https://gitter.im/amark/gun) creating a free fun future for freedom: +Decentralized alternatives to [Reddit](https://notabug.io/t/whatever/comments/36588a16b9008da4e3f15663c2225e949eca4a15/gpu-bot-test), [YouTube](https://d.tube/), [Wikipedia](https://news.ycombinator.com/item?id=17685682), etc. are already pushing terabytes of daily P2P traffic on GUN. We are a [friendly community](https://gitter.im/amark/gun) creating a free fun future for freedom: diff --git a/lib/les.js b/lib/les.js new file mode 100644 index 00000000..e6f3cb16 --- /dev/null +++ b/lib/les.js @@ -0,0 +1,121 @@ +; +(function() { + + // _ _____ ____ _ + // | | | ____/ ___| (_)___ + // | | | _| \___ \ | / __| + // | |___| |___ ___) | | \__ \ + // |_____|_____|____(_)/ |___/ + // ---------------------------- + // LES.js (Last rEcently uSed) + // ---------------------------- + // A Small, lightweight, queue-based + // Garbage Collector for Gun + // Originally By: Collin Conrad (@masterex1000) + + //NOTE: set to false is running from file in YOUR code + var USELOCALGUN = true; + + //NOTE: adds some debug messages + var DEBUG = false; + + + var Gun = (typeof window !== "undefined") ? window.Gun : (USELOCALGUN ? require('../gun') : require("gun")); + var ev = {}; + var empty = {}; + + Gun.on('opt', function(root) { + this.to.next(root); + if (root.once) + return; + if (typeof process == 'undefined') + return + var mem = process.memoryUsage; + + if (!mem) //exit because we are in the browser + return; + + //Figure out the most amount of memory we can use. TODO: make configurable? + ev.max = parseFloat(root.opt.memory || process.env.WEB_MEMORY || 512) * 0.8; + + var nodes = {}; //checks if the node already exists + var nodesArray = []; //used to easily sort everything and store info about the nodes + var memoryUpdate = 0; // last time we printed the current memory stats + + var check = function() { + ev.used = mem().rss / 1024 / 1024; //Contains the amt. of used ram in MB + setTimeout(function() { // So we can handle requests etc. before we start collecting + GC(ev.used / ev.max); // Calculate the memory ratio, and execute the garbage collector + }, 1); + } + + setInterval(check, 1000); // set the garbage collector to run every second, TODO: make configurable + + //Executed every time a node gets modifyed + root.on("put", function(e) { + var ctime = Date.now(); + var souls = Object.keys(e.put || empty); + for (var i = 0; i < souls.length; i++) { + enqueueNode(souls[i], ctime); + } + }); + + //Adds a soul the garbage collectors "freeing" queue + function enqueueNode(soul, ctime) { + if (nodes[soul] == true) { //The node already exists in the queue + var index = nodesArray.findIndex(function(e) { + return e[0] === soul; + }); + if (index == -1) { + console.err("Something happened and the node '" + soul + "' won't get garbage collection unless the value is updated agian"); + return; + } else { + nodesArray.splice(index, 1); // remove the existing ref. + nodesArray.push([soul, ctime]); // push the new instance + } + } else { + nodesArray.push([soul, ctime]); + nodes[soul] = true; + } + } + + //The main garbage collecting routine + function GC(memRatio) { + var curTime = Date.now(); // get the current time + + if (curTime - memoryUpdate >= 5000) { + console.log("|GC| %s | Current Memory Ratio: %d | Current Ram Usage %sMB | Nodes in Memory %s", new Date().toLocaleString(), round(memRatio, 2), round(ev.used, 2), Object.keys(root.graph || empty).length); + memoryUpdate = curTime; + } + + var freed = 0; + + while (nodesArray.length > 0) { + var soul = nodesArray[0][0]; + var nts = nodesArray[0][1]; + if (DEBUG) + console.log("Soul: " + soul + " | Remove Importance: " + calcRemoveImportance(nts, curTime, memRatio) + + " | Memory Ratio: " + memRatio + " | Time Existed: " + (curTime - nts) / 1000); + if (calcRemoveImportance(nodesArray[0][1], curTime, memRatio) >= 100) { + root.gun.get(nodesArray[0][0]).off(); //Remove the node + delete nodes[nodesArray[0][0]]; // remove the lookup value + nodesArray.splice(0, 1); + freed++; + } else + break; + } + if (freed > 0) + console.log("|GC| Removed %s nodes in %s seconds-----------------------------------------------------------------", freed, (Date.now() - curTime) * 0.001); + } + + //Generates a number that, after it hits a threshold, the node gets removed + function calcRemoveImportance(timestamp, ctime, memoryUsageRatio) { + var time = (ctime - timestamp) * 0.001; + return time * 10 * (memoryUsageRatio * memoryUsageRatio) + } + + function round(value, decimals) { //a basic rounding function + return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals); + } + }); +}()); \ No newline at end of file diff --git a/nts.js b/nts.js index 91f9d63d..e8a491c7 100644 --- a/nts.js +++ b/nts.js @@ -37,8 +37,8 @@ NTS.end = Gun.state(); Gun.obj.del(ask, ack); NTS.latency = (NTS.end - NTS.start)/2; - if(!at.NTS){ return } - NTS.calc = NTS.latency + at.NTS; + if(!at.nts && !at.NTS){ return } + NTS.calc = NTS.latency + (at.NTS || at.nts); Gun.state.drift -= (NTS.end - NTS.calc)/2; setTimeout(ping, 1000); } diff --git a/sea.js b/sea.js index d3b58f82..7c08fc81 100644 --- a/sea.js +++ b/sea.js @@ -267,7 +267,7 @@ // This internal func returns SHA-1 hashed data for KeyID generation const __shim = USE('./shim') const subtle = __shim.subtle - const ossl = __shim.ossl ? __shim.__ossl : subtle + const ossl = __shim.ossl ? __shim.ossl : subtle const sha1hash = (b) => ossl.digest({name: 'SHA-1'}, new ArrayBuffer(b)) module.exports = sha1hash })(USE, './sha1'); @@ -625,7 +625,7 @@ try { // base64('base64(x):base64(y)') => Buffer(xy) const pb = Buffer.concat( - Buffer.from(pub, 'base64').toString('utf8').split(':') + pub.replace(/-/g, '+').replace(/_/g, '/').split('.') .map((t) => Buffer.from(t, 'base64')) ) // id is PGPv4 compliant raw key diff --git a/sea/index.js b/sea/index.js index 52ec5f38..80a5d26f 100644 --- a/sea/index.js +++ b/sea/index.js @@ -62,7 +62,7 @@ // if there is a request to read data from us, then... var soul = msg.get['#']; if(soul){ // for now, only allow direct IDs to be read. - if(soul !== 'string'){ return to.next(msg) } // do not handle lexical cursors. + if(typeof soul !== 'string'){ return to.next(msg) } // do not handle lexical cursors. if('alias' === soul){ // Allow reading the list of usernames/aliases in the system? return to.next(msg); // yes. } else @@ -226,4 +226,4 @@ to.next(msg); // pass forward any data we do not know how to handle or process (this allows custom security protocols). } - \ No newline at end of file + diff --git a/sea/sea.js b/sea/sea.js index f85b9a3b..77032638 100644 --- a/sea/sea.js +++ b/sea/sea.js @@ -49,7 +49,7 @@ try { // base64('base64(x):base64(y)') => Buffer(xy) const pb = Buffer.concat( - Buffer.from(pub, 'base64').toString('utf8').split(':') + pub.replace(/-/g, '+').replace(/_/g, '/').split('.') .map((t) => Buffer.from(t, 'base64')) ) // id is PGPv4 compliant raw key diff --git a/sea/sha1.js b/sea/sha1.js index c18ba691..9272cffc 100644 --- a/sea/sha1.js +++ b/sea/sha1.js @@ -2,7 +2,7 @@ // This internal func returns SHA-1 hashed data for KeyID generation const __shim = require('./shim') const subtle = __shim.subtle - const ossl = __shim.ossl ? __shim.__ossl : subtle + const ossl = __shim.ossl ? __shim.ossl : subtle const sha1hash = (b) => ossl.digest({name: 'SHA-1'}, new ArrayBuffer(b)) module.exports = sha1hash \ No newline at end of file diff --git a/test/sea/sea.html b/test/sea/sea.html index 82c16de7..72aaea9e 100644 --- a/test/sea/sea.html +++ b/test/sea/sea.html @@ -1,6 +1,6 @@ - - - + + +