2 Lazy Generation of LyXText
3 --------------------------
5 Currently we generate the Row structure at the time of LyXText
6 creation. This is the "formatting" period of the document
7 loading. As can be seen this has a significant hit on the amount
8 of time used to load large documents. On my computer this
9 manifests itself as a 15 second load time of the UserGuide. In
10 many ways this is acceptable, but we actually get the same hit
11 when switching between documents. Because of this the TextCache
12 was created, however it seems that textcache has some internal
13 problems or it makes problems in LyXText show.
15 My suggestion is to make LyXText only generate Rows as need, i.e.
16 lazy evaluation/generation of the on screen formatting. This will
17 give us: blinding fast document loading. It also lessens the need
18 for the TextCache class significantly and with some small further
19 alterations TextCache can be removed completely.
21 The Rows are currently stored in a home made double linked list.
22 To achieve the lazy evaluation this should be changed slightly:
25 // Pointer to the paragraph that this rowpar holds rows for.
27 // Only used for lazy evaluation when switching between buffers.
29 typedef vector<Row> Rows;
30 // The actual rows, generated as needed.
35 LyXParagraph::size_type pos;
37 unsigned short height;
38 unsigned short ascent_of_text;
42 typedef list<RowPar> ParRowList;
45 Several LyXText methods needs to be changed to handle this new
48 Note about RowPar::par_y: If we only want top-down¹ this variable
49 is not needed. If we however want to be able to begin evaluation
50 at the location of the cursor it is needed. Then we don't have to
51 store the formatted document in the textcache. Only a list of
58 is needed. Since we regenerate all the rows subtleties with row
59 lifetime etc. are avoided.
61 Memory usage: the current Row has a size of about 28 bytes on a
62 32 bit machine and we have one Row for each line on the screen.
63 For a 10 page document with ca. 50 lines on each page this is
64 28 * 10 * 50 = 14000 bytes.
65 The approach above has three pointer less in each row, so
66 this is 16 * 10 * 50 = 8000 bytes, we have however some
67 additional overhead: the RowPars one for each paragraph if we
68 assume 5 lines per paragraph and 20 bytes for each RowPar we get:
69 10 * 50 / 5 * 20 = 2000. This is a sum of 10000 on the new scheme.
71 Speed: some operations will most likely be somewhat faster since
72 they now can operate on the number of paragraph instead of the
73 number of rows. I do not foresee any operations becoming slower.
74 The actual lazy evaluation will be done upon displaying, and when
75 the lyx process is idle (idle_callback), this will mostly be
76 initiated by LyXScreen and done in LyXText::GetRowNearY and in
77 LyXText::GetRow. Perhaps also in LyXText::GetVisibleRow. All of
78 the evaluation will be done on a per-paragraph basis.
80 If we want to operate on rows only it is easy to create iterators
81 that can handle this. (This means that a way to force the
82 evaluation of the rows might be something like:
84 // traverse all the rows and generate the missing ones.
85 for_each(rowlist.begin(), rowlist.end(), dummy_func);
87 Note about the buffer structure in the lyx repository: LyXText
88 really is orthogonal to the new buffer structure in that the
89 BufferStructure is used for storage of the paragraphs, and
90 LyXText is used for the caching of on-screen display (of
93 Note on impact on other code: Since the current rowlist is
94 internal to LyXText the impact on code outside LyXText will be
95 very small. However _inside_ LyXText the impact will be huge, and
96 all methods that access the rowlist will have to change.
98 When to begin coding on this. Of course since this is something
99 that I want to do, I'd like to begin right away. There can be
100 argued that this should wait until table and floats has been
101 moved out of LyXText, but I only partially agree. These changes
102 will be on a fairly low-level and the removal of table and floats
103 will not impact the development of this code much. Also this can
104 very well be done in a separate branch in cvs. Anyway this coding
105 will not begin until after 1.1.5 is released.
107 Fun stuff: Instead of doing the lazy evaluation only when needed
108 or by the idle callback this could also be done by a separate
109 thread taking advantage of SMP and/or io-blocking in the main
110 thread. We could even have the evaluation of each paragraph we
111 done in its own thread (or by a few² worker threads)
116 ¹ Row evaluation from the beginning of the document to the end. Never
119 ² Number of CPUs f.ex.