This is part of a series of small blog posts which will cover some of the smaller, perhaps less likely to be noticed, features of IBM MQ. Read other posts in this series.
I asked the team during the recent "IBM MQ: Ask Us Anything" event, what their favourite little feature of IBM MQ was. You can watch the full replay of that webinar here. Matthew Leming's answer was PAGECLAS. So let's learn a little about that little gem of a feature today.
To talk about PAGECLAS first we must introduce one or two other features of IBM MQ for z/OS. When you put and get messages to a queue, your best performance comes when those messages never have to be forced to the disc storage backing the queue. Both distributed and z/OS have the concept of buffers holding messages and only writing messages to disc storage (called queue files on Distributed and page sets on z/OS) when absolutely necessary. This is separate to the writing of persistent messages to log files.
On IBM MQ for z/OS, these memory buffers are called Buffer Pools, and are associated with the disc storage, that is the page sets. There is more configuration available for Buffer Pools on IBM MQ for z/OS than there is for the equivalent concept, the Queue Buffer on Distributed which is controlled through the qm.ini file attribute DefaultQBufferSize.
So, if you have a queue where performance is important, you assign it to a particular storage class which represents a pageset, and configure the pageset to use a specific buffer pool which has an appropriate numbers of buffers. You may even go to the lengths of isolating this queue so that it is on a pageset on it's own, with its own buffer pool and thus not sharing it's buffer pool with any other queue. Commands like the following allow these different objects to be tied together.
DEFINE PSID(3) BUFFPOOL(3)
DEFINE STGCLASS(VIP) DESCR('Performance Critical') PSID(3)
DEFINE QLOCAL(MY.VIP.QUEUE) STGCLASS(VIP)
N.B. There is no requirement for the Page Set ID (PSID) to match the BUFFPOOL number, but as of IBM MQ V8.0.0 both pagesets and buffer pools are able to be in the range zero through 99, whereas previously buffer pools could only go up to 15. So these days it makes sense to match them just to make the pairing more obvious.
In older versions of IBM MQ for z/OS one of the biggest storage constraints was buffer pools. The queue manager address space was a 31-bit address space and you had to squeeze in your buffer pools into the 2G of storage available below the bar. This storage also had to accommodate Common Storage (CSA), queue indexes, handles and a number of other things, so there was generally never as much storage to go round as might be needed. IBM advised not to consume more than 70% of your 31-bit storage for buffer pools.
In IBM MQ V8.0.0 this restriction was lifted and buffer pools were able to be located above the bar in 64-bit storage. This led to the expansion of the DEFINE and ALTER BUFFPOOL commands for extra configuration of buffer pools.
DEFINE BUFFPOOL(8) BUFFERS(1024) LOCATION(ABOVE)
Moving buffers above the bar has two main benefits. You relieve the storage constraint on all the other things competing for storage below the bar, and you open up much more storage available to use as buffers in 64-bit storage. In addition, moving the buffers above the bar allows you to use another new feature in IBM MQ V8.0.0, and that is Matthew's favourite feature, PAGECLAS.
DEFINE BUFFPOOL(8) BUFFERS(1024) LOCATION(ABOVE) PAGECLAS(FIXED4KB)
Normally, buffer pools use pageable 4KB pages of storage. These buffers can be paged out to auxiliary storage when not needed, to allow other storage to be paged into real storage. This new setting PAGECLASS(FIXED4KB) indicates that ALL the buffers in this buffer pool are to be page-fixed and thus permanently in real storage, and never paged out. This can give performance benefits in situations with lots of real I/O, but should also be treated with caution.
Advice from Knowledge Center suggests that if you have sufficient real storage so that your buffer pools will never be paged out, then you can consider using PAGECLAS(FIXED4KB).
The MP16: Capacity Planning & Tuning Guide states the following situation where PAGECLASS(FIXED4KB) can be useful.
Even with large buffer pools, for some kinds of processing where queue depths build up where it may not be possible to keep all of the data in the buffer pool. In these cases data is written to the page set during MQPUT and read from page set during MQGET processing. Where the highest levels of performance are required for this type of high I/O intensity workload, the buffer pool can be defined with PAGECLASS(FIXED4KB) which ensures that the buffers are permanently fixed in real storage so the overhead of the page-fix before the I/O and the unfix after I/O is removed.
Using page-fixed storage is not a decision that can be taken independently of anything else in the system. It is not a decision for the MQ administrators alone. There must be sufficient real storage available for one thing, but also, you may impact other address spaces in the system, or even bring the whole system down! Read this cautionary tale about page-fixed Db2 buffer pools from Adrian Burke.
Right-sizing your buffer pools may be a more important step than just choosing to turn on the page-fixing feature. Getting your buffer pools above the bar may allow you to size them more appropriately for your needs. Note that IBM have deprecated LOCATION(BELOW) as of IBM MQ for z/OS V9.1. This is no doubt to encourage you to consider moving any buffer pools still below the bar into 64-bit storage.
There is a section dedicated to IBM MQ buffer pools in the IBM Redpaper "Benefits of Configuring More Memory in the IBM z/OS Software Stack" which offers guidance on right-sizing your buffer pools which is an interesting read.
To finish, let's listen to a snippet of the Ask Us Anything webinar, where Matthew Leming describes this feature in his own words.
You can watch the full replay of that webinar here.
Also, there's a new Hursley webinar about IBM MQ in the calendar for March. You can register here.