Предложения по ускорению резервного копирования кода жесткого диска - PullRequest
0 голосов
/ 23 декабря 2018

У меня есть следующий код резервной копии жесткого диска, который сравнивает время .LastWriteTime () каждого файла перед копированием и работает медленнее, чем я ожидал.Я предполагаю, что он должен работать довольно быстро (порядка нескольких минут), если нет файлов для обновления.Я обнаружил, что 210 ГБ через USB 3.0 все еще занимает более часа.Мне интересно, есть ли какие-нибудь ненужные, отнимающие много времени части моего кода, которые я могу улучшить.Я также думал о том, чтобы поместить каждый вызов directorycopy () в другой поток (по крайней мере, для первого уровня каталогов, но не был уверен, что это плохая практика).

Код в основном заимствован из:

https://docs.microsoft.com/en-us/dotnet/standard/io/how-to-copy-directories

Я внес изменения, чтобы игнорировать папку $ Recycle Bin, регистрировать файлы, которые изменились или возникли проблемы, такие какдлинные имена файлов и продуманность того, как обрабатывались исключения.Но самое главное, я добавил проверку, чтобы увидеть, какой файл является более новым, перед копированием.

    private void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
    {
        // Get the subdirectories for the specified directory.
        DirectoryInfo dir = new DirectoryInfo(sourceDirName);
        if (sourceDirName.Contains("$")) // avoids $Recycle Bin
            return;

        if (!dir.Exists)
        {
            textb_Status.AppendText("Issue with " + dir.FullName + " This folder will not be compied.");
            return;
            //throw new DirectoryNotFoundException(
               // "Source directory does not exist or could not be found: "
              //  + sourceDirName);
        }

        DirectoryInfo[] dirs = dir.GetDirectories();
        // If the destination directory doesn't exist, create it.
        if (!Directory.Exists(destDirName))
        {
            Directory.CreateDirectory(destDirName);
        }

        // Get the files in the directory and copy them to the new location.
        FileInfo[] files = dir.GetFiles();
        foreach (FileInfo file in files)
        {
            string temppath = Path.Combine(destDirName, file.Name);
            try
            {
                file.CopyTo(temppath);
            }
            catch (PathTooLongException)
            {
                textb_Status.AppendText("Filename Too long \n " + file.FullName + "\n");
            }
            catch (IOException ex)
            {
                FileInfo sourcefile = new FileInfo(file.FullName);
                FileInfo destFile = new FileInfo(temppath);
                int CompareValue = sourcefile.LastWriteTime.CompareTo(destFile.LastWriteTime); //<0==> Earlier (old)  =0 ==> same  >0 Later (newer)
                //textb_Status.AppendText("CompareValue: " + CompareValue + "\n");
                if (CompareValue > 0) // Represents newer file
                {
                    file.CopyTo(temppath, true);
                    textb_Status.AppendText("Updated: " + file.FullName + "\n");
                }
            }

            catch (Exception ex2)
            {
                textb_Status.AppendText("Issue with " + file.FullName + "\n");
                textb_Status.AppendText("Error Message \n");
                textb_Status.AppendText(ex2.Message + "\n");
            }

        }

        // If copying subdirectories, copy them and their contents to new location.
        if (copySubDirs)
        {
            foreach (DirectoryInfo subdir in dirs)
            {
                string temppath = Path.Combine(destDirName, subdir.Name);
                DirectoryCopy(subdir.FullName, temppath, copySubDirs);
            }
        }
    }

Я ожидаю, что процесс резервного копирования будет порядка нескольких минут, если есть только несколько файлов дляобновить.

Ответы [ 2 ]

0 голосов
/ 23 декабря 2018

Спасибо, @derpirscher.Для каждого файла я проверял, существует ли он, прежде чем пытаться записать.Таким образом, не исключение не выбрасывается.Привод был проверен примерно за 5 секунд!Я изменил несколько файлов глубоко в исходном каталоге, чтобы убедиться, что они были обнаружены и скопированы.Они были.

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

Мой код ниже.Примечание: я получал ошибки при попытке получить файлы из папки с информацией о томе системы, поэтому я начал с проверки, чтобы убедиться, что sourceDirName не совпадает с этим каталогом.

    private void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
    {
        if (sourceDirName.Contains("System Volume Information"))
            return;
        //textb_Status.AppendText("Current Directory: " + sourceDirName +"\n");
        DirectoryInfo[] dirs = null;
        // Get the subdirectories for the specified directory.
        DirectoryInfo dir = new DirectoryInfo(sourceDirName);
        if (sourceDirName.Contains("$")) // avoids $Recycle Bin
            return;

        if (!dir.Exists)
        {
            textb_Status.AppendText("Issue with " + dir.FullName + " This folder will not be compied.");
            return;
            //throw new DirectoryNotFoundException(
            // "Source directory does not exist or could not be found: "
            //  + sourceDirName);
        }

        {

            dirs = dir.GetDirectories();

            // If the destination directory doesn't exist, create it.
            if (!Directory.Exists(destDirName))
            {
                Directory.CreateDirectory(destDirName);
            }

            // Get the files in the directory and copy them to the new location.
            FileInfo[] files = dir.GetFiles();
            foreach (FileInfo file in files)
            {
                string temppath = Path.Combine(destDirName, file.Name);
                try
                {
                    if (File.Exists(temppath)) // Check for newer
                    {
                        FileInfo sourcefile = new FileInfo(file.FullName);
                        FileInfo destFile = new FileInfo(temppath);
                        int CompareValue = sourcefile.LastWriteTime.CompareTo(destFile.LastWriteTime); //<0==> Earlier (old)  =0 ==> same  >0 Later (newer)
                                                                                                       //textb_Status.AppendText("CompareValue: " + CompareValue + "\n");
                        if (CompareValue > 0) // Represents newer file
                        {
                            file.CopyTo(temppath, true);
                            textb_Status.AppendText("********** Updated: " + file.FullName + "********* \n");
                        }
                    }
                    else
                    {
                        file.CopyTo(temppath);
                    }

                }
                catch (PathTooLongException)
                {
                    textb_Status.AppendText("Filename Too long \r\n\n " + file.FullName + "\r\n\n");
                }
                catch (IOException ex)
                {
                    FileInfo sourcefile = new FileInfo(file.FullName);
                    FileInfo destFile = new FileInfo(temppath);
                    int CompareValue = sourcefile.LastWriteTime.CompareTo(destFile.LastWriteTime); //<0==> Earlier (old)  =0 ==> same  >0 Later (newer)
                                                                                                   //textb_Status.AppendText("CompareValue: " + CompareValue + "\n");
                    if (CompareValue > 0) // Represents newer file
                    {
                        file.CopyTo(temppath, true);
                        textb_Status.AppendText("Updated: " + file.FullName + "\n");
                    }
                }

                catch (Exception ex2)
                {
                    textb_Status.AppendText("Issue with " + file.FullName + "\n");
                    textb_Status.AppendText("Error Message \n");
                    textb_Status.AppendText(ex2.Message + "\n\n");
                }
            }


            // If copying subdirectories, copy them and their contents to new location.
            if (copySubDirs)
            {
                foreach (DirectoryInfo subdir in dirs)
                {
                    string temppath = Path.Combine(destDirName, subdir.Name);
                    DirectoryCopy(subdir.FullName, temppath, copySubDirs);
                }

            }
        }
    }
0 голосов
/ 23 декабря 2018

Я не думаю, что это объем данных, который замедляет процесс, но количество файлов.Первоначальный доступ к файлу (проверьте, существует ли он, получите статистику) довольно дорог, независимо от размера файла.Кроме того, многие люди считают, что использование исключений для плохого стиля потока управления и создание и отлов исключений могут быть довольно дорогими.И из вашего варианта использования (то есть большинство файлов не изменились) выдается MANY исключений.

Кроме того, в зависимости от ваших дисков (SSD или HDD), многопоточное чтение и запись может бытьочень плохая идея и замедление всего процесса.

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

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