(no commit message)
[ikiwiki] / doc / tips / optimising_ikiwiki.mdwn
1 Ikiwiki is a wiki compiler, which means that, unlike a traditional wiki,
2 all the work needed to display your wiki is done up front. Where you can
3 see it and get annoyed at it. In some ways, this is better than a wiki
4 where a page view means running a program to generate the page on the fly.
5
6 But enough excuses. If ikiwiki is taking too long to build your wiki,
7 let's fix that. Read on for some common problems that can be avoided to
8 make ikiwiki run quick.
9
10 [[!toc]]
11
12 (And if none of that helps, file a [[bug|bugs]]. One other great thing about
13 ikiwiki being a wiki compiler is that it's easy to provide a test case when
14 it's slow, and get the problem fixed!)
15
16 ## rebuild vs refresh
17
18 Are you building your wiki by running a command like this?
19
20         ikiwiki -setup my.setup
21
22 If so, you're always telling ikiwiki to rebuild the entire site, from
23 scratch. But, ikiwiki is smart, it can incrementally update a site,
24 building only things affected by the changes you make. You just have to let
25 it do so:
26
27         ikiwiki -setup my.setup -refresh
28
29 Ikiwiki automatically uses an incremental refresh like this when handing
30 a web edit, or when run from a [[rcs]] post-commit hook. (If you've
31 configured the hook in the usual way.) Most people who have run into this
32 problem got in the habit of running `ikiwiki -setup my.setup` by hand
33 when their wiki was small, and found it got slower as they added pages.
34
35 ## use the latest version
36
37 If your version of ikiwiki is not [[!version]], try upgrading. New
38 optimisations are frequently added to ikiwiki, some of them yielding
39 *enormous* speed increases.
40
41 ## run ikiwiki in verbose mode
42
43 Try changing a page, and run ikiwiki with `-v` so it will tell you
44 everything it does to deal with that changed page. Take note of
45 which other pages are rebuilt, and which parts of the build take a long
46 time. This can help you zero in on individual pages that contain some of
47 the expensive things listed below. 
48
49 ## expensive inlines
50
51 Do you have an archive page for your blog that shows all posts, 
52 using an inline that looks like this?
53
54         \[[!inline pages="blog/*" show=0]]
55
56 Or maybe you have some tag pages for your blog that show all tagged posts,
57 something like this?
58
59         \[[!inline pages="blog/* and tagged(foo)" show=0]]
60
61 These are expensive, because they have to be updated whenever you modify a
62 matching page. And, if there are a lot of pages, it generates a large html
63 file, which is a lot of work. And also large RSS/Atom files, which is even
64 more work!
65
66 To optimise the inline, consider enabling quick archive mode. Then the
67 inline will only need to be updated when new pages are added; no RSS
68 or Atom feeds will be built, and the generated html file will be much
69 smaller.
70         
71         \[[!inline pages="blog/*" show=0 archive=yes quick=yes]]
72         
73         \[[!inline pages="blog/* and link(tag)" show=0 archive=yes quick=yes]]
74
75 Only downsides: This won't show titles set by the [[ikiwiki/directive/meta]]
76 directive. And there's no RSS feed for users to use -- but if this page
77 is only for the archives or tag for your blog, users should be subscribing
78 to the blog's main page's RSS feed instead.
79
80 For the main blog page, the inline should only show the latest N posts,
81 which won't be a performance problem:
82
83         \[[!inline pages="blog/*" show=30]]
84
85 ## expensive maps
86
87 Do you have a sitemap type page, that uses a map directive like this?
88
89         \[[!map pages="*" show=title]]
90
91 This is expensive because it has to be updated whenever a page is modified.
92 The resulting html file might get big and expensive to generate as you
93 keep adding pages.
94
95 First, consider removing the "show=title". Then the map will not show page
96 titles set by the [[ikiwiki/directive/meta]] directive -- but will also
97 only need to be generated when pages are added or removed, not for every
98 page change.
99
100 Consider limiting the map to only show the toplevel pages of your site,
101 like this:
102
103         \[[!map pages="* and !*/*" show=title]]
104
105 Or, alternatively, to drop from the map parts of the site that accumulate
106 lots of pages, like individual blog posts:
107
108         \[[!map pages="* and !blog/*" show=title]]
109
110 ## sidebar issues
111
112 If you enable the [[plugins/sidebar]] plugin, be careful of what you put in
113 your sidebar. Any change that affects what is displayed by the sidebar
114 will require an update of *every* page in the wiki, since all pages include
115 the sidebar.
116
117 Putting an expensive map or inline in the sidebar is the most common cause
118 of problems. At its worst, it can result in any change to any page in the
119 wiki requiring every page to be rebuilt.
120
121 ## avoid htmltidy
122
123 A few plugins do neat stuff, but slowly. Such plugins are tagged
124 [[plugins/type/slow]].
125
126 The worst offender is possibly [[plugins/htmltidy]]. This runs an external
127 `tidy` program on each page that is built, which is necessarily slow. So don't
128 use it unless you really need it; consider using the faster
129 [[plugins/htmlbalance]] instead.
130
131 ## be careful of large linkmaps
132
133 [[plugins/Linkmap]] generates a cool map of links between pages, but
134 it does it using the `graphviz` program. And any changes to links between
135 pages on the map require an update. So, avoid using this to map a large number
136 of pages with frequently changing links. For example, using it to map
137 all the pages on a traditional, highly WikiLinked wiki, is asking for things
138 to be slow. But using it to map a few related pages is probably fine.
139
140 This site's own [[plugins/linkmap]] rarely slows it down, because it
141 only shows the index page, and the small set of pages that link to it.
142 That is accomplished as follows:
143
144         \[[!linkmap pages="index or (backlink(index)"]]
145
146 ## overhead of the search plugin
147
148 Be aware that the [[plugins/search]] plugin has to update the search index
149 whenever any page is changed. This can slow things down somewhat.
150
151 ## profiling
152
153 If you have a repeatable change that ikiwiki takes a long time to build,
154 and none of the above help, the next thing to consider is profiling
155 ikiwiki. 
156
157 The best way to do it is:
158
159 * Install [[!cpan Devel::NYTProf]]
160 * `PERL5OPT=-d:NYTProf`
161 * `export PER5OPT`
162 * Now run ikiwiki as usual, and it will generate a `nytprof.out` file.
163 * Run `nytprofhtml` to generate html files.
164 * Those can be examined to see what parts of ikiwiki are being slow.
165
166 ## scaling to large numbers of pages
167
168 Finally, let's think about how huge number of pages can affect ikiwiki.
169
170 * Every time it's run, ikiwiki has to scan your `srcdir` to find
171   new and changed pages. This is similar in speed to running the `find`
172   command. Obviously, more files will make it take longer.
173
174 * Also, to see what pages match a [[ikiwiki/PageSpec]] like "blog/*", it has
175   to check if every page in the wiki matches. These checks are done quite
176   quickly, but still, lots more pages will make PageSpecs more expensive.
177
178 * The backlinks calculation has to consider every link on every page
179   in the wiki. (In practice, most pages only link to at most a few dozen
180   other pages, so this is not a `O(N^2)`, but closer to `O(N)`.)
181
182 * Ikiwiki also reads and writes an `index` file, which contains information
183   about each page, and so if you have a lot of pages, this file gets large,
184   and more time is spent on it. For a wiki with 2000 pages, this file
185   will run about 500 kb.
186
187 If your wiki will have 100 thousand files in it, you might start seeing
188 the above contribute to ikiwiki running slowly.