Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

[C#] A question for the experts about performance in Dictionaries

Discussion in 'Editor & General Support' started by JorobusLab, Aug 4, 2014.

  1. JorobusLab

    JorobusLab

    Joined:
    Jul 3, 2014
    Posts:
    78
    Hi fellows, how are you? I'm internationalizationing my game. I have a few Dictionary<string, string> objects which contains key strings for words or sentences as values. Each dictionary correspond to one language. I have cases in which values are wrote exactly same in many languages, so I though in make a feature that if the key is not found in a certain dictionary, just return the key capitalized. I'll put two examples: "yes" is the key, in the english dictionary it point to "Yes", and in the spanish to "Si". This is the method who gives the value:

    public static string t(string k) {
    switch (local_language) {
    case "SP":
    return(sp_d[k]);
    default:
    // default is English
    return (en_d.ContainsKey(k)) ? (en_d[k]) : ((k.Substring(0, 1).ToUpper()) + (k.Substring(1)));
    }
    }

    My question is: will this weigh in performance? Still I'm learning C# and I'm not sure how it works deeply(I come from a interpreted language). My concern is that the last line of the method will get executed each time I want to retrieve a value from the en_d dictionary, OR the compiler will iterate over my whole code and will feed with the results of queries to en_d to the variables who requires them?
    If that line of code will get executed each time I use MyDictionaryClass.t("yes") being my local language EN then I think is better to write at hand en_d["yes"] = "Yes" . With this way I'll have 1000 keys instead of 700. Hope I made my point and I'll appreciate any advice, thank you so much.

    Edit: I'm sorry, I made a mistake posting in the support part of the forum, though I was doing it in Scripting.
     
  2. MakeCodeNow

    MakeCodeNow

    Joined:
    Feb 14, 2014
    Posts:
    1,246
    The CLR will do what you expect and only execute the string manipulation if the lookup fails. Note that you are doing two lookups (Contains and []) which isn't strictly necessary, but it's probably not a huge deal either way. Ultimately its a memory vs CPU tradeoff.

    That said, I dont think its a very good solution. It makes lots of assumptions which may not be true. Do you always want uppercase first letter in English? You may think so but always is a long time. And what about the case where you don't have 1:1 language mapping. Often a you can use the same word in different ways in English but they are two different words in other languages.

    The best and time honored way to do loc text is to have the key be a unique ID (ie "abc123") and then have a complete string dictionary for each language.
     
  3. Veovis Muaddib

    Veovis Muaddib

    Joined:
    May 30, 2013
    Posts:
    7
    Also note there are some good free localization systems that already exist.

    Smart Localization (Asset Store) (Github) (Unity Forums) is free with sources and works pretty well.
     
  4. JorobusLab

    JorobusLab

    Joined:
    Jul 3, 2014
    Posts:
    78
    That's right, but, will it does on runtime or compile time? That is exactly what's not clear for me. If it does on runtime is better to do what you say: a complete string dictionary for each language, for performance reason, the game is focused on mobile devices, so I'm concerned about this issue.
     
  5. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Jorobus, I think you might want to think about it a little bit differently. The Dictionary approach really is a good approach but as MakeCodeNow has said, you should use a key for that. This gives you some flexibility. You could have a key for "yes" if you want, but you can also have keys for entire pieces of dialogue if you want.

    Also, on the point of the double check... I wouldn't do the double check if you don't have to unless you expect that it might exist but be null, then you should do:

    Code (csharp):
    1.  
    2. return (en_d.ContainsKey(k)) && !string.IsNullOrWhitespace(en_d[k]) : ((k.Substring(0, 1).ToUpper()) + (k.Substring(1)));
    3.  
    Now, you should probably avoid the extra substrings, .ToUppers, etc and only use when absolutely necessary because they will result in new strings being created in memory (string is immutable so your original string is copied and not directly modified).

    As for what you should do differently, don't load all of your languages up front. You should consider loading XML or JSON only for the language that you need, that way you're not loading strings into memory that you don't have to. You could also then pretty easily write your own tool to create / update your language files outside of Unity and have Unity just load the appropriate file for you.
     
  6. JorobusLab

    JorobusLab

    Joined:
    Jul 3, 2014
    Posts:
    78
    That's a good advice, I'll consider separate each language reference into extern files. Thanks!
     
  7. MakeCodeNow

    MakeCodeNow

    Joined:
    Feb 14, 2014
    Posts:
    1,246
    It's a runtime check. You can't avoid that because the results depend on the key. Compile time optimizations only work on static things and this is not static. As others have said the string manipulation is likely more expensive than the dictionary work.

    Totally agree on the points made by others here, esp about storing string table per language and only loading what you need.
     
    JorobusLab likes this.
  8. JorobusLab

    JorobusLab

    Joined:
    Jul 3, 2014
    Posts:
    78
    I was looking for some hint about implementing the adviced way but found almost nothing. Can you give me a light about how to implement this system with XML files?
     
  9. JorobusLab

    JorobusLab

    Joined:
    Jul 3, 2014
    Posts:
    78
    Okay I've implemented this, I'm telling to save you the time to explain, thank you both :) . See you around :) .
     
  10. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Great! Sorry I didn't have time to get in and put together an example for you. Glad you got it working.
     
    JorobusLab likes this.