Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prefer copying files over linking #6

Closed
Nemo64 opened this issue Apr 10, 2020 · 6 comments
Closed

Prefer copying files over linking #6

Nemo64 opened this issue Apr 10, 2020 · 6 comments
Assignees

Comments

@Nemo64
Copy link
Contributor

Nemo64 commented Apr 10, 2020

My initial code prefers symlinking as much as possible.

The performance advantage of that is minimal while it might make problems if the cache is not properly warmed.

Therefore it is probably best to copy everything that does not need to be in the original var folder, the overhead should be minimal.

@Nemo64 Nemo64 self-assigned this Apr 10, 2020
Nemo64 added a commit that referenced this issue Apr 10, 2020
Though this change, everything is copied except
for the dumped container.

I already tested it with #10 and it increases
the startup time from 82ms to 162ms.
The entire first request takes 1228.13ms
+ 306.20 ms init time so it isn't the biggest difference.
@Nemo64
Copy link
Contributor Author

Nemo64 commented Apr 11, 2020

As mentioned in #12:

it increases the startup time from 82ms to 162ms.

So actually copying everything should be avoided if possible
but there are still reasons symlinking isn't the best.

  • incomplete cache warmup may break the deployment
  • other bundles or libraries might create additional folders for which they need write access.

But there might be other options that work similar to overlayfs which would in 1 swup fix all possible problems since there is not symlinkung, no changing of a directory and everything would be writable without any copying at the start..
I don't think we can actually mount a real overlayfs within a lambda (but i can try) but php has a feature called StreamWrapper which may be able to emulate that.

@Nyholm
Copy link
Collaborator

Nyholm commented Apr 11, 2020

Hm, Im not sure I have any valuable input. But here are some goals I think we should focus on:

  • Make a "normal" symfony app work out of the box with optimal performance
  • If I need something custom, I could be able to customize/filter what files should be copied or not

I am okey that special use cases are for advanced users as long as it is easy for most people.

@Nyholm
Copy link
Collaborator

Nyholm commented Apr 11, 2020

Maybe a streamwrapper is a way forward.

Basically, register before each file lookup to rewrite the path if the file exists in symfony var/cache but not in the original path.

if (substr($path, 0, 10) !== '/tmp/cache') {
  return; 
}

if (file_exists($path)) {
  return;
}

$pathToFileInSymfonyVarCache = ...
if (file_exists($pathToFileInSymfonyVarCache)) {
    return $pathToFileInSymfonyVarCache;
}

@Nemo64
Copy link
Contributor Author

Nemo64 commented Apr 11, 2020

I tried streamwrappers by using https://github.com/brzuchal/filesystem-stream-wrapper and modifying it slightly so i can add multiple paths.

Result: It doesn't work with errors like these:

[2020-04-11T18:11:56.926055+02:00] php.WARNING: Warning: include_once(symfony-bridge:/vendor/symfony/security-core/User/UserCheckerInterface.php): failed to open stream: No such file or directory {"exception":"[object] (ErrorException(code: 0): Warning: include_once(symfony-bridge:/vendor/symfony/security-core/User/UserCheckerInterface.php): failed to open stream: No such file or directory at symfony-bridge://var/cache/prod/ContainerX6FflDL/srcApp_KernelProdContainer.php:4682)"} []
[2020-04-11T18:11:56.926091+02:00] php.WARNING: Warning: include_once(): Failed opening 'symfony-bridge:/vendor/symfony/security-core/User/UserCheckerInterface.php' for inclusion (include_path='.:/opt/bref/lib/php') {"exception":"[object] (ErrorException(code: 0): Warning: include_once(): Failed opening 'symfony-bridge:/vendor/symfony/security-core/User/UserCheckerInterface.php' for inclusion (include_path='.:/opt/bref/lib/php') at symfony-bridge://var/cache/prod/ContainerX6FflDL/srcApp_KernelProdContainer.php:4682)"} []
[2020-04-11T18:11:56.926159+02:00] php.WARNING: Warning: include_once(symfony-bridge:/vendor/symfony/security-core/User/UserChecker.php): failed to open stream: No such file or directory {"exception":"[object] (ErrorException(code: 0): Warning: include_once(symfony-bridge:/vendor/symfony/security-core/User/UserChecker.php): failed to open stream: No such file or directory at symfony-bridge://var/cache/prod/ContainerX6FflDL/srcApp_KernelProdContainer.php:4683)"} []
[2020-04-11T18:11:56.926195+02:00] php.WARNING: Warning: include_once(): Failed opening 'symfony-bridge:/vendor/symfony/security-core/User/UserChecker.php' for inclusion (include_path='.:/opt/bref/lib/php') {"exception":"[object] (ErrorException(code: 0): Warning: include_once(): Failed opening 'symfony-bridge:/vendor/symfony/security-core/User/UserChecker.php' for inclusion (include_path='.:/opt/bref/lib/php') at symfony-bridge://var/cache/prod/ContainerX6FflDL/srcApp_KernelProdContainer.php:4683)"} []
[2020-04-11T18:11:56.928085+02:00] php.WARNING: Warning: include_once(symfony-bridge:/vendor/symfony/security-http/Firewall/AbstractListener.php): failed to open stream: No such file or directory {"exception":"[object] (ErrorException(code: 0): Warning: include_once(symfony-bridge:/vendor/symfony/security-http/Firewall/AbstractListener.php): failed to open stream: No such file or directory at symfony-bridge://var/cache/prod/ContainerX6FflDL/srcApp_KernelProdContainer.php:4560)"} []
[2020-04-11T18:11:56.928150+02:00] php.WARNING: Warning: include_once(): Failed opening 'symfony-bridge:/vendor/symfony/security-http/Firewall/AbstractListener.php' for inclusion (include_path='.:/opt/bref/lib/php') {"exception":"[object] (ErrorException(code: 0): Warning: include_once(): Failed opening 'symfony-bridge:/vendor/symfony/security-http/Firewall/AbstractListener.php' for inclusion (include_path='.:/opt/bref/lib/php') at symfony-bridge://var/cache/prod/ContainerX6FflDL/srcApp_KernelProdContainer.php:4560)"} []
[2020-04-11T18:11:56.928231+02:00] php.WARNING: Warning: include_once(symfony-bridge:/vendor/symfony/security-http/Firewall/ListenerInterface.php): failed to open stream: No such file or directory {"exception":"[object] (ErrorException(code: 0): Warning: include_once(symfony-bridge:/vendor/symfony/security-http/Firewall/ListenerInterface.php): failed to open stream: No such file or directory at symfony-bridge://var/cache/prod/ContainerX6FflDL/srcApp_KernelProdContainer.php:4561)"} []
[2020-04-11T18:11:56.928272+02:00] php.WARNING: Warning: include_once(): Failed opening 'symfony-bridge:/vendor/symfony/security-http/Firewall/ListenerInterface.php' for inclusion (include_path='.:/opt/bref/lib/php') {"exception":"[object] (ErrorException(code: 0): Warning: include_once(): Failed opening 'symfony-bridge:/vendor/symfony/security-http/Firewall/ListenerInterface.php' for inclusion (include_path='.:/opt/bref/lib/php') at symfony-bridge://var/cache/prod/ContainerX6FflDL/srcApp_KernelProdContainer.php:4561)"} []
[2020-04-11T18:11:56.928344+02:00] php.WARNING: Warning: include_once(symfony-bridge:/vendor/symfony/security-http/Firewall/LegacyListenerTrait.php): failed to open stream: No such file or directory {"exception":"[object] (ErrorException(code: 0): Warning: include_once(symfony-bridge:/vendor/symfony/security-http/Firewall/LegacyListenerTrait.php): failed to open stream: No such file or directory at symfony-bridge://var/cache/prod/ContainerX6FflDL/srcApp_KernelProdContainer.php:4562)"} []
[2020-04-11T18:11:56.928382+02:00] php.WARNING: Warning: include_once(): Failed opening 'symfony-bridge:/vendor/symfony/security-http/Firewall/LegacyListenerTrait.php' for inclusion (include_path='.:/opt/bref/lib/php') {"exception":"[object] (ErrorException(code: 0): Warning: include_once(): Failed opening 'symfony-bridge:/vendor/symfony/security-http/Firewall/LegacyListenerTrait.php' for inclusion (include_path='.:/opt/bref/lib/php') at symfony-bridge://var/cache/prod/ContainerX6FflDL/srcApp_KernelProdContainer.php:4562)"} []

Then I tried the way I didn't expected not to work. In boot, I simply do this:

$lowerdir = $this->getProjectDir() . '/var';
$upperdir = '/tmp/var';

if (! is_dir($upperdir)) {
    mkdir($upperdir);
    shell_exec("mount -t overlayfs -olowerdir=$lowerdir,upperdir=$upperdir $lowerdir");
}

And what can I say? It works perfectly.
I can actually mount a real overlayfs within the lambda function.
This means the entire Kernel modification can actually be just those 4 lines, no path rewriting required and it should work transparently with everything that writes to the var folder.
I'll try to build a pull request with it.

Nemo64 added a commit that referenced this issue Apr 11, 2020
Through this change I made the entire /var folder
writable without needing to copy anything.

It'll even work with all bundles that somehow write
into the var folder since there is no detectable
difference to a real writable folder, even when
accessed though command and overlayfs is heavily
tested since it is one of the core components of docker.
Nemo64 added a commit that referenced this issue Apr 11, 2020
Through this change I made the entire /var folder
writable without needing to copy anything.

It'll even work with all bundles that somehow write
into the var folder since there is no detectable
difference to a real writable folder, even when
accessed though command and overlayfs is heavily
tested since it is one of the core components of docker.
@Nyholm
Copy link
Collaborator

Nyholm commented Apr 12, 2020

So mounting a filesystem does not work. Streamwrappers may seam like it is overkill (and we had a hard time making it work).

Copying files are super slow as shown in #18. I suggest closing this issue.

@Nemo64
Copy link
Contributor Author

Nemo64 commented Apr 12, 2020

Probably true. The current solution is a good compromise of cold start time and stability.

I could imagine reconfiguring the containers system cache to use a custom FileAdapter that handles the overlay logic but that would only work if the cache is properly warmed so it would trade stability.

@Nemo64 Nemo64 closed this as completed Apr 12, 2020
@Nemo64 Nemo64 mentioned this issue Apr 18, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants