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

Last Updated April 27th, 2019