问题
Hey awesome Stackoverflow people
I am currently evaluating if we should use iText 7.1.9 for Java or C#. To do this, I created a test case where I write a single PDF with a bunch of pages, each containing a big table (code below).
In Java, creating a PDF with x pages yields the following results:
- 1 page: 0 sec
- 10 pages: 1 sec
- 100 pages: 5 sec
- 1000 pages: 23 sec
This is reasonably performant. However, when I ported the exact same code to C# .Net, I got quite the shock:
- 1 page: 0 sec
- 10 pages: 1 sec
- 100 pages: 10 sec
- 1000 pages: 96 sec
The PDFs created with Java have the same size as the C# ones and the files look exactly the same. C# however seems to scale linearly while Java somehow manages to optimize bigger PDFs.
Since we'd rather use C# the questions are:
- What the hell is going on?
- Is there anything I have to do to achieve roughly the same performance as with Java?
Java code:
package pcm;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import java.io.FileInputStream;
import java.io.IOException;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfAConformanceLevel;
import com.itextpdf.kernel.pdf.PdfOutputIntent;
import com.itextpdf.kernel.pdf.PdfString;
import com.itextpdf.kernel.pdf.PdfViewerPreferences;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.AreaBreak;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.property.AreaBreakType;
import com.itextpdf.layout.property.UnitValue;
import com.itextpdf.pdfa.PdfADocument;
public class PcmSimple {
public static void main(String[] args) {
long startTime, elapsedTime;
try {
for(int i=1; i<=1000; i*=10) {
startTime = System.nanoTime();
createPdf("D:\\Pcm Test", i);
elapsedTime = System.nanoTime() - startTime;
System.out.println(String.format("%04d pages: %02d sec", i, NANOSECONDS.toSeconds(elapsedTime)));
}
} catch(Exception ex) {
System.out.println(ex.getMessage() + ": " + ex.getStackTrace());
}
}
private static void createPdf(String path, int numberOfPages) throws IOException {
PdfFont fontBold = PdfFontFactory.createFont("resources/fonts/OpenSans-Bold.ttf", true);
PdfFont fontComic = PdfFontFactory.createFont("resources/fonts/comic-sans-ms_[allfont.de].ttf", true);
// Set up the document.
PdfADocument pdfDocument = new PdfADocument(
new PdfWriter(String.format("%s\\java_%d_pages.pdf", path, numberOfPages)),
PdfAConformanceLevel.PDF_A_3B,
new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1",
new FileInputStream("resources/color/sRGB_CS_profile.icm")));
pdfDocument.setTagged();
pdfDocument.getDocumentInfo().setTitle("Reference Document");
pdfDocument.getCatalog().setViewerPreferences(new PdfViewerPreferences().setDisplayDocTitle(true));
pdfDocument.getCatalog().setLang(new PdfString("en-US"));
Document document = new Document(pdfDocument);
// Add a table to every page.
for (int i = 0; i < numberOfPages; i++) {
Table table = new Table(5);
table.setWidth(UnitValue.createPercentValue(100));
for (int j = 0; j < 5; j++) {
Cell cell = new Cell(2, 1)
.add(new Paragraph("Header " + j).setMultipliedLeading(0.5f))
.setFont(fontBold)
.setFontSize(20)
.setBackgroundColor(ColorConstants.CYAN);
table.addHeaderCell(cell);
}
for(int j=0; j<225; j++) {
Cell cell = new Cell()
.add(new Paragraph("Test " + j).setMultipliedLeading(0.5f))
.setFont(fontComic)
.setPaddingTop(4.1f);
table.addCell(cell);
}
document.add(table);
document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
}
document.close();
}
}
C# .Net Code:
using iText.Kernel.Colors;
using iText.Kernel.Font;
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;
using iText.Layout.Properties;
using iText.Pdfa;
using System;
using System.IO;
namespace PCM_Performance_Test_Console
{
class Program
{
static void Main(string[] args)
{
DateTime startTime;
long elapsedTime;
try
{
for (int i = 1; i <= 1000; i *= 10)
{
startTime = DateTime.Now;
CreatePdf("D:\\Pcm Test", i);
elapsedTime = (long)(DateTime.Now - startTime).TotalSeconds;
Console.WriteLine($"{i:d04} pages: {elapsedTime:d02} sec");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + ": " + ex.StackTrace);
}
finally
{
Console.Read();
}
}
private static void CreatePdf(String path, int numberOfPages)
{
PdfFont fontBold = PdfFontFactory.CreateFont("resources/fonts/OpenSans-Bold.ttf", true);
PdfFont fontComic = PdfFontFactory.CreateFont("resources/fonts/comic-sans-ms_[allfont.de].ttf", true);
// Set up the document.
PdfADocument pdfDocument = new PdfADocument(
new PdfWriter($"{path}\\csharp_{numberOfPages}_pages.pdf"),
PdfAConformanceLevel.PDF_A_3B,
new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1",
new FileStream("resources/color/sRGB_CS_profile.icm", FileMode.Open, FileAccess.Read)));
pdfDocument.SetTagged();
pdfDocument.GetDocumentInfo().SetTitle("Reference Document");
pdfDocument.GetCatalog().SetViewerPreferences(new PdfViewerPreferences().SetDisplayDocTitle(true));
pdfDocument.GetCatalog().SetLang(new PdfString("en-US"));
Document document = new Document(pdfDocument);
// Add a table to every page.
for (int i = 0; i < numberOfPages; i++)
{
Table table = new Table(5);
table.SetWidth(UnitValue.CreatePercentValue(100));
for (int j = 0; j < 5; j++)
{
Cell cell = new Cell(2, 1)
.Add(new Paragraph("Header " + j).SetMultipliedLeading(0.5f))
.SetFont(fontBold)
.SetFontSize(20)
.SetBackgroundColor(ColorConstants.CYAN);
table.AddHeaderCell(cell);
}
for (int j = 0; j < 225; j++)
{
Cell cell = new Cell()
.Add(new Paragraph("Test " + j).SetMultipliedLeading(0.5f))
.SetFont(fontComic)
.SetPaddingTop(4.1f);
table.AddCell(cell);
}
document.Add(table);
document.Add(new AreaBreak(AreaBreakType.NEXT_PAGE));
}
document.Close();
}
}
}
回答1:
It's not your code, it's the library, I setup a test project and best I could do was shave off around 20%, but that doesn't come close to the performance of the java version...
- 0001 pages: 0.1133129
- 0010 pages: 0.9318324
- 0100 pages: 8.2051265
- 1000 pages: 80.615356
void Main()
{
DateTime startTime;
TimeSpan elapsedTime;
int xy = 1000;
try
{
for (int i = 1; i <= xy; i *= 10)
{
startTime = DateTime.Now;
CreatePdf("D:\\Pcm Test", i);
elapsedTime = (DateTime.Now - startTime);
Console.WriteLine($"{i:d04} pages: {elapsedTime.TotalSeconds}.{elapsedTime.Milliseconds}");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + ": " + ex.StackTrace);
}
finally
{
Console.Read();
}
}
public static void CreatePdf(String path, int numberOfPages)
{
PdfFont fontBold = PdfFontFactory.CreateFont(@"C:\Users\Aydin\Desktop\arialbd.ttf", true);
PdfFont fontComic = PdfFontFactory.CreateFont(@"C:\Users\Aydin\Desktop\calibri.ttf", true);
// Set up the document.
using (var rgbCSProfile = new FileStream(@"C:\Users\Aydin\Downloads\sRGB_CS_profile.icm", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var pdfWriter = new PdfWriter($"{path}\\csharp_{numberOfPages}_pages.pdf"))
{
PdfADocument pdfDocument = new PdfADocument(pdfWriter, PdfAConformanceLevel.PDF_A_3B, new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", rgbCSProfile));
pdfDocument.SetTagged();
pdfDocument.GetDocumentInfo().SetTitle("Reference Document");
pdfDocument.GetCatalog().SetViewerPreferences(new PdfViewerPreferences().SetDisplayDocTitle(true));
pdfDocument.GetCatalog().SetLang(new PdfString("en-US"));
Document document = new Document(pdfDocument);
// Add a table to every page.
for (int i = 0; i < numberOfPages; i++)
{
Table table = new Table(5, true);
table.SetWidth(UnitValue.CreatePercentValue(100));
document.Add(table);
for (int j = 0; j < 5; j++)
{
Cell cell = new Cell(2, 1)
.Add(new Paragraph("Header " + j).SetMultipliedLeading(0.5f))
.SetFont(fontBold)
.SetFontSize(20)
.SetBackgroundColor(ColorConstants.CYAN);
table.AddHeaderCell(cell);
}
for (int j = 0; j < 225; j++)
{
if (j % 15 == 0) table.Flush();
Cell cell = new Cell().Add(new Paragraph("Test " + j)
.SetMultipliedLeading(0.5f))
.SetFont(fontComic)
.SetPaddingTop(4.1f);
table.AddCell(cell);
}
table.Complete();
document.Flush();
document.Add(new AreaBreak(AreaBreakType.NEXT_PAGE));
}
document.Close();
}
}
// Define other methods and classes here
来源:https://stackoverflow.com/questions/59307147/how-to-improve-itext-performance-when-creating-tables