I am monitoring my application using Activity Monitor and whenever NSOpenPanel is called the application appears as having 9 threads and stays like that until the application is closed.
Is there a way to release those threads?, Or am I simply misunderstanding what the threads number means?, surely it isn't a good thing to have them open for no reason.
Any help would be appreciated
It looks like the threads are created for tasks such as detecting drives being mounted, so that NSOpenPanel can add them to its sidebar. It looks like a bunch of threads get created when the panel is open, and several of them are destroyed afterwards, but a few do still hang around. The threads aren't doing any work though, they're just blocked waiting for various events to happen. So, they may take up a bit of memory, but they shouldn't affect performance or anything like that. There isn't any way for you to get rid of them in your program though.
Related
Before spending several hours to hit a dead end, I thought I should consult the experts here. I want to have a background app in Win32 which can capture the memory of other apps and dump it to a text file, then have the background app restore the app to it's exact state.
It seems like ReadProcessMemory/WriteProcessMemory are functions that were created specifically for that. I understand new memory addresses will have to be created, but is there any reason why using WriteProcessMemory with new addresses could not do this? If you completely replace the process's memory, it should bring it back, right? Even if the app was closed and reopened using CreateProcess, you should get the exact same state when you completely rewrite the process's memory with WriteProcessMemory. Would the newly created addresses know how to point to each other, or is there any way to "make them know"?
Please shed some light on this to me. Thanks to all.
Suppose you are making a GUI application, and you need to load/parse/calculate a bunch of things before a user can use a certain tool, and you know what you have to do beforehand.
Suddenly, it makes sense to start doing these calculations in the background over a period of time (as opposed to "in one go" on start-up or exactly when it is needed). However, doing too much in the background will slow down the responsiveness of the application.
Are there any standard practices in this kind of approach? Perhaps ways to detect low load on the CPU or the user being idle and execute code in those times? Arguments against this type of approach?
Thanks!
Without knowing your app or your audience, I can't give you specific advice.
My main argument against the approach is that unless you have a high-profile application which will see a lot of use by non-programmers, I wouldn't bother. This sounds like a lot of busy work that could be spent developing or refining features that actually allow people to do new things with your app.
That being said, if there is a reason to do it, there is nothing wrong with lazy-loading data.
The problem with waiting until idle time is that some people have programs like SETI#Home installed on their computer, in which case their computer has little to no idle time. If loading full-throttle kills the responsiveness of your app, you could try injecting sleeps. This is what a lot of video games do when you specify a target frame rate, to avoid pegging the CPU. This would get the data loaded faster, rather than waiting for idle time.
If parts of your app depend on data to work, and the user invokes that part of the app, you will have to abandon the lazy-loading approach and resume your full CPU/disk taxing load. If it takes a long time, or make the app unresponsive, you could display a loading dialog with a progress bar.
If your target audience will tend to have a multicore CPU and if your app startup and background initialization tasks won't contend for the same other resources (e.g. disk IO, network, ...) to the point of creating a new bottleneck, you might want to kick off a background thread to perform the initialization tasks (or even a thread per initialization task if you have several tasks that can run in parallel). That will make more efficient use of a multicore hardware architecture.
You didn't specify your target platform, but it's exceedingly easy to achieve this in .NET and so I have begun doing it in many of my desktop apps.
In my Cocoa application I need to run a task that uses unstable unfixable code. It takes little input, works independently from the rest of the app, and generates thousands of ObjC objects as a result.
How can I run the unstable part and let it crash without taking down whole application?
Is it possible to fork() Cocoa application? How UI, threads, GC, KVO, runloops are going to behave when forked?
Can I avoid creating standalone executable launched via NSTask?
If I launch separate process, how can I send and receive ObjC object instances? (I'd rather not serialize/unserialize them myself, and I need to keep them after child process ends).
How does OS X handle this problem for Spotlight and Quicklook plugins?
Is it possible to fork() Cocoa application?
Yes, but you pretty much have to exec immediately. Core Foundation will throw an exception if you try to use certain Cocoa methods or CF functions between fork and exec (or without execking at all). You might get away with some things (I was able to ask a window its frame, for example), but nothing is safe.
Launching an NSTask, of course, counts as fork and exec together, averting the problems of skipping or postponing the exec.
How UI, threads, GC, KVO, runloops are going to behave when forked?
UI: Windows (the actual ones on the screen) are not duplicated. Of course, you can't talk to your NSWindow and NSView objects anyway.
Threads: Not carried over to the subprocess. This is not as good as it may sound, as problem cases abound; for one, another thread might have held a lock in the parent, which remains locked in the child even though the thread that held it is absent.
GC: Well, the garbage collector runs on a thread…
KVO: Should be fine, since observation is normally triggered either explicitly or by KVO-supplied wrapper accessors.
Run loops: One per thread, so the main thread's run loop should still exist, but it will die if you return to it.
Can I avoid creating standalone executable launched via NSTask?
Nope.
If I launch separate process, how can I send and receive ObjC object instances?
If you don't exec, you don't.
Otherwise, you can use DO.
(I'd rather not serialize/unserialize them myself, and I need to keep them after child process ends).
Then you'll need to make a copy in the parent process. I don't know whether you can use copyWithZone: here; probably not. I suspect you will have to do some sort of plist- or archive-based serialization/unserialization.
How does OS X handle this problem for Spotlight and Quicklook plugins?
Spotlight has mdworker; Quick Look has something similar.
I use Distributed Objects to communicate between my cocoa program and a separate (unreliable) worker program. I start the worker as a NSTask. Distributed objects are very elegantly put together.
I have a application which randomly freezes, including the IDE and it's driving me mad. That makes me wonder:
What's a good general strategy for finding the cause of random freezes?
If you are wanting to check from outside of a running app then I would potentially use the sysinternals.com toolset from Mark Russonivich, the perfmon tool allows you to trace file / registry access and check the trace for delays - and what is being accessed at that time. It will show the DLL call stack at that time with the right symbols can is useful for debugging problems external to an application that are causing delays. (I've used it to find out that an I/O filter associated to a security suite was the reason an application was piccking up a number of 1.5sec delays.)
If you're lucky, you can run your code in a debugger until it freezes, then stop the debugger to find the offending line of code. But if it were that easy, you probably wouldn't be asking for advice. :-)
Two strategies that can be used together are to "divide and conquer" and "leave bread crumbs."
Divide and conquer: Comment out increasingly larger portions of your code. If it still freezes, you've reduced the amount of code that might be responsible for causing the freeze. Caveat: eventually you'll comment out some code and the program will not freeze. This doesn't mean that last bit of code is necessarily responsible for the freeze; it's just somehow involved. Put it back and comment out something else.
Leave bread crumbs: Make your program tell you where it is and what it's doing as it executes. Display a message, add to a log file, make a sound, or send a packet over the network. Is the execution path as you expected? What was the last thing it was doing before it froze? Again, be aware that the last message may have come from a different thread than the one responsible for freezing the program, but as you get closer to the cause you'll adjust what and where the code logs.
You're probably doing things in the UI thread when you shouldn't be.
I would install the UserDump tool, and follow these instructions for generating a user dump of the application....
Once you have the user dump, you can use WinDbg, or cdb to inspect the threads, stacks, and locks, etc.
Often I find hangs are caused by locked mutexes or things like that.
The good general strategy is, run the program until it hangs. Then attach a debugger to it and see what's going on. In a GUI program, you're most interested in what the UI thread is doing.
You say the application hangs the IDE. This isn't supposed to happen, and I imagine it means the program is putting so much strain on the OS (perhaps CPU load or memory) that the whole system is struggling.
Try running it until it hangs, going back to the IDE, and clicking the Stop button. You may have to be really patient. If the IDE is really permanently stuck, then you'll have to give more details about your situation to get useful help.
I'm working on a small free Cocoa app that involves some SFTP functionality, specifically working with uploads. The app is nearing completion however I've run into a pretty bad issue with regards to uploading folders that contain a lot of files.
I'm using ConnectionKit to handle the uploads:
CKTransferRecord * record;
record = [connection recursivelyUpload:#"/Users/me/large-folder"
to:#"/remote/directory"];
This works fine for most files and folders. Although in this case #"/Users/me/large-folder" has over 300 files in it. Calling this method spins my CPU up to 100% for about 30 seconds and my application is unresponsive (mac spinning ball). After the 30 seconds my upload is queued and works fine, but this is hardly ideal. Obviously whatever is enumerating these files is causing my app to lock up until it's done.
Not really sure what to do about this. I'm open to just about any solution - even using a different framework, although I've done my research and ConnectionKit seems to be the best of what's out there.
Any ideas?
Use Shark. Start sampling, start downloading, and as soon as the hang ends, stop sampling.
If the output confirms that the problem is in ConnectionKit, you have two choices:
Switch to something else.
Contribute a patch that makes it not hang.
The beauty of open-source is that #2 is possible. It's what I recommend. Then, not only will you have a fast ConnectionKit, but once the maintainers accept your patch, everyone else who uses CK can have one too.
And if Shark reveals that the problem is not in ConnectionKit (rule #2 of profiling: you will be surprised), then you have Shark's guidance on how to fix your app.
Since the problem is almost certainly on the enumeration, you'll likely need to move the enumeration into an asynchronous action. Most likely they're using NSFileManager -enumeratorAtPath: for this. If that's the main problem, then the best solution is likely to move that work onto its own thread. Given the very long time involved, I suspect they're actually reading the files during enumeration. The solution to that is to read the files lazily, right before uploading.
Peter is correct that Shark is helpful, but after being a long-time Shark fan, I've found that Instruments tends to give more useable answers more quickly. You can more easily add a disk I/O and memory allocation track to your CPU Sampler using Instruments.
If you're blocking just one core at 100%, I recommend setting Active Thread to "Main Thread" and setting Sample Perspective to "All Sample Counts." If you're blocking all your cores at 100%, I recommend setting Active Thread to "All Threads" and Sample Perspective to "Running Sample Times."