From ca8638526938a734fe226bdf184cd40da8483b7e Mon Sep 17 00:00:00 2001 From: Pete Duncanson Date: Tue, 23 Jan 2018 15:10:09 +0000 Subject: [PATCH 1/6] Prevent Pinterest messing with media in the back office Fixes: http://issues.umbraco.org/issue/U4-10865 --- src/Umbraco.Web.UI/umbraco/Views/Default.cshtml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml b/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml index f8b7eb86cf..677d28d362 100644 --- a/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml +++ b/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml @@ -43,6 +43,7 @@ + Umbraco From bb9e23ca3ea080d2a4c0191747fff38b3c4ca683 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Thu, 18 Jan 2018 11:40:46 +0000 Subject: [PATCH 2/6] Proposed patch for U4-10756 - Guid TypedContent performance This is a proposal for a temporary workaround to issue U4-10756. It uses a local static ConcurrentDictionary to store a lookup of Guid/int values. If the Guid isn't in the lookup, then the traditional XPath is used, which would add the resulting node ID (int) to the lookup. If the lookup contains the Guid, then the returned int value will be used to perform a more efficient retrieval. --- src/Umbraco.Web/PublishedContentQuery.cs | 37 ++++++++++++++++++++---- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web/PublishedContentQuery.cs b/src/Umbraco.Web/PublishedContentQuery.cs index bfe8fb5260..a609a609b7 100644 --- a/src/Umbraco.Web/PublishedContentQuery.cs +++ b/src/Umbraco.Web/PublishedContentQuery.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Xml.XPath; @@ -224,14 +225,38 @@ namespace Umbraco.Web { var doc = cache.GetById(id); return doc; - } + } + + private static ConcurrentDictionary _guidToIntLoopkup; private IPublishedContent TypedDocumentById(Guid id, ContextualPublishedCache cache) - { - // todo: in v8, implement in a more efficient way - var legacyXml = UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema; - var xpath = legacyXml ? "//node [@key=$guid]" : "//* [@key=$guid]"; - var doc = cache.GetSingleByXPath(xpath, new XPathVariable("guid", id.ToString())); + { + // We create the lookup when we first need it + if (_guidToIntLoopkup == null) + _guidToIntLoopkup = new ConcurrentDictionary(); + + IPublishedContent doc; + + // Check if the lookup contains the GUID/INT value + if (_guidToIntLoopkup.TryGetValue(id, out int nodeId) == false) + { + // If not, then we perform an inefficient XPath for the GUID + + // todo: in v8, implement in a more efficient way + var legacyXml = UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema; + var xpath = legacyXml ? "//node[@key=$guid]" : "//*[@key=$guid]"; + doc = cache.GetSingleByXPath(xpath, new XPathVariable("guid", id.ToString())); + + // When we have the node, we add the GUID/INT value to the lookup + if (doc != null) + _guidToIntLoopkup.TryAdd(id, doc.Id); + } + else + { + // Otherwise we have the node id (INT) and can perform an efficient retrieval + doc = cache.GetById(nodeId); + } + return doc; } From f7f42764858e72c0c1b8fabfd58a7a6261e8046c Mon Sep 17 00:00:00 2001 From: leekelleher Date: Thu, 18 Jan 2018 11:44:05 +0000 Subject: [PATCH 3/6] Removed the need for the `UseLegacyXmlSchema` check The enhancement in PR #2367 removed the `"@isDoc"` check, which was the main difference between the legacy and current XML schema. Reducing the XPath to `"//*[@key=$guid]"` will perform the same for both types of schema. _(and saves on a couple of allocations)_ --- src/Umbraco.Web/PublishedContentQuery.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Umbraco.Web/PublishedContentQuery.cs b/src/Umbraco.Web/PublishedContentQuery.cs index a609a609b7..73afcc8428 100644 --- a/src/Umbraco.Web/PublishedContentQuery.cs +++ b/src/Umbraco.Web/PublishedContentQuery.cs @@ -243,9 +243,7 @@ namespace Umbraco.Web // If not, then we perform an inefficient XPath for the GUID // todo: in v8, implement in a more efficient way - var legacyXml = UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema; - var xpath = legacyXml ? "//node[@key=$guid]" : "//*[@key=$guid]"; - doc = cache.GetSingleByXPath(xpath, new XPathVariable("guid", id.ToString())); + doc = cache.GetSingleByXPath("//*[@key=$guid]", new XPathVariable("guid", id.ToString())); // When we have the node, we add the GUID/INT value to the lookup if (doc != null) From 6841b2ac610f02b3df8640d018574605044925e0 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Fri, 19 Jan 2018 11:12:45 +0000 Subject: [PATCH 4/6] Amended the lookup dictionary setter, as per @JimBobSquarePants's comment: https://github.com/umbraco/Umbraco-CMS/pull/2398#discussion_r162522998 --- src/Umbraco.Web/PublishedContentQuery.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/PublishedContentQuery.cs b/src/Umbraco.Web/PublishedContentQuery.cs index 73afcc8428..4a36f1b3a4 100644 --- a/src/Umbraco.Web/PublishedContentQuery.cs +++ b/src/Umbraco.Web/PublishedContentQuery.cs @@ -247,7 +247,7 @@ namespace Umbraco.Web // When we have the node, we add the GUID/INT value to the lookup if (doc != null) - _guidToIntLoopkup.TryAdd(id, doc.Id); + _guidToIntLoopkup[id] = doc.Id; } else { From a42e568fdfac44613c0b8abd4609737494948df1 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 24 Jan 2018 11:51:53 +0000 Subject: [PATCH 5/6] Initialized the ConcurrentDictionary statically as per @JimBobSquarePants's comment: https://github.com/umbraco/Umbraco-CMS/pull/2398#discussion_r162799543 --- src/Umbraco.Web/PublishedContentQuery.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Umbraco.Web/PublishedContentQuery.cs b/src/Umbraco.Web/PublishedContentQuery.cs index 4a36f1b3a4..e865f13121 100644 --- a/src/Umbraco.Web/PublishedContentQuery.cs +++ b/src/Umbraco.Web/PublishedContentQuery.cs @@ -227,13 +227,10 @@ namespace Umbraco.Web return doc; } - private static ConcurrentDictionary _guidToIntLoopkup; + private static readonly ConcurrentDictionary _guidToIntLoopkup = new ConcurrentDictionary(); private IPublishedContent TypedDocumentById(Guid id, ContextualPublishedCache cache) { - // We create the lookup when we first need it - if (_guidToIntLoopkup == null) - _guidToIntLoopkup = new ConcurrentDictionary(); IPublishedContent doc; From 0780979469daf33672a66f137cd002a4da57359b Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 24 Jan 2018 11:53:52 +0000 Subject: [PATCH 6/6] Eagerly populating the Guid lookup as per @Shazwazza's comment: https://github.com/umbraco/Umbraco-CMS/pull/2398#issuecomment-358752346 Tested against 12,000 nodes (in the XML cache), profiling showed it took 55ms. --- src/Umbraco.Web/PublishedContentQuery.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Umbraco.Web/PublishedContentQuery.cs b/src/Umbraco.Web/PublishedContentQuery.cs index e865f13121..469d53f749 100644 --- a/src/Umbraco.Web/PublishedContentQuery.cs +++ b/src/Umbraco.Web/PublishedContentQuery.cs @@ -231,6 +231,24 @@ namespace Umbraco.Web private IPublishedContent TypedDocumentById(Guid id, ContextualPublishedCache cache) { + // Check if the loopkup is empty, if so populate it [LK] + if (_guidToIntLoopkup.Count == 0) + { + // TODO: Remove the debug profile logger + using (ApplicationContext.Current.ProfilingLogger.DebugDuration("Populate GUID/INT lookup")) + { + // NOTE, using the `@nodeTypeAlias` attribute in the XPath as this was support in both legacy & new schemas + var tmpNodes = cache.GetXPathNavigator().Select("//*[@nodeTypeAlias]"); + foreach (XPathNavigator tmpNode in tmpNodes) + { + if (int.TryParse(tmpNode.GetAttribute("id", string.Empty), out int tmpNodeId) + && Guid.TryParse(tmpNode.GetAttribute("key", string.Empty), out Guid tmpNodeKey)) + { + _guidToIntLoopkup[tmpNodeKey] = tmpNodeId; + } + } + } + } IPublishedContent doc;