1. Hang on to Objects:
If you have an application where you need to use an object on a regular basis, create the object once and hang onto it. Don't repeatedly create objects and then throw them away.
Here's an example:
Let's say that you have a routine that is regularly called. This routine checks for clips in a bin. The routine runs every 30 seconds. In this routine you use aMediaMgr object to make CheckAsset calls. Rather than creating a new MediaMgr object each time the routine is called, create the MediaMgr object once and store it somewhere in your program.
This will eliminate excessive setup and teardown of objects both in the client application and the K2.
2. Take a Breath:
If you have a routine that is repeatedly making calls that are, for example, looking for a status change, make sure that you allow enough time between calls for something to happen. If you write a tight loop with no delay between calls, both your client application and the K2 server will become so busy setting up and tearing down calls thatAppService won't have time to do the work that you are waiting on. Additionally, CPU usage of both application will go up dramatically and the client may have so many calls queued up that it runs out of worker threads to handle all of the calls.
Instead, consider how much time is appropriate between calls and make sure that your routine waits that amount between calls.
Additionally, see #3 to see how you can combine multiple property calls into one property call.
3. Get Multiple Properties in One Call:
For GetProperty or GetStatus calls, multiple properties can be requested by putting more than one string in the property query. This is more efficient than making multiple single property queries.
Property names should be separated by white space or the ‘+’ character. When a single parameter is requested, an object (for C#) or variant (for C++) is returned of the appropriate type. When returning multiple values, an object array (for C#) or a variant of variants (for C++) is returned where each contained object or variant is of the appropriate type. The order of elements in this array matches the order in the property query.
See MediaMgr's Get Asset Properties and ChanStatus's Get Channel Status properties for examples.
4. Call CloseResults after MediaMgr Enumerate* calls
For the MediaMgr calls EnumerateVolumes, EnumerateBins, and EnumerateAssets, you need to call CloseResults on the cookie when you are finished using it. Your MediaMgr object only gets ten database selectors to work with. Everytime time you make an "Enumerate" call you use one of the selectors. Once you run out of selectors, your "Enumerate" calls will fail. You will also see “Too many open select statements: limit is 10” errors in the log. CallingCloseResults frees the selector and makes it usable to MediaMgr again.
Here is an example using EnumerateBins:
[C++] IMediaMgrPtr spMediaMgr; hr = spAppServer->CreateMediaMgr(m_bstrAppName, &spMediaMgr); _bstr_t volume("V:"); long count = 0; long cookie = 0; hr = spMediaMgr->EnumerateBins(volume, &count, &cookie); printf("hr = 0x%x, # of bins = %d\n\n", hr, count); // ... loop code to GetXmlResults ... // make sure your close the results! hr = spMediaMgr->CloseResults(cookie);
See Get a List of Clips for another enumeration example.
5. GetXmlResults performance
Some MediaMgr calls are asynchronous calls. The way they work is that you make a call that returns a cookie and then make subsequent calls using that cookie to get results back. Warning: for any call that returns a cookie, you must call CloseResults on that cookie when you are finished using it. If you do not, you will soon run out of tokens and your calls will throw exceptions!
EnumerateAssets is an asynchronous call. Calling EnumerateAssets on a volume and bin will return a cookie. Use that cookie to make GetXmlResults calls to get results about the assets. GetXmlResults takes a starting index variable and maxCount variable that specify how many results to return. The K2 server internally builds aDOMDocument that contains the results. The performance of building DOMDocuments is good for small documents, but suffers as it grows large. The end result is that the GetXmlResults calls will take a long time to return for large maxCounts. For best results, you should iteratively call GetXmlResults with small maxCount sizes using code similar to the code below.
To illustrate this, for a bin with 3500 clips in it, these are the total times for iteratively calling GetXmlResults for all assets using different maxCount sizes:
|GetXmlResults timings for 3500 clips|
|maxCount||iterations||total time (in seconds)|
Given the results, it is recommended to always use a maxCount value no larger than 512 and iteratively calling GetXmlResults when necessary.
Warning: Another issue to consider is that calls that build DOMDocuments on the K2 server impact performance. The more simultaneous GetXmlResults calls that you make, the slower calls will return. Also, MediaMgr will only allow 10 cookies open at a time. The 11th request will error so, as stated before, make sure you call CloseResults on cookies when you are finished using them.
So, if you are writing a client that needs to enumerate assets on several directories, it is recommended that you build functionality in your code that both throttles the number of simultaneous XML calls and caches the data. You should also then rely onGetXmlChanges to keep your cache information up-to-date rather than calling EnumerateAssets again as GetXmlChanges is a much lighter, faster call.
See Get Event Notifications for an example.
6. Writing a Clip Cache
Many people need to keep track of the contents of a bin. The best way to do this is to:
- Get a list of all assets in a bin using MediaMgr's EnumerateAssets and GetResultProperty calls.
- Cache the results you want in your data structure.
- Periodically call MediaMgr's GetXmlChanges function to see what has changed and update the results in your data structure.
The reason for using this technique is two-fold:
- EnumerateAssets is an expensive database calls on the K2. You want to call this as infrequently as possible.
- GetXmlChanges is a light-weight call. It only returns the information that has changed since the last time you called it.
By taking advantage of this and updating your data structure, you'll get the best performance and eliminate unnecessary calls.
7. Don't Hardcode the V: Drive
Instead of using a hardcoded "V:" for the K2's volume name use MediaMgr's EnumerateVolumes() function to programatically determine the volume name. See this example on how to Query for Volume or Drive Letter.
The reasons you don't want to hardcode the drive letter are:
1. The K2 and future products may support additional drives. By enumerating the volumes you will get all volume names supported by the server.
2. The K2 Emulator uses a "C:" volume name instead of "V:". By using the EnumerateVolumes function instead your application will be able to connect to both the K2 and the K2 Emulator without needing changes to your code.
Here is an example of the XML results returned from MediaMgr's EnumerateVolumes function. The volume name can be found in the Dataset element near the bottom: