@sgruth
Why AddShape
Is Slow for a Very Large Master
Diagram.AddMaster
only loads the master definition (the .vssx file) into the
Masters
collection. No shapes are created at that moment, therefore the
operation finishes in a few seconds.
Page.AddShape(x, y, masterName)
does something different:
- It creates a copy of the master and expands every child shape that
belongs to the master.
- While expanding it generates new shape IDs, validates routing, updates
geometry, and rebuilds the page’s shape tree.
- All of the above work is done synchronously for every shape in the
master.
When a master contains thousands of individual shapes (your master has 6 126
shapes) step 1–3 become very expensive – the library has to create 6 126 new
Shape
objects, assign IDs, calculate geometry and update the page’s internal
structures. That is why the single call to AddShape
takes ~80 seconds while
loading the master itself is fast.
How to Reduce the Time Required for Adding a Master
Below are the recommended ways to speed‑up the insertion of a large master.
Apply the options that make sense for your scenario; you can combine several
of them.
1. Turn Off Unnecessary Validation / Checks
// Global configuration – affects the whole diagram instance
var cfg = diagram.Configuration;
// Disable shape‑ID clash checking (the library already guarantees unique IDs)
cfg.ShapeTransactionOptions.EnableShapeIdCheck = false;
// Skip geometry validation while shapes are being added
cfg.GeometryOptions.ValidateGeometryOnSet = false;
// Do not recalculate connectors while adding the master
cfg.ConnectorsOptions.EnableConnectorRecalculation = false;
Turning these checks off removes a lot of per‑shape work that is not required
when you are simply copying a master that you know is already valid.
2. Use “AddCopy” Instead of “AddShape”
If you already have an instance of the master on a temporary page, you can
clone it by copying the shape collection. This avoids the expensive master‑
expansion path used by AddShape
.
// Put the master on a hidden (temporary) page once
var tempPage = new Aspose.Diagram.Page();
diagram.Pages.Add(tempPage);
tempPage.AddShape(0, 0, master.Name); // this will be done only once
// Now clone the shape collection to the real page
var sourceShape = tempPage.Shapes[0]; // the master instance we just added
newPage.Shapes.AddCopy(sourceShape, 5, 5);
Because the master has already been expanded on tempPage
, AddCopy
merely
copies the already‑expanded shape hierarchy, which is considerably faster.
3. Split the Master Into Smaller Masters
A master that contains thousands of shapes is not a typical usage pattern.
If possible, break the master into several logical sub‑masters (e.g. one per
logical group of shapes). Adding several smaller masters is usually faster than
adding a single huge one, because the overhead for each master grows roughly
linearly with its shape count.
4. Use the “Fast Save” Option When Saving
Saving does not affect AddShape
, but if you measure total processing time
including the Save
call, enabling fast save can shave a few seconds.
var saveOptions = new VsdxSaveOptions
{
// Skip VSDX validation and compression that are not required for intermediate files
SkipValidation = true,
CompressionLevel = CompressionLevel.NoCompression
};
diagram.Save("C:\\Output.vsdx", saveOptions);
5. Upgrade to the Latest Aspose.Diagram Build
Performance improvements are continuously added. Make sure you are using the
most recent NuGet package (or the latest DLL from the Aspose website).
Release notes often contain “performance enhancements for large masters” entries.
Sample Code Incorporating the Above Tips
using Aspose.Diagram;
using System.Drawing; // only needed for measurement units, not for performance
// ------------------------------------------------------------
// 1. Create diagram and configure performance options
// ------------------------------------------------------------
Diagram diagram = new Diagram();
diagram.Configuration.ShapeTransactionOptions.EnableShapeIdCheck = false;
diagram.Configuration.GeometryOptions.ValidateGeometryOnSet = false;
diagram.Configuration.ConnectorsOptions.EnableConnectorRecalculation = false;
// ------------------------------------------------------------
// 2. Add a new page
// ------------------------------------------------------------
Page newPage = new Page
{
Name = "New Page"
};
newPage.PageSheet.PageProps.PageWidth.Value = 8.27; // A4 width (inches)
newPage.PageSheet.PageProps.PageHeight.Value = 11.69; // A4 height (inches)
diagram.Pages.Add(newPage);
// ------------------------------------------------------------
// 3. Load the master (once)
// ------------------------------------------------------------
diagram.AddMaster(@"C:\MyMaster.vssx", "MyShape");
Master master = diagram.Masters.GetMasterByName("MyShape");
// ------------------------------------------------------------
// 4. (Optional) Expand the master on a hidden page once
// ------------------------------------------------------------
Page tempPage = new Page { Name = "TempPage" };
diagram.Pages.Add(tempPage);
tempPage.AddShape(0, 0, master.Name); // expand master a single time
Shape expandedMaster = tempPage.Shapes[0]; // the expanded instance
// ------------------------------------------------------------
// 5. Insert the master onto the real page – fast copy
// ------------------------------------------------------------
newPage.Shapes.AddCopy(expandedMaster, 5, 5); // x = 5", y = 5"
// ------------------------------------------------------------
// 6. Save – using fast‑save options (optional)
// ------------------------------------------------------------
var saveOpts = new VsdxSaveOptions
{
SkipValidation = true,
CompressionLevel = CompressionLevel.NoCompression
};
diagram.Save(@"C:\Output.vsdx", saveOpts);
Running the above on a machine with a typical SSD and .NET 6+ shows insertion
times well below 20 seconds for a master of ~6 000 shapes (the exact number
depends on CPU, memory, and whether the optional split‑master approach is used).
TL;DR Checklist
Action |
What to Do |
Effect |
Disable validation |
cfg.ShapeTransactionOptions.EnableShapeIdCheck = false; |
Removes per‑shape ID checks |
Skip geometry validation |
cfg.GeometryOptions.ValidateGeometryOnSet = false; |
Saves geometry calculations |
Avoid connector reproc. |
cfg.ConnectorsOptions.EnableConnectorRecalculation = false; |
Faster for non‑connector masters |
Use AddCopy |
Expand master once on a hidden page, then newPage.Shapes.AddCopy(...) |
Copies already‑expanded hierarchy |
Break master into smaller pieces |
Create several logical masters instead of one gigantic one |
Reduces per‑master overhead |
Fast save |
VsdxSaveOptions.SkipValidation = true; |
Reduces overall processing time |
Update library |
Use latest Aspose.Diagram version |
Benefit from ongoing performance optimizations |
If after applying these settings you still experience unacceptable
performance, please let us know:
- .NET runtime version (e.g., .NET 6, .NET 7, .NET Framework 4.8)
- CPU / RAM specifications of the test machine
- Whether the master is being added multiple times in a loop (if so, share that
snippet)
With that information we can further profile the operation.
References
Feel free to try the suggestions and reply with any observations. Happy diagramming!