Какой самый быстрый способ перебора динамического объекта в C #? - PullRequest
3 голосов
/ 11 февраля 2012

Фон

Я работаю над приложением, которое требует использования служб JSON на сервере , а затем переупаковывает этот JSON в модель представления, на которую можно ссылаться с использованием синтаксиса Razor в представлении. Обработка этого кода на стороне сервера обязательна по разным причинам.

Мы используем C #, .NET 4, MVC3, Razor, JsonFx.

В настоящее время у нас есть код, который работает просто отлично, но для итерации 250 элементов в полученном объекте JSON требуется до минуты, и это недопустимо (не говоря уже о том, чтобы сбить с толку). Я уже выделил проблему в следующем цикле; JSON быстро-молниеносно, так что это не проблема. Вот код , работающий, но чрезвычайно медленный :

        var reader = new JsonReader();
        var json = GetJson(SPListName);

        var admItems = new List<IDictionary<String, object>>();
        dynamic _items = reader.Read(json); //This part is REALLY fast.  No problem here.
        foreach (var itm in _items)
        {
            dynamic obj = new ExpandoObject();
            foreach (dynamic admObj in itm)//Here begins the slow part.
            {
                var item = obj as IDictionary<String, object>;
                var encodedValue = "";
                try
                {
                    if(admObj.Key == "Title")
                    {
                        encodedValue = admObj.Value.ToString();
                    }else
                    {
                        encodedValue = admObj.Value[0].ToString();
                    }
                }
                catch (Exception)
                {
                    encodedValue = admObj.Value.ToString();                   
                }

                item[admObj.Key] = encodedValue.EncodeNonAscii().FixHtmlEntities();
            }
            admItems.Add(obj);
        }
        return admItems;

Вы также можете заметить несколько пользовательских методов расширения. Вот они (в случае, если это имеет значение):

public static string EncodeNonAscii(this Object str)
            {
                StringBuilder sb = new StringBuilder();
                foreach (char c in str.ToString())
                {
                    if (c > 127)
                    {
                        // This character is too big for ASCII
                        string encodedValue = "\\u" + ((int) c).ToString("x4");
                        sb.Append(encodedValue);
                    }
                    else
                    {
                        sb.Append(c);
                    }
                }
                return sb.ToString();
            }

            public static string FixHtmlEntities(this Object str)
            {
                var fixedString = str.ToString().Replace("\\u00c2\\u00ae", "&reg;");
                return fixedString;
            }

Вопрос

Какого черта я делаю неправильно / как мне ускорить это. Мой мозг сейчас гамбургер, поэтому я надеюсь, что кто-то укажет на простой упущение.

Обновление / Разрешение

Рофуине и Джошуа Энфилд оба указали на корень проблемы со скоростью: ловля исключений замедляла все.

Многие люди предлагали мне использовать Json.Net или что-то подобное. Хотя я ценю этот совет, он действительно не был в корне моей проблемы (хотя, возможно, он и появился таким образом); В прошлом я широко использовал Json.Net и несколько месяцев назад предпочел JsonFx . В этом конкретном случае меня больше интересует конструкция объекта модели представления, поскольку я уже десериализовал JSON с использованием JsonFx. Пожалуйста, дайте мне знать, если вы все еще думаете, что я упускаю вашу точку зрения;).

Причина моей безумной схемы try / catch заключалась в том, что мне нужно было делать разные вещи с каждым свойством строки JSON в зависимости от его типа (string, string [], object [] и т. Д.). Я забыл, что System.Type может справиться с этим для меня. Итак, вот окончательный код:

var reader = new JsonReader();
                var json = GetJson(SPListName);

                var admItems = new List<IDictionary<String, object>>();
                dynamic _items = reader.Read(json);
                foreach (var itm in _items)
                {
                    dynamic obj = new ExpandoObject();
                    foreach (dynamic admObj in itm)
                    {
                        var item = obj as IDictionary<String, object>;
                        var encodedValue = "";

                        Type typeName = admObj.Value.GetType();

                        switch (typeName.ToString())
                        {
                            case("System.String[]"):
                                encodedValue = admObj.Value[0].ToString();
                                break;
                            default:
                                encodedValue = admObj.Value.ToString();
                                break;
                        }

                        item[admObj.Key] = encodedValue.EncodeNonAscii().FixHtmlEntities();
                    }
                    admItems.Add(obj);
                }
                return admItems;

Надеюсь, это кому-нибудь поможет!

1 Ответ

6 голосов
/ 11 февраля 2012
            try
            {
                if(admObj.Key == "Title")
                {
                    encodedValue = admObj.Value.ToString();
                }else
                {
                    encodedValue = admObj.Value[0].ToString();
                }
            }
            catch (Exception)
            {
                encodedValue = admObj.Value.ToString();                   
            }

Передо мной нет компилятора C # или доступа к вашим данным, но мне это кажется подозрительным. Исключения составляют чрезвычайно медленный - вы часто бьете в блок захвата? Если это так, попробуйте выяснить, что вызывает исключения, и обработайте их, не вызывая исключения - оставьте исключения для обработки редких ситуаций, о которых вы даже не задумывались.

Изменить: Окончательное решение в вопросе редактирования - я не буду повторять здесь. Если у вас есть проблема с производительностью, и у вас есть обработка исключений где-то в цикле, это часто первое, что нужно попытаться устранить. Исключения ужасно медленные - гораздо больше, чем вы думаете. Их лучше хранить при очень необычных обстоятельствах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...