notes-android icon indicating copy to clipboard operation
notes-android copied to clipboard

Syncing/refreshing is extremly slow

Open lu4p opened this issue 1 year ago • 10 comments

This issue respects the following points:

Describe the bug

Refreshing/Syncing the Notes app takes way too long (~10 seconds), even if nothing has changed.

I think this means all remote notes are downloaded on every request, at least thats what I got from quickly glancing over the relevant code.

As per the Nextcloud Notes Api docs: https://github.com/nextcloud/notes/blob/main/docs/api/v1.md#get-all-notes-get-notes

PruneBefore should be used to only download notes that have been remotely changed since the last update:

 pruneBefore 	integer, optional 	All notes without change before of this Unix timestamp are purged from the response, i.e. only the attribute id is included. You should use the Unix timestamp value from the last request's HTTP response header Last-Modified in order to reduce transferred data size.

(or alternatively the ETAG contained in the response)

This is still an issue even if I'm wrong about the cause, it shouldn't take more than a second (accounting for network latency).

Expected behavior

No response

Notes Android version

3.5

Notes server version

4.11

Nextcloud Android version

3.30.6

Nextcloud version

30.0.4

Device

Samsung Galaxy Z Flip 5

Android Version

14

App Store

  • [x] Google Play Store
  • [ ] F-Droid
  • [ ] Huawei App Gallery

Stacktrace

No response

lu4p avatar Dec 30 '24 08:12 lu4p

The sync takes round about 300ms on my personal device (~2000 notes).

You can find the implementation here, as you can see pruneBefore and ETags are both considered.

stefan-niedermann avatar Dec 30 '24 14:12 stefan-niedermann

I have ~450 notes and it's running on a reasonably fast server with nextcloud data on a ssd (30ms ping time from my phone).

Here is a screen recording (switched to favorites to not leak any notes): https://github.com/user-attachments/assets/723e5d58-73af-4e92-bf58-40cd999fc1a3

I don't really know much about android development. How do I profile this to see what's taking so long?

lu4p avatar Dec 30 '24 15:12 lu4p

Maybe use curl / wget to check the lateny od your server. If it is low, we can rule out this as bottleneck

stefan-niedermann avatar Dec 30 '24 18:12 stefan-niedermann

Attached a debugger to a build of current master, some observations:

Both etag and modified are always "0".

onlyLocalChanges is always false

All 450 Notes are downloaded in full on each refresh.

lu4p avatar Dec 30 '24 20:12 lu4p

@stefan-niedermann I fixed this in my PR, did it truly work for you before? If so I might need to check the headers without taking capitalization into account.

lu4p avatar Dec 30 '24 20:12 lu4p

My response headers are as follows:

"x-notes-api-versions" -> "0.2, 1.3"
"Server" -> "cloudflare"
"vary" -> "accept-encoding"
"x-frame-options" -> "SAMEORIGIN"
"last-modified" -> "Mon, 30 Dec 2024 20:52:52 GMT"
"Report-To" -> "{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=PHwMMeLx0%2BqVoUZEGRUrzzsRvoRpC%2FcTfocbEFGEC7CpXSv5PPGxXoIb%2BvrxPApOSoZJ4ogf2DOnc7lVXVi5Xw5GUymVLdd8BRthOC60iUwwujNjYmsKYC9X%2BiP9q7GmsWK0OYcRc%2FqwbPR%2FZUFaYvRxLA%3D%3D"}],"group":"cf-nel","max_age":604800}"
"referrer-policy" -> "no-referrer"
"server-timing" -> "cfL4;desc="?proto=TCP&rtt=40726&min_rtt=25225&rtt_var=20532&sent=3&recv=6&lost=0&retrans=0&sent_bytes=203&recv_bytes=1238&delivery_rate=53439&cwnd=251&unsent_bytes=0&cid=aca0bfb80b6fae54&ts=731&x=0""
"Content-Type" -> "application/json; charset=utf-8"
"Transfer-Encoding" -> "chunked"
"x-request-id" -> "R9Reyt0ihOHBCvFmJyxb"
"CF-RAY" -> "8fa4ea80ecad7a46-DUS"
"Connection" -> "keep-alive"
"x-permitted-cross-domain-policies" -> "none"
"cf-cache-status" -> "DYNAMIC"
"Date" -> "Mon, 30 Dec 2024 20:52:52 GMT"
"feature-policy" -> "autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone 'none';payment 'none'"
"content-security-policy" -> "default-src 'none';base-uri 'none';manifest-src 'self';frame-ancestors 'none'"
"Cache-Control" -> "no-cache, no-store, must-revalidate"
"x-content-type-options" -> "nosniff"
"x-xss-protection" -> "1; mode=block"
"NEL" -> "{"success_fraction":0,"report_to":"cf-nel","max_age":604800}"
"x-robots-tag" -> "noindex, nofollow"
"etag" -> "W/"5180431749b31a5741cffd0209f567c7""
"alt-svc" -> "h3=":443"; ma=86400"

lu4p avatar Dec 30 '24 20:12 lu4p

Header names are not case sensitive.

From RFC 2616 - "Hypertext Transfer Protocol -- HTTP/1.1", Section 4.2, "Message Headers":

Each header field consists of a name followed by a colon (":") and the field value. Field names are case-insensitive.

The updating RFC 7230 does not list any changes from RFC 2616 at this part.

lu4p avatar Dec 30 '24 21:12 lu4p

Thanks for the PR! Hm. Renaming would probably fix this for you and raise the issue for me (yes, sync does work quickly here on my setup) 😆

I don't have time to check the actual comparison in the source code, but I think the solution is to use equalsIgnoreCase() (or whatever is needed here) rather than renaming the expected header names.

stefan-niedermann avatar Dec 30 '24 21:12 stefan-niedermann

@stefan-niedermann Opened a PR upstream as I think it's cleaner to fix it there.

lu4p avatar Dec 30 '24 23:12 lu4p

@lu4p Now where https://github.com/nextcloud/Android-SingleSignOn/pull/796 got closed, would you like to take another shot at upstream or should we work around this in the Notes app directly?

Doing it in the Notes app seems to be a relatively low-hanging fruit for a huge UX improvement. For me, synchronizing is very slow, which is not only annoying but also somewhat dangerous. When I am distracted, I sometimes start modifying a note that isn't up-to-date on my device yet, effectively deleting the latest changes.

Croydon avatar Mar 11 '25 09:03 Croydon