Как сделать мой файл копии приложений быстрее

Если Вы связываетесь с IEnumerable. Необходимо ли быть в цикле foreach? Если не Вы могли бы объявить переменную незадолго до цикла foreach. Установите его во время цикла. Затем используйте его после цикла (если не пустой)

5
задан tshepang 4 October 2014 в 01:14
поделиться

6 ответов

Одна из распространенных ошибок при использовании потоков - копирование байтов за раз или использование небольшого буфера. Большая часть времени, необходимого для записи данных на диск, тратится на поиск, поэтому использование большего буфера уменьшит среднее время поиска на байт.

Операционные системы записывают файлы на диск в кластерах. Это означает, что когда вы записываете один байт на диск, Windows фактически записывает блок размером от 512 до 64 КБ. Вы можете значительно повысить производительность диска, используя буфер, который является целым числом, кратным 64 КБ.

Кроме того, вы можете получить повышение за счет использования буфера, который кратен размеру страницы базовой памяти вашего процессора. Для машин x86 / x64 это может быть установлено как 4 КБ, так и 4 МБ.

Итак, вы хотите использовать целое число, кратное 4 МБ.

Кроме того, если вы используете асинхронный ввод-вывод, вы можете полностью использовать преимущества большого размера буфера.

class Downloader
{
    const int size = 4096 * 1024;
    ManualResetEvent done = new ManualResetEvent(false);
    Socket socket;
    Stream stream;

    void InternalWrite(IAsyncResult ar)
    {
        var read = socket.EndReceive(ar);
        if (read == size)
            InternalRead();
        stream.Write((byte[])ar.AsyncState, 0, read);
        if (read != size)
            done.Set();
    }

    void InternalRead()
    {
        var buffer = new byte[size];
        socket.BeginReceive(buffer, 0, size, System.Net.Sockets.SocketFlags.None, InternalWrite, buffer);
    }

    public bool Save(Socket socket, Stream stream)
    {
        this.socket = socket;
        this.stream = stream;

        InternalRead();
        return done.WaitOne();
    }
}

bool Save(System.Net.Sockets.Socket socket, string filename)
{
    using (var stream = File.OpenWrite(filename))
    {
        var downloader = new Downloader();
        return downloader.Save(socket, stream);
    }
}
4
ответ дан 14 December 2019 в 01:13
поделиться

Возможно, ваше приложение может выполнять многопоточность для получения файла с помощью несколько потоков, однако пропускная способность ограничена скоростью устройств, передающих контент

2
ответ дан 14 December 2019 в 01:13
поделиться

Самый простой способ - открыть файл в необработанном / двоичном режиме (то есть C говорит не уверен, что эквивалент C #) и читать и записывать очень большие блоки (несколько МБ) за раз.

1
ответ дан 14 December 2019 в 01:13
поделиться

Уловка, которую использует TeraCopy, заключается в том, чтобы сделать чтение и запись асинхронными. Это означает, что один блок данных может быть записан, в то время как другой читается.

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

1
ответ дан 14 December 2019 в 01:13
поделиться

Если вы запустите Process Monitor , вы сможете увидеть размеры блоков, которые использует Windows Explorer или TeraCopy.

В Vista размер блока по умолчанию для локальной сети составляет примерно 2 МБ, что значительно ускоряет копирование файлов по огромному каналу.

1
ответ дан 14 December 2019 в 01:13
поделиться

Зачем изобретать велосипед?

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

0
ответ дан 14 December 2019 в 01:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: