19

I'm currently trying to compile my thesis using LaTeX and have run up against the old ! No room for a new \write . problem. After some googling it seems the only way to actually resolve this problem is to restructure your document to minimise the number of writes being consumed.

To that end I've been looking through the .log to find where they are all being consumed. Here's the results grepped down to those lines containing write.

\write18 enabled.
(/usr/local/texlive/2010/texmf-dist/tex/latex/rvwrite/rvwrite.sty
Package: rvwrite 2010/08/25 1.2 enhanced write registers (CVR)
Package rvwrite Warning: ****************************************
(rvwrite)                Package rvwrite v,1.2 loaded
(rvwrite)                [enhanced write registers (CVR)]
(rvwrite)                ****************************************.
\rvtwrite=\write3
\openout3 = `thesis-write.tex'.
\@glossaryfile=\write4
\@outemp=\write5
\verbatim@out=\write6
runsystem(echo 'write18-test-20114121256'>"thesis.w18")...executed.
\w@pgf@writea=\write7
\tikzexternal@outfile=\write8
\glswrite=\write9
\glo@main@file=\write10
\FV@OutFile=\write11
\@outlinefile=\write12
\tikzexternal@dep@file=\write13
\tikzexternal@outmakefile=\write14
\tf@tdo=\write15

Where have \write0, \write1 & \write2 gone? Is the use of these somehow restricted?

I'm using standard packages: algorithm2e, listings, glossaries, pgf/tikz, emp. Some of these appear quite greedy with the resources. glossaries has claimed \write4, \write9, and \write10. verbatim and fancyvrb are loaded by other packages and they claim \write6 and \write11 respectively. The worst culprit seems to be PGF/TikZ taking four writes.

My compilation breaks when LaTeX is trying to construct the Table of Contents listings. I want to make a ToC, a list of Figures, Tables, Listings, and Algorithms. At present there are no where near enough writes to do this. Does anyone have any advice about how I can control the rampant \write consumption of these packages?

How do people actually make sizable documents using LaTeX with such restrictions? Am I being unreasonable assuming I'll be able to have a 7 chapter document with a ToC, 4 listofs, index, glossary, and bibliography? Or is that beyond the resource limits of LaTeX?

Martin Scharrer
  • 262,582
Alastair
  • 433

5 Answers5

14

Unfortunately there are only 16 output register in TeX and eTeX didn't expanded that number. :-(

The output registers 0, 1 and 2 are already used by (La)TeX itself, e.g. for the .log file and always open, so you don't see them in the .log file.

It's a pity that moreverb and fancyvrb consume a write register each even when you might not use the verbatim write function. If you are sure that these registers are never used you could turn back the write register counter so that these register are reassigned the next time. This can be done with \advance\count17 by -1 because the next to-be-assigned write register is stored in \count17.

Also PGF/TikZ itself only consumes one register. The other three are taken by the external library. I assume you are using it to speed up compilation, which should matter in the final compilation run. You could disable the List Of X'es during the writing process but then disable this library when you want to compile a "final" version. A good alternative to this library is the standalone class and package (written by me) where you put your TikZ pictures in external files which can be either included as source and compiled to PDF images which are then included. The upcoming version will allows to switch between both on-the-fly. It doesn't use any write register. (I really have to push the release ...)

Martin Scharrer
  • 262,582
  • At the moment my PGF/TikZ images are actually generated from embedded R code using Cameron Bracket's pgfSweave package. It would be nontrivial to switch to your standalone package. The information about (La)TeX's register allocation is invaluable (though it confirms my fears!). – Alastair Apr 12 '11 at 23:49
  • The log file doesn't use up a write register. To quote the texbook: "if the number is negative or greater than 15 then the output goes to log" (and in the second case also to the terminal). I must say that I never quite understood why latex allocates \write0 (@unused). – Ulrike Fischer Apr 13 '11 at 09:25
  • @Ulrike: Thanks, I just assumed that one was for the .log, didn't had time to study the TeXBook for it. I saw that \write0 is used by \typeout. – Martin Scharrer Apr 13 '11 at 09:45
  • Yes \typeout uses write\@unused = \write0. But this simply write to the log and the screen, so why not use e.g. \write43? – Ulrike Fischer Apr 13 '11 at 13:24
  • @Martin: I guess that many of the write streams are not active at the same time. Would it be possible to fool \newwrite into allocating the same streams to different packages? – Bruno Le Floch Apr 13 '11 at 14:44
  • @Bruno: Yes, you would have to read and set the \count17 value appropriately. – Martin Scharrer Apr 13 '11 at 14:49
  • These packages should have an option to enable the use of writes only on demand. For backwards compatibility they would need to have an option to switch it off instead. – Martin Scharrer Apr 13 '11 at 14:50
  • \let\oldnewwrite\newwrite, \let\newwrite\@gobble, \usepackage{...}, \let\newwrite\oldnewwrite? – Bruno Le Floch Apr 13 '11 at 14:51
  • @Bruno: Yes, I had such an idea myself but went for the advance-by-minus-one method instead. It's shorter :-) Of course you need to know how many \newwrites appear in the package, otherwise redefining \newrite like you did is the way to go. – Martin Scharrer Apr 13 '11 at 14:57
  • 2
    @Bruno: Naturally packages can share a write stream - but not if both want to write continuarly during the compilation (e.g. at every shipout) to their file. I don't see how LaTeX/\newwrite should be able to decide if 2 \newwrite requests will interfer. I think LaTeX should offer an stream for "immediate" writing which all packages could use (I'm using \write0 for this but it can interfer with error messages so I'm not feeling that this is really satisfactory) and packages should make an effort to save write streams. That the pgf library uses up 3 streams is simply mad. – Ulrike Fischer Apr 14 '11 at 09:17
  • @Ulrike,Bruno: Yes, I strongly agree. There should be one write register for stuff which is written only locally while no code of another package is active. A good example would be the filecontents environment and other verbatim write operations. You could check if the \write15 was not already allocated and use it, otherwise raise the usual warning. – Martin Scharrer Apr 14 '11 at 09:44
  • @Martin: rather than checking that \write15 is not allocated, I'd check that it is not opened (if possible?). I have some code to hack into \write to detect a use of \immediate before (similar to a recent question about detecting prefixes for \def). So I think that it is possible in principle in a LaTeX2e context to make an efficient use of writes. – Bruno Le Floch Apr 14 '11 at 12:07
  • @Bruno: I thought about checking if it is really open, which would further improve the situation. Unfortunately there seems to be no \ifeof or \ifopen for \write registers. Using some \write hackery didn't crossed my mind. – Martin Scharrer Apr 14 '11 at 12:18
  • @Martin: In fact, the hackery would only be on \immediate, \write, \openout, and \closeout. These do not interact with any other primitive, not even \afterassignment. – Bruno Le Floch Apr 14 '11 at 18:06
  • why are both moreverb and fancyvrb used?-- surely fancyvrb does everything moreverb can do? – wasteofspace Apr 18 '11 at 19:08
  • Robin has updated moreverb to use a write stream only when needed: https://groups.google.com/group/comp.text.tex/browse_thread/thread/9a2d1272cedf940b – Philipp Apr 18 '11 at 20:41
11

morewrites – Always room for a new write stream

The pack­age aims to solve the er­ror “No room for a new \write”, which oc­curs when the user or when the user’s pack­ages have ’al­lo­cated too many streams us­ing \newwrite (TeX has a fixed max­i­mum num­ber – 16 – [of] such streams built-in to its code). The pack­age hooks into TeX prim­i­tive com­mands as­so­ci­ated with writ­ing to files; it should be loaded near the be­gin­ning of the se­quence of load­ing pack­ages for a doc­u­ment.

http://www.ctan.org/pkg/morewrites

Stephen
  • 14,890
6

Note that the TikZ external library in 'mode=list and make' (which you appear to use) will dynamically (!) allocate more write registers than the default 'mode=convert with system call'. Thus, eliminating the 'list and make' feature will automatically free at least one register.

In case you do not use \label or \ref in your tikz images, you can also use '\tikzexternalize[aux in dpth=false]' to de-activate support for \label and \ref. This will free a further write register (if I am not mistaken, pgf 2.10 also allocates it on-demand).

I have just committed a couple of changes to PGF CVS which allow more control over the used write registers of the externalization. Now, the registers used by the image externalization process are allocated on-demand if that is possible. Furthermore, the new version has a key '\tikzexternalize[disable dependency files]' which disables generation of .dep file dependencies -- freeing one more register at the cost of no longer being able to remake figures if data files changed.

I hope this helps - at least in the future.

  • This is awesome news Christian! However, Alastair is in the unfortunate position of needing exactly 4 more write streams in order to enable his tableofcontents, listoffigures, etc and keep figure externalization. So, TikZ needs to go all the way down to 0. Of course, this is an unreasonable demand for PdfTeX. But, do you think it would be possible to add logic that detects LuaTeX and automatically switches to the Luo IO Library? – Sharpie Apr 18 '11 at 21:21
  • @Sharpie: removing rvwrite which seems unused should solve the last of his prooblems, no? – Bruno Le Floch Apr 19 '11 at 10:14
  • Unfortunately, he still needed 4 with rvwrite disabled. Using fancy externalization + tables of contents/figures/algorithms/tables/etc allocates a full 8 registers. Add the 3 LaTeX allocates by default and you're up to 11 used out of 16 before really counting the piles of other packages that get loaded for a thesis. Not very nice :(. Which is why it would be awesome if we had a drop-in replacement for newwrite and friends that used the Lua IO libraries when available and deferred to standard TeX write registers otherwise. – Sharpie Apr 19 '11 at 17:56
  • @Sharpie I am interested in that LuaTeX mode ... but I do not have enough time to study your patch and/or the LuaTeX API in the moment. If you like, you can try to add the required switches. Perhaps PGF CVS already has a LuaTeX back-end driver or some switches to check for it. If you like, you can implement it, verify it exhaustively and let me know if you are ready. The requirement is that it remains backwards-compatible. – Christian Feuersänger Apr 20 '11 at 18:05
  • Sounds great! I was tinkering around last night with adding some code to pgfutil-common.tex that switched between output modes. Everything appears to work fine in pdftex mode, but something breaks in pgfutil@IfFileExists when it switches to luatex mode. So there is some more work to be done. – Sharpie Apr 20 '11 at 18:54
4

I slapped together a quick patch to replace the \newwrites in TikZ with calls to Lua's IO library:

https://gist.github.com/925047

git://gist.github.com/925047.git

It's definitely amateur work---for example, I managed to break the makefile output as the commands required to build targets are missing. However, running a file with:

\tikzexternalize[mode=convert with system call]

Appears to be working fine and all of the images generated look ok. The patch was made against PGF 2.10 and will require that lualatex -shell-escape be used to compile the file. Hopefully this will free up 4 write streams for other purposes.

If someone who actually knows what they are doing when it comes to TeX programming has improvements to contribute, fork or comment away!

Update


I updated the patch and fixed a few dumb mistakes -- one of which was breaking the Makefile output. So, the following should work now:

\tikzexternalize[mode=list and make]
Sharpie
  • 12,844
  • 6
  • 48
  • 58
1

morewrites works indeed to remove the error ! No room for a new \write but it broke the TOC and all "List of *" for me. I ended up using scrwfile instead (with \usepackage{scrwfile}).