AutoBogus taking too long to generate data
See original GitHub issueI’ve come across a performance issue when using AutoFaker to generate test objects for use in unit tests.
I’ve been able to create a super simplified example of my domain model to demonstrate two things.
- AutoFaker generates way too many levels of data when it shouldn’t be generating data for levels beyond a reasonable level of nesting. Ideally the nesting level should be configurable…but at a max 2 levels would be more than enough for tests.
- AutoFaker becomes slower as a result and my real-world tests end up taking several minutes to complete rather than a few seconds.
Here is my unit test demonstrating the issue:
[TestMethod]
public void DemonstrateAutoFakerPerformanceIssue()
{
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
var generator = new AutoBogus.AutoFaker<Document>();
var document = generator.Generate();
document.Indicator.ShouldNotBeNull();
document.Indicator.Branch.ShouldNotBeNull();
document.Indicator.Branch.Parent.ShouldBeNull();
//document.Indicator.Branch.Documents.ShouldBeEmpty(); //Fails. Document should be populated. Indicator should be populated. Branch should have all its properties be default type. Or should be able to configure the generation depth.
document.Indicator.Branch.Documents.First().Indicator.ShouldBeNull();
document.Indicator.Branch.Documents.First().Branch.ShouldBeNull();
document.Branch.ShouldNotBeNull();
document.Branch.Documents.ShouldNotBeNull();
document.Branch.Documents.ShouldNotBeEmpty();
document.Branch.Documents.First().Branch.ShouldBeNull();
//document.Branch.Documents.First().Indicator.ShouldBeNull(); //Fails.
document.Branch.Documents.First().Indicator.Branch.ShouldBeNull();
//Show that we are able to access populated properties that are much too deep.
var generator2 = new AutoBogus.AutoFaker<Sentence>();
var sentence = generator2.Generate();
sentence.Branch.ShouldNotBeNull();
sentence.Paragraphs.ShouldNotBeNull();
sentence.Branch.Documents.ShouldNotBeEmpty();
sentence.Branch.Documents.First().Branch.ShouldBeNull();
//sentence.Branch.Documents.First().Indicator.ShouldBeNull(); //Fails
sentence.Branch.Documents.First().Indicator.Branch.ShouldBeNull();
sentence.Branch.Paragraphs.ShouldNotBeEmpty();
sentence.Branch.Paragraphs.First().Branch.ShouldBeNull();
//sentence.Branch.Paragraphs.First().Sections.ShouldBeEmpty(); //Fails
sentence.Branch.Paragraphs.First().Sections.First().Branch.ShouldBeNull();
//sentence.Branch.Paragraphs.First().Sections.First().Pages.ShouldBeNull(); //Fails
//sentence.Branch.Paragraphs.First().Sections.First().Pages.First().Documents.ShouldBeEmpty(); //Fails
sentence.Branch.Paragraphs.First().Sections.First().Pages.First().Documents.First().Branch.ShouldBeNull();
//sentence.Branch.Paragraphs.First().Sections.First().Pages.First().Documents.First().Indicator.ShouldBeNull(); //Fails
sentence.Branch.Paragraphs.First().Sections.First().Pages.First().Documents.First().Indicator.Branch.ShouldBeNull();
//sentence.Branch.Paragraphs.First().Sections.First().Pages.First().Documents.First().Indicator.Property.ShouldBeNullOrWhiteSpace(); //Fails
stopwatch.Stop();
stopwatch.ElapsedMilliseconds.ShouldBeLessThan(500);
}
The following code represents a simplified version of my domain model. Please note that I’ve tried to make it make sense without giving away our exact domain model…modeling a document so that unique sentences can be applied to other paragraphs is not realistic…it was just the closest analogy that I could come up with. We basically have objects whose configuration needs to be tracked in branches (like version control). The links between objects are the foreign key relationships in the database and our entities are creating using Entity Framework.
The things that seem to contribute to the issue are:
- Having Branch reference all objects attached to that branch
- Having all entities have a base type that allows the branch to be specified seems to create
- Having entities be able to reference other types of entities
- Auto Faker seems to generate 3 children for every collection. Branch references all entities. Each entity also has a collection to track where else in the hierarchy they have been added. Each level in the hierarchy results in AutoFaker taking longer to generate.
public class MyBranch
{
public string Property { get; set; }
public MyBranch Parent { get; set; }
public ICollection<MyBranch> Children { get; set; }
public ICollection<Document> Documents { get; set; }
public ICollection<Page> Pages { get; set; }
public ICollection<PageSection> Sections { get; set; }
public ICollection<Paragraph> Paragraphs { get; set; }
public ICollection<Sentence> Sentences { get; set; }
}
public class EntityBase
{
public MyBranch Branch { get; set; }
}
public class Document : EntityBase
{
public string MyProperty { get; set; }
public SpecialIndicator Indicator { get; set; }
public OtherSpecialIndicator OtherIndicator { get; set; }
}
public class Page : EntityBase
{
public string MyProperty { get; set; }
public OtherSpecialIndicator Indicator { get; set; }
public ICollection<Document> Documents { get; set; } //documents where this page appears
}
public class PageSection : EntityBase
{
public string MyProperty { get; set; }
public OtherSpecialIndicator Indicator { get; set; }
public ICollection<Page> Pages { get; set; } //pages where this page section appears
}
public class Paragraph : EntityBase
{
public string MyProperty { get; set; }
public OtherSpecialIndicator Indicator { get; set; }
public ICollection<PageSection> Sections { get; set; } //sections where this paragraph has been used
}
public class Sentence : EntityBase
{
public string MyProperty { get; set; }
public ICollection<Paragraph> Paragraphs { get; set; } //paragraphs where this sentance appears
}
public class SpecialIndicator : EntityBase
{
public string Property { get; set; }
}
//Adding this to other entities results in generation taking additional time
public class OtherSpecialIndicator : EntityBase
{
public string Property { get; set; }
}
Any thoughts on how this could be fixed? At the moment I am having to add rules so that for most objects Branch will be null or new Branch()…but it would be better if AutoBogus could stop itself from generating so many levels of data.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:3
- Comments:32 (13 by maintainers)

Top Related StackOverflow Question
Hey All,
Thanks for effort of @Ian1971 I think we have a performance improvement in v2.13.0. It does involve using a
WithTreeDepth()config handler.I did some top level testing and a simple model that took 4s to generate now takes 18ms 👍
Nick.
I’ve added a TreeDepth option in this PR. https://github.com/nickdodd79/AutoBogus/pull/64 This greatly helps improve performance for our use case (Xero api)