I have an app that used a lot CoreGraphics and by using "UIGraphicsGetCurrentContext()" and "CGContextDrawImage" and etc CoreGraphics founctions, these functions call mmap() and these use a lot virtual memory.
The problem is when I receive low memory warning, the memory used by mmap() in virtual memory will not release automaticly, and I don't have a way to manually release them. The app crash due to the virtual memory pressure, my real RAM usage is very low. How can I manually release the mmap() memory created by CoreGraphics? Thx
Related
I have been studying the bootloaders, and there is an explanation on most of the sources that ROM code is on most of the chips that tell the chip where to go after it power up, and then ROM code load a small chunk of code into the SRAM.
My question is that DRAM requires a controller to run, but why SRAM doesn't? Who controls the SRAM? or how it is being controlled?
Also what happens after the system is being done with the SRAM and things are running off of DRAM?
I do not know yet if it makes sense or not but it would be best if you can answer from the perspective of u-boot and Linux.
Both need controllers, DRAM however needs to be refreshed periodically to keep its state (in condensators), unlike SRAM that stores its states through latch circuits.
That means that if you want to keep the content of the memory after a reset (from Linux or U-Boot for example), you must have configured the DRAM controller to "auto refresh" the memory during the reset step. There is no such need with SRAM.
Generally when you are referring to SRAM from bootloader perspective, it is internal RAM which is accessible by the controller. This RAM is accessed by the controller using an AHB/AXI bus (for ARM based devices). There might be a memory bridge which converts the signals from AHB/AXI bus to memory bus. So speaking from a software point of view, it is transparent, no specific software configuration is required to access this RAM.
... then ROM code load a small chunk of code into the SRAM.
That is a common procedure with some SoCs, but it's not required. There are alternate boot schemes.
Etrax SoCs that used CRIS processors (which are now out of production) required the DRAM parameters to be stored in nonvolatile memory (NVM). The embedded ROM boot code accessed this NVM, and initialized the DRAM controller. The ROM boot code was thus capable of directly booting a Linux kernel.
Some ARM SoCs have a Boot Memory Selector (BMS) pin (e.g. Atmel AT91SAM9xxx and Microchip SAMA5Dx) that can disable the internal ROM code, and has the processor execute code after a reset from an external NVM (e.g. NOR flash) which has execute-in-place (XIP) capability. Such a boot scheme could be customized to initialize the external DRAM, and then load U-Boot or even a Linux kernel.
My question is that DRAM requires a controller to run, but why SRAM doesn't?
Who controls the SRAM? or how it is being controlled?
DRAM requires a controller because this type of memory technology requires periodic refreshing. The DRAM controller needs to be programmatically initialized before the DRAM can be accessed. One of the functions of the boot code that is loaded into SRAM is to perform this initialization of the DRAM controller.
Interfacing SRAM by comparison is far more straightforward. Normally there is no "SRAM controller". The control logic to interface SRAM typically does reach the level of complexity to require a "controller". For instance I've used a SBC that had its Z80 microprocessor directly connected to the SRAM (HM6264) and EPROM (MBM2764) memory ICs plus some logic for address decoding.
The "SRAM controller" found on a modern SoC is primarily a buffered interface for external SRAM with the internal system bus. The internal SRAM of the SoC does not require any software initialization, and would be accessible immediately after a reset.
Also what happens after the system is being done with the SRAM and things are running off of DRAM?
Typically the internal SRAM is left unused when it is not included as part of the memory that the Linux kernel manages. I don't know if that is due to any technical reasons such as virtual memory or caching issues, or oversight, or desire for the simplicity of homogeneous memory.
For some SoCs the amount of internal SRAM is so small (e.g. 8 KB in Atmel AT91SAM926x) that the effort to utilize it in the kernel could be deemed to have a poor cost-to-benefit trade-off.
See this discussion regarding a kernel patch for SRAM on an Atmel/Microchip SAMA5D3x
A device driver could still utilize the internal SRAM as its private memory region for high-speed buffers. For instance there was a kernel patch to use the SRAM to hold Ethernet transmit packets to avoid transmit underrun errors.
There are two types of memory in Vulkan buzzling me:
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit indicates that the host cache
management commands vkFlushMappedMemoryRanges and
vkInvalidateMappedMemoryRanges are not needed to flush host writes to
the device or make device writes visible to the host, respectively.
VK_MEMORY_PROPERTY_HOST_CACHED_BIT bit indicates that memory allocated
with this type is cached on the host. Host memory accesses to uncached
memory are slower than to cached memory, however uncached memory is
always host coherent.
From what I understand is that modification of memory of type COHERENT is seen immediately by both the host and the device, and modifications to memory of type CACHED may not be seen immediately by the host and/or the device, i.e. invalidating/flushing the memory is needed to invalidate the cache.
I have seen some implementations combine both flags, and it is valid combinations according to the 10.2. Device Memory section in the documentation. Isn't there a contradictory (cached and coherent)?
Cached/coherent memory effectively means that the GPU can see the CPU's caches. This often happens on architectures where the GPU and the CPU are sitting on the same chip. The GPU is effectively just another core on the CPU's die, with access to the CPU's core.
But it can happen on other architectures as well. Some standalone GPUs offer cached/coherent memory. Indeed, most of them don't offer cached memory without coherency. From an architectural standpoint, it represents some way for the GPU to access data through at least part of the CPU cache.
The key thing about cached/coherent memory you should remember is this: if there is an alternative memory type for that memory pool, then the alternative is probably faster for the device to access. Also, if alternatives exist, it is entirely possible that the device may not be able to have images or buffers of certain types/formats stored in such memory types. So unless you really need cached memory access from the CPU, or the device offers no alternative, it's best to avoid it.
There are cache schemes that monitor write accesses to RAM over the memory bus to invalidate the Host's cache when the memory is written to.
This allows the best of both worlds, cached coherent accesses but at the cost of a more complex architecture.
Any idea why my app's memory usage does not increase whilst using Instruments profiler (searching for leaks), but does when I don't use any profiler? To the tune of 1MB per operation performed. Instruments does not show any leaks.
OS memory management is a complex thing. It is likely that when you free memory it is not returned immediately to the system, but instead it is still "attached" to your process to make any future allocations your application needs more efficient. Although it is recorded as part of your process's memory space, it would be marked as unused, and when the system is running out of memory (or when your application exits), it would then reclaim the unused memory from your application.
If Instruments isn't reporting any leaks, you should be fine.
Memory leak snapshot with no "Hide system libraries selected"-
Memory leak snapshot with "Hide system libraries selected"-
Do I need to worry for these leaks as after many memory cycles I have come up to this point wherein I do not find a memory leak source in my application.
Is my understanding OK ?
And this image shows memory leak in cycles and roots mode -
i've been playing some time with different builds of my application and there seem strange things to happen:
my app has a 5mb idle footprint. when uploading a file memory in size of the file is reserved. after the upload the reserved memory should be freed. now there are differences in the builds (gc = garbage collector):
32bit i386 no-GC: all memory is freed instantly.
32bit i386 GC: almost all memory is freed instantly. the rest some time later.
64bit x86_64 no-GC: minimal memory is freed. like 10%
64bit x86_64 GC: no memory at all is freed. the memory stays reserved for hours. (activity mon)
i'm using LLVM with CLANG. i have been running today instruments all the time and was checking for leaks/zombies/etc. and everything seems to be clean. (the app is rather simple.)
is there an explanation for this behavior?
Update:
That's some weird stuff. I've boiled the problem to this:
I load a 20mb file into a NSData and release it. I'm doing this without any garbage collection enabled. The code is:
NSData *bla = [[NSData alloc] initWithContentsOfFile:#"/bigshit"];
[bla release];
When I build for i386 32bit the 20mb are allocated and released. When I switch the build to 64bit x86_64 the release does nothing. The 20mb stay allocated.
upper pic 32bit lower 64 http://kttns.org/zguxn
There is no difference between the two apps except that the upper one is built for 32bit and the lower one 64bit. There is no GC running. (With GC enabled the same problem appears.)
Update 2:
The Same behavior can be observed when I create a new cocoa app from scratch with only the upper code in applicationDidFinishLaunching:. In 64bit mode the memory is not released. i386 works as expected.
The same problem appears with NSString instead of NSData. It also appears when I boot the 64bit kernel. (Holding 64 at startup.)
OS is 10.6.0
First, use Instrument's Object Graph instrument to verify that the memory is no longer considered to be in use; does not have a retain count or a strong reference somewhere.
If it is no longer in use, then the memory is sticking around simply because you haven't hit the threshold at which the collector cares.
However, this statement:
64bit x86_64 no-GC: minimal memory is
freed. like 10%
Makes me wary. Specifically, if your code is designed to work in non-GC -- with retain/release -- then either (a) you have a memory leak and, if using CFRetain or some kind of global cache, that might impact GC or (b) you aren't using the right tools to figure out whether or not you have a memory leak.
So, how are you determining that you are leaking memory?
Update; you are using Activity Monitor to monitor the RSIZE/VSIZE of the process. This won't actually tell you anything useful beyond "is my process growing over time".
More likely than not (I haven't looked at the source), this code:
NSData *bla = [[NSData alloc] initWithContentsOfFile:#"/bigpoop"];
Will cause the 20MB file to be mmap()'d in to the process. There isn't a malloc() style allocation involved at all. Instead, the OS hands 20MB of contiguous address space to your process and maps the file's contents into it. As you read the contents of the NSData, it'll page fault in the file as you go.
When you release bla, the mapping is destroyed. But that doesn't mean that the VM subsystem is going to reduce your application's address space by 20MB.
So, you are burning up a bunch of address space, but not actual memory. Since your process is 64 bits, address space is pretty much an infinite resource and there is very little cost to using addresses, thus the reason why the OS is implemented this way.
I.e. there is no leak and your app is behaving correctly, GC or no.
This is a common misconception and, thus, star'd the question.
A garbage collector doesn't necessarily release memory immediately.
In the case of the Objective-C garbage collector, you can send Cocoa's garbage collector object a collectIfNeeded message to suggest that now may be a good time to do some collection, or collectExhaustively to order it to immediately start collecting any and all garbage (but even this is interruptible). See the docs.
I have a very similar problem in iPhoneOS 3.2 and I really don't think that the memory is being reclaimed -- I eventually trigger memory warnings. There is a small chance that I have overlooked a mistake of my own but I have been very thorough.
I use NSKeyedUnarchiver's unarchiveObjectWithFile: to load a custom object that contains a single large NSData and another much smaller object. The dealloc method in my custom object gets called, the NSData object is released, its retainCount == 1 just before. Physical memory does not decrement by any amount, let alone a fraction of the NSData size, and with repetition memory warnings are reliably generated: I have test until I actually received level 2 warnings. =(
Before release:
(gdb) p (int) [(NSData *) pastItsWelcomeData retainCount]
$1 = 1
After release:
(gdb) p (int) [(NSData *) pastItsWelcomeData retainCount]
Target does not respond to this message selector.