/// <summary> /// Сжатие и генерация задач записи работает в том количестве потоков, сколько процессоров доступно системе, /// давая распределённую и почти 100% нагрузку на все ядра процессора /// </summary> private void CompressingThread() { try { while (_lastZippedBlock < _totalCount && !_cancellationToken.IsCancellationRequested) { // Защита от переполнения памяти if (_writeTaskPool.TaskCount() > _maxTasks) { Thread.Sleep(_sleep); continue; } ITaskInfo taskInfo = _compressTaskPool.NextTask(); if (taskInfo == null) { Thread.Sleep(_sleep); continue; } _writeTaskPool.AddTask(_taskFactory.CreateWriteTaskInfo(taskInfo.GetId(), taskInfo.Execute(null) as byte[])); _lastZippedBlock++; } #if DEBUG Console.WriteLine("End of compressing"); #endif } catch (Exception exc) { Console.WriteLine("Error on file compressing"); #if DEBUG Console.WriteLine(exc); #endif } }
/// <summary> /// Метод для потока чтения. Чтение и генерация задач сжатия происходит в 1 поток, что даёт максимальную нагрузку на диск /// </summary> /// <param name="obj"> /// Дескриптор файла для записи /// </param> private void ReadingThread(object obj) { FileDescriptor read_file = obj as FileDescriptor; try { using (FileStream _fileToBeCompressed = read_file.GetDescription.OpenRead()) { Int64 lastBlock = 0; while (lastBlock < _totalCount && !_cancellationToken.IsCancellationRequested) { // Защита от переполнения памяти if (_compressTaskPool.TaskCount() > _maxTasks * _cores) { Thread.Sleep(1); continue; } ITaskInfo taskInfo = null; taskInfo = _readTaskPool.NextTask(); if (taskInfo == null) { Thread.Sleep(_sleep); continue; } _compressTaskPool.AddTask(_taskFactory.CreateProcessTaskInfo(lastBlock++, (taskInfo.Execute(_fileToBeCompressed) as byte[]))); } #if DEBUG Console.WriteLine("End of reading"); #endif } } catch (Exception exc) { Console.WriteLine("Error on file reading"); #if DEBUG Console.WriteLine(exc); #endif } }
/// <summary> /// Метод для потока генерации задач для чтения. Необходим для более гибкого распределения нагрузки на поток чтения файла /// </summary> private void GeneratorThread() { try { int wait = Convert.ToInt32(Math.Pow(_cores, 1.5)); for (int i = 0; i < _batchCount; ++i) { // Защита от переполнения памяти // Без этого произойдёт переполнение // Нагенерируется больше задач, чем возможно обработать за промежуток времени, проверено на SSD // TODO: Возможно подобрать более оптимальные значения maxTasks за счёт градиентного спуска if (_readTaskPool.TaskCount() > _maxTasks) { --i; Thread.Sleep(_sleep); continue; } _readTaskPool.AddTask(_taskFactory.CreateReadTaskInfo(i, _readBlockSize)); } // Обработка последнего куска if (_batchCount < _totalCount) { _readTaskPool.AddTask(_taskFactory.CreateReadTaskInfo(_batchCount, _lastPiece)); } #if DEBUG Console.WriteLine("End of generating tasksInfos"); #endif } catch (Exception exc) { Console.WriteLine("Error on generating reading tasks"); #if DEBUG Console.WriteLine(exc); #endif } }
/// <summary> /// Метод для потока чтения. Чтение и генерация задач сжатия происходит в 1 поток, что даёт максимальную нагрузку на диск /// </summary> /// <param name="obj"> /// Дескриптор файла для чтения /// </param> private void ReadingThread(object obj) { FileDescriptor readFile = obj as FileDescriptor; _fileLength = readFile.GetDescription.Length; try { using (FileStream fileToBeDecompressed = readFile.GetDescription.OpenRead()) { // Читать блоки архива, пока не закончится файл while (fileToBeDecompressed.Position < _fileLength && !_cancellationToken.IsCancellationRequested) { _position = fileToBeDecompressed.Position; // Защита от переполнения памяти if (_compressTaskPool.TaskCount() > _maxTasks * _cores) { Thread.Sleep(_sleep); continue; } ITaskInfo task = _taskFactory.CreateReadTaskInfo(_batchCount, 0); _compressTaskPool.AddTask(_taskFactory.CreateProcessTaskInfo(_batchCount++, task.Execute(fileToBeDecompressed) as byte[])); } _isReading = false; #if DEBUG Console.WriteLine("End of reading"); #endif } } catch (Exception exc) { Console.WriteLine("Error on file reading"); #if DEBUG Console.WriteLine(exc); #endif } }