Http Example multi threaded somewhere?

Is there any example about how to run 100 threads, each access via socket a website, without that the whole Xojo thing slows down to a crawl? I am trying now since a week, and slowly giving up and intent to go back to Delphi, but I have the hope somebody can guide me in the right direction on how to do that with Xojo.

I had a version with 10 threads going very nicely. Unfortunately, I got some hard crashes. Let me check if I can find this version. Why don’t you use CurlsMulti?

A small part of my Mime Parser: http://www.mothsoftware.com/downloads/socket_queue.zip .

You call the SocketQueue with a list of urls. Error handling doesn’t matter much in the classes. Either the url is there or it isn’t.

Xojo does not have real threads, it is a one thread process with time slicing mimicking threads in a cooperative way, so it means that when some part of the app is doing something, all the other “parallelized” ones are suspended. The way Xojo asks users to handle multiple real “threads” is firing multiple apps (processes) and doing something to sync their jobs after.

[quote=438406:@Beatrix Willius]A small part of my Mime Parser: http://www.mothsoftware.com/downloads/socket_queue.zip .

You call the SocketQueue with a list of urls. Error handling doesn’t matter much in the classes. Either the url is there or it isn’t.[/quote]

Very cool! Thanks a lot, I will take a look at it!

I tried to use CurlsMultiMBS, but even that is way too slow. I guess the missing of a “real” multithreading is causing all my issues and all this slowdown.

the problem is 2 fold. Firstly all the socket data available events will happen in the main thread no matter what. You can then signal a thread to read the data and process it, but some work for each received event is going to happen in the main thread. If they are busy connections that can start to bog down the main thread but it would really take a lot of receptions. The other is what Rick already said. The threads aren’t really taking advantage of the multi processors and such. What I would do, and have done, is to write a background app that does the work of opening the connection and doing most of the processing and just send the final result or the status up to the main app. You can include it in the resources of the app and launch any number of them via a shell class to do all the processing. Each one might be able to handle 10 or 20 or more individual conversations you probably don’t need 100 processes, but even just 10 or so could probably handle that many connections but that gets more complicated to manage.

Wrong
Xojo uses real threads
They are not scheduled preemptively
It happens to schedule them cooperatively
But they are real threads

[quote=438431:@Norman Palardy]Wrong
Xojo uses real threads
They are not scheduled preemptively
It happens to schedule them cooperatively
But they are real threads[/quote]

Semantics. Rick Araujo just dindt want to be technicall. Maybe: “Xojo threadig Is obsolete, al the “real threads” run in a single core, even when multicore processor have being the standar for almost 2 decades now.”

It can be done, but it deppends on the load of your work, is not really advisable to have 100 “real threads” running in a sinlge core. To use Xojo, you have to go with the Oficial xojo recomendation as James Sentman wrote, multiple helpper apps. Maybe 10 instances running with 10 threads, 5/20 or some combination.

[quote=438447:@Ivan Tellez]Semantics. Rick Araujo just dindt want to be technicall. Maybe: “Xojo threading Is obsolete, al the “real threads” run in a single core, even when multicore processor have being the standar for almost 2 decades now.”
[/quote]
Preemptive threading across multiple cores requires a thread safe runtime so it CAN be re-entrant.
None of the frameworks are thread safe or re-entrant to support this.
Making them BE this way would be a significant undertaking that I dont expect will happen.
Helpers are simpler in many ways.
But they are harder to set up in some way because you have to set up a communication mechanism.
You have to think long and hard about WHAT data to move and how to move it.
And you have write the code to move data back and forth.

But you can debug a helper as a single standalone application - you cannot do this with a thread.
You can actually reason quite correctly about the state of a helper - you cant do this well in a preemptive threading environment. (I’d actually say you cannot do it at all but …)

And forcing you to think about moving data back and forth is, IMHO, a good thing. A thread might fool you into thinking that you can safely alter some global state in your app which is a Bad Practice ESP in a preemptively threaded app.

Threads are not the panacea many folks seem to think they are

So the way seems to be to create a console app, starting it multiple times and feeding all the instances somehow with urls for them to process, then get their results back? To tell the truth, that seems to be quite a bit of a chaos in my opinion.

how is it handled with Delphi ?

In Delphi, I will just create 100+ threads, each process urls from a url pool. When a thread is done with a url, it get the next url from as pool. So i can utilize all my cpu cores, and also my bandwidth.

wouldn’t it be better handled with a xojo web app ? and load balancing.

see https://forum.xojo.com/11856-how-many-concurrent-connections/0

[quote=438491:@Jean-Yves Pochez]wouldn’t it be better handled with a xojo web app ? and load balancing.

see https://forum.xojo.com/11856-how-many-concurrent-connections/0[/quote]

How it is better to create multiple apps and create a way to sync them instead of a single app that does all of that better, faster and withe much less effort in coding?

Also, Web apps are meant to be used as a server that receives conections, not to conect to other servers and download data.

I just threw together a quick test. A single window, one button, two HTTPSockets, and a StartTime as Double property on the window. Clicking the button records the StartTime (Microseconds) and directs each socket to download a 100MB file from one of two servers.

On PageReceived each socket reports the download speed in MBps (bytes, not bits). One server is faster than the other so File1 downloads first at about 8 MBps, same as Safari. File2 downloads at about 3 MBps which is a little slower than Xojo or Safari downloading File2 by itself (3.6-3.8 MBps). Can’t blame Xojo’s threading though. 8 MBps is 64 Mbps and my home Internet connection is only about 75 Mbps. Just two Xojo sockets on one core are saturating my Internet connection while both files are downloading.

I can guarantee that 100 threads is not optimum in Delphi, unless you have a 100 core server with many NICs. In fact it should trash performance. Delphi is probably scheduling only as many threads as you have cores. As threads complete more are dispatched until they’re all done. Even with that safety net I imagine one downloader per core is too much and you’re bottlenecking the NIC.

As for Xojo: if it’s running slow then something else is going on. It could be something about how you handle events and what processing you perform. Or it could simply be that you’re attempting to start far too many downloads at once, and Xojo isn’t throttling the number of in flight sockets for you. Very quickly the core becomes preoccupied with thread switching and event dispatching rather than downloading.

If you have a gigabit connection, and if there are many slow servers which combined can saturate it, then maybe Xojo’s single core operation would become a bottleneck. In any other scenario you should be able to saturate the NIC, or come close to it, with Xojo sockets. But that means 2-5 in flight sockets cycling through the URL list. Not 100.

Shure, a SINGLE connection downloading a SINGLE big file from a server dedicated to sending that file. nothing to do with the question.

Downloading hundres or thousands of small files (pages) is much more different… You need to close the conection, create new ones, and that requiere CPU time and a little extra bandwith. Also, most servers, for pages or apis, limit the bandwith of each conection, so if you pretend to download thousands of pages one after the other with “Just two Xojo sockets”, it could take DAYS. (even if the total data is that same 100 mb)

Of course, If you are used to have only one or two long lasting connections, you cant see why something like this needs multicore support.

The idea of syncing together multiple console apps is really not that big a deal. You need some way to communicate between them but that can be a socket, an IPC socket or even STDIN/OUT if you aren’t sending that much data (that is VERY slow for sending larger amounts of data) I would call it almost but not quite trivial. I’ve done it so many times for different things that it doesn’t feel like an insurmountable barrier to me any more. Yes, you need to either pass the parameters as command line options if they are amenable to that, or to use the pipe to send data back and forth. i’ve done it with stdin/out, an IPCSocket a real socket (which is faster) and even thorough shared memory.

If Delphi can really do that with MPThreads then use that tool! But if you want the rest of what Xojo can offer then you need to spend a day or 2 sorting out the intercommunications and then you’ll be done and have a system you can push forward into a lot of other projects.

Use the best tool for the job, or invest a little time in making some tools in Xojo. Either is OK with me :slight_smile: Yes, I’d LOVE to have a multi-processor aware thread class, but so little of the framework and even the system calls that you can make are safe under those circumstances that I feel like I’d be doing almost all the work to talk between a separate process entirely anyway. Build that framework and you’ll be all set with a very extensible method for doing similar things.

THis also begs the question do you really need 100+ threads making http connections? Why can’t you start 10 and then as they complete start another one? Is it really that much faster to start them all at once? It may very well be but in my limited experience with such things there is a point of diminishing returns. Make 10 connections in the regular xojo app and as they complete pass the data off to a thread and start another one. It might be slightly slower, but it won’t be significantly slower.

It was TWO connections. Given the total time they were running they were running CONCURRENTLY. (Or more accurately: the core could easily switch between them fast enough to saturate the Internet connection and nearly saturate both server’s bandwidth for an individual client.)

Yes…you might want 4-8 in flight sockets instead of 2. If the servers are severely throttled, maybe a few more. The idea is to balance CPU independent tasks (like socket creation/tear down or writing to RAM) with network dependent tasks (accessing the NIC). But you would NEVER want 100.

Preemptive multitasking does not mean 100 threads all run simultaneously. If you have a quad core system at most 4 can actually run at the same exact time. But then if all 4 are accessing the same resource…RAM, disk, the NIC…they bottleneck each other. One gets access while the others wait. Too many threads means more time spent thread switching for no reason and more potential resource contention.

If the servers are severely bandwidth limited then the threads won’t be very busy, which means a single core can keep more of them in flight. The trick is finding the optimum number of in flight threads/sockets for the particular scenario. But whether we’re talking about fast servers or slow servers a single core should easily be able to saturate the connection.

The problem is not the lack of preemptive multitasking or multicore support. The problem lies else where.

I have an app that download some info from a Web API once a month, this task requieres 10,000 individual requests (downloads) The best use of resources and les time to download is by using 60 conections using all the 12 cores. Of course, it wasnt posible on a single app using xojo, so, it is a matter of using the right tool.

[quote=438431:@Norman Palardy]Wrong
Xojo uses real threads[/quote]

Not wrong, just semantics as Ivan said. Xojo have a non-preemptive, cooperative, non parallelized sequence of execution; time slicing with cooperative yielding. When you are doing an App.val=1, it’s guaranteed that no other “thread” will do an App.val=2 at the same time, because there is no “the same time” in Xojo.

[quote=438448:@Norman Palardy]Preemptive threading across multiple cores requires a thread safe runtime so it CAN be re-entrant.
None of the frameworks are thread safe or re-entrant to support this.[/quote]

Yes. This is the excuse for not having it, and looks like we will never will see one. Hard work to rewrite the framework. But it is no argument for a “Wrong, Xojo have real threads”. What I called “real”, is a real parallelized thread, using another core, and Xojo does not have it. Using a CPU with 2 cores, or 12, does not affect your Xojo app performance directly, because your code will use just one core, sharing execution time of one “real thread”, in virtual threads, by time slicing, managed by the cooperative time scheduller.