{"action":"created","issue":{"url":"https://api.github.com/repos/kyle-github/libplctag/issues/19","labels_url":"https://api.github.com/repos/kyle-github/libplctag/issues/19/labels{/name}","comments_url":"https://api.github.com/repos/kyle-github/libplctag/issues/19/comments","events_url":"https://api.github.com/repos/kyle-github/libplctag/issues/19/events","html_url":"https://github.com/kyle-github/libplctag/issues/19","id":119992842,"number":19,"title":"reading time in CompactLogix L32E","user":{"login":"reyanvaldes","id":11097772,"avatar_url":"https://avatars.githubusercontent.com/u/11097772?v=3","gravatar_id":"","url":"https://api.github.com/users/reyanvaldes","html_url":"https://github.com/reyanvaldes","followers_url":"https://api.github.com/users/reyanvaldes/followers","following_url":"https://api.github.com/users/reyanvaldes/following{/other_user}","gists_url":"https://api.github.com/users/reyanvaldes/gists{/gist_id}","starred_url":"https://api.github.com/users/reyanvaldes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/reyanvaldes/subscriptions","organizations_url":"https://api.github.com/users/reyanvaldes/orgs","repos_url":"https://api.github.com/users/reyanvaldes/repos","events_url":"https://api.github.com/users/reyanvaldes/events{/privacy}","received_events_url":"https://api.github.com/users/reyanvaldes/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":5,"created_at":"2015-12-02T17:21:42Z","updated_at":"2015-12-03T01:55:07Z","closed_at":null,"body":"I recently noticed that to read a single tag takes around 11 ms in CompactLogix L32E. Is there any way we can speed up this time in the reading process? The challenge is for example if need to read 200 tags, that could takes around 2 200 ms as total scan cycle. Please do you have any recommendation. Thanks"},"comment":{"url":"https://api.github.com/repos/kyle-github/libplctag/issues/comments/161492451","html_url":"https://github.com/kyle-github/libplctag/issues/19#issuecomment-161492451","issue_url":"https://api.github.com/repos/kyle-github/libplctag/issues/19","id":161492451,"user":{"login":"kyle-github","id":1820043,"avatar_url":"https://avatars.githubusercontent.com/u/1820043?v=3","gravatar_id":"","url":"https://api.github.com/users/kyle-github","html_url":"https://github.com/kyle-github","followers_url":"https://api.github.com/users/kyle-github/followers","following_url":"https://api.github.com/users/kyle-github/following{/other_user}","gists_url":"https://api.github.com/users/kyle-github/gists{/gist_id}","starred_url":"https://api.github.com/users/kyle-github/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kyle-github/subscriptions","organizations_url":"https://api.github.com/users/kyle-github/orgs","repos_url":"https://api.github.com/users/kyle-github/repos","events_url":"https://api.github.com/users/kyle-github/events{/privacy}","received_events_url":"https://api.github.com/users/kyle-github/received_events","type":"User","site_admin":false},"created_at":"2015-12-03T01:55:07Z","updated_at":"2015-12-03T01:55:07Z","body":"@Jacob - I am not sure that this will do anything.  At least on a\nControlLogix system, the processor in the ENBT/EN2T card is the limiting\nfactor, not the main CPU.  Most or all of the work for network IO is done\nvia the network module processor.\n\nAs I was noting about solution #0, a key point is that any packet sent to\nor from the PLC is handled completely asynchronously from the ladder logic\n(or can be).  Thus, suppose you build a large DINT array with your data.\nYou read it from a remote PC via libplctag (or any other library).  You can\nget data that is partially complete.  Because the read is not synchronized\nwith the ladder logic, the main CPU could be in the process of setting the\nvalues in the tag when the network module reads the data out from\nunderneath it.\n\nThe way I've combated this (and it is true whether the reader is a PC or a\nPLC), is to have what I call sentinel values in first position in the tag\nand last position in the tag.  In your ladder that sets the values, first\ncalculate a new sequence ID.  I like to use DINTs and wrap at 1000000 or\nso.  Set the first sentinel.  Set the rest of the data.  Now set the last\nsentinel.\n\nWhen you get a value from a PLC, check the sentinel values.  If they are\nthe same, you got complete data.  If they are not the same value, then you\ngot \"lucky\" and got partially completed data.\n\nYou might think that this isn't a big problem, but we found it was\nhappening far more often than we thought before implemented this.\n\nI think, but am not sure, that you can put the sentinel values anywhere in\nthe tag, but they must be written in the order I described above.  However,\nthere was some reason why we didn't do this and I can't remember what it\nwas...\n\nThis can be a problem with any tag that is updated in parts, not just ones\nthat will not fit in a packet.\n\nOn Wed, Dec 2, 2015 at 2:08 PM reyanvaldes <notifications@github.com> wrote:\n\n> Kyle\n> Thank you so much for your help and time with this. I will try option #1-\n> using multi-threads, following your recommendation of limit to 15 threads\n> and let you know. I will restructure the main reading loop thread in a\n> multiple reading threads. The solution of reading tags as group is great\n> option.\n> Thanks\n>\n> Sent from my iPhone\n>\n> On Dec 2, 2015, at 1:29 PM, Kyle Hayes <notifications@github.com> wrote:\n>\n> > 11ms is not bad. For an AB PLC, about the fastest I have seen was 8ms.\n> > There are two sources of the delay:\n> >\n> > A. The PLC takes a while to respond. This seems to be fairly large.\n> >\n> > B. When you do IO, your thread/process can get rescheduled and the time\n> > slice is often fairly large.\n> >\n> > There are three solutions:\n> >\n> > 0. Do what Jacob suggests and create a new tag in your PLC that contains\n> > all the data from the other tags you want to read. There are some tricks\n> > here such as using sequence sentinels at the beginning and end of the\n> > array. You must do something like this to make sure that you don't get\n> > partially updated data.\n> >\n> > 1. run the reads in parallel with threads. I have tested this with\n> several\n> > hundred tags. There is some code in the examples directory showing the\n> use\n> > of pthreads. HOWEVER: you need to be careful not to overrun the PLC.\n> > Their network resources are very, very limited. Try to avoid having more\n> > than 10-20 requests in flight at the same time. Possibly the best way to\n> > do this is to have a worker thread pool that grabs tags and reads them.\n> > You can limit this pool to 15 threads (for example) to keep the number of\n> > requests in flight down. I have production code (in Java) using upwards\n> of\n> > 30 threads that has been running for several years.\n> >\n> > 2. Wait. I am working on another version of libplctag that will support\n> > the AB multi-operation request packet type. With this, you will be able\n> to\n> > specify a \"read group\" for all the tags that should be read together.\n> They\n> > will be requested in a single (or very small number) of request packets\n> and\n> > all the data will be streamed back from the PLC in one (set of) response.\n> > If you need single-threaded fast reads of a lot of tags, then this is the\n> > best bet. Unfortunately, this is going slowly as I am completely\n> > overloaded right now with other work and the amount of change required to\n> > support this is quite significant. There are a few emails on the email\n> > list/board about this.\n> >\n> > When developing the library, I found out that PLCs have extremely limited\n> > resources so it is very, very easy to overrun them! The failure modes\n> were\n> > not consistent. Sometimes the connection dropped. Sometimes the request\n> > was just not handled. Sometimes request responses were returned out of\n> > order (I handle this case). Etc.\n> >\n> > If you have questions about #0 or #1, let me know and I will try to help.\n> > Getting the locking right is not always trivial and without using locks\n> in\n> > the right way (it is part of the API) you will quickly get a SEGV :-(\n> >\n> > Best,\n> > Kyle\n> >\n> > On Wed, Dec 2, 2015 at 9:27 AM Jacob Abel <notifications@github.com>\n> wrote:\n> >\n> > > I am interested to hear what Kyle says. I am unfamiliar with the\n> functions\n> > > in libplctag, but in general you should be able to pull an array as one\n> > > operation, so the solution should be to have the PLC copy values into\n> an\n> > > array and then grab the array(s).\n> > >\n> > > On Wed, Dec 2, 2015 at 9:21 AM, reyanvaldes <notifications@github.com>\n> > > wrote:\n> > >\n> > > > I recently noticed that to read a single tag takes around 11 ms in\n> > > > CompactLogix L32E. Is there any way we can speed up this time in the\n> > > > reading process? The challenge is for example if need to read 200\n> tags,\n> > > > that could takes around 2 200 ms as total scan cycle. Please do you\n> have\n> > > > any recommendation. Thanks\n> > > >\n> > > > —\n> > > > Reply to this email directly or view it on GitHub\n> > > > <https://github.com/kyle-github/libplctag/issues/19>.\n> > > >\n> > >\n> > > —\n> > > Reply to this email directly or view it on GitHub\n> > > <\n> https://github.com/kyle-github/libplctag/issues/19#issuecomment-161372106>\n> > > .\n> > >\n> > —\n> > Reply to this email directly or view it on GitHub.\n> >\n>\n> —\n> Reply to this email directly or view it on GitHub\n> <https://github.com/kyle-github/libplctag/issues/19#issuecomment-161449099>\n> .\n>\n"}}