Bug 11503 - UIColor.Red not using cached instance of UIColor
Summary: UIColor.Red not using cached instance of UIColor
Status: RESOLVED FEATURE
Alias: None
Product: iOS
Classification: Xamarin
Component: XI runtime ()
Version: 6.2.x
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2013-04-01 11:30 UTC by cod3monk3y
Modified: 2013-04-02 08:39 UTC (History)
2 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FEATURE

Description cod3monk3y 2013-04-01 11:30:21 UTC
I recently profiled my application with HeapShot. Currently, I make somewhat regular use of "standard" colors from UIColor such as UIColor.Green and UIColor.Red. I took snapshots every 5 seconds, and noticed that UIColor was at the top of my memory usage when differencing two snapshots. So I moved any unchanging color references to static variables in my app (which I should have done in the first place). But then I wondered why, if I'm just using UIColor.Green, are these showing up as memory allocations? I figured the standard colors should be at worst late created immutable instances of UIColor. 

So I noticed something in the assembly browser. It looks like accessing UIColor.Red will *always* create a new UIColor. It appears that MT tries to cache the stored color in UIColor__mt_Red_var_static, but then fails to check for the static instance before calling GetNSObject(..."redColor").

From Assembly Browser on UIColor.Red:

[CompilerGenerated]
public static UIColor Red
{
	[Export ("redColor")]
	get
	{
		UIColor uIColor = (UIColor)Runtime.GetNSObject (Messaging.IntPtr_objc_msgSend (UIColor.class_ptr, Selector.GetHandle ("redColor")));
		UIColor.__mt_Red_var_static = uIColor;
		return uIColor;
	}
}

Should the code be:

get { 
    if (UIColor.__mt_Red_var_static != null) return UIColor.__mt_Red_var_static;
    // else, create...
}

?

I don't know if the MT code is available for browsing (is it?), and maybe it's actually different than what Assembly Browser is reporting. But that looked like a bug to me. 

Thanks!
cm

**Version Info**

Xamarin.iOS
Version: 6.2.1.201 (Business Edition)
Hash: ed9807c
Branch: 
Build date: 2013-19-03 13:42:59-0400
Comment 1 Sebastien Pouliot 2013-04-02 08:39:02 UTC
This is generated code, which is general for all ObjC library bindings.

In bindings all the `__mt_*` fields are backing fields. They are meant to keep a reference alive of an ref-counted native instance so the native instance is not freed until it's managed peer is GC'ed.  IOW those fields are **not** a cache. 

OTOH there _might_ be caching involved if the ObjC (native side) returns the same instances (pointer). That's being done inside `Runtime.GetNSObject`. If they are not (cached) then there's a reason why Apple does not do it. E.g. some colors, not Red but DarkTextColor, might change values over time.

> and maybe it's actually different than what Assembly Browser is reporting.

It can be tricky for bindings because the code being executed might be can be different that you you see. There's an optimization step, when the linker is enabled, that removes a lot of extraneous conditions. However in this case it would be (close to) the same code you browsed (and in any case the removals don't change the logic, it only removes dead code).