source code
    
    
// The Computer Language Benchmarks Game
// https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
//
// contributed by Serge Smith
// further optimized (rewrote threading, random generation loop) by Jan de Vaan
// modified by Josh Goldfoot (fasta-repeat buffering)
// ported from F# version by Anthony Lloyd
using System;
using System.Text;
using System.Buffers;
using System.Threading;
using System.Runtime.CompilerServices;
class Fasta
{
    const int Width = 60;
    const int Width1 = 61;
    const int LinesPerBlock = 2048;
    const int BlockSize = Width * LinesPerBlock;
    const int BlockSize1 = Width1 * LinesPerBlock;
    const int IM = 139968;
    const float FIM = 1F/139968F;
    const int IA = 3877;
    const int IC = 29573;
    const int SEED = 42;
    static readonly ArrayPool<byte> bytePool = ArrayPool<byte>.Shared;
    static readonly ArrayPool<int> intPool = ArrayPool<int>.Shared;
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    static byte[] Bytes(int i, int[] rnds, float[] ps, byte[] vs)
    {
        var a = bytePool.Rent(BlockSize1);
        var s = a.AsSpan(0, i);
        for (i = 1; i < s.Length; i++)
        {
            var p = rnds[i] * FIM;
            int j = 0;
            while (ps[j] < p) j++;
            s[i] = vs[j];
        }
        return a;
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    static int[] Rnds(int i, int j, ref int seed)
    {
        var a = intPool.Rent(BlockSize1);
        var s = a.AsSpan(0, i);
        s[0] = j;
        for (i = 1, j = Width; i < s.Length; i++)
        {
            if (j-- == 0)
            {
                j = Width;
                s[i] = IM * 3 / 2;
            }
            else
            {
                s[i] = seed = (seed * IA + IC) % IM;
            }
        }
        return a;
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    static int WriteRandom(int n, int offset, int seed, byte[] vs, float[] ps,
        Tuple<byte[], int>[] blocks)
    {
        // make cumulative
        var total = ps[0];
        for (int i = 1; i < ps.Length; i++)
            ps[i] = total += ps[i];
        void create(object o)
        {
            var rnds = (int[])o;
            blocks[rnds[0]] =
                Tuple.Create(Bytes(BlockSize1, rnds, ps, vs), BlockSize1);
            intPool.Return(rnds);
        }
        var createDel = (WaitCallback)create;
        for (int i = offset; i < offset + (n - 1) / BlockSize; i++)
        {
            ThreadPool.QueueUserWorkItem(createDel,
                Rnds(BlockSize1, i, ref seed));
        }
        var remaining = (n - 1) % BlockSize + 1;
        var l = remaining + (remaining - 1) / Width + 1;
        ThreadPool.QueueUserWorkItem(o =>
        {
            var rnds = (int[])o;
            blocks[rnds[0]] = Tuple.Create(Bytes(l, rnds, ps, vs), l);
            intPool.Return(rnds);
        }, Rnds(l, offset + (n - 1) / BlockSize, ref seed));
        return seed;
    }
    public static void Main(string[] args)
    {
        int n = args.Length == 0 ? 1000 : int.Parse(args[0]);
        var o = Console.OpenStandardOutput();
        var blocks = new Tuple<byte[], int>[
            (3 * n - 1) / BlockSize + (5 * n - 1) / BlockSize + 3];
        ThreadPool.QueueUserWorkItem(_ =>
        {
            var seed = WriteRandom(3 * n, 0, SEED,
                new[] { (byte)'a', (byte)'c', (byte)'g', (byte)'t',
                    (byte)'B', (byte)'D', (byte)'H', (byte)'K', (byte)'M',
                    (byte)'N', (byte)'R', (byte)'S', (byte)'V', (byte)'W',
                    (byte)'Y', (byte)'\n' },
                new[] { 0.27F,0.12F,0.12F,0.27F,0.02F,0.02F,0.02F,0.02F,0.02F,
                    0.02F,0.02F,0.02F,0.02F,0.02F,0.02F,1.00F }, blocks);
            WriteRandom(5 * n, (3 * n - 1) / BlockSize + 2, seed,
                new byte[] { (byte)'a', (byte)'c', (byte)'g', (byte)'t',
                    (byte)'\n' },
                new[] { 0.3029549426680F, 0.1979883004921F,
                        0.1975473066391F, 0.3015094502008F,
                        1.0F }, blocks);
        });
        o.Write(Encoding.ASCII.GetBytes(">ONE Homo sapiens alu"), 0, 21);
        var table = Encoding.ASCII.GetBytes(
            "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
            "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
            "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
            "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
            "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
            "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
            "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA");
        var linesPerBlock = (LinesPerBlock / 287 + 1) * 287;
        var repeatedBytes = bytePool.Rent(Width1 * linesPerBlock);
        for (int i = 0; i <= linesPerBlock * Width - 1; i++)
            repeatedBytes[1 + i + i / Width] = table[i % 287];
        for (int i = 0; i <= (Width * linesPerBlock - 1) / Width; i++)
            repeatedBytes[i * Width1] = (byte)'\n';
        for (int i = 1; i <= (2 * n - 1) / (Width * linesPerBlock); i++)
            o.Write(repeatedBytes, 0, Width1 * linesPerBlock);
        var remaining = (2 * n - 1) % (Width * linesPerBlock) + 1;
        o.Write(repeatedBytes, 0, remaining + (remaining - 1) / Width + 1);
        bytePool.Return(repeatedBytes);
        o.Write(Encoding.ASCII.GetBytes("\n>TWO IUB ambiguity codes"), 0, 25);
        blocks[(3 * n - 1) / BlockSize + 1] = Tuple.Create
            (Encoding.ASCII.GetBytes("\n>THREE Homo sapiens frequency"), 30);
        for (int i = 0; i < blocks.Length; i++)
        {
            Tuple<byte[], int> t;
            while ((t = blocks[i]) == null) Thread.Sleep(0);
            t.Item1[0] = (byte)'\n';
            o.Write(t.Item1, 0, t.Item2);
            if (t.Item2 == BlockSize1) bytePool.Return(t.Item1);
        }
        o.WriteByte((byte)'\n');
    }
}