为什么 xelatex 的执行速度比 latex-dvips-ps2pdf 慢得多?

为什么 xelatex 的执行速度比 latex-dvips-ps2pdf 慢得多?

我在同一台机器上对同一个输入文件进行了基准测试。令我惊讶的是,xelatex 所需的时间几乎是 latex-dvips-ps2pdf 所需时间的 2.9 倍。为了简单起见,我复制了输入文件:xlx.texxelatex 和ltx.texlatex-dvips-ps2pdf。请参见以下结果。

结果:

在此处输入图片描述

图例:

  • xlx.tex:xelatex 的输入文件。
  • xlx.pdf:无需 gs 压缩的 pdf 输出。
  • xlx-tiny.pdf:使用 gs 压缩的 pdf 输出。
  • ltx.tex:乳胶的输入文件。
  • ltx.pdf:无需 gs 压缩的 pdf 输出。
  • ltx-tiny.pdf:使用 gs 压缩的 pdf 输出。

在此处输入图片描述

即使ps2pdf已经压缩了输出,仍然值得使用 gs 再次压缩输出。但是压缩率太小了。

用于基准测试的 C# 代码:

这不是符合最佳实践的干净代码。我会整理一下。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;

namespace LaTeXAutomator
{
    class Program
    {
        class Record
        {
            public string Activity { get; set; }
            public double Elapsed { get; set; }
            public override string ToString()
            {
                return string.Format("{0}: {1} seconds", Activity, Elapsed);
            }
        }
        class Step
        {
            public string FileName { get; set; }
            public string Arguments { get; set; }
            public bool UseShellExecute { get; set; }
            public void Start()
            {
                Process p = new Process();
                p.StartInfo.FileName = FileName;
                p.StartInfo.Arguments = Arguments;
                p.StartInfo.UseShellExecute = UseShellExecute;

                p.EnableRaisingEvents = true;
                p.Exited += (sender, e) => { Console.WriteLine("=== {0} FINISHED ===", FileName.ToUpper()); };

                p.Start();
                p.WaitForExit();
                //p.Close();
            }
        }

        static void Main(string[] args)
        {
            var records = new List<Record>();


            var filename = "xlx"; // for xelatex
            var xelatexSteps = new List<Step>()
            {
                new Step { FileName = "xelatex", Arguments = String.Format("-interaction=nonstopmode {0}.tex", filename), UseShellExecute = false },
                new Step { FileName = "xelatex", Arguments = String.Format("-interaction=nonstopmode {0}.tex", filename), UseShellExecute = false },
                new Step { FileName = "gswin64c", Arguments =  String.Format("-sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dNOPAUSE -dQUIET -dBATCH -sOutputFile={0}-tiny.pdf {0}.pdf", filename), UseShellExecute = false }//,
                //new Step { FileName = "AcroRd32", Arguments =  String.Format("{0}-tiny.pdf", filename), UseShellExecute = true }
            };
            DoBenchMark(xelatexSteps, records);
            CleanUp(filename);


            filename = "ltx"; // for latex
            var latexSteps = new List<Step>()
            {
                new Step { FileName = "latex", Arguments = String.Format("-interaction=nonstopmode {0}.tex", filename), UseShellExecute = false },
                new Step { FileName = "latex", Arguments = String.Format("-interaction=nonstopmode {0}.tex", filename), UseShellExecute = false },
                new Step { FileName = "dvips", Arguments =  String.Format("{0}.dvi", filename), UseShellExecute = false },
                new Step { FileName = "ps2pdf", Arguments =  String.Format("{0}.ps", filename), UseShellExecute = false },
                new Step { FileName = "gswin64c", Arguments =  String.Format("-sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dNOPAUSE -dQUIET -dBATCH -sOutputFile={0}-tiny.pdf {0}.pdf", filename), UseShellExecute = false }//,
                //new Step { FileName = "AcroRd32", Arguments =  String.Format("{0}-tiny.pdf", filename), UseShellExecute = true }
            };
            DoBenchMark(latexSteps, records);
            CleanUp(filename);
            Console.Clear();

            foreach (var x in records)
            {
                Console.WriteLine(x);
            }

            var totalXeTeX = records.Take(xelatexSteps.Count).Sum(x => x.Elapsed);
            var totalLaTeX = records.Skip(xelatexSteps.Count).Sum(x => x.Elapsed);

            Console.WriteLine("==========================");
            Console.WriteLine("Total time taken by XeLaTeX: {0} seconds.", totalXeTeX);
            Console.WriteLine("Total time taken by LaTeX: {0} seconds.", totalLaTeX);

            var ratio = totalXeTeX / totalLaTeX;

            Console.WriteLine("XeLaTeX runs {0} times slower than LaTeX.", ratio);


        }

        private static void DoBenchMark(List<Step> steps, List<Record> records)
        {
            Stopwatch sw = new Stopwatch();
            foreach (var step in steps)
            {
                sw.Reset();
                sw.Start();
                step.Start();
                sw.Stop();
                records.Add(new Record { Activity = step.FileName, Elapsed = sw.Elapsed.TotalSeconds });
            }
        }

        private static void CleanUp(string filename)
        {
            foreach (var filepath in Directory.GetFiles(".", String.Format("{0}.*", filename), SearchOption.TopDirectoryOnly))
            {
                if (!(Path.GetExtension(filepath) == ".tex" || Path.GetExtension(filepath) == ".pdf"))
                    File.Delete(filepath);
            }

        }
    }
}

问题:

为什么 xelatex 的执行速度比 latex-dvips-ps2pdf 慢得多?

注意:速度非常关键,因为我的在线 TeX 到 PDF 生成器应该尽可能快地执行。

TH 的评论和我的回复:

我觉得这不是一个好问题。你想要什么样的答案?“它比较慢,因为它是这样的。”“它比较慢,因为它实现 foo 的方式与 pdfTeX 不同。”“它比较慢,因为它使用了功能栏。”这些对你有用吗?

您上述的所有假设对我来说都非常有用。

答案1

要知道为什么它变慢,首先必须确定它在哪里变慢。我做了两个假设:

  1. XeTeX 的速度并不总是这么慢,但只是在特定情况下。
  2. XeTeX 速度太慢,因为它会生成很大的文件。

我的意思是,制作该文件需要付出一些努力,而这些努力正是问题所在。而不是与文件创建相关的 I/O。通常 latex-dvips-gs 和 pdflatex 生成的文件无法通过 ghostscript 压缩。

很明显,由 1 kB TeX 文件制作的 PDF 不可能有 16 MB 大小,因为文本数据。然后,我重新阅读,发现有一个名为的文件夹图片。所以,我的猜测是:

这与图像有关。尝试关闭它们 1),看看会发生什么。

1)这意味着注释掉、用复杂程度尽可能低的虚拟图像替换等等。

相关内容