public SuggestResponseDto[] SuggestForV2(int id, int limit, string key, string value) { var accounts = _repo.Accounts; var uniqueLikesOfTarget = accounts[id].GetLikesFrom().ToHashSet(); ISuggestFilter filter = null; if (key != null) { filter = _factory.CreateFilter(key, value); if (filter == null) { return(new SuggestResponseDto[0]); } } var likersData = SimilarityDictionaryPool.Rent(); foreach (var likeeId in uniqueLikesOfTarget) { long targetTsSum = 0; long targetTsCount = 0; var likersOfTargetLike = accounts[likeeId].GetLikesToWithTs(); var l = likersOfTargetLike.GetLength(0); for (int i = 0; i < l; i++) { var likerId = likersOfTargetLike[i, 0]; var ts = likersOfTargetLike[i, 1]; if (likerId == id) { targetTsCount++; targetTsSum += ts; } else if (filter == null || filter.IsOk(likerId)) { if (!likersData.ContainsKey(likerId)) { likersData[likerId] = CounterPool.Rent(); } likersData[likerId].AddTs(ts); } } var targetTs = (double)(targetTsSum / targetTsCount); foreach (var counter in likersData.Values) { counter.Calculate(targetTs); } } if (likersData.Count == 0) { return(new SuggestResponseDto[0]); } var count = likersData.Count; var sortedIdsBySimilarity = Pool.Rent(count); var index = 0; foreach (var pair in likersData) { sortedIdsBySimilarity[index] = pair; index++; } Array.Sort(sortedIdsBySimilarity, 0, count, DescSimilarityComparer); var allExceptLikes = new List <int>(); for (int i = 0; i < count; i++) { var likesFromCurrent = accounts[sortedIdsBySimilarity[i].Key].GetLikesFrom(); Array.Sort(likesFromCurrent, _descComparer); foreach (var like in likesFromCurrent) { if (!uniqueLikesOfTarget.Contains(like)) { allExceptLikes.Add(like); uniqueLikesOfTarget.Add(like); } } if (allExceptLikes.Count >= limit) { break; } } Pool.Return(sortedIdsBySimilarity); CounterPool.Return(sortedIdsBySimilarity.Take(count).Select(x => x.Value)); SimilarityDictionaryPool.Return(likersData); return(allExceptLikes.Take(limit).Select(x => _converter.Convert(x)).ToArray()); }