summaryrefslogtreecommitdiff
path: root/tests/src/GC/Stress/Tests/concurrentspin2.cs
blob: dc4ef8406c0407a9c536c4916cf917c5258c2d7f (plain)
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
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using System;
using System.Diagnostics;
using System.Threading;

internal class PriorityTest
{
    private byte[][] _old;
    private byte[][] _med;
    private Random _rand;

    private int _oldDataSize;
    private int _medDataSize;
    private int _iterCount;
    private int _meanAllocSize;
    private int _medTime;
    private int _youngTime;


    public PriorityTest(int oldDataSize, int medDataSize,
                        int iterCount, int meanAllocSize,
                        int medTime, int youngTime)
    {
        _rand = new Random(314159);
        _oldDataSize = oldDataSize;
        _medDataSize = medDataSize;
        _iterCount = iterCount;
        _meanAllocSize = meanAllocSize;
        _medTime = medTime;
        _youngTime = youngTime;
    }

    // creates initial arrays
    private void AllocTest(int oldDataSize, int medDataSize, int meanAllocSize)
    {
        _old = new byte[oldDataSize][];
        _med = new byte[medDataSize][];

        for (int i = 0; i < _old.Length; i++)
        {
            _old[i] = new byte[meanAllocSize];
        }

        for (int i = 0; i < _med.Length; i++)
        {
            _med[i] = new byte[meanAllocSize];
        }
    }

    // churns data in the heap by replacing byte arrays with new ones of random length
    // this should induce concurrent GCs
    private void SteadyState(int oldDataSize, int medDataSize,
                        int iterCount, int meanAllocSize,
                        int medTime, int youngTime)
    {
        for (int i = 0; i < iterCount; i++)
        {
            byte[] newarray = new byte[meanAllocSize];

            if ((i % medTime) == 0)
            {
                _old[_rand.Next(0, _old.Length)] = newarray;
            }
            if ((i % youngTime) == 0)
            {
                _med[_rand.Next(0, _med.Length)] = newarray;
            }
            //if (((i % 5000) == 0) && (Thread.CurrentThread.Priority != ThreadPriority.Lowest))
            //{
            //    Thread.Sleep(200);
            //}
        }
    }

    // method that runs the test
    public void RunTest()
    {
        for (int iteration = 0; iteration < _iterCount; iteration++)
        {
            AllocTest(_oldDataSize, _medDataSize, _meanAllocSize);

            SteadyState(_oldDataSize, _medDataSize,
                _iterCount, _meanAllocSize,
                _medTime, _youngTime);

            if (((iteration + 1) % 20) == 0)
                Console.WriteLine("Thread: {1} Finished iteration {0}", iteration, System.Threading.Thread.CurrentThread.Name);
        }
    }
}


internal class ConcurrentRepro
{
    public static void Usage()
    {
        Console.WriteLine("Usage:");
        Console.WriteLine("\t<num iterations> <num threads>");
    }

    public static int[] ParseArgs(string[] args)
    {
        int[] parameters = new int[2];

        // set defaults
        parameters[0] = 100;
        parameters[1] = 4;

        if (args.Length == 0)
        {
            //use defaults
            Console.WriteLine("Using defaults: 100 iterations, 4 threads");
            return parameters;
        }
        if (args.Length == parameters.Length)
        {
            for (int i = 0; i < args.Length; i++)
            {
                int j = 0;
                if (!int.TryParse(args[i], out j))
                {
                    Usage();
                    return null;
                }
                parameters[i] = j;
            }

            return parameters;
        }

        // incorrect number of arguments        
        Usage();
        return null;
    }


    public static int Main(string[] args)
    {
        // parse arguments
        int[] parameters = ParseArgs(args);
        if (parameters == null)
        {
            return 0;
        }

        // set process affinity to 1 to repro bug easier
        //Process.GetCurrentProcess().ProcessorAffinity = (IntPtr)1;


        PriorityTest priorityTest = new PriorityTest(1000000, 5000, parameters[0], 17, 30, 3);
        ThreadStart startDelegate = new ThreadStart(priorityTest.RunTest);

        // create threads
        Thread[] threads = new Thread[parameters[1]];
        for (int i = 0; i < threads.Length; i++)
        {
            threads[i] = new Thread(startDelegate);
            threads[i].Name = String.Format("Thread{0}", i);
            //if (i % 2 == 0)
            //{
            //    threads[i].Priority = ThreadPriority.Lowest;
            //}
            threads[i].Start();
        }

        // wait for threads to complete
        for (int i = 0; i < threads.Length; i++)
        {
            threads[i].Join();
        }

        return 100;
    }
}