Jump to content

John Lokanis

  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by John Lokanis

  1. QUOTE(Anish Prabu @ Nov 17 2007, 08:05 AM) Thanks! This looks like the least amount of buffer allocations possible. For those of you with exp with the map class, will that really improve the memory useage of this complex array? I thought I remember reading somewhere that LV stores arrays as linked lists already, so using the map class to construct a linked list would be functionally equivalent.
  2. QUOTE(Norm Kirchner @ Nov 13 2007, 12:31 PM) I see you are using Varient Attributes. While this is a natural data structure for representing a tree of data, I have found that accessing/adding/updating attribute elements is a very slow process in LV. I suspect that this is due to the memory allocation issue again. This would be fine for small datasets, but in my case, the tree is displaying a 24 hour looping test with over 100 elements per loop, and 100s of iterations in 24 hours, so the dataset gets huge fast. Couple that with the multiple instancs of this strucutre (50-80 on average) and my poor 8 core 4GB PC comes to a grinding halt! I am thinking I may need to start over with this whole process.
  3. QUOTE(Norm Kirchner @ Nov 13 2007, 11:45 AM) I am wondering the same thing. How can I do an 'InPlace' edit to my structure if that edit is to replace a string with a longer one? Or, add an element to a sub array of a cluster? This seems like it would force a memory allocation. My problem is finding a way to represent the data a Tree control can contain but outside the Tree Control itself. This data is quite complex when you get into multiple child rows and cell BG colors. I used to just write the data to the tree 'on the fly' but when you have 80 instances of the VI with the Tree all running in parallel and you don't need to display any of them unless a user chooses to, it seemed like a better idea to store the 'source' data in an array of clusters and then only write to the tree when it is displayed. Anyone have a better idea? I am about to abandon the tree control altogether...
  4. QUOTE(ragglefrock @ Nov 12 2007, 10:42 PM) Thanks for the reply and the VI. Unfortunatly. I am still stuck on 8.20 at this time. Any chance you can post an 8.20 version of the VI or a screenshot of the important changes ot the BD? I will try to edit the VI based on your comments above in the meantime. Thanks again, -John
  5. I have a very large application that is experiencing a memory fragmentation problem. The root cause of the problem seems to be the fact that I am building and modifying an array of complex clusters. This data structure is used to mirror the data displayed by the tree control. I have done this to avoid writing to the tree control until the user chooses to display the VI that contains the tree. The idea was to encapsulate all GUI writes into a single VI and to avoid them altogether if the data is never requested to be displayed. But the result is a large and ever growing data structure that slowly fragments the memory of the PC until the app slows to a standstill. In my app I create N instances of this data structure to track all the DUTs being tested and then I run it for 24 hours. So, by the end of the test period, 100s of MB have been consumed and every little memory allocation takes forever. After digging into the code for causes and solutions, I find that there are some functions where memory buffers are being created that I don't understand and can't seem to eliminate. These allocations seem to be making copies of the entire data structure and some of it's largest components, causing ever increasing memory allocations. I was hoping someone could point out the obvious mistake and offer a solution. Also, I was wondering if the new InPlace structure in LV8.5 could solve this problem. How complex can the code within the InPlace structure be and does ALL of it have to be in place operations? Attached is the code and an RTF document with some screen shots of the code showing the offending allocations. Thanks for any ideas you can offer, -John
  6. I have built applications that use this concept. I even have one where there are two parallel loops, each with its own event structure. The top one responds to user interaction. The bottom one runs the test process. They can fire events at each other to start tests or to exit when done or an error occurs. This seemed like a good idea at the time but ended being very complex to 'keep straight in my head' and therefore, to debug. Here are a few reasons why I no longer do this: 1. You can fire off events within the event structure to 'queue up' the next event, but once fired you cannot recall them. So, if you are in one event case and you decide to fire off a series of three cases to perform the next 3 needed operations, then you are stuck with that order. If the first or second one of those cases produces an error, you cannot go to the error case until all three complete. 2. There is a much better way to accomplish this with a queued state machine. I didn't know much about these when I first tried the event state machine concept. 3. Events seem to work best when there is some sort of asynchronous interaction happening, like a human or an external device. I use an event structure to poll a TCP connection (using the timeout case) and place the data into a queue which is then processed by a consumer loop. Sometimes, the data sent to the consumer contains a pattern when requires something to be sent out the TCP connection. In that case, I fire a user event from the consumer to tell the polling event loop to send the necessary command to the TCP port and then go back to polling for new data. This works very well. Good luck with your implementation! -John
  7. Well, I think I have this working as fast as possible now. Since the only feature of the cell that I use and that cannot be defined with the Add method is the color, I have changed my code to only write color changes to the cell properties for new rows. This sped it up a bit but it is still quite slow. I also am using a dialog box with a progress bar to entertain the user while the color updates are completed. I used a few tricks to only show this dialog for long updates (more than 300 rows).My GUI design requires each row to potentially have a different color in a specific cell. This is because I am using the tree to show test results and I want to color the cell that shows PASS or FAIL in green or red, respectively. So, the idea of coloring a whole column at once would not work, unfortunately.the real solution here is for NI to extend the Add method to include inputs for setting the cell colors, fonts, text sizes, etc... This could be done by passing in arrays for the child cells and element for the leftmost cell. This would allow the functionality of the control to be extended while still being fully backwards compatible with the current implementation. The Add method really needs to support all elements of the control.Another alternative would be to create a data type that could store all the tree information. Perhaps a typedef's cluster or arrays of clusters? The point would be to be able to write this data to the tree control in one action and have the tree display the data instantly. That would allow the developer to build up this data structure in their code quickly and only write it to the control for display when the GUI is needed by the user.Anyways, I hope someone at NI is paying attention... -John By the way, nobody seemed to notice or comment on the fact that writing the cell colors from the last tag to the first is faster than writing from the first to the last. Doesn't this seem strange to anyone? My first guess what it was a memory allocation effect (by writting the last tag first, you allocate the memory for all the cell colors at once) but this seems strange since the Add method should be allocating the entire memory structure at once. Any ideas?
  8. Unfortunatly, the coloring of the cells is an integral part of my display, so eliminating that is not an option. I will try your idea about only changing the color in the for loop and moving the symbol and test changes to the Add function call. If only I could specify the color of each cell in the add function... Thanks for the idea.
  9. Note: My comments apply to LV8.20. If you are using a newer version, YMMV... I have been trying to find a way to manage the Tree Control better in my code. I use a Tree to show the results of a series of tests. This works nicely since the tests are hierarchical in nature. My system can test many DUTs at once but I only display the results on one DUT at a time. So, I build a parallel data structure to hold the information normally written to the tree and I only update the tree when the user selects a certain DUT. This eliminates writes to the tree control except in cases where the user actually want to see the detailed data. Unfortunately, writing to the tree is VERY slow. Adding items is quick when you use Add Multiple Items To End, but if you also want to set the colors of individual cells, then it is painstakingly slow. The usual tricks of Defer Updates helps a little, but not much. So, I came up with an experiment to see what can be done about this. My discovery was that the order you access the tags in the tree dictates how slow that update is. If you write your changes form the first tag to the last, each write gets slower in an exponential manner. If you update in reverse order (last tag first) then the write speed is more constant (and quicker on average). Even so, it is still ridiculously slow. I have attached a VI that demonstrates these effects. Take a look and try the various options. Please post your results here and if you find a better solution. As for me, my best results were with Defer Update on, Update Tags in reverse and Write Tag with each update. (the defaults of the VI). In this instance, it took about 49 seconds to run the VI. thanks for any ideas you can add. -John
  10. I put the ideas in the thread to use and made an example of a transparent background splash screen that fades in and then stays visible while a startup process completes. Take a look at the attached VIs to see how this is done. You can replace the graphic with your own to customize this example. Be sure to use the PNG format for your graphic. I recommend Paint.NET as a good free editor for creating PNGs. The one in this example was built by lifting a graphic off NI's website. Hope you find this useful. -John
  11. Thanks for the code. I hacked together a simple VI to get around this issue for now. It only works on the formula left to right, one works with +, - *, / and will stop when it hits the end o the string or any non number or operator char. see attached. -John
  12. Has anyone written a VI that will take a simple math formula in a string like: 1+2-3 4+(5*3) 3-(4+5) And return the computed result? I know that NI provides this function in the Eval Formula String.vi in the Gmath library but that is the problem. They put this in a lvlib file. I am trying to build an application with the OpenG builder that includes this function and discovered that the OpenG builder cannot deal with lvlib files properly. Since my application is dependent on the namespace feature of the OpenG builder, my only option is to reinvent this math function myself outside of a lvlib. I have tried to find a way to extract this from the lvlib with no luck. So, can anyone help me not have to reinvent this wheel? Thanks for any help you can offer, -John
  13. I recently found a new way to get the reference of the current VI. There are several ways to do this but I think this new one is the cleanest I have seen so far. The original way I used to do this was to open a VI reference to the tip of the call chain, as shown in the 'old way.jpg' attachment. The problem with this method is it requires you to later close that reference (every open must have a close). The second method I started to use was to drop a property node and link it to the VI. I would simply not use the output property. This is shown in the 'second way.jpg' attachment. The new way is to just create a reference that is linked to the VI. I stumbled across this when playing around with passing object references to subvis. The only problem I see is there is no direct way to create this reference. You must always first create a reference to some FP object and then relink it to the VI itself. See the 'new way.jpg' attachement. Does anyone know of any advantage or disadvantage to any of these methods? thanks, -John
  14. I recently pointed this out to an NI Dev who is working on an improved Project view for a future release. They said they would try to resolve this issue. I agree it is very annoying as implemented now.
  15. Not sure if this is a bug or a 'feature' but I have run into an issue that is causing me some grief: I cannot register for an event on a FP object if the FP of the originating VI is not currently open. Here is how to see this: Make a VI that has an event loop structure with a register for events function. Wire a control refnum of a Boolean into the register function and select the value change event. Setup the event structure respond to this event and send the NewVal to the stop loop terminal. Make another VI with a Boolean control and create a refnum for this control. Drop your first VI onto the diagram and wire the refnum to it. Run this second VI and see it wait for you to press the button. Make a third VI that calls the second VI. Close the first two Vis and run this new one. You will get a message that states: "LabVIEW: The VI front panel is not open." OK, so on some level it makes sense to not allow events for FPs that are not open, since you would not be able to manipulate those controls. But, with VI Server calls like Value(Sig), that is not really true. I often 'push' buttons on Vis that are not open to stop them or perform some operation remotely that the user could do if the panel was open. And, I often have Vis that I only show the FP some of the time (such as in a sub-panel when they are selected from a listbox). I still want to pass their FP refs down to their sub-vis and listen for events. So, does anyone know some workaround for this that does not involve polling? That is how I have had to solve this so far, and I dislike polling almost as much as global variables... Thanks for the input. -John
  16. I have a VI that I use a ton in my code. The problem is, it is kinda slow. I am looking for a way to speed it up. The point of this code is to get a reference to a front panel control by name. The VI has an input for the VI Ref that has this control on the front panel and the name of the control to find (string). The output is the control's reference. I use this to monitor front panel objects from deep in my calling tree. One good example is to monitor an Abort button on the GUI's front panel and be able to stop a loop in some deeply buried sub-vi. The sub-vi just check the status of a button called 'Abort' on it's top static caller. If you have any thoughts on how to accomplish this code in a way that uses less CPU cycles, please post it here. thanks for the help. -John
  17. I am attaching the .llb again. I made some edits and improvements as well. You can now write data to nodes in the middle of the tree and the branches will be maintained. I also optimised the code a bit more. BTW: This is written in 8.20. I don't have a 7.1.1. system setup to downgrade the code to an older version. Sorry.
  18. Hi, I have put together a set of VIs to store data in a tree structure within LabVIEW. This method uses variant attributes to build the tree. Insertion is slower than a direct write to an array of clusters would be but reading back data is very fast. The reason insertion is slow is due to the dataflow nature of LabVIEW. The Tree must be rebuilt with each write. Take a look at the code and let me know if you find any bugs or improvements. This would be a good tool to implement with LabVOOP, but I have not yet dived into that subject so it will have to wait. The basic idea of the structure is that a variant can have attributes that are name-value pairs. The name must be a string, but the value can be anything. It can even be another variant that has it's own set of attributes. This is what enables the tree to be built. I have implemented three functions: read, write and delete. Each one operates on a single node in the tree. The data input is a variant. If a node in the branch path does not exist when writing, it is automatically added. The tips of each branch are the only places where actual data is stored in the variant. All branching nodes only contain attributes describing their sub-branches. The path to a tip node is described as an array of strings. Each element in the array is a node in the tree that leads to the tip where the data is stored. I also included some code that adds the top level caller VI name to the top of the path. This allows you to use the structure across several VIs and keep the data separate. We use this in a system where we spawn many VIs from a single VIT and need to maintain "global" local data. Storage of the tree is implemented as a LV2 Global. I hope you find this useful. If I have reinvented someone else's wheel, please send me a link to their code so I can compare and learn. -John BTW: When building this I found a bug in LabVIEW 8.20. The Get Variant Attribute function has an input called 'default value' that is supposed to default to an empty variant if nothing is wired. In practice, this function actually defaults to the last found variant from previous calls. So, to get it to work as described in the help, you need to wire an empty variant into this input.
  19. Try this: Open LabVIEW 8.2 Create an empty project Right click on the My Computer in the project and create a New VI Drop a tree control or multicolumn listbox or table onto the front panel Try to resize the column widths with the resize tool (looks like this: <-||->) If you can do this, it is because you do not have a source control system setup with LabVIEW. If you do have source control setup (I am using Perforce) and find that you cannot resize the columns (like me), try this: Locate the App Instance indicator on the lower left corner of the front panel. Change this from My Computer to Main Application Instance Now try to resize the columns in the tree or listbox or table. It should work. This must be the most bizzare bug I have ever seen in LabVIEW... -John
  20. If you did use separate app instances for your main exe and your plug-in VIs, would this whole problem go away? I am designing a new system that will use plug-in architechture and will need to solve this same issue. How many app instances can I have and how hard will it be to communicate between them? Anyone have some nice toolkits for managing all this? -John
  21. This is quite close to what I need, except I also need it to copy the background color of each cell. Not sure if I can mod it to do that. Another solution that just occured to me is to use sub panels to display the different VI's I am trying to monitor from my top level app's FP. That might be the simplest way to achive the desired results. -John
  22. Hi, I have a need to programmatically copy an object's data and attributes to another object of identical type. My application has a top level display window with a tree control. I spawn several copies of a sub process that collects data and formats it for display. Each copy of this sub process has a tree control on it's FP that it writes data to and sets attributes of (symbols, colors, etc). My top level application has a selector that chooses which of the running sub processes to monitor. When I select one, I need to copy the data and attributes of it's tree control to the tree control on the top level app's FP. I don't see any way to do this. There does not seem to be a 'get all attributes' and 'write all attributes' feature anywhere. Since they are the same datatype, this seems like it should be possible. Has anyone put together some code that does this? thanks, -John
  23. I am in desperate need of a solution today. If you have ever experienced this problem and know a work around, please let let me know how you solved it. The problem: I have a test machine with two networks cards in it. One is for connection to the corporate net and one is for connection to a local test net where my DUTs are attached. I have another machine on the corp net side that is running a LabVIEW app as a server. The test machine needs to connect as a client to the server app and send commands to control part of the test system. When I run the client code, I get error 1379: LabVIEW: The user failed a security authentication check. If I disable the network card in the client that is on the local test net (leaving the corp net connected) then everything works fine. It appears that if you have 2 network cards, then open application reference gets hosed up and will not connect. There must be a way to make this work. Thanks for any help anyone can offer in solving this. I have until the end of the day to get this system working.
  24. Hi, I need to create a LV app that will talk with other LV apps on several machines in our network. This app will allow one machine to connect to it at a time and process requests for controlling some hardware. I am trying to figure out what the best approach would be for the interface over the network. Here are the options I am considering: Straight TCP/IP Data socket Shared Variable The calling machine needs to request access, wait for it to be granted and then send and receive some data (most likely a cluster). The 'server' machine needs to accept connections from many different machines but only allow one at a time to manipulate the hardware resource. Does anyone have any experience with this sort of setup? What worked/didn't work for you? thanks, -John
  25. Yes, I store the ref in a global. In the example code, I do close that ref when the user exits. With regards to the references to the controls accessed via property nodes, since these 'references' were never opened, there is no need to 'close' them. They exist in memory as long as the VI that they belong to exists. They are really just pointers or 'sub-references' of the VI and not independant instances of the control in question. A good experiment would be to open several instances to a single VI, then close them one at a time and test your references after each close to see if they are still valid. You should see that the references not closed are still valid, since the VI is still in memory until the last reference to it is closed. Now, open a single reference to a VI and then access the references to the controls on that VI's front panel. Test each of these control references to see if they are vaild. Now, close the reference to the VI and re-test the control references, you should see that they are now invalid, since the VI is no longer in memory, even though you never 'closed' the references to the controls. A reference to a VI adds 1 to the # of callers list and causes it to stay in memory as long as the callers list is >1. This is the same way Windows works with DLLs. A reference to a control is neither opened or closed and is just a 'far pointer' to a data/display element of a VI in memory. I hope that clears things up a bit. See the attached VI as a demonstration of this. -John Download File:post-2411-1145311174.vi
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.