Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > C# (си шарп)
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 06.09.2013, 11:28   #1
WorldMaster
Старожил
 
Аватар для WorldMaster
 
Регистрация: 25.08.2011
Сообщений: 2,841
По умолчанию Нужна оптимизация

Здравствуйте, есть необходимость разработать аналитическую систему которая работает с большим количеством данных.
Большая часть системы разработана и теперь встает вопрос оптимизации скорости.
И вот что получается:
Стандартный контейнер List<> не устраивает потому что метод ToArray работает очень долго. Написал свой контейнер упрощенный - получил другую проблему. Заполнение контейнера очень долгое.

Подскажите пожалуйста как сделать свой класс-контейнер чтобы добиться максимум производительности?

Мой класс:
Код:
public class PriceCollection
    {

        double[] _list;

        public PriceCollection()
        {
            _list = new double[0];
        }

        /// <summary>
        /// Добавляет переменную в конец списка
        /// </summary>
        /// <param name="value"></param>
        public void Add(double value)
        {
            if (_list.Length == 0)
            {
                _list = new double[1] { value };
                return;
            }

            double[] tmp = new double[_list.Length + 1];
            Array.Copy(_list, tmp, _list.Length);
            tmp[_list.Length] = value;
            _list = tmp;
        }

        /// <summary>
        /// Удаляет переменную по указанному индексу
        /// </summary>
        /// <param name="Index"></param>
        public void Remove(int Index)
        {
        }

        /// <summary>
        /// Получает список всех переменных
        /// </summary>
        /// <returns></returns>
        public double[] ToArray()
        {
            return _list;
        }
    }

Результаты тестирования в прикрепленном изображении.
Хочется чтобы коллекция обладала скоростью добавления как у List а выборкой массива как у меня
Изображения
Тип файла: png test.png (4.1 Кб, 29 просмотров)
Skype - wmaster_s E-Mail - WorldMasters@gmail.com
Работаем по 3 критериям - быстро, качественно, недорого. Заказчик выбирает любые два.
WorldMaster вне форума Ответить с цитированием
Старый 06.09.2013, 12:28   #2
_-Re@l-_
C++, Java
Старожил
 
Аватар для _-Re@l-_
 
Регистрация: 10.04.2010
Сообщений: 2,665
По умолчанию

Как по-моему, производительность вашего Add упирается в Array.Copy - нехорошо. Попробуйте копировать вручную, а не существующими методами.
P.S. Могу ошибаться - пробуйте.
_-Re@l-_ вне форума Ответить с цитированием
Старый 06.09.2013, 12:49   #3
WorldMaster
Старожил
 
Аватар для WorldMaster
 
Регистрация: 25.08.2011
Сообщений: 2,841
По умолчанию

Цитата:
Сообщение от _-Re@l-_ Посмотреть сообщение
Как по-моему, производительность вашего Add упирается в Array.Copy - нехорошо. Попробуйте копировать вручную, а не существующими методами.
P.S. Могу ошибаться - пробуйте.
Все перепробовал .. и Marshal и for() - Array.Copy это самое быстрое
Skype - wmaster_s E-Mail - WorldMasters@gmail.com
Работаем по 3 критериям - быстро, качественно, недорого. Заказчик выбирает любые два.
WorldMaster вне форума Ответить с цитированием
Старый 06.09.2013, 13:49   #4
Luuzuk
Форумчанин
 
Аватар для Luuzuk
 
Регистрация: 18.01.2012
Сообщений: 975
По умолчанию

Цитата:
Array.Copy это самое быстрое
А с Buffer.BlockCopy не сравнивали?


-----------

Еще как вариант - не увеличивать количество элементов массива каждый раз при добавлении, а удваивать размер массива при недостатке места. Такая идея заложена, например, в StringBuilder

Код:
    public class ArrayableCollection<T>
    {
        // массив данных
        private T[] _data;
        // длина массива
        private Int32 _length;
        // количество элементов в массиве (меньше либо равно длине)
        private Int32 _count;

        /// <summary>
        /// Конструктор
        /// </summary>
        /// <param name="initialLength">Начальное кол-во элементов в массиве</param>
        public ArrayableCollection(int initialLength)
        {
            if (initialLength <=0)
                 throw new Exception("Длина массива должна быть больше нуля!");
            _length = initialLength;
            _data = new T[initialLength];
            _count = 0;
        }

        /// <summary>
        /// Добавляет значение в массив
        /// </summary>
        /// <param name="value">значение</param>
        public void Add(T value)
        {
            // Если элемент не помещается в массив - увеличиваем массив в 2 раза
            if (_count >= (_length - 1))
            {
                if (_length == Int32.MaxValue)
                    throw new Exception("Массив слишком велик :(");

                Int32 newLength;
                if (_length >= Int32.MaxValue / 2)
                    newLength = Int32.MaxValue;
                else newLength = _length * 2;

                T[] newData = new T[newLength];
                Buffer.BlockCopy(_data, 0, newData, 0, _count);
                _data = newData;
                _length = newLength;
            }
            _data[_count++] = value;
        }

        public T[] ToArray()
        {
            return _data;
        }
    }
P.S. класс ниразу не потокобезопасен) впрочем как и ваш
Благодарить в репутацию. Проклинать — туда же

Последний раз редактировалось Luuzuk; 06.09.2013 в 14:08.
Luuzuk вне форума Ответить с цитированием
Старый 06.09.2013, 14:13   #5
WorldMaster
Старожил
 
Аватар для WorldMaster
 
Регистрация: 25.08.2011
Сообщений: 2,841
По умолчанию

Вот результат с вашим примером ....
Как то странно время показывается ... Если первый проход то время побольше ... второй проход поменьше ...
ну в целом вот такой вот результат получился:

Потокобезопасность не очень нужна поскольку к данному массиву не будет доступа из других потоков.

Все равно штатный выигрывает почему то ..
Изображения
Тип файла: png test.png (10.6 Кб, 17 просмотров)
Skype - wmaster_s E-Mail - WorldMasters@gmail.com
Работаем по 3 критериям - быстро, качественно, недорого. Заказчик выбирает любые два.

Последний раз редактировалось WorldMaster; 06.09.2013 в 14:48.
WorldMaster вне форума Ответить с цитированием
Старый 06.09.2013, 14:51   #6
Luuzuk
Форумчанин
 
Аватар для Luuzuk
 
Регистрация: 18.01.2012
Сообщений: 975
По умолчанию

Цитата:
Как то странно время показывается
http://habrahabr.ru/post/191636/
Благодарить в репутацию. Проклинать — туда же
Luuzuk вне форума Ответить с цитированием
Старый 06.09.2013, 14:57   #7
WorldMaster
Старожил
 
Аватар для WorldMaster
 
Регистрация: 25.08.2011
Сообщений: 2,841
По умолчанию

Цитата:
Сообщение от Luuzuk Посмотреть сообщение
И еще особенность .. на выходе ToArray() мне нужен массив не содержащий пустых значений. А ваш класс вернет мне несколько пустых значений в конце ... Как с этим бороться?
Skype - wmaster_s E-Mail - WorldMasters@gmail.com
Работаем по 3 критериям - быстро, качественно, недорого. Заказчик выбирает любые два.
WorldMaster вне форума Ответить с цитированием
Старый 06.09.2013, 15:00   #8
Luuzuk
Форумчанин
 
Аватар для Luuzuk
 
Регистрация: 18.01.2012
Сообщений: 975
По умолчанию

Вернуть новый массив, обрезанный по значению поля _count с помощью того же самого Buffer.BlockCopy. И окончательно добить этим производительность
Благодарить в репутацию. Проклинать — туда же
Luuzuk вне форума Ответить с цитированием
Старый 06.09.2013, 15:03   #9
WorldMaster
Старожил
 
Аватар для WorldMaster
 
Регистрация: 25.08.2011
Сообщений: 2,841
По умолчанию

Цитата:
Сообщение от Luuzuk Посмотреть сообщение
Вернуть новый массив, обрезанный по значению поля _count с помощью того же самого Buffer.BlockCopy. И окончательно добить этим производительность
Так выход то есть какой нибудь?? Причем проблема то в методе ToArray(). В целом класс List очень устраивает ... но я как глянул на задержки ...

Неужели нету способа максимально быстро скопировать данные?
Пусть даже из List но в массив.
Skype - wmaster_s E-Mail - WorldMasters@gmail.com
Работаем по 3 критериям - быстро, качественно, недорого. Заказчик выбирает любые два.
WorldMaster вне форума Ответить с цитированием
Старый 06.09.2013, 15:23   #10
Luuzuk
Форумчанин
 
Аватар для Luuzuk
 
Регистрация: 18.01.2012
Сообщений: 975
По умолчанию

Чем массив отличается от списка? Тем, что массив занимает один большой непрерывный кусок в памяти (список может быть разбросан по оперативке как угодно). Этим и объясняются сложности в переходе от списка к массиву. Отсюда и задержки. Если для вас это настолько критично - напишите хранилище этих данных на с/с++ и работайте с неуправляемым кодом
Благодарить в репутацию. Проклинать — туда же
Luuzuk вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Нужна оптимизация кода casusbeli Общие вопросы C/C++ 5 11.03.2011 22:42
оптимизация Terrance! Помощь студентам 8 24.09.2010 10:58
Очень нужна оптимизация процесса kinogruppa Microsoft Office Excel 19 06.09.2009 15:43
Нужна оптимизация дельфинского кода JTG Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 6 29.05.2008 14:53