Может ли этот код иметь узкое место или быть ресурсоемким?

Это код, который будет выполнять 4 потока с 15-минутными интервалами. В последний раз, когда я запускал его, первые 15 минут копировались быстро (20 файлов за 6 минут), но вторые 15 минут - намного медленнее. Это что-то спорадическое, и я хочу убедиться, что, если есть какое-либо узкое место, это ограничивает пропускную способность удаленного сервера.

РЕДАКТИРОВАТЬ: я отслеживаю последний запуск и 15:00 и:45 скопированы менее чем за 8 минут каждый.: 15 не закончил и не имеет:30, и оба начались по крайней мере за 10 минут до:45.

Вот мой код:

static void Main(string[] args)
{

    Timer t0 = new Timer((s) =>
    {
        Class myClass0 = new Class();
        myClass0.DownloadFilesByPeriod(taskRunDateTime, 0, cts0.Token);
        Copy0Done.Set();
    }, null, TimeSpan.FromMinutes(20), TimeSpan.FromMilliseconds(-1));

    Timer t1 = new Timer((s) =>
    {
        Class myClass1 = new Class();
        myClass1.DownloadFilesByPeriod(taskRunDateTime, 1, cts1.Token);
        Copy1Done.Set();
    }, null, TimeSpan.FromMinutes(35), TimeSpan.FromMilliseconds(-1));

    Timer t2 = new Timer((s) =>
    {
        Class myClass2 = new Class();
        myClass2.DownloadFilesByPeriod(taskRunDateTime, 2, cts2.Token);
        Copy2Done.Set();
    }, null, TimeSpan.FromMinutes(50), TimeSpan.FromMilliseconds(-1));

    Timer t3 = new Timer((s) =>
    {
        Class myClass3 = new Class();
        myClass3.DownloadFilesByPeriod(taskRunDateTime, 3, cts3.Token);
        Copy3Done.Set();
    }, null, TimeSpan.FromMinutes(65), TimeSpan.FromMilliseconds(-1));

}

public struct FilesStruct
{
    public string RemoteFilePath;
    public string LocalFilePath;
}

Private void DownloadFilesByPeriod(DateTime TaskRunDateTime, int Period, Object obj)
{

    FilesStruct[] Array = GetAllFiles(TaskRunDateTime, Period);
    //Array has 20 files for the specific period.

    using (Session session = new Session())
    {
        // Connect
        session.Open(sessionOptions);
        TransferOperationResult transferResult;
        foreach (FilesStruct u in Array)
        {
            if (session.FileExists(u.RemoteFilePath)) //File exists remotely
            {
                if (!File.Exists(u.LocalFilePath)) //File does not exist locally
                {
                    transferResult = session.GetFiles(u.RemoteFilePath, u.LocalFilePath);
                    transferResult.Check();
                    foreach (TransferEventArgs transfer in transferResult.Transfers)
                    {
                        //Log that File has been transferred
                    }
                }
                else
                {
                    using (StreamWriter w = File.AppendText(Logger._LogName))
                    {
                        //Log that File exists locally
                    }
                }

            }
            else
            {
                using (StreamWriter w = File.AppendText(Logger._LogName))
                {
                    //Log that File exists remotely
                }
            }
            if (token.IsCancellationRequested)
            {
                break;
            }
        }
    }
}

2 ответа

Решение

Проблема была в клиенте sftp.

Цель консольного приложения состояла в том, чтобы пройтись по списку<> и загрузить файлы. Я попытался с помощью winscp, и, хотя он сделал свою работу, он был очень медленным. Я также проверил sharpSSH, и это было даже медленнее, чем winscp.

В конце концов я использовал ssh.net, который, по крайней мере, в моем конкретном случае, был намного быстрее, чем winscp и sharpssh. Я думаю, что проблема с winscp в том, что не было никакого очевидного способа разъединения после того, как я был сделан. С ssh.net я мог подключаться / отключаться после каждой загрузки файла, что я не мог сделать с winscp.

Что-то здесь не совсем так. Во-первых, вы устанавливаете 4 таймера для параллельной работы. Если вы думаете об этом, в этом нет необходимости. Вам не нужно, чтобы 4 потока работали параллельно все время. Вам просто нужно инициировать задачи через определенные промежутки времени. Так сколько таймеров вам нужно? ОДИН.

Вторая проблема почему TimeSpan.FromMilliseconds(-1)? Какова цель этого? Я не могу понять, почему ты положил это туда, но я бы не стал.

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

Вот что я бы сделал:

  1. Храните файлы, которые вам нужно скачать, в массиве / List<>. Разве вы не можете заметить, что вы делаете то же самое каждый раз? Зачем писать для этого 4 разные версии кода? Это не нужно. Храните элементы в массиве, а затем просто измените индекс в вызове!
  2. Установите таймер с интервалом 5 секунд. Когда он достигнет отметки 20 минут / 35 минут / и т. Д., Создайте новый поток для выполнения задачи. Таким образом, новая задача может начаться, даже если предыдущая не завершена.
  3. Дождитесь завершения всех потоков (прекратить). Когда они это сделают, проверьте, генерируют ли они исключения, и обработайте их / зарегистрируйте их, если это необходимо.
  4. После того, как все сделано, закройте программу.

На шаге 2 у вас есть возможность использовать новый async ключевое слово, если вы используете.NET 4.5. Но это не будет иметь заметного значения, если вы используете потоки вручную.

И почему это так медленно... почему бы вам не проверить состояние системы с помощью диспетчера задач? Процессор высок и работает или пропускная способность сети занята чем-то еще или чем? Вы можете легко сказать ответ самостоятельно оттуда.

Другие вопросы по тегам