1 |
<?xml version="1.0" encoding="us-ascii"?> |
2 |
<feed xmlns="http://www.w3.org/2005/Atom"><title>Content Considered Harmful Atom Feed</title><id>http://blog.jrock.us/</id><link href="http://blog.jrock.us/feeds/category/Catalyst/xml" rel="self"/><link href="http://blog.jrock.us/"/><subtitle type="html">This is Jonathan Rockway's Blog, quite possibily the best blog ever. |
3 |
Or something. |
4 |
</subtitle><generator uri="http://www.jrock.us/" version="0.01_01">AngerWhale</generator><updated>2006-08-10T02:43:00Z</updated><entry><title>Catalyst + Cache</title><author><name>Jonathan T. Rockway</name><email>jon@jrock.us</email></author><id>urn:guid:8D9B9CBE-27DB-11DB-B6C2-F007B8516AA5</id><link href="http://blog.jrock.us/articles/Catalyst%20+%20Cache.pod"/><category term="Catalyst" scheme="http://blog.jrock.us/categories/"/><updated>2006-08-09T19:07:58Z</updated><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><div class="pod"> |
5 |
<p>I recently posted this to the <cite>Template::Toolkit</cite> mailing list, but |
6 |
the moderator rejected it for some reason. (Probably because <code><jon-perl-list-templates AT jrock.us></code> is the address that's |
7 |
subscribed, not <code><jon AT jrock.us></code>.)</p> |
8 |
<p>Anyway, here it is. I will expand on this further with actual |
9 |
measurements, but this will have to do for now.</p> |
10 |
<h4 id="Original_Message">Original Message</h4> |
11 |
<div id="Original_Message_CONTENT"> |
12 |
<p><i>Thank you, you raise a good point that I had not fully considered. My |
13 |
goal is to display a dynamically generated page, but where most of the |
14 |
"dynamic" content is actually static for a period amount of time. |
15 |
(Take a news page, for example, where the list of news stories updates |
16 |
once an hour.)</i></p> |
17 |
|
18 |
</div> |
19 |
<h4 id="My_Reply">My Reply</h4> |
20 |
<div id="My_Reply_CONTENT"> |
21 |
<p>I have a similar problem with my blogging software. Most of the content |
22 |
is static, and it's kind of a waste to regenerate everything every time |
23 |
someone views the page. My solution to this problem is to use a |
24 |
<cite>Cache::FastMmap</cite> object to store the formatted HTML content of each post, |
25 |
keyed on the source material's MD5sum (and filetype, for reasons not |
26 |
relevant to this discussion :) </p> |
27 |
<p>This results in a nice speedup, since certain HTML filters are slow |
28 |
(OO.org document -> HTML, for example).</p> |
29 |
<p>I also cache full pages, after they've been assembled by TT, keyed on |
30 |
the md5sum of each included article and some metadata (comment count, |
31 |
tags, etc.) The end result is a 5-20x speed up. With Catalyst's |
32 |
embedded server, I can do about 5 requests per second without cache, but |
33 |
it goes up to about 40-50 requests/second with the cache. So obviously |
34 |
a speedup. (And I'm still not doing a very good job, this was just a 20 |
35 |
minute hack!)</p> |
36 |
<p>For the gory details, check out the code here:</p> |
37 |
<p><a href="http://www.jrock.us/trac/blog_software/browser/lib/Blog/Controller/Root.pm#L105">http://www.jrock.us/trac/blog_software/browser/lib/Blog/Controller/Root.pm#L105</a> |
38 |
(page cache)</p> |
39 |
<p>and: |
40 |
<a href="http://www.jrock.us/trac/blog_software/browser/lib/Blog/Model/Filesystem/Item.pm#L355">http://www.jrock.us/trac/blog_software/browser/lib/Blog/Model/Filesystem/Item.pm#L355</a> |
41 |
(object cache)</p> |
42 |
|
43 |
|
44 |
|
45 |
|
46 |
<p>Another caching strategy is to set dynamic pages to be cachable for say, |
47 |
10 seconds, and then letting Apache's mod_cache (experimental in 2.2.3, |
48 |
but it works for me) do the hard work. Your application gets hit once |
49 |
every ten seconds to refresh Apache's cache, but all the end-user |
50 |
requests are handled by serving from Apache's memory cache. With |
51 |
mpm_worker, it's *super fast*, and a 10 second update delay isn't bad.</p> |
52 |
<p>If your application is really slow, this will let you increase your |
53 |
slashdot resistance factor (as I call it) enormously. A quick ab |
54 |
against some cached content gave me a requests/per second rate of |
55 |
1638... much better than whatever your app would do by itself.</p> |
56 |
<p>And you don't really lose much by taking this approach, other than a 10 |
57 |
second delay with your articles going live... but 10 seconds is nothing |
58 |
if you're getting 1500 requests per second and handling it with an old |
59 |
PIII :) </p> |
60 |
<p>If this info is useful to anyone else, let me know (off-list) and I'll |
61 |
write up a more detailed article about it :) </p> |
62 |
|
63 |
</div> |
64 |
</div></div></content></entry><entry><title>Quantum Physics and the Template Toolkit</title><author><name>Jonathan T. Rockway</name><email>jon@jrock.us</email></author><id>urn:guid:BB054AF0-2601-11DB-9738-946FBD312859</id><link href="http://blog.jrock.us/articles/Quantum%20Physics%20and%20the%20Template%20Toolkit.pod"/><category term="Catalyst" scheme="http://blog.jrock.us/categories/"/><category term="Programming" scheme="http://blog.jrock.us/categories/"/><updated>2006-08-07T10:44:20Z</updated><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><div class="pod"> |
65 |
<p>As a programmer, you probably don't spend a lot of time thinking about |
66 |
the similarities between programming and quantum physics. Fortunately |
67 |
for us Perl users, some people <i>do</i> spend a lot of time thinking |
68 |
about physics, and they even wrap up the results in |
69 |
<a href="http://search.cpan.org">CPAN</a> modules for us!</p> |
70 |
<p>One such module is <cite>Quantum::Superpositions</cite>, which let me easily add |
71 |
some nice functionality to my <a href="http://www.jrock.us/trac/blog_software">blog software</a> the other day. </p> |
72 |
<p>As you can see (if you're looking at this article on my blog, not in |
73 |
an RSS reader), I have a list of tags to the left of my main content. |
74 |
If you click one, it shows you a list of articles that have been |
75 |
tagged with that tag. If you select more than one tag, you get this |
76 |
intersection of the two sets (tag1 AND tag2).</p> |
77 |
<p>That's nice, but I like to use the left navigation bar to show the |
78 |
user where he is <i>in addition to</i> letting him move somewhere else. |
79 |
To do this, I bold the current location, and remove the link. That |
80 |
way, the user won't try to visit the page he's already looking at. |
81 |
This is pretty simple to implement for things like the "home page" or |
82 |
the "archives". You just check the current page, and if the link |
83 |
you're about to print out matches, make it bold instead. That logic |
84 |
looks something like this:</p> |
85 |
<pre> [% FOREACH category = categories %] |
86 |
[% IF category == current_category %] |
87 |
<b>[% category %]</b> |
88 |
[% ELSE %] |
89 |
[% category %] |
90 |
[% END %] |
91 |
[% END %] |
92 |
|
93 |
</pre> |
94 |
<p>Simple, and it provides excellent visual cues as to what the user is |
95 |
looking at.</p> |
96 |
<p>The problem with tags, though, is that an article can have lots of |
97 |
them. The technique above doesn't work there; you need to do a search |
98 |
for each tag. Not a show stopper, but do you really want to do array |
99 |
searches inside the Template Toolkit? No!</p> |
100 |
<p>And this is where <cite>Quantum::Superpositions</cite> comes to the rescue. In |
101 |
quantum physics, almost nothing is "certain" -- you can't tell with |
102 |
100% certainty both where a particle is and what its velocity is. |
103 |
The state of an individual particle is in sort of a flux until you |
104 |
observe, and when you observe, a tangible state comes into existence.</p> |
105 |
<p>How does this help with tags? By thinking of the set of all tags as a |
106 |
cloud of particles, we can apply the same principle. We don't care |
107 |
what all the tags are until we look at them.</p> |
108 |
<p>So how do we do this in perl? Let's see an example:</p> |
109 |
<p>In my |
110 |
<a href="http://www.jrock.us/trac/blog_software/browser/lib/Blog/Controller/Tags.pm#L96">Tags.pm</a> |
111 |
Controller, I use the <code>any</code> method from <code>Quantum::Superpositions</code> to |
112 |
collapse the list of tags into a scalar:</p> |
113 |
<pre> $c->stash->{article_tags} = any(@tags); |
114 |
|
115 |
</pre> |
116 |
<p>Then inside my <a href="http://www.jrock.us/trac/blog_software/browser/root/navbox.tt#L40">Template Toolkit View</a>, I "observe" the state as |
117 |
necessary (with the <code>==</code> operator):</p> |
118 |
<pre> [% FOREACH tag = all_tags %] |
119 |
[% IF tag == article_tags %] |
120 |
<b>[% tag %]</b> |
121 |
[% ELSE %] |
122 |
[% tag %] |
123 |
[% END %] |
124 |
[% END %] |
125 |
|
126 |
</pre> |
127 |
<p>As you can see, this is exactly the same as what we did when we only |
128 |
had one possible value. If you think about it, it's really the same |
129 |
thing. You just needed to think more about physics :)</p> |
130 |
<p>Anyway, take a look at this in action:</p> |
131 |
<p><a href="http://blog.jrock.us/tags/%E3%83%A2%E3%83%BC%E5%A8%98%E3%80%82/music">http://blog.jrock.us/tags/%E3%83%A2%E3%83%BC%E5%A8%98%E3%80%82/music</a></p> |
132 |
<p>And then add some cool navigation features to your Catalyst app! |
133 |
</p> |
134 |
|
135 |
|
136 |
</div></div></content></entry></feed> |