public void RenderLatex() { // Seems to be some sort of problem running this in Rider - it just hangs var katexJsLatexProcessor = new KatexJsLatexProcessor(); string html1 = katexJsLatexProcessor.RenderToString("c = \\pm\\sqrt{a^2 + b^2}"); string html2 = katexJsLatexProcessor.RenderToString("c = \\pm\\sqrt{a^2 + b^2}"); Assert.NotNull(html1); Assert.NotNull(html2); }
public void RenderToStringSpeedTestMultiThreaded() { // Seems to be some sort of problem running this in Rider - it just hangs var stopwatch = new Stopwatch(); stopwatch.Start(); int renders = 1000; // Optimal jintEngine count seems to be 4 on Surface Book 2 var katexJsLatexProcessor = new KatexJsLatexProcessor(4, 2000); long initialisationMilliseconds = stopwatch.ElapsedMilliseconds; // initialisationMilliseconds tests out at about 500 ms - significant overhead _testOutputHelper.WriteLine($"{nameof(initialisationMilliseconds)}: {initialisationMilliseconds}"); stopwatch.Restart(); var options = new ParallelOptions { MaxDegreeOfParallelism = 10 }; Parallel.For(0, renders, options, async i => { _ = katexJsLatexProcessor.RenderToString("c = \\pm\\sqrt{a^2 + b^2}"); }); stopwatch.Stop(); long elapsedMilliseconds = stopwatch.ElapsedMilliseconds; double millisecondsPerRender = elapsedMilliseconds / (double)renders; _testOutputHelper.WriteLine($"{nameof(millisecondsPerRender)}: {millisecondsPerRender}"); _testOutputHelper.WriteLine($"{stopwatch.ElapsedMilliseconds}: {elapsedMilliseconds}"); Assert.True(millisecondsPerRender < 100); }
public void RenderLatexSpeedTest() { // Seems to be some sort of problem running this in Rider - it just hangs var stopwatch = new Stopwatch(); stopwatch.Start(); int renders = 1000; var katexJsLatexProcessor = new KatexJsLatexProcessor(); long initialisationMilliseconds = stopwatch.ElapsedMilliseconds; // katexScriptInitMilliseconds tests out at about 0.5 seconds - significant overhead _testOutputHelper.WriteLine($"{nameof(initialisationMilliseconds)}: {initialisationMilliseconds}"); stopwatch.Restart(); for (int i = 0; i < renders; i++) { _ = katexJsLatexProcessor.RenderToString("c = \\pm\\sqrt{a^2 + b^2}"); } stopwatch.Stop(); long elapsedMilliseconds = stopwatch.ElapsedMilliseconds; double millisecondsPerRender = elapsedMilliseconds / (double)renders; _testOutputHelper.WriteLine($"{nameof(millisecondsPerRender)}: {millisecondsPerRender}"); // 0.281 seconds if creating new KatexScript per render but only 0.025 if reusing over tested over 10000 iterations. // So there is capacity for 40 renders / second on test hardware (Surface Book 2). With caching for server side rendering // this should be performant enough per server. Assert.True(millisecondsPerRender < 100); }
public void RenderToStringSpeedTestMultiThreadedFlooded() { int renders = 1000; // Optimal jintEngine count seems to be 4 on Surface Book 2 var katexJsLatexProcessor = new KatexJsLatexProcessor(1, 500); var options = new ParallelOptions { MaxDegreeOfParallelism = 100 }; // Aggregate exception made up of timeouts Assert.Throws <AggregateException>(() => { Parallel.For(0, renders, options, i => { _ = katexJsLatexProcessor.RenderToString("c = \\pm\\sqrt{a^2 + b^2}"); }); }); }
// Docs: Note processing timings // Note required package refs // Note js equivalent library static void Main(string[] args) { // Instantiate KatexJsLatexProcessor. ILatexProcessor provides parsing for raw LaTeX strings. // ILatexProcessor can be used standalone or within IMarkdownLatexPreprocessor // The argument jintEngineCount causes KatexJsLatexProcessor // to create 4 Jint JavaScript Interpreter engine instances and load the KaTeX JS library into // each. This is because Jint is not thread safe so KatexJsLatexProcessor manages thread safety // locking during function calls. Multiple instances allows for concurrent processing using a // round robin algorithm to distribute requests to each Jint engine. // Argument jintEngineLockTimeout specifies a timeout in milliseconds after which an exception will be thrown // if a lock cannot be obtained on an instance of the underlying Jint engine if the load on KatexJsLatexProcessor // is too high. You can set this value as high as needed. var latexProcessor = new KatexJsLatexProcessor(jintEngineCount: 4, jintEngineLockTimeout: 2000); // Instantiate MarkdownLatexPreprocessor. IMarkdownLatexPreprocessor provides parsing for LaTeX strings in markdown text. var markdownLatexPreprocessor = new MarkdownLatexPreprocessor(latexProcessor); // Services can be instantiated via DI as follows // services.AddSingleton<ILatexProcessor>(new KatexJsLatexProcessor(4, 2000)); // services.AddSingleton<IMarkdownLatexPreprocessor, MarkdownLatexPreprocessor>(); // Render a raw LaTeX expression. string latexHtml = latexProcessor.RenderToStringAsync("f(a,b,c) = (a^2+b^2+c^2)^3").Result; Console.WriteLine("Latex expression output:"); Console.WriteLine(latexHtml); string markdown = @" ## Example Markdown This is an example markdown document This is an expression in inline delmiters ... $f(a,b,c) = (a^2+b^2+c^2)^3$ ... and this one with block delimiters $$ \sum_{i=1}^\infty\frac{1}{n^2}=\frac{\pi^2}{6} $$ "; // ... or use MarkdownLatexPreprocessor to process LaTeX expressions within // markdown text. var markdownHtml = markdownLatexPreprocessor.ProcessLatex(markdown); Console.WriteLine("Markdown output:"); Console.WriteLine(markdownHtml); Console.ReadLine(); }