4 Ways to Optimize a Conversion
When it comes to choosing the right data type for your application, conversion is usually one of your first concerns. This is often due to the difference in data types between your hardware API, your front panel terminals, or by data transfer APIs (most of them use strings!) And like many other high-level programming languages, LabVIEW offers more than one conversion option. Let's look at one common conversion example (a byte array to a double precision number) and compare 4 methods:
- Cast Type
- Flatten + Unflatten
- Byte Array to String + Unflatten
- MoveBlock
1. The Straight Cast
You probably know the Cast Type function, the Swiss Army knife for conversion. It accepts a whole lot of source and destination data types and usually works well as long as you convert data of the same size.
Yeah that's very simple. But what about the performance? Is that fast? Does it use a lot of memory? Because it all depends on so many factors—computer, application, OS, data types, etc.—the only answer comes from profiling. Let's benchmark the execution speed and monitor the memory usage (easy using Tools>Profile>Performance & Memory...) for 1 million conversions.
The results: 260ms, 2764B.
This is not particularly slow but I bet you can do better than this!
The Cast Type function help mentions that it flattens and unflattens the data. Let's do it manually and see how we can tune the conversion.
2. The manual way: Flatten & Unflatten
Flatten and unflatten, right?
This technique is usually used to transfer data between multiple applications or targets, but in this case, it looks more complex than our first attempt. Unfortunately it's also considerably slower (~580ms) and eats up more memory (2872B.) Flattening is rather slow as it consists in formatting the data in a certain way, and putting the data in a contiguous memory space (many data types are resizeable so they're not stored contiguously in memory.) Also, we don't want the size of the byte array to be part of the string, so we force the function to detect it and omit it in the result, and this option dramatically decreases the performance.
Just forget this option right away!
3. Is the Byte Array to String function faster?
If flattening kills the speed, you could try to replace it and keep the unflattening part. Luckily, there's a small function that greatly simplifies the conversion into a string. Let's give it a try!
Figures? 120ms and 2796B! Woot! Here's a short explanation: the Cast Type function sort of deals with an internal flattening and memory reallocation, as a byte array is naturally different from a double in memory (is non-contiguous, and stores the dimensions sizes). Here, we simply treat the array like a sequence of ASCII characters, much like in C, hence the x2.2 gain in speed. The numbers are quite satisfying, but you could try one last thing with lower-level functions.
4. Diving into memory management
What if you could control the memory by yourself? There's some documentation for this, and the MoveBlock function seems to be what you need here! That function takes a pointer to some data and moves it to the location and data type of your choice.
There's an extra setting about endianness in that solution, so you'll have to revert the array before the MoveBlock call. With or without that, the call into the LV Manager doesn't allow for any compiler optimization and that unfortunately kills the speed, as it forces a reallocation for every call, with a result of 180ms and 3113B.
Conclusion:
Do try to find alternatives to the simplest solution. Don't necessarily overdo it as you may waste your time, make your code more complex for poorer performance results.
You cand find the VI I used for this post here if you'd like to take a look or benchmark for yourself. Enjoy!