Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.75/16: Рейтинг темы: голосов - 16, средняя оценка - 4.75
Труд вопреки насмешкам
 Аватар для Etyuhibosecyu
363 / 181 / 41
Регистрация: 13.07.2017
Сообщений: 4,845
Записей в блоге: 14
.NET 8

Где в этом коде тормоза?

05.07.2024, 00:11. Показов 3976. Ответов 47
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Благодаря обдуманному ответу sau о логарифмах, тормозов в Лемпеле-Зиве стало значительно меньше. Но теперь на очереди этот код (старая ссылка), где нет логарифмов, а тормоза существенно серьёзнее. Причем в отличие от предыдущей темы, тут трудно даже выделить ключевую функцию. Разумеется, это не PrepareFields(), которая вызывается один раз, а вот Escape(), ProcessFrequency() и Increase() занимают время, пропорциональное их длине. Интересно, кто в этот раз решится помочь?

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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
namespace AresGlobalMethods;
 
/// <summary>
/// Класс, выполняющий сжатие методом PPM (Prediction by partial matching - предсказание по частичному совпадению, подробнее
/// см. <a href="https://ru.wikipedia.org/wiki/Алгоритм_сжатия_PPM">здесь</a>).<br/>
/// Использование: <tt>new PPM(input, tn).Encode(words);</tt>.<br/>
/// <tt>words</tt> равен true, если это PPM для слов, и false в остальных случаях.
/// </summary>
/// <param name="Input">Входной поток для сжатия.</param>
/// <param name="TN">Номер потока (см. <see cref="Threads"/>).</param>
/// <remarks>
/// Как привести входной поток к виду, приемлемому для этого класса, см. в проекте AresFLib в файле RootMethodsF.cs
/// в методах PreEncode() и PPMEncode().
/// </remarks>
public record class PPM(List<NList<ShortIntervalList>> Input, int TN) : IDisposable
{
    private ArithmeticEncoder[] ar = default!;
    private readonly List<NList<Interval>> outputIntervals = [];
    private int doubleListsCompleted = 0, BlocksCount = 0;
    private readonly object lockObj = new();
 
    /// <summary>Основной метод класса. Инструкция по применению - см. в описании класса.</summary>
    public virtual void Dispose()
    {
        ar?.ForEach(x => x?.Dispose());
        outputIntervals?.ForEach(x => x?.Dispose());
        outputIntervals?.Dispose();
        GC.SuppressFinalize(this);
    }
 
    /// <summary>
    /// Основной метод класса. Инструкция по применению - см. в описании класса.
    /// </summary>
    public NList<byte> Encode(bool words = true)
    {
        if (!(Input.Length >= 3 && Input.GetSlice(..3).All(x => x.Length >= 4) || words))
            throw new EncoderFallbackException();
        BlocksCount = words ? Input.Length : WordsListActualParts;
        Current[TN] = 0;
        CurrentMaximum[TN] = ProgressBarStep * (BlocksCount - 1);
        ar = RedStarLinq.FillArray(words ? Input.Length : 1, _ => new ArithmeticEncoder());
        outputIntervals.Replace(RedStarLinq.FillArray(BlocksCount, _ => new NList<Interval>()));
        if (words)
            Parallel.For(0, BlocksCount, i => EncodeBlock(i, i, i == WordsListActualParts - 1, TN));
        else if (Threads.Count(x => x != null && x.ThreadState is System.Threading.ThreadState.Running
            or System.Threading.ThreadState.Background) == 1 && BlocksCount <= ProgressBarGroups)
            Parallel.For(0, BlocksCount, i => EncodeBlock(i, 1, true, i));
        else
            for (var i = 0; i < BlocksCount; i++)
                EncodeBlock(i, 1, true, TN);
        return words ? ToBytesWords() : ToBytesNoWords();
    }
 
    private void EncodeBlock(int LocalIndex, int BlockIndex, bool LastBlock, int TN)
    {
        if (!new Encoder(Input[LocalIndex], outputIntervals[LocalIndex], BlockIndex, LastBlock, TN).Encode())
            throw new EncoderFallbackException();
        lock (lockObj)
        {
            doubleListsCompleted++;
            if (doubleListsCompleted != BlocksCount)
                Current[TN] += ProgressBarStep;
        }
    }
 
    private NList<byte> ToBytesWords()
    {
        outputIntervals.ForEach(l => l.ForEach(x => ar[0].WritePart(x)));
        Input.GetSlice(BlocksCount).ForEach(dl => dl.ForEach(l => l.ForEach(x => ar[0].WritePart(x))));
        ar[0].WriteEqual(1234567890, 4294967295);
        return ar[0];
    }
 
    private NList<byte> ToBytesNoWords()
    {
        Parallel.For(0, BlocksCount, i =>
        {
            outputIntervals[i].ForEach(x => ar[i].WritePart(x));
            ar[i].WriteEqual(1234567890, 4294967295);
        });
        NList<byte> result = [(byte)(BlocksCount - 1)];
        for (var i = 0; i < BlocksCount; i++)
        {
            NList<byte> bytes = ar[i];
            if (i != BlocksCount - 1)
            {
                result.Add((byte)(bytes.Length >> (BitsPerByte << 1)));
                result.Add(unchecked((byte)(bytes.Length >> BitsPerByte)));
                result.Add(unchecked((byte)bytes.Length));
            }
            result.AddRange(bytes);
            bytes.Dispose();
        }
        return result;
    }
}
 
file record class Encoder(NList<ShortIntervalList> Input, NList<Interval> Result, int BlockIndex, bool LastBlock, int TN)
    : IDisposable
{
    private const int LZDictionarySize = 8388607;
    private int startPos = 1;
    private uint inputBase, item;
    private ShortIntervalList appliedMethods = default!;
    private readonly SumSet<uint> globalFreqTable = [], newItemsFreqTable = [];
    private const int maxContextDepth = 12;
    private readonly LimitedQueue<NList<Interval>> preOutputBuffer = new(maxContextDepth);
    private G.IEqualityComparer<NList<uint>> comparer = default!;
    private FastDelHashSet<NList<uint>> contextSet = default!;
    private HashList<int> lzBuffer = default!;
    private readonly List<SumSet<uint>> contextFreqTableByLevel = [];
    private readonly SumSet<uint> lzPositions = [];
    private readonly SumList lzLengths = [];
    private uint lzCount, notLZCount, spaceCount, notSpaceCount;
    private readonly LimitedQueue<bool> spaceBuffer = new(maxContextDepth);
    private readonly LimitedQueue<uint> newItemsBuffer = new(maxContextDepth);
    private readonly NList<uint> currentContext = new(maxContextDepth), reservedContext = new(maxContextDepth);
    private readonly SumSet<uint> freqTable = [], excludingFreqTable = [];
    private SumSet<uint> outputFreqTable = [];
    private readonly NList<Interval> intervalsForBuffer = [];
    private int lzBufferIndex, lzBlockEnd = 0;
 
    public virtual void Dispose()
    {
        globalFreqTable?.Dispose();
        newItemsFreqTable?.Dispose();
        preOutputBuffer?.ForEach(output => output?.Dispose());
        preOutputBuffer?.Dispose();
        contextSet?.ForEach(output => output?.Dispose());
        contextSet?.Dispose();
        lzBuffer?.Dispose();
        contextFreqTableByLevel?.ForEach(output => output?.Dispose());
        contextFreqTableByLevel?.Dispose();
        lzPositions?.Dispose();
        lzLengths?.Dispose();
        spaceBuffer?.Dispose();
        newItemsBuffer?.Dispose();
        currentContext?.Dispose();
        reservedContext?.Dispose();
        freqTable?.Dispose();
        excludingFreqTable?.Dispose();
        outputFreqTable?.Dispose();
        intervalsForBuffer?.Dispose();
        GC.SuppressFinalize(this);
    }
 
    public bool Encode()
    {
        Initialize();
        for (var i = startPos; i < Input.Length; i++, _ = LastBlock ? Status[TN] = i : 0)
        {
            item = Input[i][0].Lower;
            FormContexts(i);
            intervalsForBuffer.Clear();
            ProcessContexts(i);
            var contextDepth = reservedContext.Length;
            lzBufferIndex = -1;
            Increase();
            if (contextDepth == maxContextDepth)
                lzBuffer.SetOrAdd((i - startPos - maxContextDepth) % LZDictionarySize, lzBufferIndex);
        }
        while (preOutputBuffer.Length != 0)
            preOutputBuffer.Dequeue().ForEach(x => Result.Add(new(x.Lower, x.Length, x.Base)));
        return true;
    }
 
    private void Initialize()
    {
        EnsureValidInput();
        SetupStatus();
        WriteHeader();
        PrepareFields();
    }
 
    private void EnsureValidInput()
    {
        if (Input.Length < 4)
            throw new EncoderFallbackException();
        appliedMethods = Input[0];
        startPos = appliedMethods.Length >= 1 && appliedMethods[0] == LengthsApplied ? (int)appliedMethods[1].Base + 1 : 1;
        if (Input.Length <= startPos)
            throw new EncoderFallbackException();
        var firstActual = Input[startPos];
        if (firstActual.Length is not 1 and not 2 || firstActual[0].Length != 1)
            throw new EncoderFallbackException();
        inputBase = firstActual[0].Base;
        if (inputBase < 2 || firstActual[^1].Length != 1)
            throw new EncoderFallbackException();
        var restOfInput = Input.GetRange(startPos + 1);
        if (!restOfInput.All(x => x.Length == Input[startPos].Length && x[0].Length == 1
            && x[0].Base == inputBase && (x.Length == 1 || x[1].Length == 1 && x[1].Base == Input[startPos][1].Base)))
            throw new EncoderFallbackException();
    }
 
    private void SetupStatus()
    {
        if (LastBlock)
        {
            Status[TN] = 0;
            StatusMaximum[TN] = Input.Length - startPos;
        }
    }
 
    private void WriteHeader()
    {
        for (var i = 0; i < appliedMethods.Length; i++)
            Result.Add(new(appliedMethods[i].Lower, appliedMethods[i].Length, appliedMethods[i].Base));
        if (BlockIndex == 0)
        {
            Result.Add(new(Input[1][0].Lower, 1, 3));
            Result.WriteNumber(inputBase);
            for (var i = 2; i < startPos; i++)
                for (var j = 0; j < Input[i].Length; j++)
                    Result.Add(new(Input[i][j].Lower, Input[i][j].Length, Input[i][j].Base));
        }
        Result.WriteNumber((uint)(Input.Length - startPos));
        Result.WriteNumber((uint)Min(LZDictionarySize, FragmentLength));
    }
 
    private void PrepareFields()
    {
        globalFreqTable.Clear();
        if (BlockIndex == 2)
            newItemsFreqTable.Clear();
        else
            newItemsFreqTable.Replace(new Chain((int)inputBase).Convert(x => ((uint)x, 1)));
        preOutputBuffer.Clear();
        comparer = BlockIndex == 2 ? new NListEComparer<uint>() : new EComparer<NList<uint>>((x, y) => x.Equals(y),
            x => unchecked(x.Progression(17 * 23 + x.Length, (x, y) => x * 23 + y.GetHashCode())));
        contextSet = new(comparer);
        lzBuffer = [];
        contextFreqTableByLevel.Clear();
        lzPositions.Replace([(uint.MaxValue, 100)]);
        lzLengths.Replace([1]);
        lzCount = notLZCount = spaceCount = notSpaceCount = 1;
        spaceBuffer.Clear();
        newItemsBuffer.Clear();
        currentContext.Clear();
        reservedContext.Clear();
        freqTable.Clear();
        excludingFreqTable.Clear();
        outputFreqTable.Clear();
        intervalsForBuffer.Clear();
        lzBlockEnd = 0;
    }
 
    private void FormContexts(int itemIndex)
    {
        for (int i = Max(startPos, itemIndex - maxContextDepth), index = 0; i < itemIndex; i++, index++)
            currentContext.SetOrAdd(index, Input[i][0].Lower);
        currentContext.Reverse();
        reservedContext.Replace(currentContext);
    }
 
    private void ProcessContexts(int itemIndex)
    {
        if (itemIndex < lzBlockEnd)
            return;
        if (currentContext.Length == maxContextDepth && itemIndex >= (maxContextDepth << 1) + startPos
            && TryProcessLZ(currentContext, itemIndex) && itemIndex < lzBlockEnd)
            return;
        freqTable.Clear();
        excludingFreqTable.Clear();
        SkipTrivialContexts();
        var prediction = GetPrediction();
        UpdateFreqTables();
        ProcessFrequency(prediction);
        ProcessBuffers(itemIndex);
    }
 
    private void SkipTrivialContexts()
    {
        while (currentContext.Length > 0 && !contextSet.TryGetIndexOf(currentContext, out _))
            currentContext.RemoveAt(^1);
    }
 
    private PredictionEntry GetPrediction()
    {
        long sum = 0;
        var frequency = 0;
        while (true)
        {
            if (currentContext.Length <= 0 || !contextSet.TryGetIndexOf(currentContext, out var index))
                break;
            freqTable.Replace(contextFreqTableByLevel[index]);
            freqTable.ExceptWith(excludingFreqTable);
            if ((sum = freqTable.GetLeftValuesSum(item, out frequency)) < 0 || frequency != 0)
                break;
            if (freqTable.Length != 0)
                intervalsForBuffer.Add(new((uint)freqTable.ValuesSum, (uint)freqTable.Length * 100, GetFreqTableBase(freqTable)));
            currentContext.RemoveAt(^1);
            excludingFreqTable.UnionWith(freqTable);
        }
        return new(sum, frequency);
    }
 
    private void UpdateFreqTables()
    {
        if (freqTable.Length == 0 || currentContext.Length == 0)
        {
            foreach (var (Key, _) in excludingFreqTable)
            {
                if (globalFreqTable.TryGetValue(Key, out var newValue))
                    excludingFreqTable.Update(Key, newValue);
                else
                    throw new EncoderFallbackException();
            }
            outputFreqTable = globalFreqTable.ExceptWith(excludingFreqTable);
        }
        else
            outputFreqTable = freqTable;
    }
 
    private void ProcessFrequency(PredictionEntry prediction)
    {
        var (sum, frequency) = prediction;
        if (frequency == 0)
            sum = outputFreqTable.GetLeftValuesSum(item, out frequency);
        if (frequency == 0)
            ProcessNewItem();
        else
        {
            intervalsForBuffer.Add(new(0, (uint)outputFreqTable.ValuesSum, GetFreqTableBase(outputFreqTable)));
            intervalsForBuffer.Add(new((uint)sum, (uint)frequency, (uint)outputFreqTable.ValuesSum));
            newItemsBuffer.Enqueue(uint.MaxValue);
        }
        if (freqTable.Length == 0 || currentContext.Length == 0)
            globalFreqTable.UnionWith(excludingFreqTable);
    }
 
    private void ProcessNewItem()
    {
        if (outputFreqTable.Length != 0)
        {
            var valuesSum = (uint)outputFreqTable.ValuesSum;
            var length = (uint)outputFreqTable.Length;
            Interval header = new(valuesSum, length * 100, GetFreqTableBase(outputFreqTable));
            intervalsForBuffer.Add(header);
        }
        if (BlockIndex != 2)
        {
            intervalsForBuffer.Add(new((uint)newItemsFreqTable.IndexOf(item), (uint)newItemsFreqTable.Length));
            newItemsFreqTable.RemoveValue(item);
            newItemsBuffer.Enqueue(item);
        }
    }
 
    private void ProcessBuffers(int itemIndex)
    {
        var isSpace = false;
        if (BlockIndex == 2)
        {
            isSpace = Input[itemIndex][1].Lower != 0;
            uint bufferSpaces = (uint)spaceBuffer.Count(true), bufferNotSpaces = (uint)spaceBuffer.Count(false);
            uint spaceLower, spaceFrequency;
            if (isSpace)
            {
                spaceLower = notSpaceCount + bufferNotSpaces;
                spaceFrequency = spaceCount + bufferSpaces;
            }
            else
            {
                spaceLower = 0;
                spaceFrequency = notSpaceCount + bufferNotSpaces;
            }
            intervalsForBuffer.Add(new(spaceLower, spaceFrequency, notSpaceCount + spaceCount + (uint)spaceBuffer.Length));
        }
        else
            for (var i = 1; i < Input[itemIndex].Length; i++)
                intervalsForBuffer.Add(new(Input[itemIndex][i].Lower, Input[itemIndex][i].Length, Input[itemIndex][i].Base));
        if (preOutputBuffer.IsFull)
            preOutputBuffer.Dequeue().ForEach(x => Result.Add(new(x.Lower, x.Length, x.Base)));
        preOutputBuffer.Enqueue(intervalsForBuffer.Copy());
        ProcessSpaceCount();
        spaceBuffer.Enqueue(isSpace);
    }
 
    private void ProcessSpaceCount()
    {
        if (BlockIndex == 2 && spaceBuffer.IsFull)
        {
            var space2 = spaceBuffer.Dequeue();
            if (space2)
                spaceCount++;
            else
                notSpaceCount++;
        }
    }
 
    private bool TryProcessLZ(NList<uint> context, int currentPos)
    {
        if (!preOutputBuffer.IsFull)
            return false;
        LZEntry bestValue = new(-1, -1);
        var contextIndex = contextSet.IndexOf(context);
        var indexes = lzBuffer.IndexesOf(contextIndex);
        indexes.Sort();
        foreach (var targetPos in indexes)
            ValidateLZBetterValue(currentPos, ref bestValue, targetPos);
        if (bestValue.Pos == -1)
        {
            WriteNotLZCount();
            return false;
        }
        Result.Add(new(notLZCount, lzCount, lzCount + notLZCount));
        lzCount++;
        WriteLZPosition(currentPos, bestValue.Pos);
        WriteLZLength(bestValue.Length);
        ClearBuffers();
        lzBlockEnd = currentPos + bestValue.Length;
        return true;
    }
 
    private void ValidateLZBetterValue(int currentPos, ref LZEntry bestValue, int targetPos)
    {
        var dist = (targetPos - (currentPos - startPos - maxContextDepth)) % LZDictionarySize + currentPos - startPos - maxContextDepth;
        var length = -maxContextDepth;
        while (length < Input.Length - startPos - currentPos && AreItemsEqual())
            length++;
        if (currentPos - (dist + maxContextDepth + startPos) >= 2 && length > bestValue.Length)
            bestValue = new(targetPos, length);
        bool AreItemsEqual()
        {
            var current = Input[currentPos + length];
            var target = Input[dist + maxContextDepth + startPos + length];
            return RedStarLinq.Equals(current, target, (x, y) => x.Lower == y.Lower);
        }
    }
 
    private void WriteNotLZCount()
    {
        if (preOutputBuffer.IsFull)
        {
            Result.Add(new(0, notLZCount, lzCount + notLZCount));
            notLZCount++;
        }
    }
 
    private void WriteLZPosition(int currentPos, int bestPos)
    {
        var sum = lzPositions.GetLeftValuesSum((uint)bestPos, out var posFrequency);
        if (sum >= 0 && posFrequency != 0)
        {
            Result.Add(new((uint)sum, (uint)posFrequency, (uint)lzPositions.ValuesSum));
            lzPositions.Update((uint)bestPos, posFrequency + 100);
        }
        else
        {
            var lower = (uint)lzPositions.GetLeftValuesSum(uint.MaxValue, out var escapeFrequency);
            Result.Add(new(lower, (uint)escapeFrequency, (uint)lzPositions.ValuesSum));
            lzPositions.Update(uint.MaxValue, escapeFrequency + 100);
            Result.Add(new((uint)bestPos, (uint)Min(currentPos - startPos - maxContextDepth, LZDictionarySize - 1)));
            lzPositions.Add((uint)bestPos, 100);
        }
    }
 
    private void WriteLZLength(int bestLength)
    {
        if (bestLength < lzLengths.Length - 1)
        {
            var lower = (uint)lzLengths.GetLeftValuesSum(bestLength, out var frequency);
            Result.Add(new(lower, (uint)frequency, (uint)lzLengths.ValuesSum));
            lzLengths.Increase(bestLength);
        }
        else
        {
            Result.Add(new((uint)(lzLengths.ValuesSum - lzLengths[^1]), (uint)lzLengths[^1], (uint)lzLengths.ValuesSum));
            lzLengths.Increase(lzLengths.Length - 1);
            foreach (var bit in EncodeFibonacci((uint)(bestLength - lzLengths.Length + 2)))
                Result.Add(new(bit ? 1u : 0, 2));
            new Chain(bestLength - lzLengths.Length + 1).ForEach(x => lzLengths.Insert(lzLengths.Length - 1, 1));
        }
    }
 
    private void ClearBuffers()
    {
        preOutputBuffer.Clear();
        spaceBuffer.Clear();
        if (BlockIndex != 2)
            foreach (var x in newItemsBuffer.Filter(x => x != uint.MaxValue))
                newItemsFreqTable.Add((x, 1));
        newItemsBuffer.Clear();
    }
 
    private void Increase()
    {
        IncreaseInSkipped();
        var successLength = reservedContext.Length;
        if (reservedContext.Length != 0)
        {
            currentContext.Replace(reservedContext);
            currentContext.RemoveAt(^1);
        }
        IncreaseInEncoded(successLength);
        IncreaseInGlobal(successLength);
    }
 
    private void IncreaseInSkipped()
    {
        for (; reservedContext.Length > 0 && contextSet.TryAdd(reservedContext.Copy(), out var index); reservedContext.RemoveAt(^1))
        {
            if (lzBufferIndex == -1)
                lzBufferIndex = index;
            contextFreqTableByLevel.SetOrAdd(index, [(item, 100)]);
        }
    }
 
    private void IncreaseInEncoded(int successLength)
    {
        for (; reservedContext.Length > 0 && contextSet.TryGetIndexOf(reservedContext, out var contextIndexInSet); )
        {
            if (lzBufferIndex == -1)
                lzBufferIndex = contextIndexInSet;
            IncreaseInEncodedMain(successLength, contextIndexInSet);
            reservedContext.RemoveAt(^1);
            if (reservedContext.Length != 0)
                currentContext.RemoveAt(^1);
        }
    }
 
    private void IncreaseInEncodedMain(int successLength, int contextIndexInSet)
    {
        if (!contextFreqTableByLevel[contextIndexInSet].TryGetValue(item, out var itemValue))
        {
            contextFreqTableByLevel[contextIndexInSet].Add(item, 100);
            return;
        }
        else if (reservedContext.Length == 1 || itemValue > 100)
        {
            var newItemValue = itemValue + (int)Max(Round((double)100 / (successLength - reservedContext.Length + 1)), 1);
            contextFreqTableByLevel[contextIndexInSet].Update(item, newItemValue);
            return;
        }
        ComplexIncreaseInEncoded(contextIndexInSet, itemValue);
    }
 
    private void ComplexIncreaseInEncoded(int contextIndexInSet, int itemValue)
    {
        var successIndex = contextSet.IndexOf(currentContext);
        if (!contextFreqTableByLevel[successIndex].TryGetValue(item, out var successValue))
            successValue = 100;
        var step = (double)GetFreqTableBase(contextFreqTableByLevel[contextIndexInSet]) * successValue
            / (contextFreqTableByLevel[contextIndexInSet].ValuesSum + GetFreqTableBase(contextFreqTableByLevel[successIndex]) - successValue);
        contextFreqTableByLevel[contextIndexInSet].Update(item, (int)(Max(Round(step), 1) + itemValue));
    }
 
    private void IncreaseInGlobal(int successLength)
    {
        if (globalFreqTable.TryGetValue(item, out var globalValue))
            globalFreqTable.Update(item, globalValue + (int)Max(Round((double)100 / (successLength + 1)), 1));
        else
            globalFreqTable.Add(item, 100);
    }
 
    private static uint GetFreqTableBase(SumSet<uint> freqTable) => (uint)(freqTable.ValuesSum + freqTable.Length * 100);
}
 
file record struct PredictionEntry(long Sum, int Frequency);
 
file record struct LZEntry(int Pos, int Length);
Добавлено через 17 минут
Еще раз замерил время выполнения этих трех функций, для контроля: Escape() - 19.4, ProcessFrequency() - 12.2, ProcessBuffers() - мизер, Increase() - 9.0, всего - 53.4. То есть явный "лидер" по тормозам отсутствует.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
05.07.2024, 00:11
Ответы с готовыми решениями:

Где в этом коде тормоза?
Код здесь, начиная со строки 247 или около того, функция FindMatches. Я уже несколько лет пытаюсь сам найти, но одной строки, которая...

Где в этом коде инкапсуляция, наследование и полиморфизм?
подскажите где в данном коде находятся 3 кита ООП (инкапсуляция,наследование,полиморфизм) using System; using System.IO; using...

Где в этом коде задается текст теста для вопросов и ответов
Ребят, можете кто-нибудь объяснить мне глупенькой, где в этом коде задается текст для теста для вопросов, ответов...где??:scratch:

47
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18402 / 14334 / 5370
Регистрация: 17.03.2014
Сообщений: 29,012
Записей в блоге: 1
13.01.2025, 12:58
Студворк — интернет-сервис помощи студентам
Etyuhibosecyu, в проекте есть тест (или что-то аналогичное) который можно запустить чтобы увидеть медленный код в действии?
0
Труд вопреки насмешкам
 Аватар для Etyuhibosecyu
363 / 181 / 41
Регистрация: 13.07.2017
Сообщений: 4,845
Записей в блоге: 14
13.01.2025, 13:02  [ТС]
OwenGlendower, есть программа с GUI, а также вот эти тесты, которые легко перенастроить (например, TestLZ) на PPM.
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18402 / 14334 / 5370
Регистрация: 17.03.2014
Сообщений: 29,012
Записей в блоге: 1
13.01.2025, 13:14
Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
есть программа с GUI
Не годится. Консольное было бы проще. Но это так в сторону. Не тратьте время.

Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
а также вот эти тесты, которые легко перенастроить (например, TestLZ) на PPM.
Так перенастройте, а лучше создайте новые.
0
Труд вопреки насмешкам
 Аватар для Etyuhibosecyu
363 / 181 / 41
Регистрация: 13.07.2017
Сообщений: 4,845
Записей в блоге: 14
13.01.2025, 13:18  [ТС]
Цитата Сообщение от OwenGlendower Посмотреть сообщение
Так перенастройте, а лучше создайте новые.
Это делается тривиально, достаточно в TestLZ() в этой строке:
C#
1
PresentMethodsF = UsedMethodsF.CS2 | UsedMethodsF.LZ2;
заменить CS2 на CS4.
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18402 / 14334 / 5370
Регистрация: 17.03.2014
Сообщений: 29,012
Записей в блоге: 1
13.01.2025, 13:20
Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
заменить CS2 на CS4.
Как же я не догадался. Это же так очевидно.
1
Труд вопреки насмешкам
 Аватар для Etyuhibosecyu
363 / 181 / 41
Регистрация: 13.07.2017
Сообщений: 4,845
Записей в блоге: 14
13.01.2025, 13:24  [ТС]
OwenGlendower, не понял, это ирония? Вы спрашиваете:
Цитата Сообщение от OwenGlendower Посмотреть сообщение
в проекте есть тест (или что-то аналогичное) который можно запустить чтобы увидеть медленный код в действии?
Я отвечаю, что такой тест делается тривиально. И еще, если это не очевидно, нужно рядом с AresToolsTests.csproj положить любой txt-файл.
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18402 / 14334 / 5370
Регистрация: 17.03.2014
Сообщений: 29,012
Записей в блоге: 1
13.01.2025, 13:27
Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
не понял, это ирония?
Да.

Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
И еще, если это не очевидно, нужно рядом с AresToolsTests.csproj положить любой txt-файл.
Нет, ни разу не очевидно.
0
Труд вопреки насмешкам
 Аватар для Etyuhibosecyu
363 / 181 / 41
Регистрация: 13.07.2017
Сообщений: 4,845
Записей в блоге: 14
13.01.2025, 13:35  [ТС]
OwenGlendower, вот только я не знаю, вы всерьез собрались запускать это "в действии", или спрашиваете ради забавы?

Добавлено через 6 минут
OwenGlendower, еще, к слову, я исправил большинство распространенных методов RedStarLinq, требующих огромного количества памяти, эта проблема в прошлом.
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18402 / 14334 / 5370
Регистрация: 17.03.2014
Сообщений: 29,012
Записей в блоге: 1
13.01.2025, 13:49
Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
вы всерьез собрались запускать это "в действии", или спрашиваете ради забавы?
Всерьез спрашиваю. Причем не только для себя, но и для других потенциальных помощников.

Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
нужно рядом с AresToolsTests.csproj положить любой txt-файл.
Сделайте пожалуйста готовый тест который можно сразу запустить ничего не меняя в коде. Текстовый файл тоже свой добавьте (разумного размера) чтобы у всех были одинаковые данные.
1
13.01.2025, 13:50

Не по теме:

Цитата Сообщение от OwenGlendower Посмотреть сообщение
Как же я не догадался. Это же так очевидно.
значит вы не опытный программист XD

0
13.01.2025, 13:52

Не по теме:

Цитата Сообщение от Wolfdp Посмотреть сообщение
значит вы не опытный программист
Получается так :(

0
Труд вопреки насмешкам
 Аватар для Etyuhibosecyu
363 / 181 / 41
Регистрация: 13.07.2017
Сообщений: 4,845
Записей в блоге: 14
13.01.2025, 14:37  [ТС]
OwenGlendower, ну если так трудно поменять одну цифру, то вот архив со всем необходимым кодом и с Властелином Колец в папке с тестами, и тест PPM первый в AresToolsTests.cs.
Вложения
Тип файла: 7z AresToolsSource.7z (4.89 Мб, 11 просмотров)
1
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18402 / 14334 / 5370
Регистрация: 17.03.2014
Сообщений: 29,012
Записей в блоге: 1
13.01.2025, 14:50
Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
ну если так трудно поменять одну цифру
Поменять одну цифру мне нетрудно. Дело в другом. Чтобы иметь возможность нормально помочь нужно чтобы у нас были одинаковые тесты с одинаковыми данными.

Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
вот архив
Окей. Вечером посмотрю.
0
HF
13.01.2025, 16:03

Не по теме:

Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
Я отвечаю, что такой тест делается тривиально.
Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
Только человек с невысоким интеллектом может быть на сто процентов уверенным в чем-либо!
Ну вот как-то так...

0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18402 / 14334 / 5370
Регистрация: 17.03.2014
Сообщений: 29,012
Записей в блоге: 1
13.01.2025, 22:28
Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
тест PPM первый в AresToolsTests.cs.
Странный тест. Сжатый файл весит на 1 байт больше оригинала. При запуске теста под отладчиком видно что мы попадаем на строку №38 где выбрасывается EncoderFallbackException. Дальше код в файле PPM.cs не выполняется. Соответственно непонятно что там можно оптимизировать.

Еще ваш тесты не проверяет что распакованный файл совпадает с оригиналом. Это было было логично делать. Как вам кажется?
0
Труд вопреки насмешкам
 Аватар для Etyuhibosecyu
363 / 181 / 41
Регистрация: 13.07.2017
Сообщений: 4,845
Записей в блоге: 14
13.01.2025, 22:37  [ТС]
OwenGlendower, извините, чистил лишние зависимости и затронул не то, что нужно было. Попробуйте так.
Вложения
Тип файла: 7z AresToolsSource.7z (3.09 Мб, 8 просмотров)
0
Труд вопреки насмешкам
 Аватар для Etyuhibosecyu
363 / 181 / 41
Регистрация: 13.07.2017
Сообщений: 4,845
Записей в блоге: 14
13.01.2025, 22:38  [ТС]
Цитата Сообщение от OwenGlendower Посмотреть сообщение
Еще ваш тесты не проверяет что распакованный файл совпадает с оригиналом. Это было было логично делать. Как вам кажется?
Это проверяется внутри сжатия, если в режиме Debug.
0
 Аватар для belalugoci
475 / 294 / 29
Регистрация: 01.06.2018
Сообщений: 3,676
14.01.2025, 14:58
всё не читал, я не то что не опытный программист, а скорее вовсе не программист, но писать PPM/LZ использую списки и LINQ - это сильно!!!! поиграйтесь на лбом highload сервере с заданиями чтобы научиться простым вещам, ваш код ужасен по своей сути и его оптимизация - это просто переписывание с нуля так, как должно быть. Во-первых unsafe+указатели, во-вторых - свои классы по работе с данными и никаких стандартных списков и упаси боже использовать linq.

Добавлено через 4 минуты
скачал ваш тест, открыл, ужаснулся, закрыл. Вообще и lz и ppm в таком объёме кода не нуждаются, lz пишется на 3-4 страницы кода, ppm чуть больше, даже трансформация исходников с языка Си на C# практически не увеличит код, ООП там особо и не нужно, скорее на любителя.
0
HF
 Аватар для HF
1342 / 926 / 202
Регистрация: 09.09.2011
Сообщений: 2,751
Записей в блоге: 2
14.01.2025, 22:03
Уже много выше сказали. Добавлю немного подтверждения слов выше.

- проекты невозможно запустить
Те проекты что по ссылке что-то требуют, на что-то ссылаются.
Пока оба репозитория не подцепил в одно решение, всё красное было.
В итоге заработал только AresToolsSource, так как облегчённый по максимуму и всё-таки готовый к запуску. Спасибо хоть так.
Но для публичных репозиториев - это шлак. Любой кто захочет проверить и не сможет разобраться и запустить в короткое время - выбросит и забудет.

- про качество API уже сказали много
Wolfdp хорошо отписался с примерами. Вообще удивлён как он смог это запустить.
Что происходит, что писать, зачем это, куда.... знает только сам ТС. Сам видимо и будет пользовать своим продуктом.

- попытался хотя бы один тест PPM просмотреть
Параллельно на точках останова код бегло осматривал. Я наверняка неопытнее неопытного OwenGlendower, но тут даже не надо много ума чтобы сделать выводы.

То что происходит внутри - это адский ад. Создаётся огромное количество объектов. Что-то куда-то копируется - копии блоков, проверяем кусок... снова копии блоков, перебираем... новая коллекция. Дак откуда там может быть скорость. Про память я просто покажу картинку. Я конечно слышал что эта хвалёная либа должна с огромными коллекциями работать... но откуда тут такие объёмы если мы 4 мб файл обрабатывали.
Какие-то потоки, куча блокировок. И разное чудесное...

Вообщем я не стал больше вникать. Просто закрыл.

См. картинку. Пример диагностики работы программы. 3 точка - кодирование, 4 - декодирование.
Рандомные точки, где-то ближе к концу методов.
Миниатюры
Где в этом коде тормоза?  
0
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
14.01.2025, 22:15
Цитата Сообщение от HF Посмотреть сообщение
Вообще удивлён как он смог это запустить
Очень легко -- я ничего не запускал, а просто смотрел код на репозитории.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
14.01.2025, 22:15

Что означают все эти данные вот в этом коде PITHON и где можно найти описание всех этих данных в коде
#!/usr/bin/python # Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford (jspenguin@jspenguin.org) # The author...

где ошибка в этом коде?
#include &lt;stdio.h&gt; main() { *int fahr, celsius; *int lower, upper, step; *lower = 0; *upper = 300; *step = 20; *fahr =...

Где в этом коде подпрограммы?
Подскажите, пожалуйста, где в этом коде находятся 3 подпрограммы? Вот задание: Задан целочисленный одномерный массив A из N элементов....

где в этом коде ошибка?
#include &lt;iostream&gt; using namespace std; int main() { setlocale(LC_CTYPE,&quot;rus&quot;); int a,b; cout&lt;&lt;&quot;введите...

Где ошибка в этом простом коде ?
Добрый день, код парсинга данных с инстаграма (количество подписчиков/подписок, имя, и аватар) : &lt;?php ...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru