Re: Быстрый Array.Split
От: matumba  
Дата: 10.06.13 14:33
Оценка:
Здравствуйте, Нахлобуч, Вы писали:

Н>Есть массив байтов (размер -- от нескольких байт до нескольких сотен килобайт). Нужно максимально быстро разбить его на куски.

Н>"Наивная" версия -- 20 001 мс. на 2 312 вызовов:
Н>Оптимизация, предложенная Euphoric -- 4 696 мс на 2 312 вызовов:

Не совсем понятно на каких данных вы вызывали. Вот мой вариант (извините, не знаю что за Segment вы использовали, я просто взял byte[]):

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace testSplit
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("prepare all data...");
            var rnd = new Random();
            var testData = new List<byte[]>();
            for (int iter = 0; iter < 2000; iter++) {
                byte[] arr = new byte[rnd.Next(100000, 200000)];
                for (int i = 0; i < arr.Length; i++)
                    arr[i] = (byte)rnd.Next(256);
                testData.Add(arr);
            }
            Console.WriteLine("Test started!");

            var watch = System.Diagnostics.Stopwatch.StartNew();

            for (int i = 0; i < 2000; i++) {
                var res = Split(testData[i], 10);
            }

            watch.Stop();
            Console.WriteLine("Elapsed sec: "+ (double)watch.ElapsedMilliseconds / 1000);
            Console.ReadKey();
        }

        static List<byte[]> Split(byte[] arr, byte divisor)
        {
            int len;
            var res = new List<byte[]>();
            int SegmentStart = -1;
            for (int i = 0; i < arr.Length; i++) {
                if (arr[i] == divisor) {
                    len = i - SegmentStart - 1;
                    if (len == 0)
                        res.Add(null);
                    else{
                        var seg = new byte[len];
                        Array.Copy(arr, SegmentStart+1, seg, 0, len);
                        res.Add(seg);
                    }
                    SegmentStart = i;
                }
            }
            len = arr.Length - SegmentStart - 1;
            if (len > 0) {
                var seg = new byte[len];
                Array.Copy(arr, SegmentStart + 1, seg, 0, len);
                res.Add(seg);
            }
            return res;
        }
    }
}

Т.е. 2000 массивов, каждый по 100-200КБ. Результат:

prepare all data...
Test started!
Elapsed sec: 0.33


Н>Почти в 5 раз быстрее, но все равно ужасно медленно.


Согласен ужасно медленно! (это при том, что я даже не касаюсь всяких fixed/unsafe). Может, я чо в алгоритме напортачил?
Система: Win7 x86, i7, 4GB RAM, .NET 4.5
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.