Why does APL retain the thread numbers?

General APL language issues

Why does APL retain the thread numbers?

Postby Tomas Gustafsson on Sat Sep 17, 2016 10:03 am

Stormwind rootserver running overnight, ⎕tnums:

0 14382 14356 14112 14051 13954 13310 13027 12860 12774 12362 12122 12092 12027 11983 11753 11737 11571 10704 10257 10201 10158 ... [ca 450 more]

Each time .net does an async callback and there is concurrency, eg. another packets is arriving async'ly while APL async'ly handles this packet, or the async callback in APL performs an async reply action (eg. socket.SendAsync), there seems to be born a new APL thread number.

Windows seems to invent new numbers... APL (and Windows?) seems to re-use numbers if there is no concurrency ongoing.

I recall well that John D has stated that APL stores the winthreadnr/aplthreadnr binding in order to improve something... performance? As such sounds smart. APL even does this up to a huge content in that binding pool, like up to gigabytes. Is this again really smart? Searching for a cached hit in such amount of data must also take time? And that slowly eats up all memory.

A problem here is that when i type )si (eg. in the case of callback fn errors), i get n-hundred pages of these

&14112 (system thread:5804)'s

into the session. Impossible to read.

I'd be happy to hear the indepth reason for cacheing the binding :-)? Naturally one could keep track of the APL threads and housekeep (delete) after use... But what's the smart way, performance-wise and other-wise?

Is this actually about something not getting properly deleted/Disposed?
Tomas Gustafsson
Posts: 91
Joined: Mon Sep 19, 2011 6:43 pm

Re: Why does APL retain the thread numbers?

Postby Vince|Dyalog on Wed Sep 21, 2016 11:52 am

Hi Tomas,

I think the 2501 and 2502 I-Beams will help you.

Discard Thread on Exit R←2501⌶Y

Discard Parked Threads R←2502⌶Y

Please have a look at our 15.0 I-Beam documentation for more details.


Posts: 335
Joined: Wed Oct 01, 2008 9:39 am

Re: Why does APL retain the thread numbers?

Postby Tomas Gustafsson on Thu Sep 22, 2016 10:34 pm

Thx Vince, i've heard there are new I-beams but that's not really what i wanted to know.

When trying to evaluate the importance if this, i'd like to hear what kind of performance hits or benefits there are in doing either way.

What's the advantage of retaining the thread bindings? If it's a matter of the interpreter having set up an entire new memory management instance, with housekeeping tables and whatnot, well that seems like a rather big job and i might not want that to happen each time a UDP packet comes in asynchronously. Hence the I-beam option of always clearing out the APL thread when completed becomes irrelevant, as that would always enforce a creation of a completely new binding next time.

If again retaining the binding keeps such a housekeeping instance alive but asleep, i wonder at which point (how many of them) it's beginning to cause noticeble overhead?

This is a behaviour that imho should be optimised. Leaving this at the users responsibility, to shooting 100% in blind, or leaving 100% alive, or always killing one sort of them but not the other, seems a bit rough? Is there no room for a thread pool-thinking, where APL could re-use the parked threads even if there is no exact hit in the earlier-made binding? That would keep the total amount of them low.

I'm bound to v. 14 for the moment, so i could (maybe) TKILL manually if it's worth doing so. And in v. 15, what's the guideline for knowing how to choose wisely?
Tomas Gustafsson
Posts: 91
Joined: Mon Sep 19, 2011 6:43 pm

Re: Why does APL retain the thread numbers?

Postby JohnD|Dyalog on Fri Nov 11, 2016 9:27 am

Hello Thomas,

Dyalog maintains a "map" of .NET thread numbers to APL thread numbers. The map is required for cases (usually in GUI) where code that manipulates an object always needs to be run on the same thread. For example, if thread n creates a GUI object then typically only thread n can change properties of that object.

When such a thread has no stack, Dyalog puts the thread into a state (which we called "parked") where it will not get scheduled, until a subsequent .NET call requires code to be run on the same thread. There is still some overhead to having these parked threads in the workspace, and this overhead increases with the number of parked threads. It's hard to judge the comparable overhead of the parked threads versus the overhead of spinning up a new thread on each call. However, I suspect that if you are creating about 500 threads in an overnight (let's say an 8 hour run), then thread creation is "rare" and you'd see an improvement by disabling the parking with the ibeams, and have a new thread started for each call.

Now, we realised that in many cases the use of thread pools, and other thread creation models, make the thread map unnecessary, thus the introduction of the new ibeams in 15.0. As the interpreter is not aware of the use that threads are put to we can't really automate the process. However, there may be an argument for a global setting that disables the thread map for all threads in a process, I suspect you'd use that in Stormwind.

As an experiment it would be interesting if you were able to run Stormwind on version 15.0 and use the ibeams to disable the thread parking. You may or may not see a performance improvement due to fewer threads in the workspace. There have also been significant performance improvements elsewhere in 15.0.

Best Regards
John Daintree.
User avatar
Posts: 66
Joined: Wed Oct 01, 2008 9:35 am

Return to Language

Who is online

Users browsing this forum: No registered users and 1 guest