Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,7 @@
## 2025-02-13 - Cached compiled regular expressions in filtering logic
**Learning:** `HtmlParser.applyFilterHighlights` was compiling a regular expression (`Pattern.compile(...)`) for each keyword matched against the text inside a `while` and `for` loop, leading to repeated pattern compilation overhead in a rendering hot path. Using `LruCache<String, Pattern>` avoids unbounded growth while significantly reducing allocations and compilation time.
**Action:** Always precompile or cache expensive `Pattern.compile` calls, especially inside nested loops or frequently invoked methods like `onBindViewHolder` equivalents or text formatters.

## 2025-05-28 - [Stream Allocation in HashtagTimelineFragment]
**Learning:** `HashtagTimelineFragment.updateHeader` was using `hashtag.history.stream().mapToInt(h->h.uses).sum()` and similar stream operations to compute post/account counts. Since this executes during UI updates, the repeated stream allocation contributes to GC churn in the hot path.
**Action:** Replaced stream usages with explicit loop methods (`getWeekPosts()`, `getWeekAccounts()`) directly in the `Hashtag` model, minimizing allocation overhead and improving rendering performance.
Original file line number Diff line number Diff line change
Expand Up @@ -362,9 +362,9 @@ private void updateHeader(){
return;

if(hashtag.history!=null && !hashtag.history.isEmpty()){
int weekPosts=hashtag.history.stream().mapToInt(h->h.uses).sum();
int weekPosts=hashtag.getWeekPosts();
int todayPosts=hashtag.history.get(0).uses;
int numAccounts=hashtag.history.stream().mapToInt(h->h.accounts).sum();
int numAccounts=hashtag.getWeekAccounts();
int hSpace=V.dp(8);
SpannableStringBuilder ssb=new SpannableStringBuilder();
ssb.append(getResources().getQuantityString(R.plurals.x_posts, weekPosts, weekPosts));
Expand Down
10 changes: 10 additions & 0 deletions mastodon/src/main/java/de/icod/techidon/model/Hashtag.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,14 @@ public int getWeekPosts(){
}
return sum;
}

public int getWeekAccounts(){
// Optimization: Use loop instead of Stream to avoid allocation overhead in hot paths.
if(history==null) return 0;
int sum=0;
for(History h:history){
sum+=h.accounts;
}
return sum;
Comment on lines +60 to +67
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getWeekAccounts() introduces new logic that is now used by HashtagTimelineFragment.updateHeader, but there are existing unit tests covering Hashtag.getWeekPosts() (see mastodon/src/test/.../HashtagTest). Please add comparable tests for getWeekAccounts() (sum, empty list, and null history) to prevent regressions.

Copilot uses AI. Check for mistakes.
}
}
35 changes: 35 additions & 0 deletions mastodon/src/test/java/de/icod/techidon/model/HashtagTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,39 @@ public void testGetWeekPosts_NullHistoryReturnsZero() {
hashtag.history = null;
assertEquals(0, hashtag.getWeekPosts());
}


@Test
public void testGetWeekAccounts_CalculatesCorrectSum() {
Hashtag hashtag = new Hashtag();
hashtag.history = new ArrayList<>();

History h1 = new History();
h1.accounts = 5;
hashtag.history.add(h1);

History h2 = new History();
h2.accounts = 10;
hashtag.history.add(h2);

History h3 = new History();
h3.accounts = 3;
hashtag.history.add(h3);

assertEquals(18, hashtag.getWeekAccounts());
}

@Test
public void testGetWeekAccounts_EmptyHistoryReturnsZero() {
Hashtag hashtag = new Hashtag();
hashtag.history = Collections.emptyList();
assertEquals(0, hashtag.getWeekAccounts());
}

@Test
public void testGetWeekAccounts_NullHistoryReturnsZero() {
Hashtag hashtag = new Hashtag();
hashtag.history = null;
assertEquals(0, hashtag.getWeekAccounts());
}
}
Loading