Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS 14 Widget #127

Open
maxbrogno opened this issue Jul 11, 2020 · 8 comments
Open

iOS 14 Widget #127

maxbrogno opened this issue Jul 11, 2020 · 8 comments

Comments

@maxbrogno
Copy link

Any chance someone is working on a new iOS 14 home screen widget for the app?
Would love to be able to have my local numbers easily visible.

@mhdhejazi
Copy link
Owner

Good idea. It'd be a great chance for learning too. I hope somebody jumps in and works on this.

@gklka
Copy link

gklka commented Oct 16, 2020

I'd love to have this one too.

@rhcpfan
Copy link
Contributor

rhcpfan commented Oct 18, 2020

Hello there!

I've started working on some iOS 14 widgets for CoronaTracker, but I've hit a problem: the peak memory usage for a widget cannot exceed 30 Mb.

Currently, getting all the data from DataManager.shared.download takes the memory usage to ~39 Mb.
I've stripped out getting time series data from JHU (JHURepoDataService.shared.fetchTimeSerieses) and managed to reduce the memory footprint to ~ 31 Mb.

@mhdhejazi , is there a simple way to fetch some basic data (ex. just the dailyChange) for a single Region?

P.S: This is also the reason why the existing Today Extension is not working any more.
P.P.S: Here's a sneak peak on how they currently look (the simulator does not have this limitation) 😉

@gklka
Copy link

gklka commented Oct 18, 2020

Looks great!

@rhcpfan
Copy link
Contributor

rhcpfan commented Oct 18, 2020

I think I managed to solve the issue...

By looking at memory allocations, I've found that JHURepoDataService.parseTimeSerieses(data:, completion:) had the heaviest memory footprint. This was mainly because it took all 270 header values that represented time series dates and stored them as strings. Then, for every value in every time series (probably hundreds of thousands) called

let dateStrings = headers.dropFirst(4)
if let date = dateFormatter.date(from: dateString) {
    for confirmedTimeSeries in confirmed {
        for column in confirmedTimeSeries.values.indices {
            let dateString = dateStrings[dateStrings.startIndex + column]
            if let date = dateFormatter.date(from: dateString) {
                ...
            }
        }
    }
}

All the calls to .date(from: dateString) increase a lot the amount of memory used (and computation time).

The solution was to parse only the header values as dates and use them later in the process (this also comes with a great performance improvement):

let dateStrings = headers.dropFirst(4)
let dateValues = dateStrings.compactMap({ dateFormatter.date(from: $0) })
if let date = dateFormatter.date(from: dateString) {
    for confirmedTimeSeries in confirmed {
        for column in confirmedTimeSeries.values.indices {
            let dateString = dateStrings[dateStrings.startIndex + column]
            let date = dateValues[column]
            ...
        }
    }
}

Managed to reduce the memory used by a widget to ~15Mb from ~39Mb 👍

I still have to do a bit of more UI polishing and create a pull request (most likely tomorrow).

@mhdhejazi
Copy link
Owner

Wow, great work there and a nice catch. When I created the app the dataset was relatively small (both horizontally and vertically), so I didn't see the memory and performance issue. Thank you for fixing that.

Another idea to improve performance and memory usage could be by only parsing the data relevant to the current region. It could be challenging to do that without a big refactoring, but you can take a look at it.

@rhcpfan
Copy link
Contributor

rhcpfan commented Oct 19, 2020

@mhdhejazi - just made a PR that only addresses the memory reduction stuff (#133)

@FelikZ
Copy link

FelikZ commented Nov 7, 2020

it seems its solved in #134 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants