Memory high

Hi,

I am currently developing an app for our company. I use Backendless as a data source and the app should run on iOS.
For the connection I use the iOS SDK from Backendless.

In practice, around 20,000 entries must be accessible offline. I retrieve the data from Backendless and store it locally with CoreData.
Since you can only retrieve 100 entries at a time, I use prepareNextPage in a loop.
However, there is an issue with the amount of RAM. In the normal state of the app, it uses between 40 and 60 MB and when the fetch starts, it goes up to 200-250 MB. That’s not the problem per se, but once the fetch is done, memory usage remains.
It’s not due to CoreData, because I used a function to test how the main memory behaves when I save 20,000 dummies and the main memory doesn’t really increase here. In Xcode’s analysis tools, I can also see that Backendless is consuming memory even though the fetch is already done.

Was such a problem already known and is there a solution here?

Hello @Gerrit_Marttila

I have created an internal ticket to investigate the issue BKNDLSS-29336

Hello @Gerrit_Marttila,

Also please provide a simple project or code sample that reproduces this issue.

Regards,
Olha

      let dataStoreItemInList = Backendless.shared.data.of(ArtikelInLagerplatz.self)

        let queryBuilderItemInList = DataQueryBuilder(). <— In this case I want to get all

        var schleifenCounter = 0		// COUNTER FOR THE LOOPS
    
        var itemsArtList: [ArtikelInLagerplatz] = []

        ///END
        for _ in 1...schleifenAnzahl{
        
        dataStoreItemInList.find(queryBuilder: queryBuilderItemInList, responseHandler: {
            result in
            itemsArtList = result as! [ArtikelInLagerplatz]
            
            if itemsArtList.count > 0{

                for itemArtList in itemsArtList{
                    let neu = ArtikelInLagerplatzCD(context: moc)
                    neu.updatedBL = itemArtList.updated
                    …

                    countGesamt += 1

                }
                itemsArtList.removeAll()
                
                if schleifenCounter == schleifenAnzahl-1{

                    //LOOP END NEXT FUNC


                }
            }

            schleifenCounter += 1	// COUNTER FOR THE LOOP


        }, errorHandler: {
            fault in
            

            print("Error : \(fault.message ?? "")")
   
        })

		after everything has finished: try? moc.save() to save items in CoreData

In this table we have about 11000 elements. It’s okay for RAM usage to go up, but after retrieval it should go down again.
It’s not due to CoreData, because I created and saved 10000 elements as a test and that didn’t affect the RAM.
Is there any way I can reset the fetch with the requested elements? I tried to removeAll(), but it doesn’t work.

Hello @Gerrit_Marttila,

We’ll investigate this issue as soon as possible.

Regards,
Olha

Hello @Gerrit_Marttila,

Firstly, Backendless Swift-SDK provides API for retrieving > 100 records at time. You mentioned you’ve used the prepareNextPage() method but it is absent in your example. Backendless has a unified methods for all SDKs and pagination is described here.

I’ve created a simple app to check if any memory leak appeared when retrieving objects.
The TestTable contains almost 11k records:

func fetchObjects() {
	let queryBuilder = DataQueryBuilder()
    queryBuilder.pageSize = 100
    queryBuilder.offset = 0
    let dataStore = Backendless.shared.data.ofTable("TestTable")
    dataStore.find(queryBuilder: queryBuilder, responseHandler: { result in
    	print("Fetched: \(result.count) objects")
        for obj in result {
        	print(obj["value"] as! NSNumber)
		}
		print("-------------")
        self.fetchNextPage(queryBuilder: queryBuilder)
	}, errorHandler: { fault in
    	print("Error: \(fault.message ?? "")")
	})
}
    
    
func fetchNextPage(queryBuilder: DataQueryBuilder) {
	queryBuilder.prepareNextPage()
    let dataStore = Backendless.shared.data.ofTable("TestTable")
    dataStore.find(queryBuilder: queryBuilder, responseHandler: { result in
    	if result.count > 0 {
        	print("Fetched: \(result.count)")
            for obj in result {
            	print(obj["value"] as! NSNumber)
			}
            print("-------------")
            self.fetchNextPage(queryBuilder: queryBuilder)
		}
        else {
        	print("Fetching completed")
        }
	}, errorHandler: { fault in
    	print("Error: \(fault.message ?? "")")
	})
}

The Instruments utility also shows that memory usage decreases after fetching compleded and no memory leaks occur: