Hi Aspose team!
Recently I did a lot of
performance testing of Aspose.Pdf 5.2 and found a serious bottleneck related to
hyperlinks.
So the generated document is
based on 6k data records which are rendered to approximately 2000 pages (40-70MB),
also is contains ToC, Index and embedded hyperlinks which provide just another
way to navigate the content.
After numerous tests, it appears
that Aspose.Pdf is not able to handle huge amounts of hyperlinks, e.g.: index
consists of approx. 100 pages and contains 6k+ hyperlinks linked to different
paragraphs. The code which creates PDF DOM runs pretty fast, but delay happens during
Pdf.Save(memoryStream) method. Here are details:
6k data set, no hyperlinks
- Data access and DOM generation –
1min
- Aspose.Pdf save to stream – 1min
Same but index hyperlinks on
- Data access and DOM generation –
1min
- Aspose.Pdf save to stream – 10min
(+9min with ToC/embedded hyperlinks on)
Here is the way I add hyperlinks
to text segments:
private void AddIndexItem(Section section, string
titleText, Rect frame, IEnumerable<SectionLink>
sectionLinks)
{
const string indexSep
= ", ";
var root = section.GetRoot();
var itemStyle = new TextInfo
{
FontName = “Arial”,
FontSize =10,
Color = new Color("Black"),
IsUnicode = true,
};
// Assemble and measure segments: title, indexes and
elipsis
var titleWidth = TextMeasure.GetStringWidth(titleText,
itemStyle);
var indexesText = string.Join(indexSep,
sectionLinks.Select(sl => sl.Index.ToString()));
var indexesWidth =
TextMeasure.GetStringWidth(indexesText, itemStyle);
var
ellipsisWidth = TextMeasure.GetStringWidth(ChartDocument.Elipsis,
itemStyle);
var ellipsisCount = (int)Math.Truncate((frame.Width - titleWidth -
indexesWidth) / ellipsisWidth);
var ellipsisText = ellipsisCount > 0
? new
string(ChartDocument.Elipsis[0],
ellipsisCount) : "";
// Add title with a link to first index item
var firstLink = new Hyperlink
{
LinkType = HyperlinkType.Local,
TargetID =
sectionLinks.First().SectionId,
};
var firstIndexItem = new
Text(section)
{
Segments =
{
new Segment(titleText)
{
IsSymbolReplaceable = false,
Hyperlink
= firstLink,
},
new Segment(ellipsisText)
{
Hyperlink
= firstLink
},
},
PositioningType = PositioningType.ParagraphRelative,
ReferenceParagraphID =
root.ID,
Left =
frame.Left.ToFloat(),
Top =
frame.Top.ToFloat() + 1,
TextInfo =
itemStyle,
WrapLines = 1,
};
section.Paragraphs.Add(firstIndexItem);
// Add indexes with the corresponding links
var indexItems = new Text(section)
{
PositioningType = PositioningType.ParagraphRelative,
ReferenceParagraphID = root.ID,
Left = (frame.Right - indexesWidth).ToFloat(),
Top
= frame.Top.ToFloat() + 1,
TextInfo
= itemStyle,
WrapLines = 1,
};
sectionLinks.ToList()
.ForEach(sl =>
{
indexItems.Segments.Add(); // walkaround 1
indexItems.Segments.Add(
new Segment(
sl.Index ==
sectionLinks.Last().Index
? sl.Index.ToString()
: string.Concat(sl.Index, indexSep))
{
TextInfo =
{ FontName = “Arial” }, // walkaround 2
Hyperlink =
{
LinkType = HyperlinkType.Local,
TargetID = sl.SectionId,
}
});
});
section.Paragraphs.Add(indexItems);
}
private struct SectionLink
{
public int Index;
public string
SectionId;
}
Any suggestions or ideas how to
avoid the performance degradation? Ideally I wish hyperlinks overhead to be 30
sec max instead of 9 min. The issue is urgent, because product going to release
in a few months
Thanks in advance,
Alex