Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
71 / 62 / 33
Регистрация: 03.09.2013
Сообщений: 306
1

Выделить потоку польше памяти

08.01.2014, 16:53. Показов 1355. Ответов 10
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
На килобайтных файлах все замечательно работает, а вот на больших ошибка System.OutOfMemoryException
в потоках CryptoStream и MemoryStream нужно работать с гигабайтами.
Подскажите плиз.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
08.01.2014, 16:53
Ответы с готовыми решениями:

Как выделить произвольную область в памяти для записи
Есть некоторое устройство на PCIe шине. Оно формирует в режиме master транзакции и передает поток...

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

Выделить в памяти 1024 ячейки по 8 байт и вывести их адреса(МИНИ менеджер памяти))
Вот тут появилась такая интересная задача: требуется сделать программу которая управляет 1024...

Выделить под программу максимум памяти
У меня присутствует такая ошибка компилятора: fatal error C1060: компилятору не хватает размера...

10
Эксперт .NET
17688 / 12873 / 3366
Регистрация: 17.09.2011
Сообщений: 21,138
08.01.2014, 17:22 2
На гигабайтовые файлы никакой адресной таблицы не напасешься.
Считывайте по кускам, а не целиком.

Считали кусок, обработали, считали следующий.
И так до конца.
2
71 / 62 / 33
Регистрация: 03.09.2013
Сообщений: 306
08.01.2014, 17:39  [ТС] 3
У меня прога архивирует и шифрует бекапы. По типу Rar.exe, пока её через свою прогу юзаю, но хочется сделать своё, вроде мини трукрипта.
Не в курсе как порезать поток, если ещё и распаралелить то вообше круто.
Подскажите плиз как это можно сделать.
Как то можно силами проца ускорить AES шифрование, тоже интересует.
0
192 / 199 / 82
Регистрация: 11.04.2013
Сообщений: 1,086
09.01.2014, 11:26 4
Driwars, тебе не нужно резать поток , а нужно считывать файл по кускам как уже сказали выше

Чтобы распараллелить нужно каждый кусок файла обрабатывать в отдельном потоке, каждый поток запускать на отдельном ядре , ибо нету смысла запускать больше 1 потока на одноядерном проце.

Размер кусков надо подбирать, так чтобы твое энное количество потоков не съедало всю оперативную память

Добавлено через 2 минуты
Ах да еще забыл добавить , если память не изменяет 32 разрядная винда не выделяет больше 3гб памяти на приложение
0
foo();
886 / 587 / 222
Регистрация: 03.07.2013
Сообщений: 1,549
Записей в блоге: 2
09.01.2014, 12:15 5
Цитата Сообщение от EVG-1980 Посмотреть сообщение
Ах да еще забыл добавить , если память не изменяет 32 разрядная винда не выделяет больше 3гб памяти на приложение
ну на 32 нормальные люди больше 3-х ГБ оперативки не ставят, так как она может работать максимум с 3.25 ГБ по-моему.
0
447 / 305 / 47
Регистрация: 23.01.2013
Сообщений: 661
09.01.2014, 12:28 6
Из всех режимов доступных в Aes (представленных в .Net), единственный режим который возможно поддерживает распараллеливание это режим ECB, и я бы не советовал его использовать. Можно конечно еще разбить файл на блоки и зашифровать каждый отдельно..

В относительно новых процессорах есть инструкции ускоряющие шифрование аппаратно (AES-NI) скорость равна примерно той же с которой вы копируете файл.
0
71 / 62 / 33
Регистрация: 03.09.2013
Сообщений: 306
09.01.2014, 14:14  [ТС] 7
С памятью проблем нет, программе можно вполне выделить под 3-4 гига не проблема, если это ускорит процесс.
Проблему с шифрованием решил так.
C#
1
2
3
cs.Write(data, 0, data.Length/2);
cs.Write(data, data.Length / 2, data.Length - (data.Length / 2));
cs.FlushFinalBlock();
на 300 мегабайтных работает в принципе могу и архив перед шифровкой сделать многотомным.
а вот с дешифровкой проблема
код
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public void Decrypt(byte[] data, string password, string put) 
        {
            using (MemoryStream ms = new MemoryStream(data, false))
            using (RijndaelManaged m = new RijndaelManaged())
            using (SHA256Managed h = new SHA256Managed())
            {
                try
                {
                    m.KeySize = 256;
                    m.BlockSize = 256;
 
                    byte[] hash = new byte[32];
                    ms.Read(hash, 0, 32);
                    byte[] salt = new byte[32];
                    ms.Read(salt, 0, 32);
 
                    Rfc2898DeriveBytes derivedKey = new Rfc2898DeriveBytes(password, salt) { IterationCount = 10000 };
                    m.Key = derivedKey.GetBytes(m.KeySize / 8);
                    m.IV = derivedKey.GetBytes(m.BlockSize / 8);
                    using (var output = new MemoryStream())
                    using (MemoryStream result = new MemoryStream())
                    {
                        using (CryptoStream cs = new CryptoStream(ms, m.CreateDecryptor(), CryptoStreamMode.Read))
                        {
                          //  byte[] buffer = new byte[1024];              
                           // int len;
                           // while ((len = cs.Read(buffer, 0, buffer.Length)) > 0)
                           //     result.Write(buffer, 0, len);
                            var buffer = new byte[1024];
                            var read = cs.Read(buffer, 0, buffer.Length);
                            while (read > 0)
                            {
                                output.Write(buffer, 0, read);
                                read = cs.Read(buffer, 0, buffer.Length);
                            }
                            cs.Flush();
                             
 
                        }
 
                        byte[] final = output.ToArray();
                        if (Convert.ToBase64String(hash) != Convert.ToBase64String(h.ComputeHash(final)))
                            throw new UnauthorizedAccessException();
 
                        File.WriteAllBytes(openFileDialog2.FileName + ".dicr", output.ToArray());
                        MessageBox.Show(" decrypt ok");
                    }
                }
                catch
                {
                    //never leak the exception type...
                    throw new UnauthorizedAccessException();
                }
            }
        }
В коде 2 реализации переноса из потока в поток, но либо обе не работают с большими потоками либо не понимаю в чем проблема. При компиляции срабатывает catch. Проверку на хеш тоже отключал.

П.С.
На отдельном ядре надо попробовать.
или вы имели в виду сделать вроде этого
C#
1
2
new Thread(() => cs.Write(data, 0, data.Length/2)).Start();
new Thread(() => cs.Write(cs.Write(data, data.Length / 2, data.Length - (data.Length / 2))).Start();
Добавлено через 14 минут
TryeCrypt пишет что из моей железки можно выжать 2 гигабита AES в секунду. При экстренном бекапе можно писать и на SSD так что при однократном шифровании можно ускорится солидно.
0
192 / 199 / 82
Регистрация: 11.04.2013
Сообщений: 1,086
09.01.2014, 14:18 8
Цитата Сообщение от Driwars Посмотреть сообщение
или вы имели в виду сделать вроде этого
new Thread(() => cs.Write(data, 0, data.Length/2)).Start();
new Thread(() => cs.Write(cs.Write(data, data.Length / 2, data.Length - (data.Length / 2))).Start();
я имел ввиду это только каждый поток повесить надо на отдельное ядро
1
447 / 305 / 47
Регистрация: 23.01.2013
Сообщений: 661
09.01.2014, 14:33 9
Я тоже как то делал (и доделал) программу шифрующую файлы.
Класс который использовал для симметричных шифров.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
    public sealed class Crypter :
        IDisposable
    {
        #region Constats
        private const int HeadSize = 8;
        #endregion
 
        #region Private Values
        private SymmetricAlgorithm CryptAlgorithm;
        private int BufferCoefficientValue;
        #endregion
 
        #region Properties
        /// <summary>
        /// Получает коэфициент, определяющий размер буффера (в пределах 10-100).
        /// </summary>
        public int BufferCoefficient
        {
            get 
            {
                if (Disposed)
                    throw new ObjectDisposedException("Object Disposed");
 
                return BufferCoefficientValue; 
            }
            set 
            {
                if (Disposed)
                    throw new ObjectDisposedException("Object Disposed");
 
                BufferCoefficientValue = (value >= 10 && value <= 100) ? value : 20; 
            }
        }
        #endregion
 
        #region Constructors
        /// <summary>
        /// Создает экемпляр класса FileCrypter.
        /// </summary>
        public Crypter(SymmetricAlgorithm SymmetricAlg)
        {
            if (SymmetricAlg == null)
                throw new ArgumentNullException();
 
            CryptAlgorithm = SymmetricAlg;
 
            BufferCoefficientValue = 10;
        }
        #endregion
 
        #region Public Methods
        /// <summary>
        /// Генерирует ключ и вектор инициализации.
        /// </summary>
        /// <returns>Ключ.</returns>
        public byte[] GenerateKey()
        {
            if (Disposed)
                throw new ObjectDisposedException("Object Disposed");
 
            CryptAlgorithm.GenerateKey();
            CryptAlgorithm.GenerateIV();
 
            return CryptAlgorithm.Key;
        }
 
        /// <summary>
        /// Производит шифрование потока.
        /// </summary>
        /// <param name="input_file">Поток, который будет зашифрован.</param>
        /// <param name="output_file">Поток, в который будет записан результат шифрования.</param>
        public void EncryptStream(Stream InputStream, Stream OutputStream)
        {
            if (Disposed)
                throw new ObjectDisposedException("Object Disposed");
 
            if (InputStream == null || OutputStream == null)
                throw new ArgumentNullException("One of the arguments (or two) equals null");
 
            ICryptoTransform encryptor = null;
            CryptoStream csEncrypt = null;
 
            try
            {
                int MaxBufferSizeValue = BufferCoefficientValue * 256 * 1024;
 
                encryptor = CryptAlgorithm.CreateEncryptor(CryptAlgorithm.Key, CryptAlgorithm.IV);
                csEncrypt = new CryptoStream(OutputStream, encryptor, CryptoStreamMode.Write);
 
                OutputStream.Write(BitConverter.GetBytes(InputStream.Length), 0, 8);
                OutputStream.Write(CryptAlgorithm.IV, 0, CryptAlgorithm.BlockSize / 8 );
                
                InputStream.Position = 0;
                byte[] DataBuffer = new byte[MaxBufferSizeValue];
 
                while (InputStream.Position < InputStream.Length)
                {
                    int DataSize = (InputStream.Length - InputStream.Position > MaxBufferSizeValue) ? MaxBufferSizeValue : (int)(InputStream.Length - InputStream.Position);
 
                    int WritedDataSize = CalculateDataSize(DataSize, MaxBufferSizeValue);
 
                    InputStream.Read(DataBuffer, 0, DataSize);
                    csEncrypt.Write(DataBuffer, 0, WritedDataSize);
                }     
            }
            finally
            {
                if (encryptor != null)
                    encryptor.Dispose();
            }
        }
 
        /// <summary>
        /// Производит дешифрование потока.
        /// </summary>
        /// <param name="input_file">Поток, который будет дешифрован.</param>
        /// <param name="output_file">Поток, в который будет записан результат дешифрования.</param>
        public void DecryptStream(Stream InputStream, Stream OutputStream, byte[] Key)
        {
            if (Disposed)
                throw new ObjectDisposedException("Object Disposed");
 
            if (InputStream == null || OutputStream == null)
                throw new ArgumentNullException("One of the arguments (or two) equals null");
 
            ICryptoTransform decryptor = null;
            CryptoStream csEncrypt = null;
 
            try
            {
                int MaxBufferSizeValue = BufferCoefficientValue * 256 * 1024;
 
                byte[] OriginFileLengthArray = new byte[8];
                byte[] IV = new byte[CryptAlgorithm.BlockSize / 8];
 
                InputStream.Read(OriginFileLengthArray, 0, 8);
                InputStream.Read(IV, 0, CryptAlgorithm.BlockSize / 8);
 
                long DeltaLength = InputStream.Length - HeadSize - CryptAlgorithm.BlockSize / 8 - BitConverter.ToInt64(OriginFileLengthArray, 0);
 
                decryptor = CryptAlgorithm.CreateDecryptor(Key, IV);
                csEncrypt = new CryptoStream(InputStream, decryptor, CryptoStreamMode.Read);
 
                byte[] DataBuffer = new byte[MaxBufferSizeValue];
 
                while (InputStream.Position < InputStream.Length)
                {
                    int DataSize = (InputStream.Length - InputStream.Position > MaxBufferSizeValue) ? MaxBufferSizeValue : (int)(InputStream.Length - InputStream.Position - DeltaLength);
 
                    csEncrypt.Read(DataBuffer, 0, DataSize);
                    OutputStream.Write(DataBuffer, 0, DataSize);
                }
            }
            finally
            {
                if (decryptor != null)
                    decryptor.Dispose();
            }
        }
        #endregion
 
        #region private methods
        private int CalculateDataSize(int DataSize, int MaxDataSize)
        {
            if (DataSize == MaxDataSize)
                return DataSize;
 
            int BlockSize = CryptAlgorithm.BlockSize / 8;
            DataSize = (int)Math.Ceiling((double)DataSize / BlockSize) * BlockSize;
 
            return DataSize;
        }
        #endregion
 
        #region IDisposable
        private bool Disposed = false;
 
        public void Dispose()
        {
            if (Disposed == true) return;
 
            DisposeManagedResources();
        }
 
        private void DisposeManagedResources()
        {
            CryptAlgorithm.Clear();
 
            Disposed = true;
        }
        #endregion
    }
1
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
09.01.2014, 14:51 10
Anklav, а почему ручное управление, а не юзинги? Разницы офк нет, но симпатичней же..
C#
1
2
            if (InputStream == null || OutputStream == null)
                throw new ArgumentNullException("One of the arguments (or two) equals null");
лучше бы две проверки разных

C#
1
2
            if (Disposed)
                throw new ObjectDisposedException("Object Disposed");
в четырех местах одно и то же, лучше бы метод выделили, тем более, что строковая переменная везде используется, причем потенциально везде она может быть разной...

А так очень симпатичный код. Плюсик)
0
Anklav
09.01.2014, 15:23     Выделить потоку польше памяти
  #11

Не по теме:

Psilon, я это давно писал.

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

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

1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
09.01.2014, 15:23

Как выделить определенное количество памяти?
как выделить определенное количество памяти? (С#) какую структуру лучше использовать? список? стек...

Выделить блок памяти размером 64кБайта
Данная программа выделяет блок памяти размером 64байта. Мне необходимо сделать, чтобы она выделяла...

Как выделить больше 8ГБ памяти в х64 платформе
Добрый день. Подскажите: Как выделить больше 4ГБ памяти? Пробовал malloc - больше 2ГБ не...

Работа программистом в Польше - предложение
Здравствуйте, Помогу (бесплатно) найти работу программиста в Польше в крупных, международных...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru