Documentation says flutter is single threaded even the asynchronous task is executed on the same thread which means that while we wait for another task to be completed, we will continue executing our synchronous code. But I have a situation where i need to process on multiple images, and process on each image takes approx 1.5 secconds. Sample code for this is below
for(var image in images){
processOnImage(image);
}
processOnImage(var image){
// it takes approx 1.5 secconds
}
So in above script if i have 20 images then it takes approx 30 seccond, which is too high in my case.
So I want to know that is there any way to start multithreading to reduce time consumption, like below
for(var image in images){
startNewThread processOnImage(image);
}
processOnImage(var image){
// it takes approx 1.5 secconds
}
You should read the dart docs.
https://dart.dev/guides/language/concurrency
Dart supports concurrent programming
for(var image in images){
processOnImage(image);
}
procesOnImage(var image){
var receive = ReceivePort();
Isolate.spawn(yourFunctionToRun, receive.sendPort);
}
Related
So my understanding is, any blocking file system operation (such as fs.readFileSync) is eventually delegated to one of the thread in thread pool to keep event loop free. Now, I am running my application from windows and the command i am using, set UV_THREADPOOL_SIZE=4 & node index.js
My sample code below,
const start = new Date().getTime();
readFile();
readFile();
readFile();
readFile();
readFile();
function readFile() {
fs.readFileSync('./content/1.txt');
const end = new Date().getTime();
console.log('Time took: ', (end - start) / 1000);
}
Now no matter whether I set the thread pool size to one or four, the execution time remains almost same. FYI, there are two CPU cores in my PC. Therefore my expectation was, if I set thread pool size to four (or let the default settings work) out of my 5 function call to read the file, say first four takes x secs (I understand it won't be the exact time for both call but going to be very close), then the last one (x+n), where x & n are random numbers and represents time difference in seconds.
But that's not happening. Irrespective of the number of thread pool calls are taking same time to complete and getting completed one by one.
So, looks like my understanding about how node.js thread pool works is not right. Any help would be appreciated. Thanks.
The first issue is that you're using fs.readFileSync(). That means your file operations are only going to be requested one at a time. The 2nd one won't start until the first one is done. This has nothing to do with the thread pool. This is because you're using the blocking, synchronous version of readFile(). The JS interpreter will be blocked until the first fs.readFileSync() is done and the second one only gets to start after the first one is done and so on. So, because of that, in this case it won't really matter how many threads there are to serve the file system.
If you want to engage more than one thread in file operations, you need to use asynchronous file operations like fs.readFile() so you can have more than one file operation in flight at the same time and thus have more of an opportunity to use more than one thread.
Also, file operations on the same disk are not as scalable with multiple threads/CPUs as some other types of operations because the read/write heads can only be in one place at a time so even if you do change the code to successfully engage multiple threads or CPUs you can't get full parallel file access on the same drive due to the serialization of the read/write head position.
Here's an example of a test using the asynchronous fs.readFile():
const start = new Date().getTime();
let cntr = 0;
readFile(0);
readFile(1);
readFile(2);
readFile(3);
readFile(4);
function readFile(i) {
fs.readFile('./content/1.txt', function(err, data) {
if (err) {
console.log(err);
return;
}
const end = new Date().getTime();
console.log(`Time took: ${i} ${(end - start) / 1000}`)
if (++cntr === 5) {
console.log(`All Done. Total time: ${(end - start) / 1000)}`;
}
});
}
This test would likely be more meaningful if you read a different file (that wasn't already in the OS file cache) for each call to readFile(). As it is the 2-5 requests are likely just fetching data from memory in the OS file cache, not actually accessing the disk.
I am trying to read an image manipulate the pixel data(Gaussian or any other) and write the pixels to a new image.Since the images come in big sizes(>1GB and may even be >20 GB),I read them one row at at time with whole width.So it becomes block wise reading.Now my work requires a faster mechanism to do the whole process.Will thread pool work as an effective solution.I cannot use other libraries for image processing,we have an engine built for that.
I have referred to a sample threadpool sample from code project and I am reading the image in the thread's run function but I am really not sure how it works.
HRESULT hRes = m_ObjPool.Init(10, 100); //spawning the thread
void CThreadObject::Run(CThreadPoolThreadCallback &pool)
{
//I read and write my image here using for loop
for(int i=0;i<nImageHeight;++i)
{
for(int j=0;j<nImageWidth;j++)
{
Engine.ReadImage(params);
}
}
}
What I was trying to achieve here is how do I give tasks to thread pool if the image is segmented into 10 or 100 parts(depending on the image size and block size).
I have a server-client based NODE.JS application.
server.js
...
socket.on('message', function(message) {
if(message.code == 103)
{
process_some_data()
}
else
{
console.log("UNKNOWN MESSAGE");
}
});
...
client.js
.. sending responses back to server.js
the process_some_data() function takes about 4 seconds to complete, and when i have just one client it is not a problem, but if i have 10, they all choke and wait till the the last finishes.
I found out that the entire socket event waits till he finishes the current job, for example if i comment process_some_data(), it will not be frozen
I have tried 2 tweaks but the didn't worked :
...
socket.on('message', function(message) {
if(message.code == 103)
{
setTimeout(function() {
process_some_data();
console.log("FINISH");
}, 1)
}
else
{
console.log("UNKNOWN MESSAGE");
}
});
...
And even used http://caolan.github.io/async/ ,but no use :
...
socket.on('message', function(message) {
if(message.code == 103)
{
// Array to hold async tasks
var asyncTasks = [];
async.series([
setTimeout(function() {
process_some_data();
console.log("FINISH");
}, 1)
], function (err, results) {
console.log(results);
});
}
else
{
console.log("UNKNOWN MESSAGE");
}
});
...
How to make this ASYNC? Really need this.
Thank you.
You need multiple processes to solve this with Javascript, because Javascript engines are single-threaded.
What?
When it comes to handling I/O events, such as reading a socket, writing to a file or waiting for a signal, Javascript engines give the appearance of doing multiple things at the same time.
They are actually not: it's just that, under most conditions, processing these events takes so little computation, and the events themselves occur with so much time in between (a microsecond is an eternity for a CPU), that the engine can just process them one after another with plenty of time to spare.
In human time-scale, it looks like the engine is doing a lot of stuff in parallel, but it's just working serially at great speed.
No matter how you schedule your code to run, using setTimeout or Promise, it will still block other events from being processed during the time it's actively computing. Long-running computations (in the scale of seconds, instead of milliseconds) expose the single-threaded nature of the engine: it cannot actually do multiple things at the same time.
Multiple processes
Your computer, however, probably has multiple CPU cores. Unlike the Javascript engine, your hardware is capable of tackling multiple tasks at the same time, at least 1 per core. Even with a single core, your operating system can solve the problem if you run multiple processes.
Since a single Javascript process is single-threaded, you need multiple Javascript processes for this. An easy and time-proven architecture to solve your problem is this:
One Javascript program, running in one process, reads from the socket. Instead of calling process_some_data(), however, it puts all incoming messages in a queue.
This program then sends items from the queue to another Javascript program, running in a different process, that performs the computation using another CPU core. There may be multiple copies of this second process. In a modern computer, it makes sense to have twice as many active processes as you have CPU cores.
A simple approach for Node is to write an HTTP server, using express, that runs the computationally-intensive task. The main program can then use HTTP to delegate tasks to the workers, while still being able to read from the socket.
This is a good article on the topic of multi-processing with Node, using the cluster API.
I have an array of fs.writeFile png jobs with the png headers already removed like so
canvas.toDataURL().replace(/^data:image\/\w+;base64,/,"")
jobs array like this
jobs=[['location0/file0'],['location1/file1'],['location2/file2'],['location3/file3']];
I have just started to use async and was looking at their docs and there are lots of methods
queue looks interesting and parallel..
Right now I handle my jobs (in a async.waterfall) like so
function(callback){//part of waterfall
(function fswritefile(){
if(jobs.length!==0){
var job=jobs.shift();
fs.writeFile(job[0],(new Buffer(job[1],'base64')),function(e){if(e){console.log(e);}else{fswritefile();}})
}
else{callback();}
})();
},//end of waterfall part
Could this be done more efficiently/faster using this module?
async.waterfall will process jobs sequentially. I think you could do everything in parallel with async.each:
async.each(jobs, function (job, done) {
var data = new Buffer(job[1],'base64');
fs.writeFile(job[0], data, done);
}, function (err) {
// …
});
All jobs will start everything in parallel. However, node.js always limits the number of concurrent operations on the disk to 4.
EDIT: No matter what you do, node.js will limit the number of concurrent operations on the fs. The main reason is that you have only have 1 disk and it would be inefficient to attempt more.
I have a database of items that I need to update — or rather just perform upon — every so often. I am using a message queue (Kue) to handle the concurrency of these jobs, but my process which goes about adding the jobs to the queue looks like this:
setInterval(function () {
feed.find({}, function (error, foundModels) {
jobs.create('update feeds', {
feeds: foundModels
}).save()
})
}, 6000)
Is polling like this the best way to add the jobs to the queue, do you think? Or should each feed be on its own timer (for example every job will spawn another job 6 afters after it's finished)?
I usually do it the way you've done it. In your case, it always pushes jobs at 6 second intervals. This is fine so long as your jobs don't take more than 6 seconds. If your jobs take more than 6 seconds then you'll start to get a backlog and you'll need to increase resources to handle the larger load. It can be a problem if resource usage spikes and you're not around to adjust for the spike and you don't have automated processes in place (you should).
The alternative is to only call your function 6 seconds after the last call returns. You'd do that like so:
function update() {
feed.find({}, function (error, foundModels) {
jobs.create('update feeds', {
feeds: foundModels
}).save(function() {
setTimeout(update,6000);
});
});
}
setTimeout(update, 6000);
I made the assumption that your .save method takes a callback like all good asynchronous libraries do. :-)