Measure memory usage when algorithm is running - javascript

I have app witch visualize sorting alogrith i want to show user how much memory used each one of them when was runned it should be done on button click my stack is typescript and d3.js . I use Vite.js for building the app.
This is the button click code so far
let sortingInProgress = false
let timeInfo = '0.00 s'
const sortingPromise = new Promise<void>(resolve => {
START_BUTTON.addEventListener('click', async () => {
if (sortingInProgress) {
console.log('stoped')
return
}
sortingInProgress = true
START_BUTTON.disabled = true
SELECT_DATA_SIZE.disabled = true
SELECT_SORTING_ALGORITHM.disabled = true
const startTime = performance.now()
const sort = SelectAlgorithm(data, algorithmType)
await sort(updateBars)
const endTime = performance.now()
const totalTime = ((endTime - startTime) / 1000).toFixed(2) // get alogrithm running time in seconds
console.log(totalTime)
timeInfo = `${totalTime} s`
resolve()
})
})
sortingPromise.then(() => {
svg.selectAll('rect').style('fill', 'black')
sortingInProgress = false
SELECT_DATA_SIZE.disabled = false
SELECT_SORTING_ALGORITHM.disabled = false
SORT_TIME.textContent = timeInfo
})

Related

Make JS function output while function running

Javascript code
function sleep(milliseconds) {
const date = Date.now();
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
window.CP.PenTimer.MAX_TIME_IN_LOOP_WO_EXIT = 1000000;
var money = 0
var i = 0
let dollars = document.getElementById("total")
let dollarclick = document.getElementById("click1")
let autoclick = document.getElementById("buyauto")
dollarclick.addEventListener("click", clicked)
autoclick.addEventListener("click", auto)
function clicked() {
money = money + 1
dollars.innerHTML = "$"+ money.toString()
}
function auto() {
autoclick.disabled = true
console.log("function skull")
while (i<10) {
money = money + 1
dollars.innerHTML = "$"+ money.toString()
sleep(1000)
console.log(money)
i++
}
}
How to make the function output while it is running, and not let it output after the function is already finished? Keep in mind I am making a cookie clicker type game, with the auto being able to be purchased only once. Can you help me resolve this problem? The game should be able to give the points every second, and not after the function has finished. Please help me, thank you!
You can do this in an asynchronous manner.
I have used a function (setTimeoutAsync from #3 here) that resolves a promise after a timeout, and an asynchronous recursive function (nClicks(n)) that uses await for the timeout before performing the action and awaits recursion n times before returning.
Then, the asynchronous event handler just needs to disable the button and wait for nClicks(10) to complete before doing other stuff like re-enabling the button. If you don't need to do other stuff afterwards you can omit the async declaration on the handler and just call nClicks(10) without await.
const setTimeoutAsync = function(timeout) {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
}, timeout)
})
}
let money = 0
const dollars = document.getElementById('total')
const tick = () => {
dollars.innerHTML = `$${++money}`
console.log('tick', dollars.innerHTML)
}
const nClicks = async(n) => {
if (n) {
// wait one second
await setTimeoutAsync(1000)
// then incriment
tick()
// wait for recursion to complete
await nClicks(--n)
}
}
const dollarclick = document.getElementById('click1')
const autoclick = document.getElementById('buyauto')
dollarclick.addEventListener('click', tick)
autoclick.addEventListener('click', async() => {
autoclick.disabled = true
// wait for 10 cycles
await nClicks(10)
autoclick.disabled = false
})
const autoclickOnce = document.getElementById('buyautoOnce')
autoclickOnce.addEventListener('click', () => {
autoclickOnce.disabled = true
nClicks(10)
})
<h1 id="total">$0</h1>
<button id="click1">+1</button>
<button id="buyauto">Auto</button>
<button id="buyautoOnce">Auto Once</button>

Deleting old data in Realtime database using cloud functions

I have been struggling for a very long time to achieve deleting old data in the realtime database using cloud functions. What am I doing wrong?
I want to delete data that's older than 2 hours every 60 minutes.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
'use strict';
const CUT_OFF_TIME = 2 * 60 * 60 * 1000; // 2 Hours in milliseconds.
exports.deleteOldItems = functions.pubsub.schedule('every 60 minutes').onRun(async context => {
admin.database().ref('/').once('value', async (data) => {
var ref = data.val();
const now = Date.now();
const cutoff = now - CUT_OFF_TIME;
const oldItemsQuery = ref.orderByChild('timestamp').endAt(cutoff);
const snapshot = await oldItemsQuery.once('value');
// create a map with all children that need to be removed
const updates = {};
snapshot.forEach(child => {
updates[child.key] = null;
});
return ref.update(updates);
});
});
I didn't check your code for the query based on the cutoff, but we can already see that
var ref = data.val();
//...
const oldItemsQuery = ref.orderByChild('timestamp').endAt(cutoff);
//...
return ref.update(updates);
cannot work because data.val() is not a Reference.
You should adapt your code as follows (untested):
exports.deleteOldItems = functions.pubsub.schedule('every 60 minutes').onRun(async (context) => {
const ref = admin.database().ref();
const now = Date.now();
const cutoff = now - CUT_OFF_TIME;
const oldItemsQuery = ref.orderByChild('timestamp').endAt(cutoff);
const snapshot = await oldItemsQuery.get();
// create a map with all children that need to be removed
const updates = {};
snapshot.forEach(child => {
updates[child.key] = null;
});
return ref.update(updates);
});

Is it possible to combine console.timeEnd() and console.debug()?

I would like to measure time in browser javascript.
I use console.log(), console.debug() ...etc.
But console.timeEnd() behavior is similar to console.log(). It's wrote to console in case of "log" switch is on in browser's JS-Console.
I need to write time to console only if debug messages has switched on in browser.
Is it possible somehow?
There's nothing built in that will do that for you, but it's very easy to implement it yourself: Maintain a Map of labels to start times, and use Date.now() or performance.now() to get the start and end times.
Very roughly:
const debugTimeMap = new Map();
const debugTime = label => {
if (debugTimeMap.has(label)) {
console.warn(`Timer '${label}' already exists`);
} else {
debugTimeMap.set(label, Date.now());
}
};
const debugTimeEnd = label => {
const start = debugTimeMap.get(label);
if (start === undefined) {
console.warn(`Invalid debugTime label "${label}"`);
} else {
debugTimeMap.delete(label);
console.debug(`${label}: ${Date.now() - start} ms`);
}
};
const debugTimeMap = new Map();
const debugTime = label => {
if (debugTimeMap.has(label)) {
console.warn(`Timer '${label}' already exists`);
} else {
debugTimeMap.set(label, Date.now());
}
};
const debugTimeEnd = label => {
const start = debugTimeMap.get(label);
if (start === undefined) {
console.warn(`Invalid debugTime label "${label}"`);
} else {
debugTimeMap.delete(label);
console.debug(`${label}: ${Date.now() - start} ms`);
}
};
debugTime("x");
setTimeout(() => {
debugTimeEnd("x");
}, Math.floor(Math.random() * 1000));
(Look in the real console, and don't forget to turn on debug output in the console.)

Javascript : Call function and wait seconds then

I feel stupid because I do not find what I want to do...
It is in PURE Javascript.
I wan't to call a function, and stop it (or kill it, or whatever) next some seconds.
Here is my actual code :
function scrollThumbnails() {
const thumbnails = document.querySelectorAll('.thumbnail');
for (thumbnail of thumbnails) {
thumbnail.classList.add('active');
await verticalSlider(thumbnail);
resetSliderPosition(thumbnail);
thumbnail.classList.remove('active');
}
scrollThumbnails();
}
async function verticalSlider(element) {
const slider = element.querySelector('.vertical-carrousel');
const max = slider.offsetHeight - slider.parentElement.offsetHeight;
var toTop = 0;
while (toTop > -max) {
await new Promise((resolve) => setTimeout(resolve, 50));
toTop--;
slider.style.top = toTop + 'px';
}
await new Promise((resolve) => setTimeout(resolve, 1000));
}
function resetSliderPosition(element) {
const slider = element.querySelector('.vertical-carrousel');
slider.style.removeProperty('top');
}
So here, i want to call 'verticalSlider' in my loop, but if it is over than 45 seconds, I want to stop it and go on the next thumbnail.
Is it possible ? Do I miss something ?
Thanks by advanced :)
This is simple example without async and await with manual timeout counter implementation.
// Function, which accepts time out value in seconds (counting from 0)
const myFunct = (timeOutSec) => {
// Get current time
const ct = Date.now();
// Set counter for example function logic
let secCounter = ct - 1000;
// Start eternal loop
while(true) {
// Get in loop time
const ilt = Date.now();
// Compare current time and in loop time
// If current time + timeout sec < in loop time, break it
if(ct + timeOutSec * 1000 < ilt) break;
// Here do main function logic in loop
// for example, console log each second
if(ilt - secCounter > 1000) {
console.log(`time ${ilt}`);
secCounter += 1000;
}
}
}
// Test running function for 4 sec
myFunct(3);
console.log(`Completed at ${Date.now()}`);
Or similar with promises
// Async timeout function
const timeout = (ms) => new Promise(resolve => setTimeout(resolve, ms));
// Promise function which accepts timout value in seconds (counting from 0)
const myPFunct = (timeOutSec) => {
return new Promise(async (resolve, reject) => {
// Current time
const ct = Date.now();
// start eternal loop
while(true) {
// In loop time
const ilt = Date.now();
// Check in-loop time, current time and timeout
if(ct + timeOutSec * 1000 < ilt) {
resolve(`completed at ${ilt}`);
break;
}
// Do something
console.log(`time: ${ilt}`);
// Wait 1 sec
await timeout(1000);
}
});
}
// Test async function
const test = async () => {
// Run myPFunct for 4 sec
const result = await myPFunct(3);
console.log(`Test function result: ${result}`);
}
// Run test function
test();
Thanks to #tarkh solution.
If someone try to do an horizontal slider like me, or something with loop, I have to modify the code (because with the source solution, the resolve goes up to all the async methods).
Here is the final solution (I have to name the loop to break it and resolve the current promise - there are maybe simplest solution ?) :
window.onload = function () {
scrollThumbnails();
}
const scrollThumbnails = async () => {
const thumbnails = document.querySelectorAll('.thumbnail');
for (thumbnail of thumbnails) {
thumbnail.classList.add('active');
await verticalSliderWithTimeout(thumbnail, 45000);
thumbnail.classList.remove('active');
}
scrollThumbnails();
}
const timeout = (ms) => new Promise(resolve => setTimeout(resolve, ms));
const verticalSliderWithTimeout = (element, timeoutDelay) => {
return new Promise(async (resolve, reject) => {
const currentTime = Date.now();
const slider = element.querySelector('.vertical-carrousel');
const max = slider.offsetHeight - slider.parentElement.offsetHeight;
var toTop = 0;
slider.style.top = toTop + 'px';
sliderLoop: while (toTop > -max) {
const inLoopTime = Date.now();
if(currentTime + timeoutDelay < inLoopTime) {
break sliderLoop;
}
await timeout(50);
toTop--;
slider.style.top = toTop + 'px';
}
resolve();
});
}
HTML code if needed (Handlebars) :
<div class="thumbnail">
<div class="photos-slider">
<div id="vertical-carrousel" class="vertical-carrousel">
{{#each this.photos}}
<img src="/image/{{../this.agency.product_type}}/{{../this.agency.id}}/{{../this.reference}}/{{urlencode this}}"
onerror="{{this}}" />
{{/each}}
</div>
</div>
</div>

How do I switch the running codes using the IF?

Bear with me, I just started learning JS yesterday trying to make a HTML clock by putting multiple tutorials' results together.
I made two looping animations using 2 arrays, with the intent of switching between arrays depending on if it's earlier or later than 8pm. I would like for my code to constantly check if it's 8pm every X amount of seconds, and only re-run the script if the IF result or output is different than what it currently is.
const now = new Date();
if (now.getHours() > 20) { // Time checker!!!!!
var hat = ['A','B','C','D'],
a = -1;
(function f(){
a = (a + 1) % hat.length;
const hatformatted = `${(hat[ a ])}`;
document.querySelector(".main").textContent = hatformatted;
setTimeout(f, 1000);
})();
} else {
var hat = ['1','2','3','4'],
a = -1;
(function f(){
a = (a + 1) % hat.length;
const hatformatted = `${(hat[ a ])}`;
document.querySelector(".main").textContent = hatformatted;
setTimeout(f, 1000);
})();
}
I have tried setInterval however it re-runs the script even if the IF result has not changed, and messes up the animation.
I.E - if it's 6pm, it tries to play the animation from the start every 1 second and the frames get messed up.
Any advice or help would be great, thanks!
I tried to save your code.
const checkTimeDelay = 1000;
let isAbove8PM = null;
let curTimeHandler = null;
let intervalId = null;
// checking if is above 8 pm
const checkTime = () => {
const now = new Date();
if (now.getHours() > 20) {
return true;
}
return false;
};
const above8PMHandler = () => {
var hat = ['A','B','C','D'],
a = -1;
return () => {
a = (a + 1) % hat.length;
const hatformatted = `${(hat[ a ])}`;
document.querySelector(".main").textContent = hatformatted;
// setTimeout(f, 1000);
};
};
const before8PMHandler = () => {
var hat = ['1','2','3','4'],
a = -1;
return () => {
a = (a + 1) % hat.length;
const hatformatted = `${(hat[ a ])}`;
document.querySelector(".main").textContent = hatformatted;
// setTimeout(f, 1000);
};
};
// restart clock interval on based on new handler (above8PMHandler|before8PMHandler)
const rebaseClockInterval = () => {
clearInterval(intervalId);
intervalId = setInterval(curTimeHandler, 1000);
};
// main func, checks if we should change clocks handler (above8PMHandler|before8PMHandler)
const clockTick = () => {
const curTimeChecked = checkTime();
if (curTimeChecked === isAbove8PM) { return; }
isAbove8PM = curTimeChecked;
if (isAbove8PM) {
curTimeHandler = above8PMHandler();
} else {
curTimeHandler = before8PMHandler();
}
curTimeHandler();
rebaseClockInterval();
};
// start main func
setInterval(clockTick, checkTimeDelay);
I also provide some ideas here.
function setClockInterval() {
const hat1 = ['A', 'B', 'C', 'D'];
const hat2 = ['1', '2', '3', '4'];
let prevCheck = null;
let count = 0;
const checker = () => {
return new Date().getSeconds() > 20;
};
const next = () => {
count++;
};
const reset = () => {
count = 0;
};
const render = (content) => {
// console.log(`clockInterval ${content}`); // debug output
document.querySelector(".main").textContent = content;
};
const fn = () => {
const check = checker();
const arr = check ? hat1 : hat2;
// empty arr skip
if (arr.length <= 0)
return;
// restart count to 0
if (prevCheck !== null && prevCheck !== check)
reset();
render(arr[count % arr.length]);
prevCheck = check;
next();
};
return setInterval(fn, 1000);
}
// start interval
const clock = setClockInterval();
// stop
clearInterval(clock);
You can greatly simplify your code by removing everything from inside the if block that is repeated and running it afterward. You also need to get a new Date on each iteration, otherwise the array won't change when it gets to the designated time.
I have changed the condition check to be odd/even seconds to show how it swaps between arrays without losing the index.
// Global, could be kept inside closure
let a = -1;
// Function to run each iteration
(function f() {
// OP code
// let hat = new Date().getHours() > 18? ['A','B','C','D'] : ['1','2','3','4'];
// faster iteration as example
let hat = new Date().getSeconds() % 2? ['A','B','C','D'] :['1','2','3','4'];
a = (a + 1) % hat.length;
document.querySelector(".main").textContent = hat[a];
setTimeout(f, 1000);
})();
<div class="main"></div>

Categories

Resources