Sign in to follow this  
Followers 0
KidPLC

Control Logix Memory Allocation

27 posts in this topic

I am trying to better appreciate memory usage in CLX processors in an effort to create leaner programs. If I create a single DINT with a tag name one character long (ie tag "i" of type dint) in an L61 processor it consumes 80 bytes of memory??? how is this so?? I have read that each character of the tag name consumes 1 byte of memory and the dint will then consume 4 bytes but what has the reset been used for I also read that the tag name characters are on a 4 byte boundary but if I increase the number of characters one at a time checking the memory usage along the way I need to add 8 characters before it consumes another 4 bytes. I would have expected to consume another 4 bytes on the fifth character??? I have asked the Rockwell knowledge base for feedback but have had no response.

Share this post


Link to post
Share on other sites
Greetings KidPLC ... (3) make two more DINTs - named “Y” and “Z” ... notice that each additional DINT requires another a full 80 bytes worth of memory ... (4) make an array of three DINTS and name it “B” ... notice that you get the same equivalent amount of storage space (32 bits times 3 DINTS equals 96 bits) as when you made the three separate DINTS (“X” and “Y” and “Z”) ... but this time it only takes up 92 bytes of memory (instead of 240 bytes) ... this is a significant savings ... so what’s the catch? ... the inevitable trade-off is that with an array you lose the ability to give each separate DINT its own individual descriptive tagname ... (5) which brings up the topic of tagnames ... as you already pointed out, longer names usually require more memory ... so rename your BOOL “A” and call it “A234567890123456789012345678901234567890” which is the maximum allowed length (40 characters) for a tagname ... and now notice that our one little storage space - which holds only a single little ONE or ZERO status - now costs us 116 bytes of memory ... (and of course 116 bytes times 8 bits per byte equals 928 bits - which is closing in on about 1K of memory - just to store a ONE or a ZERO status) ... summing up: there aren’t any “free lunches” here ... when you gain the ControlLogix advantage of storing “tagnames/addresses” in the processor, then it costs you in your “available memory” pocketbook ... friendly advice: be “aware” of these issues - but don’t “worry” about them ... just buy the biggest processor that the project can afford and then get on with your life ... (sort of puts us right back at the “sales pitch” where we came in - doesn’t it?) ... finally, congratulations! ... as far as I know you’re the first person to ask these types of questions on either of the forums that I read ... (my apologies to anyone else whom I might have inadvertently missed - fortunately I don’t have as much spare time to hang out on the forums as I used to) ... Edited by Ron Beaufort

Share this post


Link to post
Share on other sites
Hi Ron, Thanks for the great reply! I take on board your comments re "why make the program leaner just buy a bigger processor" but I tend to take a different approach. Like lots of programmers I am always trying to develop better more efficient code and as you have correctly pointed out CLX can be very hungry on memory...for example if you where to create 32 bools as compared to 1 dint and using the 32 bits individually. These are the little tricks that a "good" programmer should be acutely aware of......that is only my humble opinion. My journey into memory has been encouraged buy examining the machinery I have inherited since I started here in January this year, it is all custom built, all of the processors are operating in either the yellow or red zone of the controller properties memory graph. When I examine the code it is heavily weighted down with groups of 32 bools where dints could have been used (ageed flexibilty with tag naming is compromised) and also inefficient code itself. Yes one option would be to increase the processor size but in my opinon the better solution is to structure better code and tag naming standards. I am developing a library of reusable code modules and I would like to make them lean and mean (just because I can) as I start this process I am also digging into who uses what memory (that includes programs, routines, instructions, sfc vrs ladder etc etc) in an effort to make the code as efficient as I possibly can. I fully understand that I have no control over how much memory a dint will consume however my natural curiosity wants to know where it goes?? It probably won't aid my code library much but a little more understanding certainly can't do any harm. Thanks again

Share this post


Link to post
Share on other sites
I've made this argument before, but never with such a good explanation. Someone said that you should keep your tag descriptions to 12 characters or something to keep memory usage down. I said then and I say now that your should use whatever length tag is necessary to describe it...without it being so long that you can only fit one instruction per line. I say if your strapped for memory then you need to get a bigger processor. Period, the end. But are you sure your strapped for memory? I've ran into many "large" Controllogix programs that were full of unused memory. Your's may be truly "full", but I would love to take a look at it

Share this post


Link to post
Share on other sites
UDT's also make a huge difference. A UDT is equivalent to a C "struct". In terms of actual storage (ignoring the program data), you can have 32 bools if you create them in a UDT and aside from the overhead and the necessity of referring to them by the name <udtname>.<bool>, they will take up exactly 32 bits of memory. Depending on what you are trying to achieve, a UDT may be a simpler solution. It also lends itself to doing arrays. Just as with ALL programming languages, optimization is just plain good practice. For example, consider the following commands: CPT X X+1 vs. ADD X 1 X CTU Ctr CPT X 0 vs. MOV 0 X vs. CLR X Which one(s) are more efficient in terms of speed? What about memory usage? Finally, here's a good reason NOT to use BOOL's, BOOL arrays, bits out of a DINT, etc. I don't know exactly what processor is inside a CLX (haven't destroyed one so that I have an excuse to take it apart yet). Assuming that the processor inside the CLX is an off the shelf model (Coldfire, Pentium, etc.), then it's a 32 bit processor and optimized for accesses to memory on 32-bit word boundaries. This, the various arrays and/or UDT's of BOOL's and such destroy the word boundary properties and require shifts and masking operations to get at the individual bits, making the memory access much slower than the individual DINT, although memory usage is clearly very bad. So...you could be trading processing speed for memory.
1 person likes this

Share this post


Link to post
Share on other sites
I agree...the documentation I have read so far indicates that working strictly with dints and ladder is the most efficient way to go. Even doing a simple add instruction with two sints for example takes longer than doing the exact same thing with dints. Don't get me wrong I agree that the benefits of the different languages and the flexibility of meaningful tag names etc far out weights being a miser with memory however for me personally I would prefer to understand where the memory is disappearing along the program development journey this way I can make educated decisions about how I code. The "where does 80 bytes of dint memory go" question will have no real bearing on how efficient I can use memory as it has already been correctly stated....I can't do anything about.....but never the less I am still in wonder Thanks for the replies

Share this post


Link to post
Share on other sites
Forget about your actual ladder, SFC, function blocks, and structured text. These instructions aren't going to be your memory hogs, especially if the machine is simple. Look for places where the program writer may have made an array of 200 elements when they are only using 10. Go to your tag editor and click on the "Show" button and "Filter On" "Unused". Are there any tags show? That will be a much better use of your time than trying to understand why a DINT requires 80 bytes.

Share this post


Link to post
Share on other sites
Ron - I respectively disagree. I can create a tag called Bool_Array_1 which is a DINT and consumes 80- bytes I can then create alias tags named as follows: ALIAS_BOOL_0 for Bool_Array_1.0 ALIAS_BOOL_1 for Bool_Array_1.1 ALIAS_BOOL_2 for Bool_Array_1.2 All the way to ALIAS_BOOL_31 for Bool_Array_1.31 This consumes approx 1744 bytes versus the 2560 for 32 Bools. I can create a tag called DINT_Array which is a DINT[32] I can then create alias tags named as follows: ALIAS_DINT_0 for Dint_Array[0] ALIAS_DINT_1 for Dint_Array[1] ALIAS_DINT_2 for Dint_Array[2] All the way to ALIAS_DINT_31 for Dint_Array[31] This consumes fewer bytes than 32 DINTS. The names ALIAS_BOOL_# and ALIAS_DINT_# can be made quite unique. The most efficient program I ever co authored was 7 base tags. BOOL_ARRAY_ONE DINT[1024] DINT_ARRAY_ONE DINT[1024] DINT_ARRAY_TWO DINT[1024] DINT_ARRAY_THREE DINT[1024] REAL_ARRAY_ONE REAL[1024] REAL_ARRAY_TWO REAL[1024] REAL_ARRAY_THREE REAL[1024] All other tags were aliased to addresses in the arrays. On a CLGX Version 13 Redundant Setup scan time was 25 ms and memory was 65% used for L55. This consumes approx 1744 bytes versus the 2560 for 32 Bools.
1 person likes this

Share this post


Link to post
Share on other sites
I think you are getting the wrong idea here TW I merely asked the question on the 80 bytes I am not planning a to write a thesis on it or anything.....if it is not solved I certainly won't dwell on it. I am however really enjoying the discussion it has generated. You have really planted a seed there BobL I had never considered what you have proposed it is quite clever actually, I have always aliased inputs and outputs and controller scope UDT's to program scope UDT's but it never dawned on me to do something like you have done. There has to be a trade off somewhere?? it seems to easy. I plan to investigate this further. Thanks Guys

Share this post


Link to post
Share on other sites
Just for the record... this is the recommended practice for boolean tags - straight from the horse's mouth (so to speak)... The "horse" I'm speaking of is Rockwell's ControlLogix guru, Ron Bliss.

Share this post


Link to post
Share on other sites
Thanks for the feedback Gerry I think I will definitely be heading down this path with bools in the future. PS Ron Bliss wouldn't have been involved with the "Power Programming" stuff that Rockwell has on their sample code website would he??

Share this post


Link to post
Share on other sites
Kid you then write your code using the alias names which are meaningful and everyone is fat, dumb and happy. But when you move a block of data to your HMI you use the base tag, take the block and parse it in your HMI script code. This keeps your network traffic and connection counts low as well. I actually saw an HMI displaying three on/off running lamps generate six seperate connections to the PLC, due to the addressing scheme the original programmer used. I did that and a hundred more in one connection. Imagine the savings.

Share this post


Link to post
Share on other sites
Hi BobL Once again you have triggered my curiosity. I am aware of the concept of connections however I have not delved too deeply into the way an HMI manages connections....Panelview Plus in particular. Where you said that the HMI generated six connections with three on/off lamps, how is this so?? I have always been taught to consolidate hmi tags into one block of memory for efficient hmi plc comms however these days with RSView Machine Edition you can navigate directly to the plc tag database and poll tags all over the place.....does this impact on connections. I have tried to find info on Rockwell knowledgebase regarding this but I can't seem to find any.

Share this post


Link to post
Share on other sites
Yes going for tags all over the place can impact on connections.

Share this post


Link to post
Share on other sites
Hello All, I know you are dying to know this....for the record a Tag with name "A" of type dint consumes 80 bytes because............................. When we create a tag in the controller, 3 areas of memory are created. 1. Data Table - Size varies depending on the array 2. Symbol Information - 36 bytes (Always Constant) 3. Tag Name (String) - The smallest the tag name can be is 16 bytes , 8 for firmware memory markers and 8 for tag name. Of this 8 bytes, 1 byte is for string length so size of this is based on tag name and this is always padded out to be 32 bit based. So this is why a tag "A" that is a DINTconsumes 80 bytes of memory and why increasing the tag name will not change the size until you go over the 7th character. This applies to all templated/default datatypes. This is straight from RA engineering. Now I can sleep at night armed with this new information .....not sure what I will do with this knowledge but atleast my curiosity has been satisfied. Thanks guys for the other great info on tags that has been generated along the way.
1 person likes this

Share this post


Link to post
Share on other sites
Thanks for the update. Obviously, there are some who regard this information as useless trivia, but I, for one, think it is very useful to have as much understanding as possible of what happens beneath the surface. There may be no immediate or spectacular benefit from having this information, but most likely, having this little factoid stored away will have some subtle influence for the better on your programming style and/or lead to better understanding of other aspects of the hardware.

Share this post


Link to post
Share on other sites
I don't think anyone regards it as useless trivia Gerry. I'm glad KidPLC shared his findings with us. But as far as solving his memory problems, I still think there are better approaches than micromanaging the tags

Share this post


Link to post
Share on other sites
Hello Gentlemen, Reading back over this post I probably didn't kick it off with the correct wording and it has sent us off down two parallel paths. In hindsight I should have excluded any reference to memory conservation as it really wasn't what I was trying to achieve by understanding a "dint". The question was possed purley because of my curiosity and desire to learn in general, especially when things like a 32 bit entity takes up 80 bytes....for a bloke like me that's a question just begging to be asked right there......so I did. I understood that it was completely out of my control before I even asked the question. I appreciated Gerrys comments because in the end I was feeling a bit silly for asking the "dint" question at all. Conservation of memory and efficient programing structure is still a subject I am extremely interested in (this now has absolutely nothing to do with a dint consuming 80 bytes....if it comes up at a pub trivia night somewhere I will have the answer thanks RA support) The second path of this post is about memory conservation and as it turns out I am actually doing an exercise to better understand one of our existing programs memory use and the fact that it had devoured so much. I am extremely intersted in developing better programming techniques and the feedback regarding Aliasing has gone a long way to developing that. TW you have made a comment:- "But as far as solving his memory problems, I still think there are better approaches than micromanaging the tags" I am keen to have more discussion surrounding this, if we could forget about the 80 byte thing for a moment and I where to have written my original post as " How do I use CLX memory more efficiently?" what would your response have been? What are the better approaches.

Share this post


Link to post
Share on other sites
It would be tough without a program to evaluate, but I understand that many companies don't allow this. You may be optimizing memory to it's fullest...of course then I would be back to recommending a larger processor

Share this post


Link to post
Share on other sites
I think you'd agree that there are some general approaches that work better than others in terms of optimizing memory and/or increasing speed. When I started where I'm working now, most PLC's had scan times in the range of 50-100 ms (PLC-5). One of the big things was I had never encountered (nor used) multiple MCP's before and this was in heavy use throughout the plant. In addition, there was even some program-level manipulation of the MCP's. Mind you, this wasn't done for any good reason (some sort of program merge, or wanting to execute one routine multiple times during a scan for performance reasons). After working with it, I simply can't tell you how utterly frustrating and confusing it was for everyone involved in troubleshooting when these various MCP's were turning on and off to figure out exactly which ladders were really "active" and which weren't, much less doing all the bit math (the guy who did it used masked moves to turn things on and off) just to figure out what is going on. To facilitate troubleshooting, I rewrote it and removed all that MCP stuff. I converted it to the conventional approach of a single main ladder calling everything else as a subroutine. Without ANY further code changes, scan times dropped from 80 ms to about 25 ms! On further examination, I found out that the PLC does house keeping (and I/O if you let it) when executing every single one of those MCP blocks! From then on, I got a 4 fold improvement in scan times and a general improvement in responsiveness simply by removing multiple MCP's. In addition, most of the programs were riddled with old, dead code. About 50%-75% of the code was dead as a general rule. It was still being executed but wasn't actually in use (and never would be). AFI's with no functional purpose and hardware that had been removed/abandoned were rampant. There were forces left on all over the place. Removing that stuff wasn't as dramatic but it still improved both memory and performance. All of the PLC's were programmed with the same basic strategy. Someone took an old PLC program and deleted all the ladders. Then they started programming. If a data table wasn't big enough, they simply made it bigger. Most PLC's were loaded with about 100 data tables, of which perhaps only 10-20 were actually in use. In addition, and this is more of a performance problem, there were huge strength reduction problems. I actually believe that nobody knew what the CLR instruction does. I saw lots of "CPT" blocks used to set variables to 0 (the worst case), and several more MOV instructions for the same thing. I also saw some curious COPy blocks which used a length of 1. Like 10 of them in a row. Seems that somebody tried to create something like a FIFO queue but didn't know that if you do this with COPy, you must run it "backwards" (new locations go at the highest array location, oldest one is at the start of the array). In addition, there were FIFO's everywhere that were hundreds of memory locations long. Replacing them with simple ring queues did tremendous things for performance. In addition, there were PID instructions where they simply used the sign of the error value to drive a double acting cylinder up and down or some such (no PWM/PFM or replacing it with a sliding mode controller). There were also lots and lots of SQI/SQO instructions with all kinds of playing with the index register and ignoring what SQI/SQO is intended for or does. Now in addition to all that, another problem was with indexed addressing. For example, this was commonly done in several programs: If Hour=0, update midnight counter If Hour=1, update 1 AM counter If Hour=2, update 2 AM counter . . . This was all replaced with a single indexed addressing rung. This improved both performance AND memory. Remember scan times of 50-100 ms (PLC-5's mostly)? Now scan times are typically 5-15 ms after introducing these various optimizations. One of my projects was to merge two programs. One was about 42 K words on a PLC-5/40E (48K words of memory) and another one which was 24 K words. After the merge, the resulting program which subsumed all the functions of BOTH ended up coming in at a whopping 26 Kwords of memory. Scan times went from 82 ms on one PLC and 38 ms on the other to about 20-25 ms. So I guess the point I'm getting at is that some basic optimization and programming techniques can often have dramatic improvements in performance and memory footprints. In the case at hand, I've never been too fond of SFC's in general. They are NOT a good choice in my opinion if what you are trying to do is process oriented. That's best done in ladder. They are also NOT a good choice if what you are doing is a sequential operation. This is also best done either in the phase editor or in ladder as a state machine. Depending on how complicated it is, it can also be done efficiently (though with some troubleshooting caveats) on the drum sequencer instructions (SQI/SQO). One of the problems in terms of memory with SFC's on top of the SFC storage itself is that you end up with lots of duplicated rungs due to the fact that all your ladders being called by the SFC are not executing most of the time. The place where SFC's make sense is if you have a sequential operation BUT that it involves multiplel simultaneous activities occurring simultaneously that interact with tight interaction. If there isn't tight interaction (say multiple process stations along a production line that only interact in terms of "ready for product/hold product" or a walking beam where each station has to become ready), ladder-based state machines are still the way to go. Otherwise, I'd seriously consider rewriting/removing the SFC's completely.

Share this post


Link to post
Share on other sites
I would absolutely agree with you. One thing that RsLogix 5000 lacks is a good way to see which tags within an array are actually used. I've seen programs with tag databases that were so unorganized you didn't really know where to begin. But many times you will find the arrays in these programs are not fully utilized. Kind of funny we're talking about this now, I ran into an example of this that I had never seen in a SLC yesterday. The data files from 9-190 were all integer files with a size of 256. But only one variable was assigned to each data file. That's right, 1 integer for each of the 189 data files. I guess the guy thought that a size of 256 would allow for the largest value to be stored?!? While that's an extreme example, you can probably even find some examples of this in most of my programs where I left a little space while developing the program and never cleaned them up before I left.

Share this post


Link to post
Share on other sites
Hi Guys, Thanks for the very informative replies Great comments paul I really appreciate your insights I also picked up on your suggestion re "phase editor". Months back I posted a question to see if anyone was using it and it appeared not many where. I am seriously considering using it on my next project it is a custom built assembly machine. If you are using Phase manager I would love to hear your opinion and experiences. Also I have been doing some digging around re Panelview Plus and connections the local Rockwell guy put me onto CLxperf.htm it is on the rslinx classic and professional CD. For someone wishing to learn more about how data exchange is managed it is very good I thought. I is centred around RSLinx Classic and Professional not RSLinx Enterprise that Panelview Plus uses but the Rockwell guy assures me the concepts presented are pretty much the same in both applications.

Share this post


Link to post
Share on other sites
Greetings to all ... I don't have any particular reason to dredge up this old thread except to answer my distinguished colleague BobLfoot ... your disagreement was well-founded, Bob, and graciously accepted ... the "alias of an array" memory-saving approach that you mentioned in Post #8 was a good idea that I'd never seen done before ... I meant to say that back when I first read your comments - but somehow I must have gotten tied up in something else and never got around to making a response ... thank you for sharing ...

Share this post


Link to post
Share on other sites

Why get so caught up in the weeds?  Agreed that some people need to understand this at a low level, like the people building the hardware and software. But we as the PLC programmer should be free from the worry about this stuff that doesn't add value to our programming. Just my thought. Get more than enough memory and get on with programming.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0