I did not intend to post on this, but it so has happened that I have found myself involved with studying the differences in the ASE 15.7 new kernel: threaded as opposed to process. There are a lot of differences in the new ASE. But the difference in the way engine resources are treated in the two kernel modes is something that one has to pause on.
Probably most of us feel that the ASE 15.7 came out as yet another revolution. Whereas ASE 15.x has kicked off the old optimizer code (and silently eliminated the APL system catalog, eh?), ASE 15.7 has kicked off the old SMP architecture. It is true that this time the new architecture is brought in more gracefully (you can still use the old “process” mode – I wonder how much it resembles the pre-15.7 kernel). Still, the “threaded” kernel has been made a default – a definite statement of what the engineering team suggests the product customers must choose in the long run.
I don’t mind that my ASE runs faster (unless it is choked by its own speed), nor do I mind that I have different threads servicing different tasks in different manner (RTC, time slice, whatever). What I do mind is that the new ASE is by now definitely a new product. Especially for those that still live in an old world of ASE 12.5.x….
Never mind. Since I am touching on the subject of resource management (Distributing Engine Resources, Chapter IV in Performance & Tuning Guide, Basics), I will only touch on differences between the two kernel modes which are important to keep in mind when one subdivides its ASE into subsets of engine groups, execution classes, &c.
It is true that with the old process mode, you might have divided your server into subsets of engines, just as (??) you may subdivide your available engines into thread pools in the threaded kernel. But there is a huge difference in the outcome.
The documentation says: “You can use the logical process manager to establish task affinity so the manager runs a task, or set of tasks, only on a specific engine or specific set of engines. In threaded mode, use thread pools to accomplish task affinity. In process mode, use engine groups” (SAG. 2, Ch. V, p. 124).
Remember the run queues and the scheduler assigning tasks to it? The algorithm goes like this: look into your (engine) own high priority queue, if nothing found, look into global high priority queue, if nothing found move to the medium priority (engines-global), nothing found move to the low priority (engines-global), still nothing – start stealing tasks from other engines queues (network IO is a separate topic here).
This was true in the old process mode. In the threaded mode this is no longer the case. To quote again:
The scheduler search space refers to where engine schedulers look for work (run queue checking):
• In process mode, the scheduler search space is server-wide, meaning all engines share a global run queue. Engines check the run queues of all other engines.
• In threaded mode, the scheduler search space is specific to the thread pool. Each engine thread pool has its own global queue, and the engines within that pool look for tasks associated only with that pool (P&T – Basics, Ch. IV, p. 64).
What this means is that whereas dividing the engines into engine groups in the process mode has left engines available to the ASE in general (you might have actually assign the same engines twice to different engine groups – say you have tasks that run at different time slots and you want to assign both of them to the same ASE engines). In the threaded kernel when you set engines aside as a separate pool you loose them to the ASE in general. Only the tasks assigned to that pool will see them. For all the rest they become completely invisible. Actually, you don’t even work with engines, but with pool sizes. In other words:
Thread pools and engine groups have different behaviors. Engines in a thread pool execute tasks assigned only to that thread pool. The scheduler search space (the area in which the scheduler searches for runnable tasks) is limited to engines in that thread pool. Engines in an engine group may run any task, as long as the task is not restricted to engines in a different group. That is, including a task in an engine group restricts where the task may run, but does not reserve the engines in the group for that task (SAG2, Ch. V, p. 124).
I found it interesting for two reasons. One is academical.
Knowing that the behavior is vastly different is crucial for the task of subdividing the available resources in a meaningful way. For example, in the old good ASE with its process-oriented kernel I might have set aside a set of 4 engines out of my 16 and assign them tasks that I would not care being lost in the run queue for some time. I did not have to care much. Since the same engines receive from the scheduler other tasks, selecting them for another, less important subset of tasks was ok. Well, sort of. It did raise a purely academical question of what happens to those unfortunate tasks that land in the queue which is longer that the queue of other engines (is scheduler sensitive to it?). In the threaded mode the situation is different altogether. If I have a set of tasks that for me are not so important, I will still have to steal engines from the general ASE workload. Now, it is true that this does not create an imbalanced situation when some engines do more that others. Yet, I wonder how much do I gain from loosing the engines for the ASE in general for the tasks I don’t really care about. Hm?
The other reason was purely practical. I have had once a need to subdivide my ASE into subsets of engine groups – tie the tasks that I care less to small subsets of engines, so that they do not choke the whole of the ASE. Doing it with the set of SPs that ASE provides has pissed me off, so I designed a simplistic tool to make my life easier. Not long ago I have decided to make this tool a bit more useful, and started to put into it some rethinking and remodeling. And then I stumbled upon ASE 15.7 with its brand new threaded kernel mode, which is managed by somewhat different semantics. By the way, for those who like having fun with their ASE, I suggest transforming the server back and forth from threaded to process mode and back. Have a look what it does to the recommendation not to leave the threaded ASE without an independent IO thread… A lab for you….
This purely practical effort has resulted into a more functional tool which I publish here. I called it ASE Logical Resource Manager.
It is simple to operate. On the one hand, what it is designed to do is to help to subdivide the ASE into logical sub-groups more easily (it is so much easier to select and click than to keep writing scripts and run them – also an option). But what it designed to do as a surplus is to make “researching” the brain surgery of the ASE more convenient. Documentation has a long tirade about the need to test and check, test and check, and test again (clearly a warning sign to the reader). It is, again, so much more easy to test and check when you have things collected together and available at your fingertips.
For example, you want to check your subdivision? move some processes on the fly? check the task to engine ratio? engine load?
You want to see your spinlocks (wait2grab or spin2wait)? Why not:
Collect some query metrics (for ASEs that do that)?
I have been much offended once (hm, I feel as if I am quoting Hamlet…. strange feeling….) by being asked to send logs to support rather that being assisted to see things on my own as they happen. It is a bad, bad feeling and I don’t want others to have it. So here you are – you may use this tool, if you find it handsome, worksome, helpsome….
It is available here: ResourceManager.