0

I'm developing an Grammatical Evolution Engine that does the following:

  1. Parse a file with the BNF rules.
    <letter> ::= a|b|c|d

  2. Generates random solutions based in some specific rules. (Basically, generates int arrays)
    i1 = [22341,123412,521123, 123123], i2 = [213213, 123,5125,634643]

  3. Maps those int arrays into the rules in the bnf file:
    i1 = [22341,123412,521123, 123123] => ddbca

  4. Checks those solutions with some target previously defined.
    i1 value ('ddbca') is ('hello_world') ? 0, else 1

  5. Selects the best performing solutions (top 5, top 10, etc) for latter usage

  6. Randomly, picks 2 solutions from the solution list, and perform a crossover:
    i1 = [22341,123412,521123, 123123], i2 = [213213, 123,5125,634643]
    i1 x i2 => [22341,123412, 5125,634643]

  7. Based in some predefined probability, executes a mutation in all individuals:

for(int i = 0; i < i3.length; i++)
{
    if(random.NextDouble() <= 0.5) {
        i3[i] = random.Next()
    }
}
  1. Again, execute mapping:
    i3 = [22341,123412, 5125,634643] => qwerast

9. Check this new solution against target.
10. Goes back to step 5, and executes everything again.

The problem that i'm facing is: My algorithm is generating really large int arrays, but all of then are small lived. After a generation, all solutions that weren't selected, should be disposed. But, since the arrays are getting bigger, almost all of then go to the LOH, and when the GC goes to collect then, my application performance drops drastically.


In a single core environment, it starts at 15 generations/s, and after 160 generations, this drops to 3 generations per second.

I already tried to use ArrayPool, but, since i have hundreds of solutions in memory, i saw no performance improvement, and a great impact on memory usage.

I tried to used the ChunkedList Idea from this link, and the performance did not improve, but the LOH drops considerably.

I already change most of my classes to structs, tried to optimize most simple thing (Avoid Linq, use for insted of foreach, etc), but the big performance hit are in those large arrays.

Any of you can think in some kind of solution for this problem that i'm facing?

Thank you in advance!

4
  • ArrayPool (see remarks) has a limit on pooled items so if you request more arrays then it has configured (or larger then maximum size of pooled array) it will just create an array and will not pool it. You can try using ArrayPool<T>.Create to create a pool with custom settings. Commented Jan 28, 2022 at 18:25
  • @AlexeiLevenkov: So, disposing an array with 100 elements, and an array with 1000 and 10000 elements should is exactly the same? I saw that the problem was the GC using hte performance profiler in visual studio. Commented Jan 28, 2022 at 18:35
  • @GuruStron I will try that later, thanks! Commented Jan 28, 2022 at 18:37
  • @Ubler I heavily doubt that it will help you. Also you can implement your custom pool which will reuse arrays rather then getting them collected. Also note that custom array pool is designed to rent scenarios i.e. it will not grow past some limit and not returning arrays to it is bad (cause if all arrays are rented then it will just act as pass through array creation method). Commented Jan 28, 2022 at 18:41

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.