Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by Pharan · Sep 01, 2015 at 12:55 PM · stringtagsstringsstring comparison

Does Unity's Mono do a reference compare in its string == operator?

According to this page: http://www.dotnetperls.com/string-intern

"It is faster to compare interned strings because the method that C# implements string comparisons with always checks references first. If the references are equal, the comparison succeeds."

Internally, code supposedly looks like this:

     public static bool Equals(string a, string b)
     {
         return ((a == b) || (((a != null) && (b != null)) && EqualsHelper(a, b)));
     }    

But this page is describing Microsoft's CLR.

  • Does the same behavior apply to Unity's version of Mono as well? Does the == operator between strings do a reference compare before the per-character string compare?

  • And if so, would GameObject tags be interned at runtime?

Apart from the lack of code completion (although Visual Studio now checks misspellings), I've always avoided using and creating string interfaces because of the performance implications. But, barring the lack of code completion, string interfaces are arguably more scaleable and easier to set up, versus setting up reference identification or new enums. Those are really good things to skip if you're still at prototyping stages.

But if string interning does what it does, we could just have a preparatory step for string member fields where applicable (calling myString = string.Intern(myString); on initialization), and the resulting reference comparisons from == operators would theoretically make it fast enough even for performance-critical code.

More info: https://msdn.microsoft.com/en-us/library/system.string.intern%28v=vs.85%29.aspx

EDIT: I guess to clarify, the insight here was that interned strings might be used to identify certain kinds of data in a collection, for example, if you had a centralized place for playing UI sounds and you wanted to identify sounds by their name.

But I guess in actual use, getting data identified by a string through a string interface would involve either traversing a List and checking each item, or accessing it through a Dictionary.

The List solution is nicer in Unity because Lists serialize. And in this case, you'd still be traversing a List, but one could at least rest easy that you could reliably do reference comparisons object.ReferenceCompare(string1, string2); if you interned your strings correctly.

I guess the == operator didn't really matter, 'cause if that fails, it would still attempt the char-by-char comparison.

It just wouldn't matter in the Dictionary case either since access is through hash values.

I guess this still has other uses somehow.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
3
Best Answer

Answer by Bunny83 · Sep 01, 2015 at 01:20 PM

Yes, strings are compared by reference first. However i'm not entirely sure if tags are interned. You could simply test it by using IsInterned on the returned tag of a gameobject to see if it's an interned value. All literal string constants in your code are interned by default.

While it's true that an interned string comparison is quite a bit faster than a char by char comparison it most likely won't increase the performance. "char by char" comparison isn't that slow as it's just a for loop. Also it only has to check the full length of the string if they actually match. The first character that doesn't match yields an early exit.

So if you check:

 if (gameObject.tag == "MyLongTagName")

if the actual tag is "Player1234567" it only compares one character ('M' and 'P') and returns false

if the actual tag is "MyLongTagName2" it usually should early exit as well since the length of both strings doesn't match.

Only in cases where the actual tag is something like "MyLongTagNamX" it would have to check all characters up to the X until it realises that they don't match.

So in reality it won't make much of a difference. It's much more important to avoid things like that:

 int i = 1;
 if (gameObject.tag == ("MyTag" + i))

The comparison here is quite irrelevant but that you create a new string each time you execute this line. Cache strings where possible if they are dynamically build.


edit

Just did a quick test and yes, tag returned an interned string if the string exists in the intern pool.

I simply did this on the MainCamera:

 if (string.IsInterned(gameObject.tag) != null)
     Debug.Log("Is interned");

If i just execute this it won't print. However if i have the string "MainCamera" somewhere in my project it will print.

edit2

Oh, i think i've misinterpreted what IsInterned actually does ^^. It doesn't check if the string is actually interned but if the string that you pass to the method exists in the intern table. It doesn't say anything about if the passed in string is actually interned...

So after a bit more testing it turned out that the string is not interned. If you do:

 if ((object)gameObject.tag == (object)"MainCamera")

It will never return true.... Even "MainCamera" is an interned string, the string returned by "tag" is not interned.

So the final answer is: Interning a string for tag comparison doesn't help at all ^^. I guess that CompareTag might use an interned or look up table internally since it was always stated that it's faster than a normal string comparison.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Pharan · Sep 01, 2015 at 02:52 PM 0
Share

Thanks! Those are all great insights. And thanks for investigating it thoroughly too.

I wasn't planning to use it for tags in particular, but your insight on that was helpful too.

I was thinking of using a string as an identifier for items in a collection. I guess that's technically what Dictionaries are for, and string interning doesn't even factor into that because it just uses hashcodes.

I'm sure there's an appropriate use for this somewhere. XD

Do you think a Dictionary is abusive? XD I could access stuff from it by passing it a (object)myInternedString so it does a reference hashcode ins$$anonymous$$d of a string hashcode. hahaha

avatar image
2

Answer by steakpinball · Sep 01, 2015 at 01:45 PM

This does apply to unity's implementation. You can view their implementation on Github. https://github.com/Unity-Technologies/mono/blob/unity-staging/mcs/class/corlib/System/String.cs

     public static bool operator == (String a, String b)
     {
         return Equals (a, b);
     }
     public static unsafe bool Equals (string a, string b)
     {
         if ((a as object) == (b as object))
             return true;

         if (a == null || b == null)
             return false;
             ...
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Pharan · Sep 01, 2015 at 02:54 PM 0
Share

Thanks! Wow, that's a helpful link.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

Grab part of a string by looking for keyword 2 Answers

Problem splitting up strings 2 Answers

Performace Overhit for String Concatenation in Online Pool Game Posted 0 Answers

Random String from list of string without repeated letters 2 Answers

Remove String Line If Contains Specific Word C# 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges