---
title: "Optimizations"
canonical: "https://documentation.chaos.com/space/APPSDK/132809019/Optimizations"
format: markdown
---
In this chapter we'll talk about possible optimizations when integrating App SDK for different languages.

## **Language agnostic**

---

### Material previews

If you implement a material preview pane in your application, you will need to start multiple renders of the same simple scene with different materials applied. You may notice that renderer initialization isn't particularly fast due to internal reasons, which will slow the load time of the pane. The workaround is to create an Interactive renderer instead of production, set `keepInteractiveRunning=true` and just apply the different materials to the same base object loaded from a preset scene. This should be used only in a for-loop. When the list of materials to be previewed is exhausted the renderer should be stopped to release its resources.

### Commit group of changes

In Interactive mode, use the `autoCommit=false` option of the renderer in addition to explicitly calling `renderer.commit()` to allow for a group of changes to be applied together. This will decrease the total time needed to apply the changes.

### GUI message processing

As the GUI message processing is enabled by default, disabling it during internal waits could improve the overall responsiveness of the integration software. The interface is called `setGUIMessageProcessing(bool enable)`.

### Memory and performance optimizations

- A performance optimization could come frоm transferring efficiently large data (vertices, map_channels, raw bitmap buffers) to V-Ray memory.
- Aside from external files, large data is contained mostly in typed lists such as VectorList and IntList (which can also be nested inside general heterogenic lists as is the case with map_channels).

> ℹ️ Plugin properties (parameters) are always set and read by value in all supported programming languages.

### List plugin parameter optimization tips

In all supported programming languages App SDK uses "smart" plugin parameter value setters that can guess and efficiently convert data in many cases:

- If e.g. the definition type of a plugin property being set is VectorList and you try to assign an array or a list of 3*N floats or doubles to it, the data will be automatically reinterpreted or converted to a VectorList of N elements often more efficiently than doing it in your code. This can be useful in cases where you receive the data in a format different from the expected one.
- So code like this will work (Python/js-like syntax is used in the examples below but the technique would work in all supported languages):   
`mesh.vertices = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9] # values are automatically converted`  
or  
`mesh.vertices = FloatList(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9) # value is directly reinterpreted`  
`mesh.vertices` value is now `VectorList(Vector(1.1, 2.2, 3.3), Vector(4.4, 5.5, 6.6), Vector(7.7, 8.8, 9.9))`
- Note that e.g. std::vector<double> in C++ and List<double> or double[] in C# will be automatically converted to FloatList, VectorList or ColorList efficiently depending on the property definition type.   
But to use it you'd have to call the general `Plugin.setValue(propertyName, value)` function because the property setters in C++ and properties in C# are strongly typed and wouldn't accept data of any other type.

## **Node.js specific**

---

> ⚠️ Plugin properties (parameters) are always set and read by **value**, not by reference!

### Sync/async

- Many methods in the Node.js binding offer both synchronous and asynchronous versions. When you don't have to wait for the whole process to complete, you can use the asynchronous version.
- In addition to the standard synchronous VRayRenderer object construction, the asynchronous API `vray.createVRayRenderer(callback, options)` is also available.
- Similarly, `vray.createVRayServer(callback, options)` could be used to construct a VRayServer object asynchronously.
- The following VRayRenderer methods have sync/async versions:` start, export, pickPlugin, pickPlugins, load, append, loadAsText, appendAsText, loadFromBuffer, appendFromBuffer, loadFiltered, appendFiltered, loadAsTextFiltered, appendAsTextFiltered, appendFromBufferFiltered, saveIrradianceMapFile, saveLightCacheFile, savePhotonMapFile, saveCausticsFile, addHosts, removeHosts, resetHosts, getAllHosts, getActiveHosts, getInactiveHosts`
- The following VRayServer methods have sync/async versions:` addHosts, removeHosts, resetHosts, getAllHosts, getActiveHosts, getInactiveHosts`
- The following VRayImage methods have sync/async versions: `createFromBuffer,` `save, compress, getDownscaled, getResized, getDownscaledCropped, getResizedCropped, getFitIn, getFitOut, getCutIn, load, loadSize`
- The following VFB methods have sync/async versions: `saveImage, loadImage`

### Typed Lists

- General lists in Node.js use JavaScript `Array`/`[]`. Typed lists are based on JavaScript typed arrays.
- `FloatList`, `VectorList` and `ColorList` are very thin wrappers around `Float32Array` and can be freely used as such (and Float32Array can be used instead in place of them in most cases).
- Similarly `IntList` is a thin wrapper around `Int32Array`.
- When you read plugin properties, you always get a copy of the underlying list data.
- However, when you set plugin properties, you may opt to set the Javascript typed array data directly into V-Ray memory. The behavior is controlled per VRayRenderer instance by its `VRayRenderer.maxTypedListsCopyByteSize` property. If a typed list data size in bytes is above the threshold specified by `maxTypedListsCopyByteSize`, the data contained in the Javascript typed array will be set directly to V-Ray memory. The default value of `maxTypedListsCopyByteSize` is -1 which means data will always be copied. You can changed it to 0 or to a small value (e.g. 200) to reduce memory consumption and make the code faster.
- V-Ray typed lists in Node.js once created, they cannot be resized (because typed arrays in JavaScript cannot be resized).

If needed, you may freely "convert" among all the different types of typed lists, typed arrays and node buffers by accessing their underlying `ArrayBuffer` binary data storage and passing it to the new type constructor:


<details>
<summary>Node.js</summary>

```javascript
var a = FloatList(0.1, 0.2, 0.3, 0.4, 0.5, 0.6); // let's have a float list
var b = Buffer.from(a.buffer); // now the buffer 'b' shares its bytes with 'a'
var c = new VectorList(b.buffer); // now the VectorList shares its data with buffer 'b' and the list 'a'
// 'c' is VectorList(Vector(0.1, 0.2, 0.3), Vector(0.4, 0.5, 0.6))
```
</details>

<u>Since v6.20</u>

Two new typed-list types were added in version 6.20:

- `PluginList` is a resizable plugin container that inherits from JavaScript `Array` but can store (only) plugin objects efficiently. Now functions like VRayRenderer.classes.Node.getInstances() return `PluginList` instead of js array which allows hundreds of thousand instances to be returned without much memory overhead. In most cases the already written user code will continue to work without noticing the underlying change. Also, user code can construct `PluginList`s explicitly and pass them to plugin property setters where lists of plugins are expected (but this is not mandatory).
- `TransformList` is a non-resizable array-like `Transform` objects container, somewhat similar to `VectorList`, `ColorList`, etc. but instead of being a thin wrapper around `Float32Array`, it contains its data in a `FloatList`/`Float32Array` internally. So when you access e.g. the element `transList[index]` you'll get or set a `Transform` object, not just a number as is the case with `VectorList` or `ColorList`.  
You can access the underlying `FloatList` data directly using the `TransformList.floatList` property.  
The function `GeomUtils.readScatterData()` returns a `TransformList` as part of the returned data.  
Also, user code can construct `TransformList`s explicitly (e.g. by wrapping existing `FloatList`/`Float32Array` instances) and pass them to plugin property setters where lists of transforms are expected.

## **C++ specific**

---

### Typed Lists

- The typed lists in C++ are based on `std::vector`, e.g. `IntList` is `std::vector<int>`, `VectorList` is `std::vector<Vector>`, etc. The general list `ValueList` is also based on std::vector and is `std::vector<Value>`
- The `Value` type is a union of all types that can be inserted in a list and can contain typed lists or `ValueList`.
- In C++ it is possible to set the data contained in long typed lists directly to V-Ray memory without copying leveraging the power of C++11 move semantics.
- All lists (based on `std::vector`), the `Value` type and plugin property setters support both copy and move semantics.
- For small data sizes (short lists up to several hundred elements) it is not beneficial to use move semantics as it has a small (a few bytes) dynamic memory allocation cost. But even if used, the data will be moved only above a certain threshold.


Plugin property setters selectively move or copy data depending on the type and size of the lists:

<details>
<summary>C++</summary>

```c++
VectorList vectors(500000); // A large list of vectors
// Fill in the list...

// This will set a copy of vectors inside V-Ray memory
GeomStaticMesh.set_vertices(vectors);

// But this will get the vertices data pointer and set it directly into V-Ray memory avoiding the expensive copy operation
GeomStaticMesh.set_vertices(std::move(vectors));
```
</details>


Or in a more complex example:

<details>
<summary>C++</summary>

```c++
VectorList vectors(500000); // A large list of vectors
IntList ints(1500000); // A large list of ints
// Fill in the lists...

ValueList channel;
channel.push_back(Value(1));
channel.push_back(Value(std::move(vectors))); // Move vectors data to Value and Value to ValueList
channel.push_back(Value(std::move(ints))); // Move ints data to Value and Value to ValueLis

ValueList mapChannels;
mapChannels.push_back(Value(std::move(channel))); // Move channel data to Value and Value to mapChannels
mesh.set_map_channels(std::move(mapChannels)); // Move large data (vectors and ints) to V-Ray memory and copy the rest
```
</details>

### Ref lists

This is an advanced feature, enabled by the `VRAY_SDK_INTEROPERABILITY` macro. Use these types for large lists of primitives. The available types are: IntRefList, FloatRefList, VectorRefList, ColorRefList, CharString, CharStringRefList, Value, ValueRefList. They are also suitable for migrating existing code written against the V-Ray SDK to the App SDK.

## **C# specific**

---

> ℹ️ Plugin properties (parameters) are always set and read by value, not by reference!

### Typed Lists and Arrays

- The data from/to .NET-managed memory is always copied to/from V-Ray unmanaged memory. But we need to minimize additional unnecessary copies.
- Typed lists in .NET are presented as `IList<T>` and are mostly based on `List<T>`. And `List<T>` (cast to `IList<T>`) is what you'll get when you read a plugin property.
- Plugin property setters also accept `IList<T>`. Although any type supporting the interface would work, the underlying code is highly optimized for `List<T>` and `T[]`.
- It is very important to note that arrays in .NET support the `IList<T>` interface explicitly. So if your data is contained in a `T[]` array, assign it directly to any property or pass it directly to any function that accepts `IList<T>`! It's counter-productive to convert `T[]` to `List<T>` in order to pass it as `IList<T>` and it will make unnecessary memory allocations and copies.
- When you know the length of the list beforehand, create it with the desired size. This will avoid unnecessary reallocations caused by extending the container. Or even better, just use a plain `T[length]` array.


### In summary

- Use `T[]` or `List<T>` when you create lists for V-Ray.
- Do NOT try to convert `T[]` to `List<T>`, use it directly! (`T[]` is convertible to `IList<T>`).
- Do NOT try to convert `List<T>` to `T[]`, use it directly.
- Pre-allocate the lists with the needed length (or just use arrays) where possible.


## **Python specific**

---

> ℹ️ Plugin properties (parameters) are always set and read by value, not by reference!

### Typed Lists

- The General lists in Python use Python `lists`/`[]`.
- The V-Ray typed lists, however, use dedicated types - `IntList`, `FloatList`, `VectorList`, `ColorList` and, since version 6.20, also `TransformList` and `PluginList` and they all support the sequence protocol. This means that in most cases they can be used as Python lists but they are much more efficient.
- All standard list operations like `a.append(4)` and `b+=a` work as well.
- Typed lists also support the memory view buffer protocol.

  
To be able to be as efficient as possible and to cover all practical cases, typed lists have some peculiarities. E.g. their positional and keyword arguments are entirely different:


<details>
<summary>Python</summary>

```python
a=IntList(1, 2, 3) # create an int list 'a' of 3 elements and a[0]=1, a[1]=2, a[2]=3
b=IntList(count=300) # create an int list 'b' with 300 elements initialized to 0. You can set their values later.

s=[1, 2, 3, 4] # if you already have a different sequence and want to create a typed array from its elements
a=IntList(source=s) # the 'source' keyword can be used.
```
</details>