[TYPO3-core] RFC #5045, #5077, #8649: Import/Export requires lot of memory

Bernhard Kraft kraftb at kraftb.at
Thu Jul 24 13:23:55 CEST 2008


Martin Kutschker schrieb:

> I didn't get it right from readig the patch. You have create an external
> temporary zip file which you append to the .t3d and flag it so that the
> importer can detach and uncompress it. Is it working like this?

*smile* I hoped someone asks this ...

As usual I like to be very explicit and go into every detail when 
explaining something. So I hope it is not too long for you too read 
(come on - manuals have hundreds of pages - this is just a  half A4 :).

We use hundreds of lines of code for solving our "requirements" - so I 
think it should be ok to use tens of lines of writings/mails do 
"describe" our solutions.

****************************

You surely remember good old games like "Monkey Island", "Indiana Jones" 
or other Lucas Arts Adventures, or games like "Doom". Before those games 
a computer game in DOS worlds was often built up of hundreds of small 
files like "sprt0001.spr"  for small sprite or sound effect.
But games like noted above started to take an approach which has one or 
more "container" files (when games were distributed playable from 5.25" 
floppies or similar they simply used more than one container).

In the container of the first disk was a kind of "index" which told the 
game-engine at which byte-offset it could find which game-element 
(sprite, sound effect, level map, items or whatever) and which length in 
bytes this data element had.

So I used a similar approach. In the code of the originial import export 
module you find a block reading:
---------------------------------------------
$fileRec['content'] = t3lib_div::getUrl($fI['ID_absFile']);
$fileRec['content_md5'] = md5($fileRec['content']);
---------------------------------------------
Here the complete file gets read into array key 'content' and a md5 sum 
is created.

Now this is the biggest problem in the import/export tool - if you 
export i.e. 50 files each 2MB in overall size you will fill up 100 MB of 
memory - you get the point. Exporting "small" page trees is possible - 
large trees with lot of pictures/pdfs, etc. wouldn't work.

I replaced above code by:
--------------------------------------------
$fileRec['content'] = 
$this->export_appendFileToContainer($fI['ID_absFile']);
$fileRec['content_md5'] = $fileRec['content']['md5'];
--------------------------------------------
So I set the 'content' key of the $fileRec array to the return value of 
"export_appendFileToContainer". This method simply appends the file with 
supplied name to a temporarily created container (plain at this time - 
not zipped) and returns the byte offset and length where the file has 
been put to (in the container) ...

$fileRec gets simply handled like before my patch - inserted into the 
export-data-array which will be serialized and stored as .T3D file. But 
after serialization the contents of the temporarily created container 
gets appended to the .T3D file in a manner it can get "extracted" from 
the T3D file again (when importing)

When importing the same game goes in the other direction - a file going 
to be saved from the import-t3d is not simply saved from the 'content' 
key of the array - but rather "fetched" out of the container.



> I guess this could work for the xml export as well if you ship the file
> zip as an extra file. Not quite as convenient as a single file but it'd
> work. Though I don't get it why one would need an xml export.

The thing about the "zip" or better "gzip" methods is the following: 
When creating the .t3D and compression is active (this is the default) 
the serialized-data gets written to disk (or stdout) using the "gzwrite" 
method.

When writing the files to the container I can not use "gzwrite" as later 
on - when importing it might be required to extract a file from the 
"middle" of the container - and gz-files must/should always get 
read/written serially - no skipping should occur:
---------------------------
http://de.php.net/manual/en/function.gzseek.php
If the file is opened for reading, this function is emulated but can be 
extremely slow. If the file is opened for writing, only forward seeks 
are supported; gzseek() then compresses a sequence of zeroes up to the 
new starting position.
---------------------------

So I simply compress the whole container when finished - and append the 
whole compressed container. When importing I first decompress the whole 
file container - and then simply proceed as usual.


> I don't want to go into nitpicking (like "use of new instead of
> t3lib_div::createInstance) right now as I like the idea :-)

Sorry. At the moment of writing I didn't have t3lib_div::makeInstance in 
mind :) I will fix this.



> PS: Ok, onme thing: could you please name the feature internally
> sonething like "externalFiles" or "fileContainer"? "saveMemory" doesn't
> really tell what happens. ;-)

Yes. Give me 1 hour and you get a fixed version.



greets,
Bernhard
-- 
Freiheit ist immer Freiheit des Andersdenkenden.
Rosa Luxemburg, 1871-1919
--------------------------------------------------
www.think-open.at


More information about the TYPO3-team-core mailing list