Schrift
[thread]9083[/thread]

Template Toolkit: BLOCK + WRAPPER

Leser: 2


<< |< 1 2 >| >> 15 Einträge, 2 Seiten
bloonix
 2007-06-13 00:50
#77462 #77462
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
Hallo liebe Community,

heute bin ich in den Genuss des WRAPPERs von CPAN:Template gekommen.
Mein Gedanke war es, alle Templates zu Begin des FastCGI-Prozesses in
eine Hashstruktur zu laden und im Speicher zu halten, um die Platten-
zugriffe zu minimieren. Mein altes Konstrukt hat da natürlich nicht
mitgespielt...

Bislang habe ich meine Struktur immer wie folgt aufgebaut (so wie ich es
auch zu Zeiten mit HTML::Template gemacht habe):

beispiel.tmpl
Code: (dl )
1
2
3
4
5
6
[% INCLUDE header.tmpl %]
[% INCLUDE navigation.tmpl %]

<p>Mein Content</p>

[% INCLUDE footer.tmpl %]


Dabei enthält header.tmpl immer die gesamten Header Informationen,
angefangen mit <html> und endend mit </head>... navigation.tmpl
entält immer meine Navigationsleiste und footer.tmpl den Abschluss...
so schaut es zumindest meistens aus.

Da mir das aber - wie schon geschrieben - zuviele Plattenzugriffe sind und
es sogut wie unmöglich ist, auf Templates mit INCLUDE zuzugreifen, die
in einer Hashstruktur liegen, habe ich dann einen Tipp zu dem WRAPPER
bekommen.

Nun habe ich mir folgendes überlegt (beispielhaft):

main.tmpl
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[% BLOCK main %]
<html>
<head>
  <title>[% title %]</title>
</head>
<body>
<ul>
[% FOREACH link = links %]
  <li>[% link %]</li>
[% END %]
</ul>
[% content %]
</body>
</html>
[% END %]


index.tmpl
Code: (dl )
1
2
3
4
5
6
[% WRAPPER main
  title = 'Meine Homepage'
  links = [ 'foo', 'bar', 'baz' ]
%]
<p>Mein Content</p>
[% END %]


test.pl
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
use Template;

my $t = Template->new(
  INCLUDE_PATH => '.',
  PRE_PROCESS  => 'main.tmpl'
) or die $!;

open my $fh, '<', 'index.tmpl' or die $!;
my $template = do { local $/; <$fh> };
close $fh;

while ( sleep 1 ) {
  $t->process(\$template) or die $!;
}


Ausgabe
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<html>
<head>
  <title>Meine Homepage</title>
</head>
<body>
<ul>

  <li>foo</li>

  <li>bar</li>

  <li>baz</li>

</ul>

<p>Mein Content</p>

</body>
</html>


Ich lade also zuerst main.tmpl worin alle meine BLOCKs definiert sind und
kann dann nachher individuell in den anderen Templates den Content mit
dem WRAPPER zusammen basteln, dabei liegt alles schön im Speicher und
läuft recht fix.

Ich weiß, ich bin bestimmt nicht der erste, der darauf gekommen ist. :)

Nun meine Frage... wie macht ihr das so und habt ihr vielleicht noch Tipps
oder Anregungen, wie man es eventuell noch besser machen könnte?

Bzgl. Speicher... die Gesamtgröße aller Templates ist ca. 1 MB und bei
knapp 100 FastCGI Prozessen sind das verkraftbare 100 MB Haupt-
speicher.

Viele Grüße,
opi
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
ptk
 2007-06-13 01:14
#77463 #77463
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
[quote=opi,12.06.2007, 22:50]Da mir das aber - wie schon geschrieben - zuviele Plattenzugriffe sind und ...[/quote]
Bist du sicher, dass dabei *Plattenzugriffe* entstehen? Jedes vernünftige Betriebssystem hat verschiedene Formen von Caches, um Read-Operationen auf Festplatten zu minimieren. Das kann man leicht mit time von tcsh oder iostat feststellen. Beim ersten
Zugriff mit einer ungefähr 6 MB großen Includedatei sehe ich folgendes:
Code: (dl )
1
2
time tpage test.tmpl > /dev/null
0.551u 0.124s 0:00.80 83.7% 15+152680k 48+0io 0pf+0w

(Die Zahlen vor "io" zeigen die IO-Operationen in irgendeiner Einheit an)
Danach sieht es immer so aus:
Code: (dl )
1
2
time tpage test.tmpl > /dev/null
0.537u 0.138s 0:00.71 92.9% 16+158706k 0+0io 0pf+0w

iostat bestätigt, dass nichts von der Platte gelesen wird.

Es ist klar, dass man trotzdem etwas gewinnen kann, wenn alles schon als Perl-Skalar vorliegt, man spart schließlich ein paar Syscalls. Aber der Effekt dürfte geringer sein, als man glaubt, und man muss selbst mehr tun, z.B. sich selbst um das Caching (und auch das Aufräumen) kümmern.
bloonix
 2007-06-13 01:59
#77464 #77464
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
Hallo ptk,

du hast natürlich recht... das Caching sollte natürlich seinen Dienst tun!
Aber das war nicht mein einziger Gedanke.

Quote
Es ist klar, dass man trotzdem etwas gewinnen kann, wenn alles schon als Perl-Skalar vorliegt, man spart schließlich ein paar Syscalls.

Das dachte ich mir auch, dass es auch sonst ein wenig zügiger sein sollte,
aber nix da...

Ich habe das obige Beispiel einfach mal umgesetzt und getestet.
Folgendes ist dabei raus gekommen:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use strict;
use warnings;
use Benchmark;
use Template;

open my $fh, '<', 'index1.tmpl' or die $!;
my $template = do { local $/; <$fh> };
close $fh;

my $t1 = Template->new(INCLUDE_PATH => '.', PRE_PROCESS => 'main.tmpl') or die $!;

sub program { $t1->process(\$template, undef, '/dev/null') or die $!; }
sub cache { $t1->process('index1.tmpl', undef, '/dev/null') or die $!; }

Benchmark::cmpthese(-1, {
  program => \&program,
  cache => \&cache,
});


Rate program cache
program 610/s -- -69%
cache 1982/s 225% --
\n\n

<!--EDIT|opi|1181686026-->
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
ptk
 2007-06-13 02:01
#77465 #77465
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
Kannst du die PRE_PROCESS-Variante schneller bekommen, indem du TT-Compiling einschaltest?
bloonix
 2007-06-13 02:09
#77466 #77466
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
[quote=ptk,13.06.2007, 00:01]Kannst du die PRE_PROCESS-Variante schneller bekommen, indem du TT-Compiling einschaltest?[/quote]
Sorry, PRE_PROCESS hatte in dem Beispiel eigentlich nichts verloren,
da es mit dem Vergleich an sich nichts zu tun haben sollte, da ich ja nur
die Übergabe des Templates testen wollte... ob nun als Dateiname oder
als Skalar. Ich habe jetz beides mit PRE_PROCESS gemacht - siehe oben.\n\n

<!--EDIT|opi|1181686223-->
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
bloonix
 2007-06-13 02:11
#77467 #77467
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
Also scheint intern irgendwas mit \$template zu geschehen, was die Sache
verlangsamt.
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
bloonix
 2007-06-13 02:15
#77468 #77468
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
So, hier nochmal ganz simple... wenn du es mal ausprobieren möchtest...

index.tmpl
Code: (dl )
1
2
3
4
5
6
7
<html>
<head>
  <title></title>
</head>
<body>
</body>
</html>


test.pl
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use strict;
use warnings;
use Benchmark;
use Template;

open my $fh, '<', 'index.tmpl' or die $!;
my $template = do { local $/; <$fh> };
close $fh;

my $t1 = Template->new(INCLUDE_PATH => '.') or die $!;

sub program { $t1->process(\$template, undef, '/dev/null') or die $!; }
sub cache   { $t1->process('index.tmpl', undef, '/dev/null') or die $!; }

Benchmark::cmpthese(-1, {
  cache   => \&cache,
  program  => \&program,
});


         Rate program   cache
program 2277/s      --    -53%
cache   4886/s    115%      --
\n\n

<!--EDIT|opi|1181686528-->
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
ptk
 2007-06-13 09:52
#77469 #77469
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
Komisch. Wenn man mit "truss" in das Skript schaut, sieht man, dass kaum open()-Calls auf index.tmpl vorhanden sind. Es sieht also so aus, als ob TT2 selbst schon Caching von Template-Dateien macht. Und vielleicht cacht es nur Dateien, aber keine Strings? Jedenfalls ist nicht das Einlesen das Teure, sondern das Parsen eines Templates.
pq
 2007-06-13 11:35
#77470 #77470
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
also bei HTC hat man die preload-methode, mit der man alle vorkompilierten
templates von der platte einmal zu beginn des programms in den speicher lädt.
sowas muss es doch bei TT auch geben...
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
pq
 2007-06-13 11:38
#77471 #77471
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
TT cached templates per default im memory, ja.
siehe http://search.cpan.org/~abw....Options
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
<< |< 1 2 >| >> 15 Einträge, 2 Seiten



View all threads created 2007-06-13 00:50.