Optimize stories list generation.

This commit is contained in:
John Preston 2024-04-18 09:46:06 +04:00
parent 645ad5e1bd
commit 4fb03e532c
5 changed files with 57 additions and 69 deletions

View File

@ -78,45 +78,19 @@ using UpdateFlag = StoryUpdate::Flag;
} // namespace
int IndexRespectingPinned(const StoriesIds &ids, StoryId id) {
const auto i = ids.list.find(id);
if (ids.pinnedToTop.empty() || i == end(ids.list)) {
return int(i - begin(ids.list));
}
const auto j = ranges::find(ids.pinnedToTop, id);
if (j != end(ids.pinnedToTop)) {
return int(j - begin(ids.pinnedToTop));
}
auto result = int(i - begin(ids.list));
for (const auto &pinnedId : ids.pinnedToTop) {
if (pinnedId < id) {
++result;
}
}
Ensures(result < int(ids.list.size()));
return result;
}
StoryId IdRespectingPinned(const StoriesIds &ids, int index) {
Expects(index >= 0 && index < int(ids.list.size()));
std::vector<StoryId> RespectingPinned(const StoriesIds &ids) {
if (ids.pinnedToTop.empty()) {
return *(begin(ids.list) + index);
} else if (index < int(ids.pinnedToTop.size())) {
return ids.pinnedToTop[index];
return ids.list | ranges::to_vector;
}
auto i = begin(ids.list) + index - int(ids.pinnedToTop.size());
auto sorted = ids.pinnedToTop;
ranges::sort(sorted, ranges::greater());
for (const auto &pinnedId : sorted) {
if (pinnedId >= *i) {
++i;
auto result = std::vector<StoryId>();
result.reserve(ids.list.size());
result.insert(end(result), begin(ids.pinnedToTop), end(ids.pinnedToTop));
for (const auto &id : ids.list) {
if (!ranges::contains(ids.pinnedToTop, id)) {
result.push_back(id);
}
}
Ensures(i != end(ids.list));
return *i;
return result;
}
StoriesSourceInfo StoriesSource::info() const {

View File

@ -40,9 +40,7 @@ struct StoriesIds {
const StoriesIds&) = default;
};
// ids.list.size() if not found.
[[nodiscard]] int IndexRespectingPinned(const StoriesIds &ids, StoryId id);
[[nodiscard]] StoryId IdRespectingPinned(const StoriesIds &ids, int index);
[[nodiscard]] std::vector<StoryId> RespectingPinned(const StoriesIds &ids);
struct StoriesSourceInfo {
PeerId id = 0;

View File

@ -39,14 +39,15 @@ rpl::producer<StoriesIdsSlice> SavedStoriesIds(
}
const auto &saved = stories->saved(peerId);
const auto sorted = RespectingPinned(saved);
const auto count = stories->savedCount(peerId);
auto aroundIndex = IndexRespectingPinned(saved, aroundId);
if (aroundIndex == int(saved.list.size())) {
const auto around = saved.list.lower_bound(aroundId);
aroundIndex = int(around - begin(saved.list));
auto i = ranges::find(sorted, aroundId);
if (i == end(sorted)) {
const auto j = saved.list.lower_bound(aroundId);
i = begin(sorted) + int(j - begin(saved.list));
}
const auto hasBefore = aroundIndex;
const auto hasAfter = int(saved.list.size()) - aroundIndex;
const auto hasBefore = int(i - begin(sorted));
const auto hasAfter = int(end(sorted) - i);
if (hasAfter < limit) {
stories->savedLoadMore(peerId);
}
@ -54,8 +55,8 @@ rpl::producer<StoriesIdsSlice> SavedStoriesIds(
const auto takeAfter = std::min(hasAfter, limit);
auto ids = std::vector<StoryId>();
ids.reserve(takeBefore + takeAfter);
for (auto i = aroundIndex - takeBefore; i != aroundIndex + takeAfter; ++i) {
ids.push_back(IdRespectingPinned(saved, i));
for (auto j = i - takeBefore; j != i + takeAfter; ++j) {
ids.push_back(*j);
}
const auto added = int(ids.size());
state->slice = StoriesIdsSlice(
@ -118,14 +119,15 @@ rpl::producer<StoriesIdsSlice> ArchiveStoriesIds(
}
const auto &archive = stories->archive(peerId);
const auto count = stories->archiveCount(peerId);
auto aroundIndex = IndexRespectingPinned(archive, aroundId);
if (aroundIndex == int(archive.list.size())) {
const auto around = archive.list.lower_bound(aroundId);
aroundIndex = int(around - begin(archive.list));
const auto sorted = RespectingPinned(archive);
const auto count = stories->savedCount(peerId);
auto i = ranges::find(sorted, aroundId);
if (i == end(sorted)) {
const auto j = archive.list.lower_bound(aroundId);
i = begin(sorted) + int(j - begin(archive.list));
}
const auto hasBefore = aroundIndex;
const auto hasAfter = int(archive.list.size()) - aroundIndex;
const auto hasBefore = int(i - begin(sorted));
const auto hasAfter = int(end(sorted) - i);
if (hasAfter < limit) {
stories->archiveLoadMore(peerId);
}
@ -133,8 +135,8 @@ rpl::producer<StoriesIdsSlice> ArchiveStoriesIds(
const auto takeAfter = std::min(hasAfter, limit);
auto ids = std::vector<StoryId>();
ids.reserve(takeBefore + takeAfter);
for (auto i = aroundIndex - takeBefore; i != aroundIndex + takeAfter; ++i) {
ids.push_back(IdRespectingPinned(archive, i));
for (auto j = i - takeBefore; j != i + takeAfter; ++j) {
ids.push_back(*j);
}
const auto added = int(ids.size());
state->slice = StoriesIdsSlice(

View File

@ -77,8 +77,10 @@ struct SameDayRange {
[[nodiscard]] SameDayRange ComputeSameDayRange(
not_null<Data::Story*> story,
const Data::StoriesIds &ids,
const std::vector<StoryId> &sorted,
int index) {
Expects(index >= 0 && index < ids.list.size());
Expects(index >= 0 && index < sorted.size());
const auto pinned = int(ids.pinnedToTop.size());
if (index < pinned) {
@ -90,7 +92,7 @@ struct SameDayRange {
const auto stories = &story->owner().stories();
const auto now = base::unixtime::parse(story->date());
for (auto i = index; i != 0;) {
const auto storyId = IdRespectingPinned(ids, --i);
const auto storyId = sorted[--i];
if (const auto maybeStory = stories->lookup({ peerId, storyId })) {
const auto day = base::unixtime::parse((*maybeStory)->date());
if (day.date() != now.date()) {
@ -99,8 +101,8 @@ struct SameDayRange {
}
--result.from;
}
for (auto i = index + 1, c = int(ids.list.size()); i != c; ++i) {
const auto storyId = IdRespectingPinned(ids, i);
for (auto i = index + 1, c = int(sorted.size()); i != c; ++i) {
const auto storyId = sorted[i];
if (const auto maybeStory = stories->lookup({ peerId, storyId })) {
const auto day = base::unixtime::parse((*maybeStory)->date());
if (day.date() != now.date()) {
@ -700,16 +702,19 @@ void Controller::rebuildFromContext(
}, [&](StoriesContextSaved) {
if (stories.savedCountKnown(peerId)) {
const auto &saved = stories.saved(peerId);
const auto i = IndexRespectingPinned(saved, id);
if (i < saved.list.size()) {
auto sorted = RespectingPinned(saved);
const auto i = ranges::find(sorted, id);
const auto tillEnd = int(end(sorted) - i);
if (tillEnd > 0) {
_index = int(i - begin(sorted));
list = StoriesList{
.peer = peer,
.ids = saved,
.sorted = std::move(sorted),
.total = stories.savedCount(peerId),
};
_index = i;
if (saved.list.size() < list->total
&& (saved.list.size() - i) < kPreloadStoriesCount) {
&& tillEnd < kPreloadStoriesCount) {
stories.savedLoadMore(peerId);
}
}
@ -718,16 +723,19 @@ void Controller::rebuildFromContext(
}, [&](StoriesContextArchive) {
if (stories.archiveCountKnown(peerId)) {
const auto &archive = stories.archive(peerId);
const auto i = IndexRespectingPinned(archive, id);
if (i < archive.list.size()) {
auto sorted = RespectingPinned(archive);
const auto i = ranges::find(sorted, id);
const auto tillEnd = int(end(sorted) - i);
if (tillEnd > 0) {
_index = int(i - begin(sorted));
list = StoriesList{
.peer = peer,
.ids = archive,
.sorted = std::move(sorted),
.total = stories.archiveCount(peerId),
};
_index = i;
if (archive.list.size() < list->total
&& (archive.list.size() - i) < kPreloadStoriesCount) {
&& tillEnd < kPreloadStoriesCount) {
stories.archiveLoadMore(peerId);
}
}
@ -761,7 +769,11 @@ void Controller::rebuildFromContext(
}
if (const auto maybe = peer->owner().stories().lookup(storyId)) {
const auto now = *maybe;
const auto range = ComputeSameDayRange(now, _list->ids, _index);
const auto range = ComputeSameDayRange(
now,
_list->ids,
_list->sorted,
_index);
_sliderCount = range.till - range.from + 1;
_sliderIndex = _index - range.from;
}
@ -779,6 +791,7 @@ void Controller::rebuildFromContext(
_list = StoriesList{
.peer = peer,
.ids = { { id } },
.sorted = { id },
.total = 1,
};
_index = 0;
@ -1523,8 +1536,8 @@ StoryId Controller::shownId(int index) const {
return _source
? (_source->ids.begin() + index)->id
: (index < int(_list->ids.list.size()))
? IdRespectingPinned(_list->ids, index)
: (index < int(_list->sorted.size()))
? _list->sorted[index]
: StoryId();
}

View File

@ -194,6 +194,7 @@ private:
struct StoriesList {
not_null<PeerData*> peer;
Data::StoriesIds ids;
std::vector<StoryId> sorted;
int total = 0;
friend inline bool operator==(