% language=uk \startcomponent mk-luafitsin \environment mk-environment \chapter{How \LUA\ fits in} \subject{introduction} Here I will discuss a few of the experiments that drove the development of \LUATEX. It describes the state of affairs around the time that we were preparing for \TUG\ 2006. This development was pretty demanding for Taco and me but also much fun. We were in a kind of permanent Skype chat session, with binaries flowing in one direction and \TEX\ and \LUA\ code the other way. By gradually replacing (even critical) components of \CONTEXT\ we had a real test bed and torture tests helped us to explore and debug at the same time. Because Taco uses \LINUX\ as platform and I mostly use \MSWINDOWS, we could investigate platform dependent issues conveniently. While reading this text, keep in mind that this is just the beginning of the game. I will not provide sample code here. When possible, the \MKIV\ code transparantly replaces \MKII\ code and users will seldom notices that something happens in different way. Of course the potential is there and future extensions may be unique to \MKIV. \subject{compatibility} The first experiments, already conducted with the experimental versions involved runtime conversion of one type of input into another. An example of this is the (TI) calculator math input handler that converts a rather natural math sequence into \TEX\ and feeds that back into \TEX. This mechanism eventually will evolve into a configurable math input handler. Such applications are unique to \MKIV\ code and will not be backported to \MKII. The question is where downward compatibility will become a problem. We don't expect many problems, apart from occasional bugs that result from splitting the code base, mostly because new features will not affect older functionality. Because we have to reorganize the code base a bit, we also use this opportunity to start making a variant of \CONTEXT\ which consists of building blocks: \METATEX. This is less interesting for the average user, but may be of interest for those using \CONTEXT\ in workflows where only part of the functionality is needed. \subject{metapost} Of course, when I experiment with such new things, I cannot let \METAPOST\ leave untouched. And so, in the early stage of \LUATEX\ development I decided to play with two \METAPOST\ related features: conversion and runtime processing. Conversion from \METAPOST\ output to \PDF\ is currently done in pure \TEX\ code. Apart from convenience, this has the advantage that we can let \TEX\ take care of font inclusions. The tricky part of this conversion is that \METAPOST\ output has some weird aspects, like \DVIPS\ specific linewidth snapping. Another nasty element in the conversion is that we need to transform paths when pens are used. Anyhow, the converter has reached a rather stable state by now. One of the ideas with \METAPOST\ version 1\high{+} is that we will have an alternative output mode. In the perspective of \LUATEX\ it makes sense to have a \LUA\ output mode. Whatever converter we use, it needs to deal with \METAFUN\ specials. These are responsible for special features like transparency, graphic inclusion, shading, and more. Currently we misuse colors to signal such features, but the new pre|/|post path hooks permit more advanced implementations. Experimenting with such new features is easier in \LUA\ than in \TEX. The \MKIV\ converter is a multi||pass converter. First we clean up the \METAPOST\ output, next we convert the \POSTSCRIPT\ code into \LUA\ calls. We assume that this \LUA\ code eventually can be output directly from \METAPOST. We then evaluate this converted \LUA\ blob, which results in \TEX\ commands. Think of: \starttyping 1.2 setlinejoin \stoptyping turned into: \starttyping mp.setlinejoin(1.2) \stoptyping becoming: \starttyping \PDFcode{1.2 j} \stoptyping which is, when the \PDFTEX\ driver is active, equivalent to: \starttyping \pdfliteral{1.2 j} \stoptyping Of course, when paths are involved, more things happen behind the scenes, but in the end an \type {mp.path} enters the \LUA\ machinery. When the \MKIV\ converter reached a stable state, tests demonstrated then the code was upto 20\% slower that the pure \TEX\ alternative on average graphics, and but faster when many complex path transformations (due to penshapes) need to be done. This slowdown was due to the cleanup (using expressions) and intermediate conversion. Because Taco develops \LUATEX\ as well as maintains and extends \METAPOST, we conducted experiments that combine features of these programs. As a result of this, shortcuts found their way into the \METAPOST\ output. \useMPlibrary[mis] \placefigure [] [fig:mptopdf] {converter test figure} {\scale[width=\hsize]{\useMPgraphic{mptopdf-test}}} Cleaning up the \METAPOST\ output using \LUA\ expressions takes relatively much time. However, starting with version 0.970 \METAPOST\ uses a preamble, which permits not only short commands, but also gets rid of the weird linewidth and filldraw related \POSTSCRIPT\ constructs. The moderately complex graphic that we use for testing (\in {figure} [fig:mptopdf]) takes over 16 seconds when converted 250 times. When we enable shortcuts we can avoid part of the cleanup and runtime goes down to under 7.5 seconds. This is significantly faster than the \MKII\ code. We did experiments with simulated \LUA\ output from \METAPOST\ and then the \MKIV\ converter really flies. The values on Taco's system are given between parenthesis. \starttabulate[|||||] \HL \NC \bf prologues/mpprocset \NC \bf 1/0 \NC \bf 1/1 \NC \bf 2/0 \NC \bf 2/1 \NC \NR \HL \NC \MKII \NC ~8.5 (~5.7) \NC ~8.0 (5.5) \NC ~8.8 \NC ~8.5 \NC \NR \NC \MKIV \NC 16.1 (10.6) \NC ~7.2 (4.5) \NC 16.3 \NC ~7.4 \NC \NR \HL \stoptabulate The main reason for the huge difference in the \MKIV\ times is that we do a rigourous cleanup of the older \METAPOST\ output in order avoid messy the messy (but fast) code that we use in the \MKII\ converter. Think of: \starttyping 0 0.5 dtransform truncate idtransform setlinewidth pop closepath gsave fill grestore stroke \stoptyping In the \MKII\ converter, we push every number or keyword on a stack and use keywords as trigger points. In the \MKIV\ code we convert the stack based \POSTSCRIPT\ calls to \LUA\ function calls. Lines as shown are converted to single calls first. When \type {prologues} is set to~2, such line no longer show up and are replaced by simple calls accompanied by definitions in the preamble. Not only that, instead of verbose keywords, one or two character shortcuts are used. This means that the \MKII\ code can be faster when procsets are used because shorter strings end up in the stack and comparison happens faster. On the other hand, when no procsets are used, the runtime is longer because of the larger preamble. Because the converter is used outside \CONTEXT\ as well, we support all combinations in order not to get error messages, but the converter is supposed to work with the following settings: \starttyping prologues := 1 ; mpprocset := 1 ; \stoptyping We don't need to set \type {prologues} to~2 (font encodings in file) or~3 (also font resources in file). So, in the end, the comparison in speed comes down to 8.0 seconds for \MKII\ code and 7.2 seconds for the \MKIV\ code when using the latest greatest \METAPOST. When we simulate \LUA\ output from \METAPOST, we end up with 4.2 seconds runtime and when \METAPOST\ could produce the converter's \TEX\ commands, we need only 0.3 seconds for embedding the 250 instances. This includes \TEX\ taking care of handling the specials, some of which demand building moderately complex \PDF\ data structures. But, conversion is not the only factor in convenient \METAPOST\ usage. First of all, runtime \METAPOST\ processing takes time. The actual time spent on handling embedded \METAPOST\ graphics is also dependent on the speed of starting up \METAPOST, which in turn depends on the size of the \TEX\ trees used: the bigger these are, the more time \KPSE\ spends on loading the \type {ls-R} databases. Eventually this bottleneck may go away when we have \METAPOST\ as a library. (In \CONTEXT\ one can also run \METAPOST\ between runs. Which method is faster, depends on the amount and complexity of the graphics.) Another factor in dealing with \METAPOST, is the usage of text in a graphic (\type {btex}, \type {textext}, etc.). Taco Hoekwater, Fabrice Popineau and I did some experiments with a persistent \METAPOST\ session in the background in order to simulate a library. The results look very promising: the overhead of embedded \METAPOST\ graphics goes to nearly zero, especially when we also let the parent \TEX\ job handle the typesetting of texts. A side effect of these experiments was a new mechanism in \CONTEXT\ (and \METAFUN) where \TEX\ did all typesetting of labels, and \METAPOST\ only worked with an abstract representation of the result. This way we can completely avoid nested \TEX\ runs (the ones triggered by \METAPOST). This also works ok in \MKII\ mode. Using a persistent \METAPOST\ run and piping data into it is not the final solution if only because the terminal log becomes messed up too much, and also because intercepting errors is real messy. In the end we need a proper library approach, but the experiments demonstrated that we needed to go this way: handling hundreds of complex graphics that hold typeset paragraphs (being slanted and rotated and more by \METAPOST), tooks mere seconds compared to minutes when using independent \METAPOST\ runs for each job. \subject{characters} Because \LUATEX\ is \UTF\ based, we need a different way to deal with input encoding. For this purpose there are callbacks that intercept the input and convert it as needed. For context this means that the regime related modules get a \LUA\ based counterparts. As a prelude to advanced character manipulations, we already load extensive unicode and conversion tables, with the benefit of being able to handle case handling with \LUA. The character tables are derived from unicode tables and \MKII\ \CONTEXT\ data files and generated using \MTXTOOLS. The main character table is pretty large, and this made us experiment a bit with efficiency. It was in this stage that we realized that it made sense to use precompiled \LUA\ code (using \type {luac}). During format generation we let \CONTEXT\ keep track of used \LUA\ files and compiled them on the fly. For a production run, the compiled files were loaded instead. Because at that stage \LUATEX\ was already a merge between \PDFTEX\ and \ALEPH, we had to deal with pretty large format files. About that moment the \CONTEXT\ format with the english user interface amounted to: \starttabulate[|c|c|c|c|c|] \NC \bf date \NC \bf luatex \NC \bf pdftex \NC \bf xetex \NC \bf aleph \NC \NR \NC 2006-09-18 \NC 9 552 042 \NC 7 068 643 \NC 8 374 996 \NC 7 942 044 \NC \NR \stoptabulate One reason for the large size of the format file is that the memory footprint of a 32 bit \TEX\ is larger than that of good old \TEX, even with some of the clever memory allocation techniques as used in \LUATEX. After some experiments where size and speed were measured Taco decided to compress the format using a level~3 \ZIP\ compression. This brilliant move lead to the following size: \starttabulate[|c|c|c|c|c|] \NC \bf date \NC \bf luatex \NC \bf pdftex \NC \bf xetex \NC \bf aleph \NC \NR \NC 2006-10-23 \NC 3 135 568 \NC 7 095 775 \NC 8 405 764 \NC 7 973 940 \NC \NR \stoptabulate The first zipped versions were smaller (around 2.3 meg), but in the meantime we moved the \LUA\ code into the format and the character related tables take some space. \start \it How stable are the mentioned numbers? Ten months after writing the previous text we get the following numbers: \stop \starttabulate[|c|c|c|c|c|] \NC \bf date \NC \bf luatex \NC \bf pdftex \NC \bf xetex \NC \bf aleph \NC \NR \NC 2007-08-16 \NC 5 603 676 \NC 7 505 925 \NC 8 838 538 \NC 8 369 206 \NC \NR \stoptabulate They are all some 400K larger, which is probably the result of changes in hyphenation patterns (we now load them all, some several times depending on the font encodings used). Also, some extra math support has been brought in the kernel and we predefine a few more things. However, \LUATEX's format has become much larger! Partly this is the result of more \LUA\ code, especially \OPENTYPE\ font handling and attributes related code. The extra \TEX\ code is probably compensated by the removal of obsolete (at least for \MKIV) code. However, the significantly larger number is mostly there because a different compression algorithm is used: speed is now favoured over efficiency. \subject{debugging} In the process of experimenting with callbacks I played a bit with handling \TEX\ error information. An option is to generate an \HTML\ page instead of spitting out the usual blob of into on the terminal. In \in {figure} [fig:error] and \in {figure} [fig:debug] you can see an example of this. \placefigure[][fig:error]{An example error screen.}{\externalfigure[mk-error.png][width=\textwidth]} \placefigure[][fig:debug]{An example debug screen.}{\externalfigure[mk-debug.png][width=\textwidth]} Playing with such features gives us an impression of what kind of access we need to \TEX's internals. It also formed a starting point for conversion routines and a mechanism for embedding \LUA\ code in \HTML\ pages generated by \CONTEXT. \subject{file io} Replacing \TEX's in- and output handling is non||trival. Not only is the code quite interwoven in the \WEBC\ source, but there is also the \KPSE\ library to deal with. This means that quite some callbacks are needed to handle the different types of files. Also, there is output to the log and terminal to take care of. Getting this done took us quite some time and testing and debugging was good for some headaches. The mechanisms changed a few times, and \TEX\ and \LUA\ code was thrown away as soon as better solutions came around. Because we were testing on real documents, using a fully loaded \CONTEXT\ we could converge to a stable version after a while. Getting this \IO\ stuff done is tightly related to generating the format and starting up \LUATEX. If you want to overload the file searching and \IO\ handling, you need overload as soon as possible. Because \LUATEX\ is also supposed to work with the existing \KPSE\ library, we still have that as fallback, but in principle one could think of a \KPSE\ free version, in which case the default file searching is limited to the local path and memory initialization also reverts to the hard coded defaults. A complication is that the soure code has \KPSE\ calls and references to \KPSE\ variables all over the place, so occasionally we run into interesting bugs. Anyhow, while Taco hacked his way around the code, I converted my existing \RUBY\ based \KPSE\ variant into \LUA\ and started working from that point. The advantage of having our own \IO\ handler is that we can go beyond \KPSE. For instance, since \LUATEX\ has, among a few others, the \ZIP\ libraries linked in, we can read from \ZIP\ files, and keep all \TEX\ related files in \TDS\ compliant \ZIP\ files as well. This means that one can say: \starttyping \input zip:///somezipfile.zip?name=/somepath/somefile.tex \stoptyping and use similar references to access files. Of course we had to make sure that \KPSE\ like searching in the \TDS\ (standardized \TEX\ trees) works smoothly. There are plans to link the curl library into \LUATEX, so that we can go beyong this and access repositories. Of course, in order to be more or less \KPSE\ and \WEBC\ compliant, we also need to support this paranoid file handling, so we provide mechanisms for that as well. In addition, we provide ways to create sandboxes for system calls. Getting to intercept all log output (well, most log output) was a problem in itself. For this I used a (preliminary) \XML\ based log format, which will make log parsing easier. Because we have full control over file searching, opening and closing, we can also provide more information about what files are loaded. For instance we can now easily trace what \TFM\ files \TEX\ reads. Implementing additional methods for locating and opening files is not that complex because the library that ships with \CONTEXT\ is already prepared for this. For instance, implementing support for: \starttyping \input http://www.someplace.org/somepath/somefile.tex \stoptyping involved a few lines of code, most of which deals with caching the files. Because we overload the whole \IO\ handling, this means that the following works ok: % \bgroup \loggingall \startbuffer \placefigure [][] {http handling} {\externalfigure [http://www.pragma-ade.com/show-gra.pdf] [page=1,width=\textwidth]} \stopbuffer \typebuffer \ifx\ctxlua \undefined \else \getbuffer \fi % \egroup Other protocols, like \FTP\ are also supported, so one can say: \starttyping \typefile {ftp://anonymous:@ctan.org/tex-archive/systems\ /knuth/lib/plain.tex} \stoptyping On the agenda is playing with database, but by the time that we enter that stage linking the \type {curl} libraries into \LUATEX\ should have taken place. \subject{verbatim} The advance of \LUATEX\ also permitted us to play with a long standing wish of catcode tables, a mechanism to quickly switch between different ways of treating input characters. An example of a place where such changes take place is verbatim (and in \CONTEXT\ also when dealing with \XML\ input). We already had encountered the phenomena that when piping back results from \LUA\ to \TEX, we needed to take care of catcodes so that \TEX\ would see the input as we wished. Earlier experiments with applying \type {\scantokens} to a result and thereby interpreting the result conforming the current catcode regime was not sufficient or at least not handy enough, especially in the perspective of fully expandable \LUA\ results. To be honest, the \type {\scantokens} command was rather useless for this purposes due to its pseudo file nature and its end||of||file handling but in \LUATEX\ we now have a convenient \type {\scantextokens} which has no side effects. Once catcode tables were in place, and the relevant \CONTEXT\ code adapted, I could start playing with one of the trickier parts of \TEX\ programming: typesetting \TEX\ using \TEX, or verbatim. Because in \CONTEXT\ verbatim is also related to buffering and pretty printing, all these mechanism were handled at once. It proved to be a pretty good testcase for writing \LUA\ results back to \TEX, because anything you can imagine can and will interfere (line endings, catcode changes, looking ahead for arguments, etc). This is one of the areas where \MKIV\ code will make things look more clean and understandable, especially because we could move all kind of postprocessing (needed for pretty printing, i.e.\ syntax highlighting) to \LUA. Interesting is that the resulting code is not beforehand faster. Pretty printing 1000 small (one line) buffers and 5000 simple \type {\type} commands perform as follows: \starttabulate[|l|c|c|c|c|] \NC \NC \TEX\ normal \NC \TEX\ pretty \NC \LUA\ normal \NC \LUA\ pretty \NC \NR \NC buffer \NC 2.5 (2.35) \NC ~4.5 (3.05) \NC 2.2 (1.8) \NC ~2.5 (2.0) \NC \NR \NC inline \NC 7.7 (4.90) \NC 11.5 (7.25) \NC 9.1 (6.3) \NC 10.9 (7.5) \NC \NR \stoptabulate Between braces the runtime on Taco's more modern machine is shown. It's not that easy to draw conclusions from this because \TEX\ uses files for buffers and with \LUA\ we store buffers in memory. For inline verbatim, \LUA\ call's bring some overhead, but with more complex content, this becomes less noticable. Also, the \LUA\ code is probably less optimized than the \TEX\ code, and we don't know yet what benefits a Just In Time \LUA\ compiler will bring. \subject{xml} Interesting is that the first experiments with \XML\ processing don't show the expected gain in speed. This is due to the fact that the \CONTEXT\ \XML\ parser is highly optimized. However, if we want to load a whole \XML\ file, for instance the formal \CONTEXT\ interface specification \type {cont-en.xml}, then we can bring down loading time (as well as \TEX\ memory usage) down from multiple seconds to a blink of the eyes. Experiments with internal mappings and manipulations demonstrated that we may not so much need an alternative for the current parser, but can add additional, special purpose ones. We may consider linking \XSLTPROC\ into \LUATEX, but this is yet undecided. After all, the problem of typesetting does not really change, so we may as well keep the process of manipulating and typesetting separated. \subject{multipass data} Those who know \CONTEXT\ a bit will know that it may need multiple passes to typeset a document. \CONTEXT\ not only keeps track of index entries, list entries, cross references, but also optimizes some of the output based on information gathered in previous passes. Especially so called two||pass data and positional information puts some demands on memory and runtime. Two||pass data is collapsed in lists because otherwise we would run out of memory (at least this was true years ago when these mechanisms were introduced). Positional information is stored in hashes and has always put a bit of a burden on the size of a so called utility file (\CONTEXT\ stores all information in one auxiliary file). These two datatypes were the first we moved to a \LUA\ auxiliary file and eventually all information will move there. The advantage is that we can use efficient hashes (without limitations) and only need to run over the file once. And \LUA\ is incredibly fast in loading the tables where we keep track of these things. For instance, a test file storing and reading 10.000 complex positions takes 3.2 seconds runtime with \LUATEX\ but 8.7 seconds with traditional \PDFTEX. Imagine what this will save when dealing with huge files (400 page 300 Meg files) that need three or more passes to be typeset. And, now we can without problems bump position tracking to milions of positions. \subject{resources} Finding files is somewhat tricky and has a history in the \TEX\ community and its distributions. For reasons of packaging and searching files are organized in a tree and there are rules for locating files of given types in this tree. When we say \starttyping \input blabla.tex \stoptyping \TEX\ will look for this file by consulting the path specification associated with the filetype. When we say \starttyping \input blabla \stoptyping \TEX\ will add the \type {.tex} suffix itself. Most other filetypes are not seen by users but are dealt with in a similar way internally. As mentioned before, we support reading from other resources than the standard file system, for instance we can input files from websites or read from \ZIP\ archives. Although this works quite well, we need to keep in mind that there are some conflicting interests: structured search based on type related specifications versus more or less explicit requests. \starttyping \input zip:///archive.zip?name=blabla.tex \input zip:///archive.zip?name=/somepath/blabla.tex \stoptyping Here we need to be rather precise in defining the file location. We can of course build rather complex mechanisms for locating files here, but at some point that may backfire and result in unwanted matches. If you want to treat a \ZIP\ archive as a \TEX\ tree, then you need to register the file: \starttyping \usezipfile[archive.zip] \usezipfile[tex.zip][texmf-local] \usezipfile[tex.zip?tree=texmf-local] \stoptyping The first variant registers all files in the archive, but the next two are equivalent and only register a subtree. The registered tree is prepended to the \type {TEXMF} specification and thereby may overload existing trees. If an acrhive is not a real \TEX\ tree, you can access files anywhere in the tree by using wildcards \starttyping \input */blabla.tex \input */somepath/blabla.tex \stoptyping These mechanisms evolve over time and it may take a while before they stabelize. For instance, the syntax for the \ZIP\ inclusion has been adapted more than a year after this chapter was written (which is why this section is added). \stopcomponent