So I am currently building an app, do display some user analytics. In order to check if all my background calculations and the corresponding plots look descent, I have written a function to generate some mock Data, called addMockData and looks something like this:
func addMockdata() {
let ClassToHoldData = ClassToHoldData()
for i in 0...15 {
let otherClassToHoldData = otherClassToHoldData()
for j in 0...12000 {
let fx = ...
let fy = ...
let fz = ...
fx.append(...)
fy.append(...)
fz.append(...)
}
otherClassToHoldData.fx = fx
otherClassToHoldData.fy = fy
otherClassToHoldData.fz = fz
ClassToHoldData.info.append(otherClassToHoldData)
try! realm.write {
realm.objects(UserModel.self)[index].data.append(ClassToHoldData)
}
}
I call addMockData in the AppDelegate under the application(...) method. Thus when I build and run the app for the first time addMockData gets called. This works fine in the simulator and the data is generated without a hitch and memory usage peaking at around 450 Mb when generating the mock data.
The issue arises when I run the program on an actual device, in my case an Ipad Air (3rd Gen). There after generating roughly half of the mock data, it terminates with the message "Message from debugger: Terminated due to memory issue". The memory usage steadily rises until it reaches roughly 1.7 Gb, when it crashes. It seems like it does not deallocate all the data generated in the for loop.
I have tried wrapping my for loops in a autoreleasepool{} and have checked that Zombie Objects are disabled.
What else could I try? Any help is greatly appreciated!
Related
In my iOS app, I have an auxiliary function that receives an html-formatted string and removes the explicit height tags from images.
This is the complete function:
/// This function removes any explicit height in image tag
/// - Parameter htmlString: target HTML
/// - Returns: string HTML after removing height from any aimge tag
private func removeExplicitHeightFromImgTag(for htmlString: String) -> String {
var result = NSString(string: htmlString)
/// Potential breakpoint / Infinite look: This while loop seems to be causing infinite loop behaviour.
while let imagTagrange = (result as String).firstRangeThatMatches(for: "<img.*height\\s*=\\s*(\\\")?[0-9]+(\\\")?") {
let imageTag = result.substring(with: imagTagrange)
if let heightRange = imageTag.firstRangeThatMatches(for: "height\\s*=\\s*(\\\")[0-9]+(\\\")?") {
let tagWithoutHeight = NSString(string: imageTag).replacingCharacters(in: heightRange, with: "")
result = result.replacingCharacters(in: imagTagrange, with: tagWithoutHeight) as NSString
}
}
return result as String
}
The specific block that seems to be causing havoc is the following:
/// Potential breakpoint / Infinite look: This while loop seems to be causing infinite loop behaviour.
while let imagTagrange = (result as String).firstRangeThatMatches(for: "<img.*height\\s*=\\s*(\\\")?[0-9]+(\\\")?") {
let imageTag = result.substring(with: imagTagrange)
if let heightRange = imageTag.firstRangeThatMatches(for: "height\\s*=\\s*(\\\")[0-9]+(\\\")?") {
let tagWithoutHeight = NSString(string: imageTag).replacingCharacters(in: heightRange, with: "")
result = result.replacingCharacters(in: imagTagrange, with: tagWithoutHeight) as NSString
}
}
The input for this function would be an html block encoded as string, which represents the body of an online article.
For example, the following url: https://www.architecturaldigest.com/story/inside-an-art-filled-hollywood-regency-pied-a-terre
Would be parsed and assigned to the htmlString parameter as:
<div><p>Busting a move to Los Angeles seemed only natural for Houston-based interior designer Garrett Hunter and architect Michael Landrum. Although the two friends maintain independent practices, they share an office space and frequently collaborate on projects. The two are also partners in an ever-evolving, experimental gallery/showroom project that first came to life in Houston in 2016 named Tienda X. Two years later, Hunter and Landrum moved the gallery—which hosts a compelling mix of fine and decorative art spanning the contemporary and the antique—to a Mediterranean-style stone house in Austin. They dubbed the operation Villa X.</p><span><img alt=\"pIn a sitting room a Maison Jansen sofa is accompanied by indigo pillows by Christopher Wrobleski a Spanish Majolica oil...\" src=\"https://media.architecturaldigest.com/photos/601c24457d77c6f2f298922d/master/w_1600%2Cc_limit/2020-11-12-Watsonia-AD0080_r2.jpg\"></span><span><p>In a sitting room...
Could you please help in understanding how to solve this and if there is a way to proceed?
I am really stuck and would be enormously grateful to you :)
I'm trying to write a program to shift the key of a midi file. Basically, I just need to shift every note event by a given amount and live the rest unchanged. I found it easy to use MIKMIDI to read, parse, modify and write back the stream.
Unfortunately, I have a problem that I'm unable to solve. I've a loop in which I select the note events and add/subtract the desired shift value, but when I append the event in the output track I get a message from the MIKMIDI library:
"Warning: attempted to insert a NULL event".
The code I wrote is the following:
for event in inputTrack.events {
if event.eventType == .midiNoteMessage {
var tmpData = event.data
if (event.data[0] != 9) { // skip percussion channel
tmpData[1] = event.data[1] - shift
}
let outEvent = MIKMIDIEvent(timeStamp: event.timeStamp, midiEventType: .midiNoteMessage, data: tmpData)!
outputSeq.tracks[i].events.append(outEvent)
}
else {
outSeq.tracks[i].events.append(event)
}
}
BTW, the code works perfectly (the midi file is plays as expected), it is just that it takes minutes to execute in debugging mode due to the infinite sequence of warning messages printed in the debug screen.
Thanks!
I have this stack trace in Crashlytics:
The source code are running is below:
#objc private func playerTimerTick() {
mediaDurationInSeconds = Int32(mediaDuration)
mediaCurrentPositionInSeconds = Int32(currentTimeInSeconds)
if elapsedTimeNeedStoreStartPosition {
elapsedTimeNeedStoreStartPosition = false
elapsedTimeStartPosition = mediaCurrentPositionInSeconds
}
}
The line 1092 is mediaDurationInSeconds = Int32(mediaDuration).
The mediaDuration variable is a Double type and receive a duration in seconds from a AVURLAsset.
This method (playerTimerTick) is running by a Timer.scheduledTimer every 1 second. I have already performed several debugs of this source code and this function and there is no crash. But in the release version is occurring with multiple users and without any explanation.
Has anyone ever had anything like this or do you have any idea what might be causing this crash?
I'm a swift newbie and I'm working on a Swift Mac App as a demo project.The app stores stock symbols in a sqlite table, fetches the stock price, calculates value and then finally displays the results in a table view.
I'm looking for ways to improve execution speed when fetching data to populate my table view. So I used Dispatch Queue as shown below. The problem is that the
Stock Price and Stock Value columns (calculated in the async closure) are always empty. What am i doing wrong? The function getStocksData returns a NSMutableArray which is the datasource for my table view
func getStocksData() -> NSMutableArray {
sharedInstance.database!.open()
let resultSet: FMResultSet! = sharedInstance.database!.executeQuery("select stock_id,symbol,company,qty from stocks ", withArgumentsIn: [])
let stocksDBRowsArray : NSMutableArray = NSMutableArray()
if (resultSet != nil) {
while resultSet.next() {
let stockInfo : StockInfo = StockInfo()
stockInfo.StockID = resultSet.string(forColumn: "stock_id")!
stockInfo.Symbol = resultSet.string(forColumn: "symbol")!
stockInfo.StockCompany = resultSet.string(forColumn: "company")!
stockInfo.Qty = resultSet.string(forColumn: "qty")!
//create queue with unique label to fetch stock price
let queue=DispatchQueue(label:stockInfo.Symbol)
queue.async {
//code to fetch stock price goes here
.....
stockInfo.StockPrice=stockPrice
stockInfo.StockValue=stockPrice*stockInfo.Qty
}
stocksDBRowsArray.add(stockInfo)
}
}
sharedInstance.database!.close()
return stocksDBRowsArray
}
What am i doing wrong?
When your getStocksData() method returns, the StockInfo values may, or may not yet be filled with fetched values. StockInfo values eventually get filled, at some undefined point in time, in an undefined application thread.
That's what the provided code snippet does. Of course this is not what you want, but what you want is not very clear either.
The documentation for Swift's Dispatch library is very terse, and won't help you much understand what is happening. I instead suggest that you study the documentation for dispatch_async, which is the C equivalent of the Swift DispatchQueue.async. It is documented with much more details, and you'll read this key sentence:
Calls to this function always return immediately after the block has been submitted and never wait for the block to be invoked.
Generally don't hesitate switching to the Objective-C documentation when the Swift documentation is lacking. Mastering some Swift technologies sometimes requires this little inconvenience. You'll learn a great deal of information there.
I have a console app on Swift3 that read line by line from very large file.txt (~200GB):
guard let reader = LineReader(path: "/Path/to/file.txt") else { return; }
for line in reader {
// do something with each line
}
It takes about 8+ hours to read all data from file. My server has 6 hardware cores, how to read this file in 6 threads?
LineReader from here: https://github.com/andrewwoz/LineReader
PS. Files from the beginning is separate by 1GB per file.
Never thought about multithread reading a .txt file with 200gb but I'd probably let the console detect how many cores (e.x. 6core)are available and split it into (e.x. 6parts). (-> One part for every process)
As far as I know Ubuntu will automatically evenly distribute to processes.
Hope this helped
!!! This solution works only if you read file using POSIX fopen() like here: https://github.com/andrewwoz/LineReader
let reader = LineReader(path: pathToFile)
var threads = [Thread]()
func readTxtFile() {
while let line = reader?.nextLine {
autoreleasepool {
// To do with each line
}}
}
for threadNumber in 0...threadsCount-1 {
threads.append(Thread(){ readTxtFile() })
threads[threadNumber].start()
}
select(0, nil, nil, nil, nil)
Also the real time profit only with hardware cores, not with HT threads. If your CPU has 2 cores and 4 threads, use 2 threads in the code.