import std.conv : to; 
import std.getopt;
import std.stdio : write;
import std.format;

void setOp (T...) (T arguments)
{
    immutable string newline = "\r\n";

    write("*", arguments.length, newline); // Number of arguments

    foreach (arg; arguments)
    {
        write("$", arg.length, newline); // length of the argument
        write(arg, newline);             // name of the argument
    }
}

int main (string[] args)
{
    auto num_records = 1_000_000UL;
    auto help = false;

    getopt(args, "records|n", &num_records);

    foreach (i; 0..num_records)
    {
        auto key = "Key%d".format(i);
        auto value = "Value%d".format(i);
        setOp("SET", key, value);
    }

    return 0;
}

Running ^ that program piping it to redis-cli took just a few seconds.

$ /usr/bin/time -v -p sh -c './proto -n 1000000 | redis-cli --pipe'
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 1000000
    Command being timed: "sh -c ./proto -n 1000000 | redis-cli --pipe"
    User time (seconds): 2.56
    System time (seconds): 0.14
    Percent of CPU this job got: 114%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:02.36
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 6544
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 0
    Minor (reclaiming a frame) page faults: 578
    Voluntary context switches: 10840
    Involuntary context switches: 72
    Swaps: 0
    File system inputs: 0
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0

Anyway I'd like my program using vibe.d to have a similar performance.