Mark Hanson · Jan 4, 2016 go to post

Both these issues are addressed in the version we have scheduled for 2016.2.

Previousy the worker jobs are owned by the process asking for the work, in the new version we have a global pool of jobs available for any work. This allows the work queue manager to work in CSP processes. Also when you ask for a work group you can now specify how many processes you require.

Note that the 'ForceJobs' setting is unsupported and undocumented so we may remove it at some point.

Mark Hanson · Jan 6, 2016 go to post

The syntax is great as it exactly expresses what you want to achieve, however if your code is performance critical it is faster to:

Set r=$list(colors,1),o=$list(colors,2),y=$list(colors,3)

Hopefully the 'set $lb' syntax will be optimized at some point as it is clearer than the multiple $list alternative and it should be possbible to make it faster.

Mark Hanson · Jan 29, 2016 go to post

I think they should disable the points totally until they figure out exactly how they will be used.

Mark Hanson · Feb 5, 2016 go to post

The worker jobs do not have access to the memory of the master process. These are just regular Cache processes. If you wish to share information between jobs then use globals and locks to synchronize access to pieces you need to change.

Mark Hanson · Mar 9, 2016 go to post

Thanks John, hint taken, I have just checked in a change to the SAMPLES to remove direct calls to %apiOBJ.

Mark Hanson · Mar 9, 2016 go to post

Personaly I just registered both email accounts separately in Gravatar, and having my corporate email account for these community pages could mean I can have a nice professional picture here and a more relaxed one for my private account (not that I did, but it is an option).

Mark Hanson · Mar 15, 2016 go to post

The RSS feed for groups (or communities as the link currently says) does not include a title, e.g. for:

https://community.intersystems.com/group/8081/feed

Starts with:

    <title></title>
    <link>https://community.intersystems.com/group/8081</link>
    <description></description>

So there is no title or description of this feed. Also is there a feed for all content posted to this site, so not filtered by tag/group at all?

Mark Hanson · Apr 5, 2016 go to post

While ^GLOBUFF is useful for showing the makeup of the current global buffer pool it is not really useful for sizing the buffer pool. If for example ^GLOBUFF shows that ^MyLogGlobal is using a lot of the buffer pool you may want to investigate if you are logging too much data and if this is pushing your main application globals out of the buffer pool sooner.

Most applications will not have sufficient memory to allow their entire working set to reside in the buffer pool so it is perfectly normal for the buffer pool to be 100% used as shown by ^GLOBUFF. The point of the buffer pool is to cache values in memory to avoid disk IO, so to size this use a tool like ^mgstat which shows global references and and physical reads. If the physical reads is too high try increasing the buffer pool in the hope that caching more data will reduce the disk IO.

On the original question my general rule is the user should be able to calculate how many processes they will need to run their application and measure how much memory each process takes and so calculate how much memory will be needed for this. Then based on the total available memory on the machine they can subtract this out, and allocate say 70% of the remaining to the global buffer pool. However like any performance related issue the only way to know for sure is to measure and be willing to update your configuration based on these measurements.

Mark Hanson · Apr 8, 2016 go to post

Do you have any estimate when the RSS feed will be fixed to add title and description tags? 

Mark Hanson · Apr 14, 2016 go to post

The problem with this is I believe they do not want the object saved into the database at all. It seams like a worthwhile enhancement that export to XML could optionally call %ValidateObject on the objects as it walks the tree.

Mark Hanson · Apr 16, 2016 go to post

I often do this too, I think this sort of pattern is a good way to make the error handling simple and consistent.

Mark Hanson · May 11, 2016 go to post

I would generally advise against using %File class for reading files as this is a very low level wrapper around the COS file commands. For example if you want to apply a translate table you need to know about the 'K' flag on the open command. I much prefer using the %Stream.FileBinary or %Stream.FileCharacter classes as these provide a much more consistent interface to the file.

Mark Hanson · May 12, 2016 go to post

The use of ZZW was a mistake and we removed this in the next release after it was introduced.

I did not see any documentation that said that 'ZZ' was reserved for any particular use and the examples in the documentation show functions that do not use 'ZZ' as part of their name so I was trying to avoid user extensions in naming the item 'ZZPRINT' by assuming we can use 'ZZ' and customers will use 'Z<something else>'. I apologize if this caused a problem for you, that was the opposite of my intension.

Mark Hanson · May 12, 2016 go to post

I fully agree with hoisting constants out of a loop and have recently spent a while optimizing code to use $listnext in SQL and so agree it is a much faster way to iterate over $listbuild structures.

However in your first case of a 'For' loop the end condition is evaluated when entering the loop the first time and is not re-evaluated at all, for example run this:

CACHE20164:USER>set a=2 for i=1:1:a { set a=10 write i,! }
1
2

As you can see it always stops at '2' rather than going on to '10'.

Also there is overhead in converting from a delimited string into a $list format in order to use the more efficient $listnext, you can avoid the O(n^2) overhead with the regular $piece(string,",",i) code in a loop using $find with a starting position and then $extract the item you need. This should perform better than $listnext version of the loop at least for mid sized strings as it avoids the conversion overhead.

Mark Hanson · May 13, 2016 go to post

The MAK4540 fix was approved for porting to 2016.1.1 and all later releases.

Mark Hanson · May 13, 2016 go to post

Much better, the main page request is down to 1.0s and total load time is 1.7s which while still slow is no where near as bad as >6s, thanks.

Mark Hanson · May 16, 2016 go to post

FYI: I get consistently slower performance with the 'for' loop variation here (around 10% slower) so at least in my simple test the while loop both looks nicer and runs faster.

Mark Hanson · May 20, 2016 go to post

Thank you for this really useful article, there is some great information here.

Mark Hanson · Jun 23, 2016 go to post

You are right, I had missed this was creating a %Status and thought they just needed the error code. To create a %Status value I would always use the $$$ERROR macro as you suggest.

Mark Hanson · Jul 23, 2016 go to post

You do not need to override the propGet method here as this will be generated automatically to call the sqlcomputecode if that is defined.

Mark Hanson · Sep 9, 2016 go to post

Why do you want the connection id to change? In CSP we route multiple requests to a few server processes to be able to handle massive numbers of client efficiently. However the process that handles the request does not hold any information about the session at all, all this information such as the license we hold is in the %session object so as long as you have a new %session object this is a brand new connection.

Mark Hanson · Sep 23, 2016 go to post

The 'Do While' is in fact identical to the 'For' block structure except it adds a redundant while condition at the end which is never false as it will have already exited this block from the 'Quit:Sub1=""' condition earlier, so you should probably remove this as it just takes the 'For' structure and adds this extra test which will slow the loop down.

A disadvantage of the 'While' structure is first you need to repeat the iteration construct, e.g. 'Set Sub1=$O(^Trans(Sub1))' before entering the loop and at the end. Also if you need to skip an item with say the 'For' structure you can just issue a 'Continue' but with the 'While' structure you have to advance the current subscript value manually before issuing a 'Continue'

In the 'Method Levels' the lines like 'Goto Level1' are not needed as the previous line says 'Set Sub2="" Goto Level2' so it will always be evaluating this 'Goto Level2' and so will never get to the next line. Rather than having this you can simplify to just 'Set Sub2=""' and remove both 'Goto' statements so it will just drop down into Level2 automatically.

Mark Hanson · Sep 29, 2016 go to post

This is then identical to the 'For' loop example except you have a redundant 'If 1' test each time around the loop, so why not just use the 'For' structure in the original post?

Mark Hanson · Dec 19, 2016 go to post

Note that any time you build a query as a string if you allow users to insert parameter values or control the string you are building in any way into you need to be aware of SQL injection attacks. This is not a problem with '?' query argument substitution as it is designed to avoid injection attacks, but if you have say:

Set sql="select Name from MyTable where Age > "_userage

And the user supplies 'userage' then they could provide "100; drop table MyTable;" or worse.

Mark Hanson · Jan 6, 2017 go to post

The key bit of information here is the 'service unavailable' error being returned rather than say a 'not authorized' or 'not found' errors. By default when out of licenses we return the service unavailable error so if anyone else sees this they should check license usage as a first step. If you get not authorized errors it is probably a security issue so check the audit log as this often shows the exact problem.