diff --git a/.coveralls.yml b/.coveralls.yml index 53bda82..bc71b62 100644 --- a/.coveralls.yml +++ b/.coveralls.yml @@ -1,3 +1,2 @@ coverage_clover: clover.xml json_path: coveralls-upload.json -src_dir: src diff --git a/.gitattributes b/.gitattributes index 7325c69..ea5703b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,5 +4,5 @@ .gitattributes export-ignore .gitignore export-ignore .travis.yml export-ignore -.php_cs export-ignore +phpcs.xml export-ignore phpunit.xml.dist export-ignore diff --git a/.gitignore b/.gitignore index a7fc91d..28d2d11 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ .*.un~ nbproject tmp/ +doc/html/ +zf-mkdoc-theme/ clover.xml composer.lock diff --git a/.php_cs b/.php_cs deleted file mode 100644 index 8f4dd5a..0000000 --- a/.php_cs +++ /dev/null @@ -1,45 +0,0 @@ -in('src') - ->in('test') - ->notPath('TestAsset') - ->notPath('_files') - ->filter(function (SplFileInfo $file) { - if (strstr($file->getPath(), 'compatibility')) { - return false; - } - }); -$config = Symfony\CS\Config\Config::create(); -$config->level(null); -$config->fixers( - array( - 'braces', - 'duplicate_semicolon', - 'elseif', - 'empty_return', - 'encoding', - 'eof_ending', - 'function_call_space', - 'function_declaration', - 'indentation', - 'join_function', - 'line_after_namespace', - 'linefeed', - 'lowercase_keywords', - 'parenthesis', - 'multiple_use', - 'method_argument_space', - 'object_operator', - 'php_closing_tag', - 'remove_lines_between_uses', - 'short_array_syntax', - 'short_tag', - 'standardize_not_equal', - 'trailing_spaces', - 'unused_use', - 'visibility', - 'whitespacy_lines', - ) -); -$config->finder($finder); -return $config; diff --git a/.travis.yml b/.travis.yml index 73f4c14..bc184c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,16 @@ branches: cache: directories: - $HOME/.composer/cache + - $HOME/.local + - zf-mkdoc-theme + +env: + global: + - SITE_URL: https://zendframework.github.io/zend-memory + - GH_USER_NAME: "Matthew Weier O'Phinney" + - GH_USER_EMAIL: matthew@weierophinney.net + - GH_REF: github.com/zendframework/zend-memory.git + - secure: "QsaJwTAeNgLt3HlCLHsMy43lSLQsYym0lbvmMbSZd0ykJt/2ViNjCM9xwRDIGsYYFCGZRqUITeKgnF9sMh43hsMwLryvdN3jQGw/4MmS9QXPpb74kWgm1s2McCnD0XtuSAtxGkUZGCbqJXciAEpj+bc1iXkPvmtxt3mFrSILTiYK6U70HNp7K7Agx6bVhJ0sy7AK273bQzyQDmi1aNhzFd+prZtN6UO2dEpdNk5cRL9m8zp7lz9Wk4DWUDQRjp1B01hk72vqOkLaGXDyH+vhoZ2lNUrgERe81BAl2mmgI1KEZl3itMuWHGlEr0YAntyHeJgK+ThfghKzTgDeUXQ2slXp7V9KM/VXQLRkxydZp1h7oTl9Fc0I0CLUUvrDoH3gxB/+W7xBdYy3pkyD02C0QL13HBnOLr8SdZXxH5Crf6dwHl4qcT1/FUuggdDAc98IG3Xp5p4dt6lIJHaJvlBe9KkSt7CEPDTZWByHf3j51EDc7XmkdoVl4zfqm4FiURdFAnC9EUFEksolaI7tBpd2CKfy4EIEw2eycTBjp+WDAzLTFRwAib3GQlEEZjZFu6MWmQy5EF44JCLgOxiBRKwHzm22qQjt1SVftH3fZNHVvU2BQ6UEuzy+PxcKIjnasobGijtj14ns49PDxVxbfJb7SgKKeKGNOTUFyH+6VmgFJg0=" matrix: fast_finish: true @@ -20,10 +30,11 @@ matrix: - php: 5.6 env: - EXECUTE_TEST_COVERALLS=true + - DEPLOY_DOCS="$(if [[ $TRAVIS_BRANCH == 'master' && $TRAVIS_PULL_REQUEST == 'false' ]]; then echo -n 'true' ; else echo -n 'false' ; fi)" + - PATH="$HOME/.local/bin:$PATH" - php: 7 - php: hhvm allow_failures: - - php: 7 - php: hhvm notifications: @@ -39,9 +50,13 @@ install: - travis_retry composer install --no-interaction --ignore-platform-reqs script: - - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then ./vendor/bin/phpunit --coverage-clover clover.xml ; fi - - if [[ $EXECUTE_TEST_COVERALLS != 'true' ]]; then ./vendor/bin/phpunit ; fi - - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then ./vendor/bin/php-cs-fixer fix -v --diff --dry-run ; fi + - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then composer test-coverage ; fi + - if [[ $EXECUTE_TEST_COVERALLS != 'true' ]]; then composer test ; fi + - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then composer cs-check ; fi + - if [[ $DEPLOY_DOCS == "true" && "$TRAVIS_TEST_RESULT" == "0" ]]; then wget -O theme-installer.sh "https://raw.githubusercontent.com/zendframework/zf-mkdoc-theme/master/theme-installer.sh" ; chmod 755 theme-installer.sh ; ./theme-installer.sh ; fi + +after_success: + - if [[ $DEPLOY_DOCS == "true" ]]; then echo "Preparing to build and deploy documentation" ; ./zf-mkdoc-theme/deploy.sh ; echo "Completed deploying documentation" ; fi after_script: - - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then ./vendor/bin/coveralls ; fi + - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then composer upload-coverage ; fi diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..95a77c8 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,25 @@ +# Changelog + +All notable changes to this project will be documented in this file, in reverse chronological order by release. + +## 2.5.2 - 2016-05-11 + +### Added + +- [#11](https://github.com/zendframework/zend-memory/pull/11) and + [#12](https://github.com/zendframework/zend-memory/pull/12) add and publish + the documentation to https://zendframework.github.io/zend-memory/ + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#12](https://github.com/zendframework/zend-memory/pull/12) updates the + PHP requirement to allow either 5.5+ or 7.0+, and pins the zend-cache version + for testing to 2.7+. diff --git a/README.md b/README.md index 71745f8..02ef167 100644 --- a/README.md +++ b/README.md @@ -3,17 +3,15 @@ [![Build Status](https://secure.travis-ci.org/zendframework/zend-memory.svg?branch=master)](https://secure.travis-ci.org/zendframework/zend-memory) [![Coverage Status](https://coveralls.io/repos/zendframework/zend-memory/badge.svg?branch=master)](https://coveralls.io/r/zendframework/zend-memory?branch=master) -The `Zend\Memory` component is intended to manage data in an environment with -limited memory. +zend-memory manages data in an environment with limited memory. -Memory objects (memory containers) are generated by memory manager by request -and transparently swapped/loaded when it’s necessary. +Memory objects (memory containers) are generated by the memory manager, and +transparently swapped/loaded when required. For example, if creating or loading a managed object would cause the total memory usage to exceed the limit you specify, some managed objects are copied to cache storage outside of memory. In this way, the total memory used by managed objects does not exceed the limit you need to enforce. - - File issues at https://github.com/zendframework/zend-memory/issues -- Documentation is at http://framework.zend.com/manual/current/en/index.html#zend-memory +- Documentation is at https://zendframework.github.io/zend-memory/ diff --git a/composer.json b/composer.json index 7dd7ff7..22c9283 100644 --- a/composer.json +++ b/composer.json @@ -13,15 +13,15 @@ } }, "require": { - "php": ">=5.5" + "php": "^5.5 || ^7.0" }, "require-dev": { - "zendframework/zend-cache": "~2.5", - "fabpot/php-cs-fixer": "1.7.*", - "phpunit/PHPUnit": "~4.0" + "zendframework/zend-cache": "^2.7", + "squizlabs/php_codesniffer": "^2.3.1", + "phpunit/PHPUnit": "^4.8" }, "suggest": { - "zendframework/zend-cache": "To support swap the memory objects" + "zendframework/zend-cache": "To support swapping memory objects into and out of non-memory cache storage" }, "minimum-stability": "dev", "prefer-stable": true, @@ -35,5 +35,16 @@ "psr-4": { "ZendTest\\Memory\\": "test/" } + }, + "scripts": { + "check": [ + "@cs-check", + "@test" + ], + "upload-coverage": "coveralls -v", + "cs-check": "phpcs", + "cs-fix": "phpcbf", + "test": "phpunit", + "test-coverage": "phpunit --coverage-clover clover.xml" } -} \ No newline at end of file +} diff --git a/doc/book/index.html b/doc/book/index.html new file mode 100644 index 0000000..dbf54a6 --- /dev/null +++ b/doc/book/index.html @@ -0,0 +1,12 @@ +
+
+

zend-memory

+ +

+ Manage data in an environment with limited memory. +

+ +
$ composer require zendframework/zend-memory
+
+
+ diff --git a/doc/book/index.md b/doc/book/index.md new file mode 100644 index 0000000..fe84005 --- /dev/null +++ b/doc/book/index.md @@ -0,0 +1 @@ +../../README.md \ No newline at end of file diff --git a/doc/book/intro.md b/doc/book/intro.md new file mode 100644 index 0000000..9844555 --- /dev/null +++ b/doc/book/intro.md @@ -0,0 +1,113 @@ +# Introduction + +zend-memory assists with managing data in an environment with limited memory. + +Memory objects (memory containers) are generated by the memory manager at your +request and transparently swapped/loaded when necessary. + +For example, if creating or loading a managed object would cause the total +memory usage to exceed the limit you specify, some managed objects are copied to +cache storage outside of memory. In this way, the total memory used by managed +objects does not exceed the limit you need to enforce. To provide this +functionality, the memory manager can compose [zend-cache storage adapters](http://zendframework.github.io/zend-cache/storage/adapter/) +as storage providers. + +## Usage + +Instantiate the memory manager class: + +```php +use Zend\Memory\MemoryManager; + +// No caching backend: +$memoryManager = new MemoryManager(); +``` + +Optionally, you can create a cache storage adapter, and pass it to the +`MemoryManager` constructor: + +```php +use Zend\Cache\StorageFactory; +use Zend\Memory\MemoryManager; + +// Use a filesystem adapter, placing memory blocks in the tmp directory +// under which the application is running. +$cache = StorageFactory::factory([ + 'adapter' => [ + 'name' => 'filesystem', + 'options' => ['cache_dir' => './tmp/'], + ], +]); + +$memoryManager = new MemoryManager($cache); +``` + +Once you have a `MemoryManager` instance, you can start pushing values to it and +pulling values from it. + +```php +$loadedFiles = array(); + +for ($count = 0; $count < 10000; $count++) { + $f = fopen($fileNames[$count], 'rb'); + $data = fread($f, filesize($fileNames[$count])); + $fclose($f); + + $loadedFiles[] = $memoryManager->create($data); +} + +echo $loadedFiles[$index1]->value; + +$loadedFiles[$index2]->value = $newValue; + +$loadedFiles[$index3]->value[$charIndex] = '_'; +``` + +## Theory of Operation + +zend-memory operates with the following concepts: + +- Memory manager +- Memory container + - Locked memory object + - Movable memory object + +### Memory manager + +The memory manager generates memory objects (locked or movable) by request of +the application, and returns them wrapped into a memory container object. + +### Memory container + +The memory container has a virtual or actual `value` attribute of type `string`. +This attribute contains the data value specified at memory object creation time. + +You can operate with this `value` attribute as an object property: + +```php +$memObject = $memoryManager->create($data); + +echo $memObject->value; + +$memObject->value = $newValue; + +$memObject->value[$index] = '_'; + +echo ord($memObject->value[$index1]); + +$memObject->value = substr($memObject->value, $start, $length); +``` + +### Locked memory + +Locked memory objects are always stored in memory. Data stored in locked memory +are never swapped to the cache backend. + +### Movable memory + +Movable memory objects are transparently swapped and loaded to/from the cache +backend by the `MemoryManager` when necessary. + +The memory manager does not swap objects with size less than the specified +minimum, due to performance considerations. See [the settings section](memory-manager.md#settings) +for more details. diff --git a/doc/book/memory-manager.md b/doc/book/memory-manager.md new file mode 100644 index 0000000..be39b8f --- /dev/null +++ b/doc/book/memory-manager.md @@ -0,0 +1,139 @@ +# Memory Manager + +## Creating a Memory Manager + +You can create new a memory manager (`Zend\Memory\MemoryManager` object) using its constructor: + +```php +__construct(Zend\Cache\Storage\StorageInterface $cache = null) : void +``` + +As an example, the following creates an instance which *is not* backed by cache +storage: + +```php +$memoryManager = new Zend\Memory\MemoryManager(); +``` + +While the following creates an instance backed by a filesystem cache storage +adapter, storing memory blocks in the `tmp/` directory of the current working +directory: + +```php +use Zend\Cache\StorageFactory; +use Zend\Memory\MemoryManager; + +$cache = StorageFactory::factory([ + 'adapter' => [ + 'name' => 'Filesystem', + 'options' => [ + 'cache_dir' => './tmp/', // Directory in which to put swapped memory blocks + ], + ], +]); + +$memoryManager = new MemoryManager($cache); +``` + +The `MemoryManager` uses [zend-cache storage adapters](http://zendframework.github.io/zend-cache/storage/adapter/) +to cache memory blocks; if no cache instance is provided, the system temporary +directory is used. This is useful if you know that memory is not limited or the +overall size of objects never reaches the memory limit. + +## Managing Memory Objects + +This section describes creating and destroying objects in the managed memory, +and settings to control memory manager behavior. + +### Creating Movable Objects + +Create movable objects (objects which may be swapped into cache storage) using +the `Zend\Memory\MemoryManager::create([$data])` method: + +```php +$memObject = $memoryManager->create($data); +``` + +The `$data` argument is optional and used to initialize the object value. If the +`$data` argument is omitted, the value is an empty string. + +### Creating Locked Objects + +Create locked objects (objects which will never be swapped into cache storage) +using the `Zend\Memory\MemoryManager::createLocked([$data])` method: + +```php +$memObject = $memoryManager->createLocked($data); +``` + +The `$data` argument is optional and used to initialize the object value. If the +`$data` argument is omitted, the value is an empty string. + +### Destroying Objects + +Memory objects are automatically destroyed and removed from memory when they go +out of scope: + +```php +function foo() use ($memoryManager, $memList) { + // ... + + $memObject1 = $memoryManager->create($data1); + $memObject2 = $memoryManager->create($data2); + $memObject3 = $memoryManager->create($data3); + + // ... + + $memList[] = $memObject3; + + // ... + + unset($memObject2); // $memObject2 is destroyed here + + // ... + // $memObject1 is destroyed here + // but $memObject3 object is still referenced by $memList + // and is not destroyed +} +``` + +This applies to both movable and locked objects. + +## Settings + +### Memory Limit + +The memory limit is the maximum number of bytes allowed for use by loaded +movable objects. + +If loading or creation of an object causes memory usage to exceed of this limit, +then the memory manager swaps some other objects. + +You can retrieve or set the memory limit setting using the `getMemoryLimit()` and +`setMemoryLimit($newLimit)` methods: + +```php +$oldLimit = $memoryManager->getMemoryLimit(); // Get memory limit in bytes +$memoryManager->setMemoryLimit($newLimit); // Set memory limit in bytes +``` + +A negative value for memory limit means 'no limit'. + +The default value is two-thirds of the value of `memory_limit` in `php.ini` or +'no limit' (-1) if `memory_limit` is not set in `php.ini`. + +### MinSize + +The `MinSize` is the minimum size an object must be before it will be swapped to a +cache backend; objects with sizes smaller than this value will not be swapped. +This reduces the number of swap/load operations. + +You can retrieve or set the minimum size using the `getMinSize()` and +`setMinSize($newSize)` methods: + +```php +$oldMinSize = $memoryManager->getMinSize(); // Get MinSize in bytes +$memoryManager->setMinSize($newSize); // Set MinSize limit in bytes +``` + +The default minimum size value is 16KB (16384 bytes). diff --git a/doc/book/memory-objects.md b/doc/book/memory-objects.md new file mode 100644 index 0000000..3d5183f --- /dev/null +++ b/doc/book/memory-objects.md @@ -0,0 +1,173 @@ +# Memory Objects + +## Movable + +"Movable" memory objects are ones that may be swapped into the cache backend and +unloaded from memory when not in active use. + +Create movable memory objects using the `create([$data])` method of the memory +manager: + +```php +$memObject = $memoryManager->create($data); +``` + +Such objects will be retrieved from the cache and/or memor when accessed again. + +## Locked + +"Locked" memory objects will never be swapped to cache or unloaded from memory. + +Create locked memory objects using the `createLocked([$data])` method of the +memory manager: + +```php +$memObject = $memoryManager->createLocked($data); +``` + +Locked objects implement the same interface as movable objects +(`Zend\Memory\Container\Interface`), and can be used interchangably with movable +objects. Use them when you have performance considerations that dictate keeping +the information in memory. Access to locked objects is faster, because the +memory manager doesn't need to track changes for these objects. + +The locked objects class (`Zend\Memory\Container\Locked`) guarantees virtually +the same performance as working with a string variable. The overhead is a single +dereference to get the class property. + +## Memory container 'value' property + +Use the memory container (movable or locked) `value` property to operate with +memory object data: + +```php +$memObject = $memoryManager->create($data); + +echo $memObject->value; + +$memObject->value = $newValue; + +$memObject->value[$index] = '_'; + +echo ord($memObject->value[$index1]); + +$memObject->value = substr($memObject->value, $start, $length); +``` + +An alternative way to access memory object data is to use the +[getRef()](#getref-method); method. + +## Memory container interface + +Each memory container type provides the following methods: + +### getRef() method + +```php +&getRef() : mixed +``` + +The `getRef()` method returns a reference to the object value. + +Movable objects are loaded from the cache at this moment if the object is not +already in memory. If the object is loaded from the cache, this might cause +swapping of other objects if the memory limit would be exceeded by having all +the managed objects in memory. + +Tracking changes to data needs additional resources. The `getRef()` method +returns a reference to the string value used to store the data, which is changed +directly by user application. Use the `getRef()` method for value data +processing where you want to ensure the data changes without necessarily +interacting directly with the memory container: + +```php +$memObject = $memoryManager->create($data); + +$value = &$memObject->getRef(); + +for ($count = 0; $count < strlen($value); $count++) { + $char = $value[$count]; + // ... +} +``` + +### touch() method + +```php +touch() : void +``` + +The `touch()` method should be used in conjunction with `getRef()`. It signals +that object value has been changed: + +```php +$memObject = $memoryManager->create($data); +... + +$value = &$memObject->getRef(); + +for ($count = 0; $count < strlen($value); $count++) { + // ... + if ($condition) { + $value[$count] = $char; + } + // ... +} + +$memObject->touch(); +``` + +### lock() method + +```php +lock() : void +``` + +The `lock()` methods locks the object in memory. It should be used to prevent +swapping of the object. Normally, this is not necessary, because the memory +manager uses an intelligent algorithm to choose candidates for swapping. But if +you know that at a specific point in the code an object should not be swapped, +you may lock it. + +Locking objects in memory also guarantees that the reference returned by the +`getRef()` method is valid until you unlock the object: + +```php +$memObject1 = $memoryManager->create($data1); +$memObject2 = $memoryManager->create($data2); +... + +$memObject1->lock(); +$memObject2->lock(); + +$value1 = &$memObject1->getRef(); +$value2 = &$memObject2->getRef(); + +for ($count = 0; $count < strlen($value2); $count++) { + $value1 .= $value2[$count]; +} + +$memObject1->touch(); +$memObject1->unlock(); +$memObject2->unlock(); +``` + +### unlock() method + +```php +unlock() : void +``` + +The `unlock()` method unlocks object when it's no longer necessary to be locked. +See the example above. + +### isLocked() method + +```php +isLocked() : bool +``` + +The `isLocked()` method can be used to check if object is locked. It returns +`true` if the object is locked, or `false` if it is not locked. This is always +`true` for "locked" objects, and may be either `true` or `false` for "movable" +objects. diff --git a/doc/book/zend.memory.memory-manager.md b/doc/book/zend.memory.memory-manager.md deleted file mode 100644 index 208e44a..0000000 --- a/doc/book/zend.memory.memory-manager.md +++ /dev/null @@ -1,128 +0,0 @@ -# Memory Manager - -## Creating a Memory Manager - -You can create new a memory manager (`Zend\Memory\MemoryManager` object) using its constructor: -`Zend\Memory\MemoryManager::__construct(Zend\Cache\Storage\StorageInterface $cache = null)`. - -```php -$cache = Zend\Cache\StorageFactory::factory(array( - 'adapter' => array( - 'name' => 'Filesystem', - 'options' => array( - 'cache_dir' => './tmp/', // Directory where to put the swapped memory blocks - ), - ), -)); - -$memoryManager = new Zend\Memory\MemoryManager($cache); -``` - -`Zend\Memory\MemoryManager` uses \[ZendCache storage adapters\](zend.cache.storage.adapter) to cache -memory blocks; if no cache instance is provided the system temporary directory is used. - -```php -$memoryManager = new Zend\Memory\MemoryManager(); -``` - -This is useful if you know that memory is not limited or the overall size of objects never reaches -the memory limit. - -## Managing Memory Objects - -This section describes creating and destroying objects in the managed memory, and settings to -control memory manager behavior. - -### Creating Movable Objects - -Create movable objects (objects, which may be swapped) using the -`Zend\Memory\MemoryManager::create([$data])` method: - -```php -$memObject = $memoryManager->create($data); -``` - -The `$data` argument is optional and used to initialize the object value. If the `$data` argument is -omitted, the value is an empty string. - -### Creating Locked Objects - -Create locked objects (objects, which are not swapped) using the -`Zend\Memory\MemoryManager::createLocked([$data])` method: - -```php -$memObject = $memoryManager->createLocked($data); -``` - -The `$data` argument is optional and used to initialize the object value. If the `$data` argument is -omitted, the value is an empty string. - -### Destroying Objects - -Memory objects are automatically destroyed and removed from memory when they go out of scope: - -```php -function foo() -{ - global $memoryManager, $memList; - - ... - - $memObject1 = $memoryManager->create($data1); - $memObject2 = $memoryManager->create($data2); - $memObject3 = $memoryManager->create($data3); - - ... - - $memList[] = $memObject3; - - ... - - unset($memObject2); // $memObject2 is destroyed here - - ... - // $memObject1 is destroyed here - // but $memObject3 object is still referenced by $memList - // and is not destroyed -} -``` - -This applies to both movable and locked objects. - -## Memory Manager Settings - -### Memory Limit - -Memory limit is a number of bytes allowed to be used by loaded movable objects. - -If loading or creation of an object causes memory usage to exceed of this limit, then the memory -manager swaps some other objects. - -You can retrieve or set the memory limit setting using the `getMemoryLimit()` and -`setMemoryLimit($newLimit)` methods: - -```php -$oldLimit = $memoryManager->getMemoryLimit(); // Get memory limit in bytes -$memoryManager->setMemoryLimit($newLimit); // Set memory limit in bytes -``` - -A negative value for memory limit means 'no limit'. - -The default value is two-thirds of the value of 'memory\_limit' in php.ini or 'no limit' (-1) if -'memory\_limit' is not set in php.ini. - -### MinSize - -MinSize is a minimal size of memory objects, which may be swapped by memory manager. The memory -manager does not swap objects that are smaller than this value. This reduces the number of swap/load -operations. - -You can retrieve or set the minimum size using the `getMinSize()` and `setMinSize($newSize)` -methods: - -```php -$oldMinSize = $memoryManager->getMinSize(); // Get MinSize in bytes -$memoryManager->setMinSize($newSize); // Set MinSize limit in bytes -``` - -The default minimum size value is 16KB (16384 bytes). diff --git a/doc/book/zend.memory.memory-objects.md b/doc/book/zend.memory.memory-objects.md deleted file mode 100644 index d9f74ee..0000000 --- a/doc/book/zend.memory.memory-objects.md +++ /dev/null @@ -1,167 +0,0 @@ -# Memory Objects - -## Movable - -Create movable memory objects using the `create([$data])` method of the memory manager: - -```php -$memObject = $memoryManager->create($data); -``` - -"Movable" means that such objects may be swapped and unloaded from memory and then loaded when -application code accesses the object. - -## Locked - -Create locked memory objects using the `createLocked([$data])` method of the memory manager: - -```php -$memObject = $memoryManager->createLocked($data); -``` - -"Locked" means that such objects are never swapped and unloaded from memory. - -Locked objects provides the same interface as movable objects (`Zend\Memory\Container\Interface`). -So locked object can be used in any place instead of movable objects. - -It's useful if an application or developer can decide, that some objects should never be swapped, -based on performance considerations. - -Access to locked objects is faster, because the memory manager doesn't need to track changes for -these objects. - -The locked objects class (`Zend\Memory\Container\Locked`) guarantees virtually the same performance -as working with a string variable. The overhead is a single dereference to get the class property. - -## Memory container 'value' property - -Use the memory container (movable or locked) '`value`' property to operate with memory object data: - -```php -$memObject = $memoryManager->create($data); - -echo $memObject->value; - -$memObject->value = $newValue; - -$memObject->value[$index] = '_'; - -echo ord($memObject->value[$index1]); - -$memObject->value = substr($memObject->value, $start, $length); -``` - -An alternative way to access memory object data is to use the getRef() -<zend.memory.memory-objects.api.getRef> method. This method **must** be used for *PHP* -versions before 5.2. It also may have to be used in some other cases for performance reasons. - -## Memory container interface - -Memory container provides the following methods: - -### getRef() method - -```php -public function &getRef(); -``` - -The `getRef()` method returns reference to the object value. - -Movable objects are loaded from the cache at this moment if the object is not already in memory. If -the object is loaded from the cache, this might cause swapping of other objects if the memory limit -would be exceeded by having all the managed objects in memory. - -The `getRef()` method **must** be used to access memory object data for *PHP* versions before 5.2. - -Tracking changes to data needs additional resources. The `getRef()` method returns reference to -string, which is changed directly by user application. So, it's a good idea to use the `getRef()` -method for value data processing: - -```php -$memObject = $memoryManager->create($data); - -$value = &$memObject->getRef(); - -for ($count = 0; $count < strlen($value); $count++) { - $char = $value[$count]; - ... -} -``` - -### touch() method - -```php -public function touch(); -``` - -The `touch()` method should be used in common with `getRef()`. It signals that object value has been -changed: - -```php -$memObject = $memoryManager->create($data); -... - -$value = &$memObject->getRef(); - -for ($count = 0; $count < strlen($value); $count++) { - ... - if ($condition) { - $value[$count] = $char; - } - ... -} - -$memObject->touch(); -``` - -### lock() method - -```php -public function lock(); -``` - -The `lock()` methods locks object in memory. It should be used to prevent swapping of some objects -you choose. Normally, this is not necessary, because the memory manager uses an intelligent -algorithm to choose candidates for swapping. But if you exactly know, that at this part of code some -objects should not be swapped, you may lock them. - -Locking objects in memory also guarantees that reference returned by the `getRef()` method is valid -until you unlock the object: - -```php -$memObject1 = $memoryManager->create($data1); -$memObject2 = $memoryManager->create($data2); -... - -$memObject1->lock(); -$memObject2->lock(); - -$value1 = &$memObject1->getRef(); -$value2 = &$memObject2->getRef(); - -for ($count = 0; $count < strlen($value2); $count++) { - $value1 .= $value2[$count]; -} - -$memObject1->touch(); -$memObject1->unlock(); -$memObject2->unlock(); -``` - -### unlock() method - -```php -public function unlock(); -``` - -`unlock()` method unlocks object when it's no longer necessary to be locked. See the example above. - -### isLocked() method - -```php -public function isLocked(); -``` - -The `isLocked()` method can be used to check if object is locked. It returns `TRUE` if the object is -locked, or `FALSE` if it is not locked. This is always `TRUE` for "locked" objects, and may be -either `TRUE` or `FALSE` for "movable" objects. diff --git a/doc/book/zend.memory.overview.md b/doc/book/zend.memory.overview.md deleted file mode 100644 index 8b2dca5..0000000 --- a/doc/book/zend.memory.overview.md +++ /dev/null @@ -1,97 +0,0 @@ -# Overview - -## Introduction - -The `Zend\Memory` component is intended to manage data in an environment with limited memory. - -Memory objects (memory containers) are generated by memory manager by request and transparently -swapped/loaded when it's necessary. - -For example, if creating or loading a managed object would cause the total memory usage to exceed -the limit you specify, some managed objects are copied to cache storage outside of memory. In this -way, the total memory used by managed objects does not exceed the limit you need to enforce. - -The memory manager uses \[ZendCache backends\](zend.cache.backends) as storage providers. - -**Using ZendMemory component** - -`Zend\Memory\Memory::factory()` instantiates the memory manager class with specified backend -options. - -```php -$backendOptions = array( - 'cache_dir' => './tmp/' // Directory where to put the swapped memory blocks -); - -$memoryManager = Zend\Memory\Memory::factory('File', $backendOptions); - -$loadedFiles = array(); - -for ($count = 0; $count < 10000; $count++) { - $f = fopen($fileNames[$count], 'rb'); - $data = fread($f, filesize($fileNames[$count])); - $fclose($f); - - $loadedFiles[] = $memoryManager->create($data); -} - -echo $loadedFiles[$index1]->value; - -$loadedFiles[$index2]->value = $newValue; - -$loadedFiles[$index3]->value[$charIndex] = '_'; -``` - -## Theory of Operation - -`Zend\Memory` component operates with the following concepts: - -> - Memory manager -- Memory container -- Locked memory object -- Movable memory object - -### Memory manager - -The memory manager generates memory objects (locked or movable) by request of user application and -returns them wrapped into a memory container object. - -### Memory container - -The memory container has a virtual or actual `value` attribute of string type. This attribute -contains the data value specified at memory object creation time. - -You can operate with this `value` attribute as an object property: - -```php -$memObject = $memoryManager->create($data); - -echo $memObject->value; - -$memObject->value = $newValue; - -$memObject->value[$index] = '_'; - -echo ord($memObject->value[$index1]); - -$memObject->value = substr($memObject->value, $start, $length); -``` - -> ## Note -If you are using a *PHP* version earlier than 5.2, use the getRef() -<zend.memory.memory-objects.api.getRef> method instead of accessing the value property -directly. - -### Locked memory - -Locked memory objects are always stored in memory. Data stored in locked memory are never swapped to -the cache backend. - -### Movable memory - -Movable memory objects are transparently swapped and loaded to/from the cache backend by -`Zend\Memory` when it's necessary. - -The memory manager doesn't swap objects with size less than the specified minimum, due to -performance considerations. See \[this section\](zend.memory.memory-manager.settings.min-size) for -more details. diff --git a/doc/bookdown.json b/doc/bookdown.json deleted file mode 100644 index ffb6811..0000000 --- a/doc/bookdown.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "title": "Zend\\Memory", - "target": "html/", - "content": [ - "book/zend.memory.overview.md", - "book/zend.memory.memory-manager.md", - "book/zend.memory.memory-objects.md" - ] -} \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..bb6de36 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,12 @@ +docs_dir: doc/book +site_dir: doc/html +pages: + - index.md + - Intro: intro.md + - Reference: + - "Memory Manager": memory-manager.md + - "Memory Objects": memory-objects.md +site_name: zend-memory +site_description: zend-memory +repo_url: 'https://github.com/zendframework/zend-memory' +copyright: 'Copyright (c) 2016 Zend Technologies USA Inc.' diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000..e994eae --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,21 @@ + + + Zend Framework coding standard + + + + + + + + + + + + + + + + src + test + diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 55b4f29..c5e1a40 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,7 +1,7 @@ diff --git a/src/Container/Movable.php b/src/Container/Movable.php index 68ec50a..784aefe 100644 --- a/src/Container/Movable.php +++ b/src/Container/Movable.php @@ -118,7 +118,11 @@ public function isLocked() public function __get($property) { if ($property != 'value') { - throw new Exception\InvalidArgumentException('Unknown property: \Zend\Memory\Container\Movable::$' . $property); + throw new Exception\InvalidArgumentException(sprintf( + 'Unknown property: %s::$%s', + __CLASS__, + $property + )); } if (!($this->state & self::LOADED)) { @@ -139,7 +143,11 @@ public function __get($property) public function __set($property, $value) { if ($property != 'value') { - throw new Exception\InvalidArgumentException('Unknown property: \Zend\Memory\Container\Movable::$' . $property); + throw new Exception\InvalidArgumentException(sprintf( + 'Unknown property: %s::$%s', + __CLASS__, + $property + )); } $this->state = self::LOADED; diff --git a/src/MemoryManager.php b/src/MemoryManager.php index 3b43571..4f0a0f9 100644 --- a/src/MemoryManager.php +++ b/src/MemoryManager.php @@ -222,7 +222,7 @@ public function getMinSize() */ public function create($value = '') { - return $this->_create($value, false); + return $this->createContainer($value, false); } /** @@ -235,22 +235,23 @@ public function create($value = '') */ public function createLocked($value = '') { - return $this->_create($value, true); + return $this->createContainer($value, true); } /** - * Create new Zend\Memory object + * Create new Zend\Memory container object * * @param string $value * @param bool $locked - * @return \Zend\Memory\Container\ContainerInterface - * @throws \Zend\Memory\Exception\ExceptionInterface + * @return Container\ContainerInterface + * @throws Exception\ExceptionInterface */ - private function _create($value, $locked) + private function createContainer($value, $locked) { $id = $this->nextId++; - if ($locked || ($this->cache === null) /* Use only memory locked objects if backend is not specified */) { + // Use only memory locked objects if backend is not specified + if ($locked || ($this->cache === null)) { return new Container\Locked($value); } @@ -261,7 +262,8 @@ private function _create($value, $locked) // Store last object size as 0 $this->sizes[$id] = 0; - // prepare object for next modifications + + // Prepare object for next modifications $this->lastModified = $valueObject; return new Container\AccessController($valueObject); diff --git a/test/AccessControllerTest.php b/test/AccessControllerTest.php index a1f14ed..ebed201 100644 --- a/test/AccessControllerTest.php +++ b/test/AccessControllerTest.php @@ -24,11 +24,11 @@ class AccessControllerTest extends \PHPUnit_Framework_TestCase * * @var CacheAdapter */ - private $_cache = null; + private $cache = null; public function setUp() { - $this->_cache = CacheFactory::adapterFactory('memory', ['memory_limit' => 0]); + $this->cache = CacheFactory::adapterFactory('memory', ['memory_limit' => 0]); } /** @@ -36,10 +36,10 @@ public function setUp() */ public function testCreation() { - $memoryManager = new Memory\MemoryManager($this->_cache); + $memoryManager = new Memory\MemoryManager($this->cache); $memObject = $memoryManager->create('012345678'); - $this->assertInstanceOf('Zend\Memory\Container\AccessController', $memObject); + $this->assertInstanceOf(Memory\Container\AccessController::class, $memObject); } /** @@ -47,7 +47,7 @@ public function testCreation() */ public function testValueAccess() { - $memoryManager = new Memory\MemoryManager($this->_cache); + $memoryManager = new Memory\MemoryManager($this->cache); $memObject = $memoryManager->create('0123456789'); // getRef() method @@ -64,7 +64,7 @@ public function testValueAccess() $this->assertEquals((string) $memObject->value, '012_456_89'); $memObject->value = 'another value'; - $this->assertInstanceOf('Zend\Memory\Value', $memObject->value); + $this->assertInstanceOf(Memory\Value::class, $memObject->value); $this->assertEquals((string) $memObject->value, 'another value'); } @@ -73,7 +73,7 @@ public function testValueAccess() */ public function testLock() { - $memoryManager = new Memory\MemoryManager($this->_cache); + $memoryManager = new Memory\MemoryManager($this->cache); $memObject = $memoryManager->create('012345678'); $this->assertFalse((bool) $memObject->isLocked()); diff --git a/test/MemoryManagerTest.php b/test/MemoryManagerTest.php index 7108015..b34117f 100644 --- a/test/MemoryManagerTest.php +++ b/test/MemoryManagerTest.php @@ -23,11 +23,11 @@ class MemoryManagerTest extends \PHPUnit_Framework_TestCase * * @var CacheAdapter */ - private $_cache = null; + private $cache = null; public function setUp() { - $this->_cache = CacheFactory::adapterFactory('memory', ['memory_limit' => 0]); + $this->cache = CacheFactory::adapterFactory('memory', ['memory_limit' => 0]); } /** @@ -37,12 +37,12 @@ public function testCreation() { /** Without caching */ $memoryManager = new Memory\MemoryManager(); - $this->assertInstanceOf('Zend\Memory\MemoryManager', $memoryManager); + $this->assertInstanceOf(Memory\MemoryManager::class, $memoryManager); unset($memoryManager); /** Caching using 'File' backend */ - $memoryManager = new Memory\MemoryManager($this->_cache); - $this->assertInstanceOf('Zend\Memory\MemoryManager', $memoryManager); + $memoryManager = new Memory\MemoryManager($this->cache); + $this->assertInstanceOf(Memory\MemoryManager::class, $memoryManager); unset($memoryManager); } @@ -51,7 +51,7 @@ public function testCreation() */ public function testSettings() { - $memoryManager = new Memory\MemoryManager($this->_cache); + $memoryManager = new Memory\MemoryManager($this->cache); // MemoryLimit $memoryManager->setMemoryLimit(2*1024*1024 /* 2Mb */); @@ -68,22 +68,22 @@ public function testSettings() */ public function testCreate() { - $memoryManager = new Memory\MemoryManager($this->_cache); + $memoryManager = new Memory\MemoryManager($this->cache); $memObject1 = $memoryManager->create('Value of object 1'); - $this->assertInstanceOf('Zend\Memory\Container\AccessController', $memObject1); + $this->assertInstanceOf(Memory\Container\AccessController::class, $memObject1); $this->assertEquals($memObject1->getRef(), 'Value of object 1'); $memObject2 = $memoryManager->create(); - $this->assertInstanceOf('Zend\Memory\Container\AccessController', $memObject2); + $this->assertInstanceOf(Memory\Container\AccessController::class, $memObject2); $this->assertEquals($memObject2->getRef(), ''); $memObject3 = $memoryManager->createLocked('Value of object 3'); - $this->assertInstanceOf('Zend\Memory\Container\Locked', $memObject3); + $this->assertInstanceOf(Memory\Container\Locked::class, $memObject3); $this->assertEquals($memObject3->getRef(), 'Value of object 3'); $memObject4 = $memoryManager->createLocked(); - $this->assertInstanceOf('Zend\Memory\Container\Locked', $memObject4); + $this->assertInstanceOf(Memory\Container\Locked::class, $memObject4); $this->assertEquals($memObject4->getRef(), ''); } @@ -92,7 +92,7 @@ public function testCreate() */ public function testProcessing() { - $memoryManager = new Memory\MemoryManager($this->_cache); + $memoryManager = new Memory\MemoryManager($this->cache); $memoryManager->setMinSize(256); $memoryManager->setMemoryLimit(1024*32); @@ -118,7 +118,7 @@ public function testProcessing() public function testNotEnoughSpaceThrowException() { - $memoryManager = new Memory\MemoryManager($this->_cache); + $memoryManager = new Memory\MemoryManager($this->cache); $memoryManager->setMinSize(128); $memoryManager->setMemoryLimit(1024); @@ -129,7 +129,7 @@ public function testNotEnoughSpaceThrowException() $memObjects[] = $memObject; } - $this->setExpectedException('Zend\Memory\Exception\RuntimeException'); + $this->setExpectedException(Memory\Exception\RuntimeException::class); $memoryManager->create('a'); } } diff --git a/test/MovableTest.php b/test/MovableTest.php index d2ef744..0c63b8d 100644 --- a/test/MovableTest.php +++ b/test/MovableTest.php @@ -22,10 +22,10 @@ class MovableTest extends \PHPUnit_Framework_TestCase */ public function testCreation() { - $memoryManager = new DummyMemoryManager(); + $memoryManager = new TestAsset\DummyMemoryManager(); $memObject = new Container\Movable($memoryManager, 10, '0123456789'); - $this->assertInstanceOf('Zend\Memory\Container\Movable', $memObject); + $this->assertInstanceOf(Container\Movable::class, $memObject); } /** @@ -33,7 +33,7 @@ public function testCreation() */ public function testValueAccess() { - $memoryManager = new DummyMemoryManager(); + $memoryManager = new TestAsset\DummyMemoryManager(); $memObject = new Container\Movable($memoryManager, 10, '0123456789'); // getRef() method @@ -50,7 +50,7 @@ public function testValueAccess() $this->assertEquals((string) $memObject->value, '012_456_89'); $memObject->value = 'another value'; - $this->assertInstanceOf('Zend\Memory\Value', $memObject->value); + $this->assertInstanceOf(Memory\Value::class, $memObject->value); $this->assertEquals((string) $memObject->value, 'another value'); } @@ -59,7 +59,7 @@ public function testValueAccess() */ public function testLock() { - $memoryManager = new DummyMemoryManager(); + $memoryManager = new TestAsset\DummyMemoryManager(); $memObject = new Container\Movable($memoryManager, 10, '0123456789'); $this->assertFalse($memObject->isLocked()); @@ -76,7 +76,7 @@ public function testLock() */ public function testTouch() { - $memoryManager = new DummyMemoryManager(); + $memoryManager = new TestAsset\DummyMemoryManager(); $memObject = new Container\Movable($memoryManager, 10, '0123456789'); $this->assertFalse($memoryManager->processUpdatePassed); @@ -93,7 +93,7 @@ public function testTouch() */ public function testValueUpdateTracing() { - $memoryManager = new DummyMemoryManager(); + $memoryManager = new TestAsset\DummyMemoryManager(); $memObject = new Container\Movable($memoryManager, 10, '0123456789'); // startTrace() method is usually invoked by memory manager, when it need to be notified @@ -111,50 +111,17 @@ public function testValueUpdateTracing() public function testInvalidGetThrowException() { - $memoryManager = new DummyMemoryManager(); + $memoryManager = new TestAsset\DummyMemoryManager(); $memObject = new Container\Movable($memoryManager, 10, '0123456789'); - $this->setExpectedException('Zend\Memory\Exception\InvalidArgumentException'); + $this->setExpectedException(Memory\Exception\InvalidArgumentException::class); $value = $memObject->unknowProperty; } public function testInvalidSetThrowException() { - $memoryManager = new DummyMemoryManager(); + $memoryManager = new TestAsset\DummyMemoryManager(); $memObject = new Container\Movable($memoryManager, 10, '0123456789'); - $this->setExpectedException('Zend\Memory\Exception\InvalidArgumentException'); + $this->setExpectedException(Memory\Exception\InvalidArgumentException::class); $memObject->unknowProperty = 5; } } - -/** - * Memory manager helper - */ -class DummyMemoryManager extends Memory\MemoryManager -{ - /** @var bool */ - public $processUpdatePassed = false; - - /** @var integer */ - public $processedId; - - /** @var Container\Movable */ - public $processedObject; - - /** - * Empty constructor - */ - public function __construct() - { - // Do nothing - } - - /** - * DummyMemoryManager value update callback method - */ - public function processUpdate(Container\Movable $container, $id) - { - $this->processUpdatePassed = true; - $this->processedId = $id; - $this->processedObject = $container; - } -} diff --git a/test/TestAsset/DummyMemoryManager.php b/test/TestAsset/DummyMemoryManager.php new file mode 100644 index 0000000..693e9ab --- /dev/null +++ b/test/TestAsset/DummyMemoryManager.php @@ -0,0 +1,53 @@ +processUpdatePassed = true; + $this->processedId = $id; + $this->processedObject = $container; + } +} diff --git a/test/TestAsset/DummyMovableContainer.php b/test/TestAsset/DummyMovableContainer.php new file mode 100644 index 0000000..e89c3fe --- /dev/null +++ b/test/TestAsset/DummyMovableContainer.php @@ -0,0 +1,29 @@ +assertInstanceOf('Zend\Memory\Value', $valueObject); + $valueObject = new Memory\Value('data data data ...', new TestAsset\DummyMovableContainer()); + $this->assertInstanceOf(Memory\Value::class, $valueObject); $this->assertEquals($valueObject->getRef(), 'data data data ...'); } @@ -32,7 +32,7 @@ public function testCreation() */ public function testGetRef() { - $valueObject = new Memory\Value('0123456789', new DummyMovableContainer()); + $valueObject = new Memory\Value('0123456789', new TestAsset\DummyMovableContainer()); $valueRef = &$valueObject->getRef(); $valueRef[3] = '_'; @@ -44,7 +44,7 @@ public function testGetRef() */ public function testToString() { - $valueObject = new Memory\Value('0123456789', new DummyMovableContainer()); + $valueObject = new Memory\Value('0123456789', new TestAsset\DummyMovableContainer()); $this->assertEquals($valueObject->__toString(), '0123456789'); $this->assertEquals(strlen($valueObject), 10); @@ -56,7 +56,7 @@ public function testToString() */ public function testArrayAccess() { - $valueObject = new Memory\Value('0123456789', new DummyMovableContainer()); + $valueObject = new Memory\Value('0123456789', new TestAsset\DummyMovableContainer()); $this->assertEquals($valueObject[8], '8'); $valueObject[2] = '_'; @@ -70,22 +70,3 @@ public function testArrayAccess() error_reporting($error_level); } } - -class DummyMovableContainer extends Container\Movable -{ - /** - * Empty constructor - */ - public function __construct() - { - // Do nothing - } - - /** - * Dummy value update callback method - */ - public function processUpdate() - { - // Do nothing - } -} diff --git a/test/bootstrap.php b/test/bootstrap.php deleted file mode 100644 index c715d95..0000000 --- a/test/bootstrap.php +++ /dev/null @@ -1,34 +0,0 @@ -