Vault Performance tip – don’t access the server in a loop

By Wayne Brill

When using the Vault API to access the server you can improve performance by not having server calls inside a loop. Below is a code snippet that is using GetPropertyValue and GetFoldersByIds in a loop. (highlighted lines). In this example if there are 1,000 files in myResults, there will be 1,000 server calls. With network latency, there is just not a good way to make 1,000 server calls very quickly.

foreach (File myFile in myResults)
{
VDF.Vault.Currency.Entities.FileIteration fileIter = new VDF.Vault.Currency.Entities.FileIteration(base.VaultConnection, myFile);

EntityStatusImageInfo statusInfo = base.VaultConnection.PropertyManager.GetPropertyValue(fileIter, statusProp, null) as EntityStatusImageInfo;
MYVaultFileStatus myVltFileStatus = new MYVaultFileStatus(
myFile.Name);

 

myVltFileStatus.VaultStatusText = statusInfo.Description;
myVltFileStatus.VaultStatusImage = statusInfo.GetImage();
long folderID = myFile.FolderId;

var folderFoundIn = base.VaultConnection.FolderManager.GetFoldersByIds(new long[] { folderID });

 

VDF.Vault.Currency.Entities.Folder folderOfFile;

folderFoundIn.TryGetValue(folderID, out folderOfFile);
myVltFileStatus.VaultPath = folderOfFile.FolderPath;
myVltFileStatus.VaultFileID = myFile.Id;
listDocumentStatus.Add(myVltFileStatus);
}

A better approach is to use web service calls that allow you to retrieve properties for a group or batch of files with a single call to the server. These methods typically accept an array of IDs or proxy objects so that you can retrieve a large collection of values with a single call.

The PropertyManager GetPropertyValues is nearly identical to  GetPropertyValue except that it takes an array of entities and property definitions and retrieves all the property values at once with a single server call. This is what “using batch API methods as a best practice” means.

Here is an update to the example code with just two calls to the server:

 
// batch up entities to retrieve properties for
List<VDF.Vault.Currency.Entities.FileIteration> fileIterations =
new List<VDF.Vault.Currency.Entities.FileIteration>(myResults.Select(result => new VDF.Vault.Currency.Entities.FileIteration(base.VaultConnection, result)));

// make a single call to get property values
VDF.Vault.Currency.Properties.PropertyValues propValues = base.VaultConnection.PropertyManager.GetPropertyValues(fileIterations, new VDF.Vault.Currency.Properties.PropertyDefinition[] { statusProp }, null);

// make a single call to get parent folders
IDictionary<long, VDF.Vault.Currency.Entities.Folder> folderIdsToFolderEntities = base.VaultConnection.FolderManager.GetFoldersByIds(fileIterations.Select(file => myFile.FolderId));

// individually process results returned from the server
foreach (VDF.Vault.Currency.Entities.IEntity fileIteration in fileIterations)
{
VDF.Vault.Currency.Properties.EntityStatusImageInfo statusInfo = propValues.GetValue(fileIteration, statusProp) as VDF.Vault.Currency.Properties.EntityStatusImageInfo;
MYVaultFileStatus myVltFileStatus = new MYVaultFileStatus(fileIteration.EntityName);

stVltFileStatus.VaultStatusText = statusInfo.Description;
stVltFileStatus.VaultStatusImage = statusInfo.GetImage();
VDF.Vault.Currency.Entities.Folder folderOfFile;

if (folderIdsToFolderEntities.TryGetValue(fileIteration.FolderId, out folderOfFile))
{
stVltFileStatus.VaultPath = folderOfFile.FolderPath;
}
stVltFileStatus.VaultFileID = fileIteration.EntityIterationId;
listDocumentStatus.Add(stVltFileStatus);
}

The key is that the calls to the server have been moved outside the loop.


Comments

One response to “Vault Performance tip – don’t access the server in a loop”

  1. Tommy Dager Avatar
    Tommy Dager

    Hi Wayne
    Thanks for a nice article.
    Unfortunately your sample results in a implicit webcall for folder information for each call to propValues.GetValue(fileIteration, statusProp)
    If the result files are in the same folder this can easily fixed just by getting and adding the entityfolder to the fileiteration call:
    List fileIterations =
    new List(myResults.Select(result => new VDF.Vault.Currency.Entities.FileIteration(base.VaultConnection, entityFolder, result)));

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading