A Case Study in LabVIEW Upgrades: Part 1 - Telecom Test Executive
Table of Contents
Overview
Throughout the years, National Instruments R&D has developed a process for upgrading LabVIEW applications internally. To help programmers upgrade their LabVIEW applications, NI is publicizing this upgrade process, along with several examples of NI R&D assisting customers upgrade their large LabVIEW applications. This tutorial is Part 1 of a two-part series of case studies documenting these R&D-assisted upgrades. Each case study walks through the upgrade process for a specific code set, examines issues that arose, and offers information on the techniques used to solve each issue.
For more information on the upgrade process used throughout these case studies, click here.
Visit ni.com/labview/upgrade for more information on upgrading your LabVIEW applications.
Code Description
This international telecommunications company has been developing a test sequencing application, known as Eagle for the purpose of this case study, in LabVIEW over the past 10 to 15 years. The main engine, the “core,” of Eagle dynamically runs tests based on a profile that the user provides. These tests are created in LabVIEW by developers in many different groups all over the world. Recently, this company upgraded Eagle and associated tests from LabVIEW 7.1 to 8.5. Doing so produced several broken VIs that effectively broke many hundreds of VIs upstream. Among other challenges of the upgrade were the perception of poor performance and memory management by LabVIEW, with a specific example being a cyclic redundancy check (CRC) function developed in LabVIEW compared to one developed in C. Furthermore, the test sequences run in Eagle were taking much longer to execute than other similar applications developed in languages such as .NET.
Size of application: 3,000 VIs
The Upgrade
This upgrade case study is unique in that the international telecommunications company had attempted to perform its upgrade, and approached NI with three specific complaints:
• Performance degradation during previous upgrade from LabVIEW 7.1 to LabVIEW 8.2
• Performance of CRC function in LabVIEW versus that in C
• Large number of broken VIs upon initial opening in LabVIEW 8.5
This paper examines the resolution of these issues as well as a few LabVIEW coding suggestions that can be applied across many large applications.
Performance Degradation during Previous Upgrade
The developers at the telecomm company were able to load Eagle and all of the associated source code in LabVIEW 7.1 but not in LabVIEW 8.2. Attempting to do so caused LabVIEW 8.2 to crash, which was extremely reproducible. Doing the same thing in LabVIEW 8.5 also caused a crash, but before crashing, LabVIEW displayed a "Not enough memory to complete this operation" dialog. LabVIEW 8.5 is Large Address Aware, which enables the LabVIEW process to take advantage of the /3GB Windows setting. Enabling the /3GB flag in the Windows boot.ini file allows the LabVIEW process to use another gigabyte of user-level virtual memory and creates space for master_library.vi (and all of the Eagle source code) to be loaded in memory. However, this should be viewed only as a temporary solution because it is not scalable.
The perceived performance decrease after upgrading LabVIEW was actually a misconception. When benchmarking the actual performance of the software on test computers at NI, the result was a performance increase, not decrease. When the company’s developers similarly ran benchmarking tests on their upgraded code, they saw the same performance improvement. The perception of slowness was because of the requirement to recompile the VIs when they are first loaded into a newer version, which was not done. The solution in this case was to perform a mass compile operation on the source base to bring it all up to the current version.
Performance of CRC Function in LabVIEW versus C
The CRC function developed in LabVIEW originally took almost 7 seconds to execute. The CRC function was analyzing small chunks at a time of a large string. Instead of iterating through the string chunk by chunk using a string index, they were splitting the string into two separate strings each time. This resulted in new memory allocations each time the loop iterated. By using the Show Buffer Allocations tool, the developers were able to identify the potentially inefficient memory allocations in their code. Modifying the VI to use a string index improved execution performance from 7 seconds to fewer than 50 milliseconds.
Large Number of Broken VIs upon Initial Opening in LabVIEW 8.5
When initially opened in LabVIEW 8.5, the top-level VI reported more than 100 broken VIs, rendering the application unable to be run. Using the Error List dialog box in LabVIEW 8.5, NI engineers determined that the high number of broken VIs was due to seven broken subVIs. Because these subVIs were used extensively throughout the application, these errors propagated up the VI hierarchy and inflated the number of VIs originally thought needed to be fixed. The main cause of the broken VIs was a series of code interface nodes (CINs) containing external subroutines, which LabVIEW no longer supported as of Version 8.2. The VIs containing CINs with external subroutines were actually copies of old vi.lib VIs from the analysis library in LabVIEW 6.x.
When NI makes changes to a VI contained in vi.lib, mutation code is also created. This code runs when a VI created in an earlier version of LabVIEW is loaded. This mutation code modifies the code so that it works the same way as it did in previous versions, only with the new version of the VI. Furthermore, fixes internal to the VIs in vi.lib do not affect how they are used but do affect performance and compatibility, such as rewriting VIs to use DLLs instead of CINs with external subroutines. Take, for example, a scenario where a customer wants to upgrade from LabVIEW 6 to LabVIEW 8.5. Copies of vi.lib VIs were made outside of vi.lib, which works great so long as the customers does not upgrade. However, when it becomes time to upgrade, LabVIEW 8.5 replaces all calls to vi.lib VIs with the new version of those VIs, including all bug fixes. Because a copy was used, LabVIEW is no longer able to recognize that copy as belonging to vi.lib and leaves it as is (in other words, in its LabVIEW 6.0 state, without the benefit of any bug fixes or performance enhancements).
For a successful upgrade to LabVIEW 8.5 in this specific case, while maintaining their current structure, the copies of vi.lib VIs saved to LabVIEW 6.x needed to be saved over with the corresponding LabVIEW 7.1 versions so that the target upgrade version of LabVIEW would recognize them as vi.lib VIs. Because these VIs were older versions of vi.lib VIs, newer versions of these VIs were able to be used, in lieu of rewriting the entire source code for the CINs. During the LabVIEW 6.x timeframe a local copy of the required vi.lib VIs was saved and linked to as source code. These vi.lib VIs were required by the dynamic tests called by the main application with the intention of being able to run Eagle as an executable on a machine with only the LabVIEW RTE installed. This type of architecture is highly discouraged. The recommended solution was to use a build process (source distribution) to output the test VIs linked to a support LLB, or directory, containing the dependent vi.lib VIs.
Additional Issues That Are Widely Applicable
By virtue of having NI R&D eyes on the Eagle source code, NI was able to provide several other suggestions for optimization to the telecom company. The remainder of this paper outlines these suggestions.
Declaring Variables
One coding practice commonly used throughout Eagle that we discourage was creating front panel objects as a way to instantiate a variable and then use local variables for all access to this data. In fact, some controls were not even used for front panel manipulation or data passing, but for data storage instead. The intention was that local variables were used for all controls and indicators as a way of making the code more readable in addition to the ability to write data back to controls for data storage. Because using local variables is significantly slower than wiring from the terminal, this was causing the system to be much less responsive than if the developers used dataflow to pass data in their VI. Furthermore, the performance penalty of using local variables was discussed, and a plan was set in place for the Eagle developers moving forward.
Non-connector Pane Changes and Upstream Recompiles
One point of contention was the reasons why apparently insignificant changes to a VI required a recompile of many VIs upstream, that is, the callers of that VI. LabVIEW has a memory management algorithm, called the inplaceness algorithm, that determines when memory can be reused and when new memory must be allocated. If a VI is changed such that an item on its connector pane can be operated on in place, then the calling VI does not need to allocate extra memory for the data passed out of the VI. Even though there is no change to the source code (visually, the calling VI looks exactly the same), there is a required change to the object code of the calling VI to reflect the new memory optimization. Because LabVIEW does not separate the source and object code into separate files, such as foo.c and foo.o, changes to a VI that seem inconsequential but affect whether callers need to allocate memory requires recompilation of these callers to create the necessary object code. This is actually a common point of confusion with LabVIEW developers, especially with large application developers from a text-based background.
Summary
The case of Eagle is a great example of how to avoid becoming overwhelmed when you first open your code in a new version. Be sure to use the VI Hierarchy and the Error List dialog box to identify exactly which VIs are broken. Broken subVIs propagate up, so always start at the bottom and work your way up.
If you are interested in reading more, view the second part of this series, A Case Study in Upgrading LabVIEW: Part 2 - Automated Semiconductor Characterization
For more information on the upgrade process, click here.
For more information on upgrading LabVIEW applications, visit ni.com/labview/upgrade.
Reader Comments | Submit a comment »
Legal
This tutorial (this "tutorial") was developed by National Instruments ("NI"). Although technical support of this tutorial may be made available by National Instruments, the content in this tutorial may not be completely tested and verified, and NI does not guarantee its quality in any way or that NI will continue to support this content with each new revision of related products and drivers. THIS TUTORIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND AND SUBJECT TO CERTAIN RESTRICTIONS AS MORE SPECIFICALLY SET FORTH IN NI.COM'S TERMS OF USE (http://ni.com/legal/termsofuse/unitedstates/us/).
