A client required a CSV data export from a view in their Drupal 8 administration tools. After implementing the views data export module, I found that the response was running out of memory with large data sets.
Using a method called in a request event subscriber, I was able to implement ini_set directives early enough in the execution of the script to increase memory and execution time.
class RequestMemoryManager implements EventSubscriberInterface {
/** @var \Drupal\Core\Routing\RouteMatchInterface */
protected $routeMatch;
public function __construct(RouteMatchInterface $routeMatch) {
$this->routeMatch = $routeMatch;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return ([KernelEvents::REQUEST => [['manageRequestMemory']]]);
}
/**
* provide more memory for certain routes
* @param GetResponseEvent $event
* @return void
*/
public function manageRequestMemory(GetResponseEvent $event) {
if (!$event->isMasterRequest()) {
return;
}
if ($this->routeMatch->getRouteName() === 'view.my_view.data_export') {
ini_set('memory_limit', "1024M");
ini_set('max_execution_time', 600);
}
}
}
And the service implementation
my_module.request_memory_manager:
class: Drupal\my_module\EventSubscriber\RequestMemoryManager
arguments:
- '@current_route_match'
tags:
- { name: event_subscriber }
If you want to experiment with setting other directives in a similar way, it's important to test that they actually get set. The ini_set method returns false on failure, so you can wrap in a condition to test.
if ( ini_set( 'memory_limit', "512M" ) === false ) {
throw new \Exception('Unable to alter memory_limit');
}
if ( ini_set( 'max_execution_time', 300 ) === false ) {
throw new \Exception('Unable to alter max_execution_time');
}
More about the render pipeline and request lifecycle in Drupal 8