Hi,
I have just made a patch so that tilesGen.pl forks in RenderTile
function (which generates png from svg). It is quite simple, as it
calls fork() at the first run of RenderTile. Parent and child then just
draw a different part of the tile.
I originally wanted to make it multi-thread, but it segfaulted in the
for loop line 1237, but I didn't investigate any more. (it could be a
problem in how GD library is used).
Patch contains the following modifications:
* make temporary files safer, by using tempfile() to generate unique
file names.
* addition of $parent_pid so that the child can get the name of the
output-* files used by xml2svg(). This could be replaced by using
coordinates of the tile in file name.
* a new configuration in tilesAtHome.conf to enable or deactivate
fork().
I measured time on a very simple tile (2129,1489) which contains only a
road. Total time went from 2:30 to 1:30 on my dual core.
The patch can be easily be modified to use 3 children instead of only 1,
and I think that xml2svg could use some fork() too.
Jocelyn
Index: tilesGen.pl
===================================================================
--- tilesGen.pl (révision 5614)
+++ tilesGen.pl (copie de travail)
@@ -2,6 +2,7 @@
use LWP::UserAgent;
use Math::Trig;
use File::Copy;
+use File::Temp qw(tempfile);
use FindBin qw($Bin);
use tahconfig;
use tahlib;
@@ -129,6 +130,9 @@
# Create the working directory if necessary
mkdir $Config{WorkingDirectory} if(!-d $Config{WorkingDirectory});
+# We need to keep parent PID so that child get the correct files after fork()
+my $parent_pid = $PID;
+
# Subdirectory for the current job (layer & z12 tileset),
# as used in sub GenerateTileset() and tileFilename()
my $JobDirectory;
@@ -667,7 +671,7 @@
# Faff around
for (my $i = $Zoom ; $i <= $maxzoom ; $i++)
{
- killafile("$Config{WorkingDirectory}output-$PID-z$i.svg");
+ killafile("$Config{WorkingDirectory}output-$parent_pid-z$i.svg");
}
my $Margin = " " x ($Zoom - 8);
@@ -778,7 +782,7 @@
# Render the file
if (xml2svg(
"map-features-$PID.xml",
- "$Config{WorkingDirectory}output-$PID-z$i.svg",
+ "$Config{WorkingDirectory}output-$parent_pid-z$i.svg",
$i))
{
# Delete temporary rules file
@@ -794,7 +798,7 @@
}
# Find the size of the SVG file
- my ($ImgH,$ImgW,$Valid) = getSize("$Config{WorkingDirectory}output-$PID-z$maxzoom.svg");
+ my ($ImgH,$ImgW,$Valid) = getSize("$Config{WorkingDirectory}output-$parent_pid-z$maxzoom.svg");
# Render it as loads of recursive tiles
my $empty = RenderTile($layer, $X, $Y, $Y, $Zoom, $Zoom, $N, $S, $W, $E, 0,0,$ImgW,$ImgH,$ImgH,0);
@@ -802,7 +806,7 @@
# Clean-up the SVG files
for (my $i = $Zoom ; $i <= $maxzoom; $i++)
{
- killafile("$Config{WorkingDirectory}output-$PID-z$i.svg");
+ killafile("$Config{WorkingDirectory}output-$parent_pid-z$i.svg");
}
#if $empty then the next zoom level was empty, so we only upload one tile unless RenderFullTileset is set.
@@ -907,8 +911,23 @@
my $YA = $Ytile * 2;
my $YB = $YA + 1;
- RenderTile($layer, $X, $Y, $YA, $Zoom+1, $ZOrig, $N, $LatC, $W, $E, $ImgX1, $ImgYC, $ImgX2, $ImgY2,$ImageHeight,$SkipEmpty);
- RenderTile($layer, $X, $Y, $YB, $Zoom+1, $ZOrig, $LatC, $S, $W, $E, $ImgX1, $ImgY1, $ImgX2, $ImgYC,$ImageHeight,$SkipEmpty);
+ if ($Config{Fork} && $Zoom == 12) {
+ my $pid = fork();
+ if (not defined $pid) {
+ return cleanUpAndDie("RenderTile: could not fork, exiting","EXIT",4,$PID);
+ } elsif ($pid == 0) {
+ RenderTile($layer, $X, $Y, $YA, $Zoom+1, $ZOrig, $N, $LatC, $W, $E, $ImgX1, $ImgYC, $ImgX2, $ImgY2,$ImageHeight,$SkipEmpty);
+ exit(0);
+ } else {
+ RenderTile($layer, $X, $Y, $YB, $Zoom+1, $ZOrig, $LatC, $S, $W, $E, $ImgX1, $ImgY1, $ImgX2, $ImgYC,$ImageHeight,$SkipEmpty);
+ waitpid($pid,0);
+ }
+ $progressPercent=100;
+ statusMessage("Finished $X,$Y for layer $layer", $Config{Verbose}, $currentSubTask, $progressJobs, $progressPercent, 1);
+ } else {
+ RenderTile($layer, $X, $Y, $YA, $Zoom+1, $ZOrig, $N, $LatC, $W, $E, $ImgX1, $ImgYC, $ImgX2, $ImgY2,$ImageHeight,$SkipEmpty);
+ RenderTile($layer, $X, $Y, $YB, $Zoom+1, $ZOrig, $LatC, $S, $W, $E, $ImgX1, $ImgY1, $ImgX2, $ImgYC,$ImageHeight,$SkipEmpty);
+ }
return $SkipEmpty; ## main call wants to know wether the entire tileset was empty so we return 1 if the tile was empty
}
@@ -1018,10 +1037,12 @@
{
my($Zoom, $ZOrig, $layer, $SizeX, $SizeY, $X1, $Y1, $X2, $Y2, $ImageHeight, $X, $Y, $Ytile) = @_;
- my $TempFile = $Config{WorkingDirectory}.$PID."_part.png";
+ my $TempFile;
+ my $stdOut;
+ (undef, $TempFile) = tempfile($PID."_part-XXXXXX", DIR => $Config{WorkingDirectory}, SUFFIX => ".png");
+ (undef, $stdOut) = tempfile("$PID-XXXXXX", DIR => $Config{WorkingDirectory}, SUFFIX => ".stdout");
+
- my $stdOut = $Config{WorkingDirectory}.$PID.".stdout";
-
my $Cmd = "";
my $Left = $X1;
@@ -1041,7 +1062,7 @@
$Left,$Top,$Width,$Height,
$TempFile,
$Config{WorkingDirectory},
- "output-$PID-z$Zoom.svg",
+ "output-$parent_pid-z$Zoom.svg",
$stdOut);
}
elsif ($Config{Batik} == "2")
@@ -1069,7 +1090,7 @@
$X1,$Y1,$X2,$Y2,
$TempFile,
$Config{WorkingDirectory},
- "output-$PID-z$Zoom.svg",
+ "output-$parent_pid-z$Zoom.svg",
$stdOut);
}
Index: tilesAtHome.conf.windows
===================================================================
--- tilesAtHome.conf.windows (révision 5614)
+++ tilesAtHome.conf.windows (copie de travail)
@@ -47,3 +47,6 @@
# Set to the location of the batik rasterizer jar. The Batik libraries should reside in the same folder,
# or in a sub-folder named lib
BatikPath=c:\tilesAtHome\batik\batik-rasterizer.jar
+
+# If set to 1, it will enable forking to render tiles
+Fork=0
Index: tilesAtHome.conf.linux
===================================================================
--- tilesAtHome.conf.linux (révision 5614)
+++ tilesAtHome.conf.linux (copie de travail)
@@ -63,3 +63,5 @@
# Only used for Batik jar
BatikJVMSize=1536M
+# If set to 1, it will enable forking to render tiles
+Fork=0
_______________________________________________
Tilesathome mailing list
[email protected]
http://lists.openstreetmap.org/cgi-bin/mailman/listinfo/tilesathome