On 15.08.2016 15:42, Thomas Munro wrote:
This implementation is using a spinlock for the arrival counter, and signals (via Robert's condition variables and latches) for waking up peer processes when the counter reaches the target. I realise that using signals for this sort of thing is a bit unusual outside the Postgres universe, but won't a semaphore-based implementation require just as many system calls, context switches and scheduling operations?

Yes, you are right.
I never expected that this combination of signal+local socket+select can provide performance comparable with pthread_cond_t. I have implemented simple test where two background workers are emulating request-response round-trip using latches and pthread primitives. Result (average round-trip time) was 7.49 microseconds for Postgres latches vs. 4.59 microseconds for pthread_cond_timedwait.




#define N_ROUNDTRIPS 1000000
#define WAIT_LATCH_TIMEOUT 60000

static void PongLatch(Datum arg)
{
    int i;
    timestamp_t start;
    int result;

    BackgroundWorkerUnblockSignals();

    Mtm->pong = MyProc->pgprocno;
    ResetLatch(&MyProc->procLatch);
    MtmSleep(1000000);
    Assert(Mtm->ping);


    for (i = 0; i <= N_ROUNDTRIPS; i++) {
result = WaitLatch(&MyProc->procLatch, WL_LATCH_SET|WL_TIMEOUT, WAIT_LATCH_TIMEOUT);
        Assert(result & WL_LATCH_SET);
        ResetLatch(&MyProc->procLatch);
SetLatch(&ProcGlobal->allProcs[Mtm->ping].procLatch);
        if (i == 0) {
               start = MtmGetSystemTime();
        }
    }
fprintf(stderr, "Average roundrip time: %f microsconds\n", (double)(MtmGetSystemTime() - start) / N_ROUNDTRIPS);
}

static void PingLatch(Datum arg)
{
    int i;
    timestamp_t start;
    int result;

    BackgroundWorkerUnblockSignals();

    Mtm->ping = MyProc->pgprocno;
    ResetLatch(&MyProc->procLatch);
    MtmSleep(1000000);
    Assert(Mtm->pong);

    for (i = 0; i <= N_ROUNDTRIPS; i++) {
SetLatch(&ProcGlobal->allProcs[Mtm->pong].procLatch);
result = WaitLatch(&MyProc->procLatch, WL_LATCH_SET|WL_TIMEOUT, WAIT_LATCH_TIMEOUT);
        Assert(result & WL_LATCH_SET);
        ResetLatch(&MyProc->procLatch);
        if (i == 0) {
               start = MtmGetSystemTime();
        }
    }
fprintf(stderr, "Average roundrip time: %f microseconds\n", (double)(MtmGetSystemTime() - start) / N_ROUNDTRIPS);
}


static BackgroundWorker Pinger = {
    "ping",
    BGWORKER_SHMEM_ACCESS,// | BGWORKER_BACKEND_DATABASE_CONNECTION,
    BgWorkerStart_ConsistentState,
    BGW_NEVER_RESTART,
    PingLatch
};

static BackgroundWorker Ponger = {
    "pong",
    BGWORKER_SHMEM_ACCESS,// | BGWORKER_BACKEND_DATABASE_CONNECTION,
    BgWorkerStart_ConsistentState,
    BGW_NEVER_RESTART,
    PongLatch
};

static void PingPong()
{
    RegisterBackgroundWorker(&Pinger);
    RegisterBackgroundWorker(&Ponger);
}




--
Konstantin Knizhnik
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company



--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to