Caching

Objectiphy uses an in-process cache to avoid unnecessary database lookups and object hydration, and a persistent cache for mapping information and proxy class definitions. By default, a file-based cache is used for persisting mapping information, but you can pass in any PSR-16 cache of your choice instead (eg. to use Redis or Memcached). To pass in your own cache, just call the setCache method on the repository factory before you create any repositories.

Production mode and Development mode

The behaviour of in-process and persistent caches is different depending on whether Objectiphy is running in development mode or production mode (details about these differences are explained below). By default, Objectiphy runs in development mode, but you can tell it to run in production mode by passing true as the third argument to the constructor when creating a repository factory (see the quick start page for more information and examples). When running in production mode, you must also supply a directory for the cache to write to as the second argument - even if you are using a non-file-based PSR-16 cache (because the proxy class definitions still need to be saved to the file system, even if you are not using the file system for caching).

Important! Please ensure that the cache directory used is not publicly accessible, as you don't want hackers looking through your cache files! Although they do not contain any of your data, they do contain details that give clues about your source code and data structures.

It is recommended to ensure that you do set Objectiphy to production mode on your live system, as this will bring performance and memory usage benefits (note: Objectiphy's integration tests run about 4 times faster in production mode than in dev mode). In addition, if you leave Objectiphy in development mode and do not specify a cache directory, it will use the PHP temp directory by default, and this could cause issues if the garbage collector deletes files that are being accessed by more than one process. As part of your deployment process, you should ensure that the cache directory (ie. the directory you specify as the second argument to the constructor when creating a repository factory) is cleared down (otherwise, any changes you made to your entities might clash with the proxy class definitions and cached mapping information, causing errors).

In-process Entity Cache

Creating entities requires a significant amount of processing - parsing mapping information, loading data from the database, and traversing the object model to hydrate all of the properties. Objectiphy therefore holds onto the entities it creates for as long as the repository factory exists, so that it does not have to create them again. Typically a repository factory exists for the duration of a request, so expensive objects are only built once per request. Keeping track of entities that have already been created also allows Objectiphy to detect changes and therefore only save the fields that have changed.

Whilst this in-process caching can greatly improve performance, it comes at the price of increased memory usage, as it holds onto references to created objects, preventing the garbage collector from freeing up memory. If you find yourself in the situation of needing to reduce memory usage, and can tolerate increased CPU usage and slower performance, you can clear the in-process cache by calling the clearCache method on a repository. When calling the method, you can optionally restrict the cache clear to objects relating to one particular entity class name, and you also have the option of clearing the mapping cache at the same time (this clears the persistent cache, described below).

If you want to turn off in-process caching, you can use the DISABLE_ENTITY_CACHE config option to automatically clear down the cache on each call (note, the cache will still be used to prevent recursion, but every method call on the repository will clear the cache down before it executes).

In-process Explanation Cache

When in development mode, or if you specifically request it in production mode by setting the RECORD_QUERIES config option to true, all query objects that are executed and all SQL that is generated are stored in memory for debugging purposes. If you run a large number of queries, or very large queries, this can also consume a lot of memory. You can clear down this cache by calling clearQueryHistory on a repository, or setting the RECORD_QUERIES config option to false to stop it from storing these activity explanations (note, the default is false when in production mode, so you don't usually need to do anything as long as you have sufficient memory available on your development machine).

Note that this in-process cache is never persisted, so there is no possibility of leaking confidential data via the file system or any other persistent cache - only mapping information is stored in the persistent cache, which does not contain any of your actual data (as noted above, the persistent cache will contain potentially sensitive information about your source code and database, so always ensure the cached data is stored somewhere that is not publicly accessible).

Persistent Proxy Class Definition Cache

In order to support lazy loading and object references, Objectiphy must create class definition files that can be 'included' by PHP to extend your entities and intercept requests to perform lazy loading, or to represent an object by its primary key only. When running in development mode, proxy classes are re-generated on every call to ensure that any changes you make to your entities are reflected in the proxies. In production mode, it is assumed that you will not be making changes to your entities, so the proxy class definition files are not cleared down, thus saving overhead on subsequent calls.

It is therefore important that as part of your deployment process, you ensure that the cache directory you specify when creating a repository factory is cleared down, so that the proxy classes (and persistent mapping cache - see below) can be re-generated.

Persistent Mapping Cache

When Objectiphy is asked to load or save entities, it must first create a collection of mapping information for every entity involved in the object hierarchy and all of the relationships between them. Rather than re-build this mapping collection on every call, a persistent cache is used to save the mapping information.

When in development mode, the persistent cache is cleared down whenever a repository factory is created, so that any changes you make are immediately available without needing to manually clear the cache. Of course this limits the usefulness of the cache as it will only come into play if you need to access the same mapping information multiple times in the same request. When in production mode however, the persistent cache is not cleared, so it remains available across multiple requests, resulting in a significant performance boost.

By default, Objectiphy uses its own file-based caching system to serialize mapping collections and store them in text files in the cache directory you specified when you created the repository factory. If you have the igbinary PHP extension installed, it will use that to serialize and unserialize objects, as this is usually a little faster and less memory intensive than the native PHP functions, but it will fall back to native functions if igbinary is not available.

File-based caching is relatively slow as far as caches go, so if you have a caching service such as Redis available, you might find some further performance improvements by using that. Any PSR-16 compatible cache can be used. To specify a cache, just call the setCache method on the repository factory before you create any repositories.

Cache Warming

As Objectiphy does not know up-front which entities it might be asked to handle, it is not currently possible to warm the cache with known mapping information, proxy class definitions, etc. so these files are created as required the first time they are requested. The ability to pass one or more directories that contain your entity class definitions might be added to a future version to allow for up-front cache warming.

Last updated