/// <summary> /// Try to intern the string. /// Return true if an interned value could be returned. /// Return false if it was added to the intern list, but wasn't there already. /// Return null if it didn't meet the length criteria for any of the buckets. Interning was rejected /// </summary> private bool?TryIntern(IInternable candidate, out string interned) { int length = candidate.Length; // First, try the hard coded intern strings. // Each of the hard-coded small strings below showed up in a profile run with considerable duplication in memory. if (!_dontTrack) { if (length == 2) { if (candidate[1] == '#') { if (candidate[0] == 'C') { interned = "C#"; return(true); } if (candidate[0] == 'F') { interned = "F#"; return(true); } } if (candidate[0] == 'V' && candidate[1] == 'B') { interned = "VB"; return(true); } } else if (length == 4) { if (candidate[0] == 'T') { if (candidate[1] == 'R' && candidate[2] == 'U' && candidate[3] == 'E') { interned = "TRUE"; return(true); } if (candidate[1] == 'r' && candidate[2] == 'u' && candidate[3] == 'e') { interned = "True"; return(true); } } if (candidate[0] == 'C' && candidate[1] == 'o' && candidate[2] == 'p' && candidate[3] == 'y') { interned = "Copy"; return(true); } if (candidate[0] == 't' && candidate[1] == 'r' && candidate[2] == 'u' && candidate[3] == 'e') { interned = "true"; return(true); } if (candidate[0] == 'v' && candidate[1] == '4' && candidate[2] == '.' && candidate[3] == '0') { interned = "v4.0"; return(true); } } else if (length == 5) { if (candidate[0] == 'F' && candidate[1] == 'A' && candidate[2] == 'L' && candidate[3] == 'S' && candidate[4] == 'E') { interned = "FALSE"; return(true); } if (candidate[0] == 'f' && candidate[1] == 'a' && candidate[2] == 'l' && candidate[3] == 's' && candidate[4] == 'e') { interned = "false"; return(true); } if (candidate[0] == 'D' && candidate[1] == 'e' && candidate[2] == 'b' && candidate[3] == 'u' && candidate[4] == 'g') { interned = "Debug"; return(true); } if (candidate[0] == 'B' && candidate[1] == 'u' && candidate[2] == 'i' && candidate[3] == 'l' && candidate[4] == 'd') { interned = "Build"; return(true); } if (candidate[0] == 'W' && candidate[1] == 'i' && candidate[2] == 'n' && candidate[3] == '3' && candidate[4] == '2') { interned = "Win32"; return(true); } } else if (length == 6) { if (candidate[0] == '\'' && candidate[1] == '\'' && candidate[2] == '!' && candidate[3] == '=' && candidate[4] == '\'' && candidate[5] == '\'') { interned = "''!=''"; return(true); } if (candidate[0] == 'A' && candidate[1] == 'n' && candidate[2] == 'y' && candidate[3] == 'C' && candidate[4] == 'P' && candidate[5] == 'U') { interned = "AnyCPU"; return(true); } } else if (length == 7) { if (candidate[0] == 'L' && candidate[1] == 'i' && candidate[2] == 'b' && candidate[3] == 'r' && candidate[4] == 'a' && candidate[5] == 'r' && candidate[6] == 'y') { interned = "Library"; return(true); } if (candidate[0] == 'M' && candidate[1] == 'S' && candidate[2] == 'B' && candidate[3] == 'u' && candidate[4] == 'i' && candidate[5] == 'l' && candidate[6] == 'd') { interned = "MSBuild"; return(true); } if (candidate[0] == 'R' && candidate[1] == 'e' && candidate[2] == 'l' && candidate[3] == 'e' && candidate[4] == 'a' && candidate[5] == 's' && candidate[6] == 'e') { interned = "Release"; return(true); } } // see Microsoft.Build.BackEnd.BuildRequestConfiguration.CreateUniqueGlobalProperty else if (length > MSBuildConstants.MSBuildDummyGlobalPropertyHeader.Length && candidate[0] == 'M' && candidate[1] == 'S' && candidate[2] == 'B' && candidate[3] == 'u' && candidate[4] == 'i' && candidate[5] == 'l' && candidate[6] == 'd' && candidate[7] == 'P' && candidate[8] == 'r' && candidate[9] == 'o' && candidate[10] == 'j' && candidate[11] == 'e' && candidate[12] == 'c' && candidate[13] == 't' && candidate[14] == 'I' && candidate[15] == 'n' && candidate[16] == 's' && candidate[17] == 't' && candidate[18] == 'a' && candidate[19] == 'n' && candidate[20] == 'c' && candidate[21] == 'e' ) { // don't want to leak unique strings into the cache interned = candidate.ExpensiveConvertToString(); return(null); } else if (length == 24) { if (candidate[0] == 'R' && candidate[1] == 'e' && candidate[2] == 's' && candidate[3] == 'o' && candidate[4] == 'l' && candidate[5] == 'v' && candidate[6] == 'e') { if (candidate[7] == 'A' && candidate[8] == 's' && candidate[9] == 's' && candidate[10] == 'e' && candidate[11] == 'm' && candidate[12] == 'b' && candidate[13] == 'l' && candidate[14] == 'y') { if (candidate[15] == 'R' && candidate[16] == 'e' && candidate[17] == 'f' && candidate[18] == 'e' && candidate[19] == 'r' && candidate[20] == 'e' && candidate[21] == 'n' && candidate[22] == 'c' && candidate[23] == 'e') { interned = "ResolveAssemblyReference"; return(true); } } } } else if (length > _ginormousThreshold) { lock (_ginormous) { LinkedListNode <WeakReference> current = _ginormous.First; while (current != null) { if (current.Value.Target is string last && last.Length == candidate.Length && candidate.IsOrdinalEqualToStringOfSameLength(last)) { interned = last; _ginormousHits++; _ginormousCharsSaved += last.Length; _ginormous.Remove(current); _ginormous.AddFirst(current); return(true); } current = current.Next; } _ginormousMisses++; interned = candidate.ExpensiveConvertToString(); LinkedListNode <WeakReference> lastNode = _ginormous.Last; _ginormous.RemoveLast(); _ginormous.AddFirst(lastNode); lastNode.Value.Target = interned; return(false); } } #if !CLR2COMPATIBILITY else if (_useSimpleConcurrency) { var stringified = candidate.ExpensiveConvertToString(); interned = _internedStrings.GetOrAdd(stringified, stringified); return(true); } #endif else if (length >= _hugeMruThreshold) { lock (_hugeMru) { return(_hugeMru.TryGet(candidate, out interned)); } } else if (length >= _largeMruThreshold) { lock (_largeMru) { return(_largeMru.TryGet(candidate, out interned)); } } else if (length >= _smallMruThreshold) { lock (_smallMru) { return(_smallMru.TryGet(candidate, out interned)); } } } interned = candidate.ExpensiveConvertToString(); return(null); }
/// <summary> /// Try to get one element from the list. Upon leaving the function 'candidate' will be at the head of the Mru list. /// This function is not thread-safe. /// </summary> internal bool TryGet(IInternable candidate, out string interned) { if (_size == 0) { interned = candidate.ExpensiveConvertToString(); return(false); } int length = candidate.Length; Node secondPrior = null; Node prior = null; Node head = _mru; bool found = false; int itemCount = 0; while (head != null && !found) { if (head.Value.Length == length) { if (candidate.IsOrdinalEqualToStringOfSameLength(head.Value)) { found = true; } } if (!found) { secondPrior = prior; prior = head; head = head.Next; } itemCount++; } if (found) { // Move it to the top and return the interned version. if (prior != null) { if (!candidate.ReferenceEquals(head.Value)) { // Wasn't at the top already, so move it there. prior.Next = head.Next; head.Next = _mru; _mru = head; interned = _mru.Value; return(true); } else { // But don't move it up if there is reference equality so that multiple calls to Intern don't redundantly emphasize a string. interned = head.Value; return(true); } } else { // Found the item in the top spot. No need to move anything. interned = _mru.Value; return(true); } } else { // Not found. Create a new entry and place it at the top. Node old = _mru; _mru = new Node(candidate.ExpensiveConvertToString()) { Next = old }; // Cache miss. Use this opportunity to discard any element over the max size. if (itemCount >= _size && secondPrior != null) { secondPrior.Next = null; } interned = _mru.Value; return(false); } }
/// <summary> /// Try to get one element from the list. Upon leaving the function 'candidate' will be at the head of the Mru list. /// This function is not thread-safe. /// </summary> internal bool TryGet(IInternable candidate, out string interned) { if (_size == 0) { interned = candidate.ExpensiveConvertToString(); return false; } int length = candidate.Length; Node secondPrior = null; Node prior = null; Node head = _mru; bool found = false; int itemCount = 0; while (head != null && !found) { if (head.Value.Length == length) { if (candidate.IsOrdinalEqualToStringOfSameLength(head.Value)) { found = true; } } if (!found) { secondPrior = prior; prior = head; head = head.Next; } itemCount++; } if (found) { // Move it to the top and return the interned version. if (prior != null) { if (!candidate.ReferenceEquals(head.Value)) { // Wasn't at the top already, so move it there. prior.Next = head.Next; head.Next = _mru; _mru = head; interned = _mru.Value; return true; } else { // But don't move it up if there is reference equality so that multiple calls to Intern don't redundantly emphasize a string. interned = head.Value; return true; } } else { // Found the item in the top spot. No need to move anything. interned = _mru.Value; return true; } } else { // Not found. Create a new entry and place it at the top. Node old = _mru; _mru = new Node(candidate.ExpensiveConvertToString()); _mru.Next = old; // Cache miss. Use this opportunity to discard any element over the max size. if (itemCount >= _size && secondPrior != null) { secondPrior.Next = null; } interned = _mru.Value; return false; } }
/// <summary> /// Try to intern the string. /// Return true if an interned value could be returned. /// Return false if it was added to the intern list, but wasn't there already. /// Return null if it didn't meet the length criteria for any of the buckets. /// </summary> private bool? TryIntern(IInternable candidate, out string interned) { int length = candidate.Length; // First, try the hard coded intern strings. // Each of the hard-coded small strings below showed up in a profile run with considerable duplication in memory. if (!_dontTrack) { if (length == 2) { if (candidate[1] == '#') { if (candidate[0] == 'C') { interned = "C#"; return true; } if (candidate[0] == 'F') { interned = "F#"; return true; } } if (candidate[0] == 'V' && candidate[1] == 'B') { interned = "VB"; return true; } } else if (length == 4) { if (candidate[0] == 'T') { if (candidate[1] == 'R' && candidate[2] == 'U' && candidate[3] == 'E') { interned = "TRUE"; return true; } if (candidate[1] == 'r' && candidate[2] == 'u' && candidate[3] == 'e') { interned = "True"; return true; } } if (candidate[0] == 'C' && candidate[1] == 'o' && candidate[2] == 'p' && candidate[3] == 'y') { interned = "Copy"; return true; } if (candidate[0] == 't' && candidate[1] == 'r' && candidate[2] == 'u' && candidate[3] == 'e') { interned = "true"; return true; } if (candidate[0] == 'v' && candidate[1] == '4' && candidate[2] == '.' && candidate[3] == '0') { interned = "v4.0"; return true; } } else if (length == 5) { if (candidate[0] == 'F' && candidate[1] == 'A' && candidate[2] == 'L' && candidate[3] == 'S' && candidate[4] == 'E') { interned = "FALSE"; return true; } if (candidate[0] == 'f' && candidate[1] == 'a' && candidate[2] == 'l' && candidate[3] == 's' && candidate[4] == 'e') { interned = "false"; return true; } if (candidate[0] == 'D' && candidate[1] == 'e' && candidate[2] == 'b' && candidate[3] == 'u' && candidate[4] == 'g') { interned = "Debug"; return true; } if (candidate[0] == 'B' && candidate[1] == 'u' && candidate[2] == 'i' && candidate[3] == 'l' && candidate[4] == 'd') { interned = "Build"; return true; } if (candidate[0] == 'W' && candidate[1] == 'i' && candidate[2] == 'n' && candidate[3] == '3' && candidate[4] == '2') { interned = "Win32"; return true; } } else if (length == 6) { if (candidate[0] == '\'' && candidate[1] == '\'' && candidate[2] == '!' && candidate[3] == '=' && candidate[4] == '\'' && candidate[5] == '\'') { interned = "''!=''"; return true; } if (candidate[0] == 'A' && candidate[1] == 'n' && candidate[2] == 'y' && candidate[3] == 'C' && candidate[4] == 'P' && candidate[5] == 'U') { interned = "AnyCPU"; return true; } } else if (length == 7) { if (candidate[0] == 'L' && candidate[1] == 'i' && candidate[2] == 'b' && candidate[3] == 'r' && candidate[4] == 'a' && candidate[5] == 'r' && candidate[6] == 'y') { interned = "Library"; return true; } if (candidate[0] == 'M' && candidate[1] == 'S' && candidate[2] == 'B' && candidate[3] == 'u' && candidate[4] == 'i' && candidate[5] == 'l' && candidate[6] == 'd') { interned = "MSBuild"; return true; } if (candidate[0] == 'R' && candidate[1] == 'e' && candidate[2] == 'l' && candidate[3] == 'e' && candidate[4] == 'a' && candidate[5] == 's' && candidate[6] == 'e') { interned = "Release"; return true; } } else if (length == 24) { if (candidate[0] == 'R' && candidate[1] == 'e' && candidate[2] == 's' && candidate[3] == 'o' && candidate[4] == 'l' && candidate[5] == 'v' && candidate[6] == 'e') { if (candidate[7] == 'A' && candidate[8] == 's' && candidate[9] == 's' && candidate[10] == 'e' && candidate[11] == 'm' && candidate[12] == 'b' && candidate[13] == 'l' && candidate[14] == 'y') { if (candidate[15] == 'R' && candidate[16] == 'e' && candidate[17] == 'f' && candidate[18] == 'e' && candidate[19] == 'r' && candidate[20] == 'e' && candidate[21] == 'n' && candidate[22] == 'c' && candidate[23] == 'e') { interned = "ResolveAssemblyReference"; return true; } } } } else if (length > _ginormousThreshhold) { lock (_ginormous) { LinkedListNode<WeakReference> current = _ginormous.First; while (current != null) { string last = current.Value.Target as string; if (last != null && last.Length == candidate.Length && candidate.IsOrdinalEqualToStringOfSameLength(last)) { interned = last; _ginormousHits++; _ginormousCharsSaved += last.Length; _ginormous.Remove(current); _ginormous.AddFirst(current); return true; } current = current.Next; } _ginormousMisses++; interned = candidate.ExpensiveConvertToString(); var lastNode = _ginormous.Last; _ginormous.RemoveLast(); _ginormous.AddFirst(lastNode); lastNode.Value.Target = interned; return false; } } else if (length >= _hugeMruThreshhold) { lock (_hugeMru) { return _hugeMru.TryGet(candidate, out interned); } } else if (length >= _largeMruThreshhold) { lock (_largeMru) { return _largeMru.TryGet(candidate, out interned); } } else if (length >= _smallMruThreshhold) { lock (_smallMru) { return _smallMru.TryGet(candidate, out interned); } } } interned = candidate.ExpensiveConvertToString(); return null; }
/// <summary> /// Try to intern the string. /// Return true if an interned value could be returned. /// Return false if it was added to the intern list, but wasn't there already. /// Return null if it didn't meet the length criteria for any of the buckets. /// </summary> private bool?TryIntern(IInternable candidate, out string interned) { int length = candidate.Length; // First, try the hard coded intern strings. // Each of the hard-coded small strings below showed up in a profile run with considerable duplication in memory. if (!_dontTrack) { if (length == 2) { if (candidate[1] == '#') { if (candidate[0] == 'C') { interned = "C#"; return(true); } if (candidate[0] == 'F') { interned = "F#"; return(true); } } if (candidate[0] == 'V' && candidate[1] == 'B') { interned = "VB"; return(true); } } else if (length == 4) { if (candidate[0] == 'T') { if (candidate[1] == 'R' && candidate[2] == 'U' && candidate[3] == 'E') { interned = "TRUE"; return(true); } if (candidate[1] == 'r' && candidate[2] == 'u' && candidate[3] == 'e') { interned = "True"; return(true); } } if (candidate[0] == 'C' && candidate[1] == 'o' && candidate[2] == 'p' && candidate[3] == 'y') { interned = "Copy"; return(true); } if (candidate[0] == 't' && candidate[1] == 'r' && candidate[2] == 'u' && candidate[3] == 'e') { interned = "true"; return(true); } if (candidate[0] == 'v' && candidate[1] == '4' && candidate[2] == '.' && candidate[3] == '0') { interned = "v4.0"; return(true); } } else if (length == 5) { if (candidate[0] == 'F' && candidate[1] == 'A' && candidate[2] == 'L' && candidate[3] == 'S' && candidate[4] == 'E') { interned = "FALSE"; return(true); } if (candidate[0] == 'f' && candidate[1] == 'a' && candidate[2] == 'l' && candidate[3] == 's' && candidate[4] == 'e') { interned = "false"; return(true); } if (candidate[0] == 'D' && candidate[1] == 'e' && candidate[2] == 'b' && candidate[3] == 'u' && candidate[4] == 'g') { interned = "Debug"; return(true); } if (candidate[0] == 'B' && candidate[1] == 'u' && candidate[2] == 'i' && candidate[3] == 'l' && candidate[4] == 'd') { interned = "Build"; return(true); } if (candidate[0] == 'W' && candidate[1] == 'i' && candidate[2] == 'n' && candidate[3] == '3' && candidate[4] == '2') { interned = "Win32"; return(true); } } else if (length == 6) { if (candidate[0] == '\'' && candidate[1] == '\'' && candidate[2] == '!' && candidate[3] == '=' && candidate[4] == '\'' && candidate[5] == '\'') { interned = "''!=''"; return(true); } if (candidate[0] == 'A' && candidate[1] == 'n' && candidate[2] == 'y' && candidate[3] == 'C' && candidate[4] == 'P' && candidate[5] == 'U') { interned = "AnyCPU"; return(true); } } else if (length == 7) { if (candidate[0] == 'L' && candidate[1] == 'i' && candidate[2] == 'b' && candidate[3] == 'r' && candidate[4] == 'a' && candidate[5] == 'r' && candidate[6] == 'y') { interned = "Library"; return(true); } if (candidate[0] == 'M' && candidate[1] == 'S' && candidate[2] == 'B' && candidate[3] == 'u' && candidate[4] == 'i' && candidate[5] == 'l' && candidate[6] == 'd') { interned = "MSBuild"; return(true); } if (candidate[0] == 'R' && candidate[1] == 'e' && candidate[2] == 'l' && candidate[3] == 'e' && candidate[4] == 'a' && candidate[5] == 's' && candidate[6] == 'e') { interned = "Release"; return(true); } } else if (length == 24) { if (candidate[0] == 'R' && candidate[1] == 'e' && candidate[2] == 's' && candidate[3] == 'o' && candidate[4] == 'l' && candidate[5] == 'v' && candidate[6] == 'e') { if (candidate[7] == 'A' && candidate[8] == 's' && candidate[9] == 's' && candidate[10] == 'e' && candidate[11] == 'm' && candidate[12] == 'b' && candidate[13] == 'l' && candidate[14] == 'y') { if (candidate[15] == 'R' && candidate[16] == 'e' && candidate[17] == 'f' && candidate[18] == 'e' && candidate[19] == 'r' && candidate[20] == 'e' && candidate[21] == 'n' && candidate[22] == 'c' && candidate[23] == 'e') { interned = "ResolveAssemblyReference"; return(true); } } } } else if (length > _ginormousThreshhold) { lock (_ginormous) { LinkedListNode <WeakReference> current = _ginormous.First; while (current != null) { string last = current.Value.Target as string; if (last != null && last.Length == candidate.Length && candidate.IsOrdinalEqualToStringOfSameLength(last)) { interned = last; _ginormousHits++; _ginormousCharsSaved += last.Length; _ginormous.Remove(current); _ginormous.AddFirst(current); return(true); } current = current.Next; } _ginormousMisses++; interned = candidate.ExpensiveConvertToString(); var lastNode = _ginormous.Last; _ginormous.RemoveLast(); _ginormous.AddFirst(lastNode); lastNode.Value.Target = interned; return(false); } } else if (length >= _hugeMruThreshhold) { lock (_hugeMru) { return(_hugeMru.TryGet(candidate, out interned)); } } else if (length >= _largeMruThreshhold) { lock (_largeMru) { return(_largeMru.TryGet(candidate, out interned)); } } else if (length >= _smallMruThreshhold) { lock (_smallMru) { return(_smallMru.TryGet(candidate, out interned)); } } } interned = candidate.ExpensiveConvertToString(); return(null); }