FAQ: Development Issues


16.1 How can I improve performance?

 

Use Binary V

Using binary V rather than ASCII V will help improve the performance of your application. Binary V never has to be parsed, so AVS/Express will be faster to start and it will be faster when you access objects. Note that binary V is also more secure since your end users will not be able to read your V files.

To create a binary V file, leave off the .v extension for that file when you refer to it from within another V file, such as templ.v. Here are two examples showing this, the first using a newer library syntax, and the second using the older, libfile syntax. Both of these library specifications could be included in a templ.v file:

“v_files/MyAppTemplates”: TemplatesLib; /* new syntax */
flibrary TemplatesLib<libfile=”v_files/MyAppTemplates”,...

Notice that in both cases, there is no .v extension used when referencing the MyAppTemplates.v file. When the Object Manager loads that V file, it checks to see if a .vo file exists for it. If it does not, or if the .vo file is not current, the Object Manager creates one. Any subsequent time the Object Manager loads MyAppTemplates, it will load this .vo binary V file.

You can also save and read binary V files programmatically, using the OMbsave_objs and OMopen_file Object Manager library calls. For more information on these calls, see the OMopen_file and OMbsave_objs on-line reference pages.

Imaging Applications

This section lists tips to help you improve performance of applications that use image data.

To make your imaging applications run as fast as possible, consider the following list of suggestions.

  • Always turn off caching for imaging.

  • Specify the visual class to be 8-bit visual (even if 24-bit available. Note that multiple visuals are supported under UNIX only). It is slower to push around 24 bits than 8. For many images, the extra color resolution is not needed or does not buy you much. For example, to produce gray, the values for red, green and blue are almost the same. So there are only about 256 shades of gray. If all your images are gray-scale, having 8 million colors available will not greatly improve the color resolution of the image. You specify the visual class by setting the vclass subobject of a virtual palette object such as BestVirtPal. Set vclass to 3 to specify a PsuedoColor visual.

  • For scalar data with an 8 bit visual - use a linear ramp rather than dithering the image. Note that this suggestion applies only to scalar data and makes sense only when using an 8-bit visual (vector RGB values provide an exact color specification; neither a dithering technique nor a datamap is used).

  • Dithering is slower than using a ramp. To specify a linear ramp, first set the cube size to a reasonable value. This will often be 4, but the size will depend on what you are displaying. You specify the cube size by setting the cube_size subobject of the virtual palette object (a cube size of 4 is 64 colors). This is probably enough colors to get acceptable results when using the cube (for any RGB images you might have), but still enough colors for your ramp.

  • Specify that a linear ramp be used by setting the dith_tech subobject of the GD Object to 1 (0 specifies dithering).

  • If you need to render two or more images, they can share the colors if they use the same datamap and ramp values. Otherwise, the available colors will have to be divided up amongst them.

  • Point sampling is the fastest interpolation type for images. To set the interpolation type to point sampling, set interp_type (in GD Object) to 0.

  • For best performance when slicing through a volume (cine-ing), make sure the images are contiguous in memory (within each image), specify single buffer mode and turn the clear option off in the viewer.

  • Regarding the position of the data in memory, consider the hydrogen data set. This data is ordered in memory as a series of slices orthogonal to the Z axis. If you animate an orthoslice of hydrogen, you should see that it runs faster when the orthoslice axis is 2 than when the axis is 0 or 1. This is because orthoslice has to rummage through memory to construct a slice when the data is not contiguous. The same will be true for your data. (Note that you can also use the tile_volume module.)

  • The clear option in the viewer is on by default. This causes the viewer to erase the viewer window to the background color before drawing each frame. If you are attempting to draw animated frames as quickly as possible, and if the frames contains images that cover the same extents in the viewer window, there is no need to clear the viewer window for each new frame. Setting clear=0 in the GD View will avoid the cost of the unnecessary window clear operation. There is currently no interface to the clear parameter from the Data Viewer, so you need to set the value in the object directly. For a Uviewer2D in a SingleWindowApp, its path is:
             SingleWindowApp.Uviewer2D.Scene.View.clear

  • Note that this subobject is different from the Clear button in the DataViewer’s View Editors/Output panel. That clear button clears the frame buffer/Z buffer output; it is not related at all to GDview.clear.

  • In order to smoothly animate scenes, the default option for our views is to draw to one buffer, and then move (bitblt) the result to the view. This creates a smooth transition.

  • When animating through a series of images and the clear option is turned off, this extra copy is not necessary, so setting buffer mode to Single saves yet a little more time. (Single buffer mode with clear set to 1 will flicker as you loop through the volume.) Set the buffer mode in the buffer subobject of the View object, for example,      SingleWindowApp.Uviewer2D.Scene.View.buffer

3D Applications

The following suggestions are ways in which you can speed up rendering time in 3D applications. A few of the suggestions apply to 2D applications as well, but they give the greatest benefit with 3D rendering.

  • Turn auto normalize off in the camera. The auto-normalize feature is useful, but it takes rendering time to refresh the view and you may not need to do so in your application (or perhaps you will need to refresh the view, but you want to control how often and when). In some applications, it makes sense to turn auto normalize off. To do so, set Auto Normalize to None. The user interface for auto normalize is in the general panel of the Data Viewer’s Camera Editor.

  • In some cases, it makes sense to force an object to be rendered with 2D primitives, which is faster than rendering a 3D scene. To do this, set the space subobject of the GDObject(DefaultObject) to 1, Force 2D. You would typically set this on an alternate object - usually when the alternate object is a bounding box or wire-frame mesh. It increases performance by rendering 2D primitives, not a 3D scene. It is especially useful when running to a remote display.

  • Another way to improve performance is to use the smallest 3D renderer window that is reasonable for your application, especially for the software renderer.

  • You will get improved performance if you do not incur the cost (both time and memory) of generating normals, but you can do this only if they are not needed, for example if you have no lighting mode specified. You can access this feature from Modes selection in the DataViewer’s Object Editor. Set Normals Generation to None.

  • If the values in your Field that are used in the datamap will stay constant, you can set min and max to constant values. This will speed up rendering since the max and min values will never need to be recomputed. BE CAREFUL with this tip because you do not want to disable the computation of the datamap min and max if they are needed.

  • If you do want to disable the datamap min and max from being recomputed, you can set the instance property of DataObject.MinMax off (0). You can also rewire the network to remove the MinMax object and store this subclass of DataObject in a library (before you delete MinMax, note what values it outputs for min and max and use these constants in the Datamap module.)

  • Remember to use a lighter weight DataObject, if possible. See Chapter 16, Application Design Issues of the Using AVS/Express manual for information on how to pare down a DataObject (or use the DataObjectLite provided in AVS/Express version 3.1 and later).

  • Cell set rendering traversal is expensive, so use as few cell sets as possible. When writing new modules that create output meshes with cells sets, group as many primitive cells as possible in each cell set. Use polyhedron type cell sets where possible for efficient rendering.

  • You may want to disable the caching of geometric data in some cases. To render an object, a Field is first converted to geometric data structures. Then a renderer specific routine is called to render the data. By default, the geometric data structures are cached (DefaultObject.cached = 1). This is so this conversion which can be relatively expensive is done only once.

  • It is possible to disable caching by setting the cached subobject of DefaultObject to 0. When caching is disabled, the conversion from field to geometric data structure occurs each time you render. You trade off compute-time for a benefit in the amount of memory required. You can render much larger data sets with less memory, but it will be slower.

  • Note that the geometry data is most often larger than the original field data since it contains normals (3 floats) and colors (3 floats) for each node where there may have only been 1 byte of data in the Field. Turning caching off along with the default surface conversion attributes (chunking of 1000 cells at a time) means that the GD imposes virtually no memory overhead on the system -- at the expense of having to recompute the geometry every time.

  • This recomputation varies depending on the type of cell set. A polytri cell set may see just a little degradation with caching off but a tri or quad cell set will see a lot of degradation with caching off.

  • There is one more case where you might want to turn caching off. The OpenGL renderer has severe performance problems with frequent create/delete operations on display lists. This cycle happens every time you change the isosurface level for example. If you are using the OpenGL renderer and performing an operation such as animating iso level changes, turning off caching will give you better performance.

  • Remember that if you turn caching off, set it off in all applicable objects (the object itself, Top and so on).

General

Some other ways you can speed up the performance of AVS/Express are listed below.

  • Turn off module flashing (from Options menu). This is a useful feature but has a performance cost associated with it.

  • Disable status checking. This feature, while useful, can be quite expensive. If you disable status checking, you cannot interrupt an executing module and the status bar which indicates the progress of a module will not update. To disable status checking click the Disable status button on DataViewer status bar.

  • Set the compile_subs property off on libraries that do not contain any modules (source code). Doing this will speed up Project->Compile because the Object Manager will not need to look in those libraries for objects it needs to compile.

  • Use the $set_arr_trace V command to show memory allocations/frees. This command will show you where memory allocation is occurring in your code and may point out way you can manage memory better. Remember that the information returned is for only those arrays allocated using the ARR routines (that is, all arrays that are stored in Object Manager objects).

  • Link objects into the express process for your final application. External processes, such as user, are useful for development. Applications run much faster when all modules are linked into a single process, so you will want to ship your application with all objects linked into the express process.

  • Use Project->Configure to link in only those libraries you require. This will make your project’s version of express or your runtime application smaller and faster. You must relink express after you configure out a library.

  • Use the buffered property to specify that a library be buffered. Buffered libraries to speed up load time. (Note that buffered is actually a base type and not a property so you cannot access it through the Properties Editor; you must set it in V).

  • Buffered libraries speed up load time because they are loaded in two phases. First the V-file is loaded in its entirety. Each object in the library is stored as a stripped down list of V commands necessary to define that object. When an object in the library is opened, the V is parsed as ASCII V and the object’s full definition is loaded.

    Example:
      library+buffered FOO {
         group OBJ1 {
            int a; /* parameter a */
            int b;
         };
      };


    After loading the first stage the definition of the library looks like this:

      library+buffered FOO {
         buffer OBJ1;
      };


    Internally OBJ1 would store the string:

      “group OBJ1 { int a, int b; };”

  • In the Network Editor, the OBJ1 object is displayed with parentheses around its name “(OBJ1)”. You cannot yet see its input and output ports. When OBJ1 is accessed, the V is parsed as ASCII V, the parentheses disappear and the object’s ports are displayed.

Array manipulation in V

Avoid performing a lot of array manipulation in V. If you have V code that contains chains of concat_array, interleave_array, etc., performance can suffer. The OM is written to optimize for storage space at all cost. Every time you access an array element, the OM follows the chain of references back to the original array. This can be significant overhead if you are repetitively accessing the array elements. Either write a module to do the array manipulation or use the cache V function.