Scalability

While the default library suffices for small-scale WebDAV installations, there are areas that can be optimized for maximum performance, and operations in a load-balanced environment.

This manual aims to cover the most important bits.

Tree

All operations are done on Nodes managed by the Tree class. In order for the ObjectTree to find the nodes, it must traverse the entire tree.

You should optimize getChildren() and getChild() in your nodes as much as possible to accommodate for it.

You can avoid traversing the tree by subclassing Sabre\DAV\Tree and overriding getChild, getChildren and childExists with your own methods.

If this really helps you highly depends on your situation. Profile first, optimize after.

Move and Copy

Move and Copy operations can be slow, especially when moving/copying bigger objects.

Each of these methods traverses the entire tree, and operates on them one-by-one, as an example, a move of a directory follows the following pattern:

It's possible to optimize move a great deal by implementing Sabre\DAV\IMoveTarget. This interface allows a collection to 'receive' a node that's being moved.

There's currently not an equivalent for copy, because moves are typically an operation that can be optimized in a lot of systems if it's a simple 'rename', but this is often not true for copy operations.

To optimize copy, you must subclass the Tree class and reimplement the function there.

Delete

Delete operations might also by default traverse the tree and delete nodes one by one. If your backend allows it, you might be able to optimize quickly deleting subtrees simply by making modifications to a Node-specific delete function.

CalDAV

If you created your own CalDAV backend, it may make sense to try to optimize calendarQuery. The Sabre\CalDAV\Backend\AbstractBackend class provides a standard implementation, that fetches every object for a calendar and tries to see if the query filters out the object, or not.

The Sabre\CalDAV\Backend\PDO class tries to optimize this, by filtering a bunch of common queries and directly applying them to the SQL queries.

In some cases it's confident enough to know that no further iCalendar parsing is needed to figure out the final results.

It is also recommended to make sure that your getCalendarObjects method does not return the iCalendar object, but it does return the 'size' and 'etag' property.

This allows the server to not have to fetch the objects at all for certain large operations, which can save a lot of memory.

Multiget

If you use CalDAV, CardDAV or WebDAV-Sync operations, the server often has to access many nodes by name.

This can be optimized by nodes by implementing the Sabre\DAV\IMultiGet interface. This is implemented by default by the CalDAV and CardDAV backends.

Load Balanced SabreDAV

SabreDAV has a few standard utilities for locking and catching 'temporary files'. These classes (Sabre\DAV\TemporaryFileFilterPlugin and Sabre\DAV\Locks\Backend\File) store information on the filesystem.

It would be possible to store these files on a network location instead, as long as the network filesystem has proper support for flock() (which NFS as an example doesn't).

The Locks backend in particular also comes in a Sabre\DAV\Locks\Backend\PDO flavour, which can store locks in MySQL or PostgreSQL database.

Currently 'temporary files' don't get cleaned up, and a cron job should be made to delete older files (>1 hour).

Large Files

Read: Working with large files.