Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.Linq;
- namespace tmp
- {
- public class StringSegments
- {
- public static void Do()
- {
- Console.WriteLine("Baseline");
- BaseLine();
- GC.Collect(2);
- Console.WriteLine("Optimized");
- Optimized();
- }
- private static void BaseLine()
- {
- Console.WriteLine(GC.GetGCMemoryInfo().HeapSizeBytes / 1024 / 1024);
- var segments = Enumerable.Range(1, 10).Select(s => Guid.NewGuid().ToString("N")).ToArray();
- var items = new List<string>();
- var r = new Random();
- for (int i = 0; i < 10_000_000; i++)
- {
- var item = string.Concat(
- segments[r.Next(0,9)], "_",
- segments[r.Next(0,9)], "_",
- segments[r.Next(0,9)]);
- items.Add(item);
- }
- GC.Collect(2);
- Console.WriteLine(GC.GetGCMemoryInfo().HeapSizeBytes / 1024 / 1024);
- Console.ReadKey();
- }
- private static void Optimized()
- {
- Console.WriteLine(GC.GetGCMemoryInfo().HeapSizeBytes / 1024 / 1024);
- var segments = Enumerable.Range(1, 10).Select(s => Guid.NewGuid().ToString("N")).ToArray();
- var items = new List<StringSegment>();
- var r = new Random();
- for (int i = 0; i < 10_000_000; i++)
- {
- var item = string.Concat(
- segments[r.Next(0,9)], "_",
- segments[r.Next(0,9)], "_",
- segments[r.Next(0,9)]);
- items.Add(item);
- }
- GC.Collect(2);
- Console.WriteLine(GC.GetGCMemoryInfo().HeapSizeBytes / 1024 / 1024);
- Console.ReadKey();
- }
- }
- public class StringSegment
- {
- static ConcurrentDictionary<int, X> hashMap = new ConcurrentDictionary<int,X>();
- private const char Delimiter = '_';
- private readonly List<int> _segments;
- private StringSegment(List<int> segments) => _segments = segments;
- public static implicit operator StringSegment(string src) => FromString(src);
- private static StringSegment FromString(string src)
- {
- var refs = new List<int>();
- var segments = src.Split(Delimiter, StringSplitOptions.RemoveEmptyEntries);
- foreach (var segment in segments)
- {
- var hash = segment.GetHashCode();
- if (hashMap.TryGetValue(hash, out var existing))
- {
- existing.Inc();
- refs.Add(hash);
- }
- else
- {
- hashMap.TryAdd(hash, new X(segment, 1));
- refs.Add(hash);
- }
- }
- return new StringSegment(refs);
- }
- public override string ToString()
- {
- var a = new List<string>();
- foreach (var segment in _segments)
- {
- if (!hashMap.TryGetValue(segment, out var str))
- {
- throw new Exception("original data is destroyed!");
- }
- a.Add(str.value);
- }
- return string.Join(Delimiter, a);
- }
- ~StringSegment()
- {
- foreach (var segment in _segments)
- {
- if (hashMap.TryGetValue(segment, out var existing))
- {
- existing.Dec();
- if (existing.count <= 0)
- {
- hashMap.TryRemove(segment, out _);
- }
- }
- }
- }
- }
- public class X
- {
- public X(string value, int count)
- {
- this.value = value;
- this.count = count;
- }
- public string value { get; }
- public int count { get; private set; }
- public void Dec() => count--;
- public void Inc() => count++;
- public override string ToString() => $"{value}:{count}";
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement