{"action":"created","issue":{"url":"https://api.github.com/repos/aspnet/EntityFrameworkCore/issues/12162","repository_url":"https://api.github.com/repos/aspnet/EntityFrameworkCore","labels_url":"https://api.github.com/repos/aspnet/EntityFrameworkCore/issues/12162/labels{/name}","comments_url":"https://api.github.com/repos/aspnet/EntityFrameworkCore/issues/12162/comments","events_url":"https://api.github.com/repos/aspnet/EntityFrameworkCore/issues/12162/events","html_url":"https://github.com/aspnet/EntityFrameworkCore/issues/12162","id":327453171,"number":12162,"title":"Bad AddRange performance","user":{"login":"jessetabak","id":5311393,"avatar_url":"https://avatars2.githubusercontent.com/u/5311393?v=4","gravatar_id":"","url":"https://api.github.com/users/jessetabak","html_url":"https://github.com/jessetabak","followers_url":"https://api.github.com/users/jessetabak/followers","following_url":"https://api.github.com/users/jessetabak/following{/other_user}","gists_url":"https://api.github.com/users/jessetabak/gists{/gist_id}","starred_url":"https://api.github.com/users/jessetabak/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jessetabak/subscriptions","organizations_url":"https://api.github.com/users/jessetabak/orgs","repos_url":"https://api.github.com/users/jessetabak/repos","events_url":"https://api.github.com/users/jessetabak/events{/privacy}","received_events_url":"https://api.github.com/users/jessetabak/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-05-29T19:19:16Z","updated_at":"2018-05-29T19:40:52Z","closed_at":null,"author_association":"NONE","body":"I'm inserting a few million entities (in batches of +/- 100.000) and while I expect it to take a while it really is too slow. I profiled the operation and there seems to be one method call that causes 99% of the delay. It's the Add(object, object) method in the ClrICollectionAccessor class. Internally it does a Contains() on a List which obviously will get slow with lots of records. The SaveChanges() method has exactly the same issue. I included the profile report from resharper:\r\n\r\nAddRange():\r\n![image](https://user-images.githubusercontent.com/5311393/40678271-60fa1be8-6380-11e8-91fa-35acc1326e18.png)\r\n\r\nSaveChanges():\r\n![image](https://user-images.githubusercontent.com/5311393/40678354-ad94d31c-6380-11e8-8783-8b00bbf90233.png)\r\n\r\nEntities:\r\n```c#\r\npublic partial class Machine\r\n{\r\n    public Machine()\r\n    {\r\n        Segment = new HashSet<Segment>();\r\n    }\r\n\r\n    public long ID { get; set; }    \r\n    public string Name { get; set; }            \r\n    public ICollection<Segment> Segment { get; set; }\r\n}\r\n\r\n\r\npublic partial class Segment\r\n{\r\n    public Segment()\r\n    {        \r\n        Event = new HashSet<Event>();        \r\n    }\r\n\r\n    public long ID { get; set; }\r\n    public long? MachineID { get; set; }\r\n    public long Number { get; set; }\r\n    public string Serial { get; set; }\r\n\r\n    public Machine Machine { get; set; }\r\n    \r\n    public ICollection<Event> Event { get; set; }    \r\n}\r\n\r\n\r\npublic partial class Event\r\n{\r\n    public long ID { get; set; }\r\n    public long Timestamp { get; set; }\r\n    public string Message { get; set; }\r\n    public long SegmentID { get; set; }\r\n\r\n    public Segment Segment { get; set; }\r\n}\r\n```\r\n\r\nEntity tree creation:\r\n```c#\r\nvar events = new List<Event>();\r\n\r\nvar machine = new Machine\r\n{    \r\n    Name = \"Machine01\"\r\n};\r\n\r\nvar segment = new Segment\r\n{\r\n    Number = 1,\r\n    Serial = \"xxx\",\r\n    Machine = machine\r\n};\r\n\r\n// +/- 100.000 iterations\r\nforeach (var logEntry in logEntries)\r\n{\r\n    var @event = new Event\r\n    {\r\n        Message = logEntry.FullMessage,\r\n        Timestamp = logEntry.DateTimeStamp\r\n        Segment = segment        \r\n    };\r\n                            \r\n    events.Add(@event);\r\n}\r\n\r\nDbContext.ChangeTracker.AutoDetectChangesEnabled = false;\r\nDbContext.ChangeTracker.LazyLoadingEnabled = false;\r\nDbContext.Event.AddRange(events);\r\nDbContext.SaveChanges();\r\n```\r\n\r\n### Further technical details\r\nEF Core version: 2.1.0-preview2-final\r\nDatabase Provider: Microsoft.EntityFrameworkCore.Sqlite\r\nOperating system: Windows 10\r\nIDE: Visual Studio 2017 15.6.6\r\n"},"comment":{"url":"https://api.github.com/repos/aspnet/EntityFrameworkCore/issues/comments/392916933","html_url":"https://github.com/aspnet/EntityFrameworkCore/issues/12162#issuecomment-392916933","issue_url":"https://api.github.com/repos/aspnet/EntityFrameworkCore/issues/12162","id":392916933,"user":{"login":"anpete","id":1210944,"avatar_url":"https://avatars0.githubusercontent.com/u/1210944?v=4","gravatar_id":"","url":"https://api.github.com/users/anpete","html_url":"https://github.com/anpete","followers_url":"https://api.github.com/users/anpete/followers","following_url":"https://api.github.com/users/anpete/following{/other_user}","gists_url":"https://api.github.com/users/anpete/gists{/gist_id}","starred_url":"https://api.github.com/users/anpete/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/anpete/subscriptions","organizations_url":"https://api.github.com/users/anpete/orgs","repos_url":"https://api.github.com/users/anpete/repos","events_url":"https://api.github.com/users/anpete/events{/privacy}","received_events_url":"https://api.github.com/users/anpete/received_events","type":"User","site_admin":false},"created_at":"2018-05-29T19:40:52Z","updated_at":"2018-05-29T19:40:52Z","author_association":"MEMBER","body":"@jessetabak This is due to the navigation fix-up occurring in the state manager. A couple of things to improve this:\r\n\r\n1) Use different collection types for collection navigations. I.e. You can use HashSet<T> so that Contains is faster.\r\n2) Remove the navigations if possible so fix-up doesn't even need to take place.\r\n\r\nRelated to #10632\r\n"}}
{"actor":{"display_login":"anpete"}}