Skip to content
This repository has been archived by the owner on Jan 13, 2022. It is now read-only.

Add Memcached support for the MediaWiki target #87

Merged
merged 1 commit into from
Jan 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions base/MemcachedDaemon.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?hh
/*
* Copyright (c) 2017, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
final class MemcachedDaemon extends Process {

private int $maxMemory = 2048;

public function __construct(
private PerfOptions $options,
private PerfTarget $target,
) {
parent::__construct($this->options->memcached);
}

public function start(): void {
parent::startWorker(
$this->options->daemonOutputFileName('memcached'),
$this->options->delayProcessLaunch,
$this->options->traceSubProcess,
);
}

public function getNumThreads(): int {
$output = [];
$ret = -1;
if ($this->options->memcachedThreads != 0) {
return $this->options->memcachedThreads;
}

exec('nproc', &$output, &$ret);
if ($ret != 0) {
invariant_violation('%s', 'Execution of nproc failed');
exit(1);
}
$numProcs = (int)($output[0]);

// for small number of cores, use the default, which is 4;
// otherwise, we probably need more
if ($numProcs <= 8)
return 4;

return 32;
}

<<__Override>>
protected function getPidFilePath(): string {
return $this->options->tempDir.'/memcached.pid';
}

<<__Override>>
protected function getArguments(): Vector<string> {
if ($this->options->cpuBind) {
$this->cpuRange = $this->options->helperProcessors;
}
return Vector {
'-m',
(string) $this->maxMemory,
'-l',
'127.0.0.1',
'-t',
(string) $this->getNumThreads(),
'-p',
(string) $this->options->memcachedPort,
'-P', # pid file
$this->getPidFilePath()
};
}
}
18 changes: 17 additions & 1 deletion base/PerfOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ final class PerfOptions {

public string $siege;
public string $nginx;
public string $memcached;

public ?string $dbUsername;
public ?string $dbPassword;
Expand Down Expand Up @@ -87,6 +88,8 @@ final class PerfOptions {

public bool $applyPatches = false;

public bool $useMemcached = true;

//
// All times are given in seconds, stored in a float.
// For PHP code, the usleep timer is used, so fractional seconds work fine.
Expand All @@ -97,6 +100,7 @@ final class PerfOptions {
//
public float $delayNginxStartup;
public float $delayPhpStartup;
public float $delayMemcachedStartup;
public float $delayProcessLaunch; // secs to wait after start process
public float $delayCheckHealth; // secs to wait before hit /check-health

Expand All @@ -123,6 +127,8 @@ final class PerfOptions {
public bool $notBenchmarking = false;

public string $dbHost = '127.0.0.1'; //The hostname/IP of server which hosts the database.
public int $memcachedPort; //The hostname/IP of server which hosts memcached.
public int $memcachedThreads; // Number of memcached threads

private array $args;
private Vector<string> $notBenchmarkingArgs = Vector {};
Expand All @@ -140,6 +146,7 @@ public function __construct(Vector<string> $argv) {
'no-fpm',
'siege:',
'nginx:',
'memcached:',
'wait-at-end',
'wait-after-warmup',
'no-proxygen',
Expand Down Expand Up @@ -176,6 +183,7 @@ public function __construct(Vector<string> $argv) {
'trace',
'delay-nginx-startup:',
'delay-php-startup:',
'delay-memcached-startup:',
'delay-process-launch:',
'delay-check-health:',
'max-delay-unfreeze:',
Expand All @@ -192,6 +200,9 @@ public function __construct(Vector<string> $argv) {
'server-threads:',
'client-threads:',
'remote-siege:',
'memcached-port:',
'memcached-threads:',
'no-memcached', // do not use memcached (even if target supports it)
};
$targets = $this->getTargetDefinitions()->keys();
$def->addAll($targets);
Expand Down Expand Up @@ -238,6 +249,9 @@ public function __construct(Vector<string> $argv) {

$this->siege = hphp_array_idx($o, 'siege', 'siege');
$this->nginx = hphp_array_idx($o, 'nginx', 'nginx');
$this->memcached = hphp_array_idx($o, 'memcached', 'memcached');
$this->memcachedPort = (int) hphp_array_idx($o, 'memcached-port', 11888);
$this->memcachedThreads = (int) hphp_array_idx($o, 'memcached-threads', 0);

$isFacebook = array_key_exists('fbcode', $o);
$fbcode = "";
Expand Down Expand Up @@ -276,6 +290,7 @@ public function __construct(Vector<string> $argv) {
$this->statCache = $this->getBool('stat-cache');
$this->jit = !$this->getBool('no-jit');
$this->applyPatches = $this->getBool('apply-patches');
$this->useMemcached = !$this->getBool('no-memcached');

$fraction = $this->getFloat('cpu-fraction', 1.0);
if ($fraction !== 1.0) {
Expand Down Expand Up @@ -318,6 +333,7 @@ public function __construct(Vector<string> $argv) {
$this->phpFCGIChildren = $this->getInt('php-fcgi-children', 100);
$this->delayNginxStartup = $this->getFloat('delay-nginx-startup', 0.1);
$this->delayPhpStartup = $this->getFloat('delay-php-startup', 1.0);
$this->delayMemcachedStartup = $this->getFloat('delay-memcached-startup', 1.0);
$this->delayProcessLaunch = $this->getFloat('delay-process-launch', 0.0);
$this->delayCheckHealth = $this->getFloat('delay-check-health', 1.0);
$this->maxdelayUnfreeze = $this->getFloat('max-delay-unfreeze', 60.0);
Expand All @@ -344,7 +360,7 @@ public function __construct(Vector<string> $argv) {
if (array_key_exists('client-threads', $o)) {
$this->clientThreads = $this->args['client-threads'];
}

if ($argTempDir === null) {
$this->tempDir = tempnam('/tmp', 'hhvm-nginx');
// Currently a file - change to a dir
Expand Down
8 changes: 8 additions & 0 deletions base/PerfRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ private static function RunWithOptionsAndEngine(
Process::sleepSeconds($options->delayNginxStartup);
invariant($nginx->isRunning(), 'Failed to start nginx');

if ($options->useMemcached && $target->supportsMemcached()) {
$memcached = new MemcachedDaemon($options, $target);
self::PrintProgress('Starting Memcached ('.
$memcached->getNumThreads().' threads)');
Process::sleepSeconds($options->delayMemcachedStartup);
$memcached->start();
}

self::PrintProgress('Starting PHP Engine');
$php_engine->start();
Process::sleepSeconds($options->delayPhpStartup);
Expand Down
4 changes: 4 additions & 0 deletions base/PerfTarget.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,8 @@ public function __toString(): string {
public function getSiegeRCPath(): ?string {
return null;
}

public function supportsMemcached(): bool {
return false;
}
}
9 changes: 7 additions & 2 deletions base/SystemChecks.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
class SystemChecks {
public static function CheckAll(PerfOptions $options): void {
self::CheckNotRoot();
self::CheckPortAvailability();
self::CheckPortAvailability($options);
self::CheckCPUFreq();
self::CheckTCPTimeWaitReuse();
self::CheckForAuditd($options);
Expand Down Expand Up @@ -71,13 +71,18 @@ private static function CheckCPUFreq(): void {
}
}

private static function CheckPortAvailability(): void {
private static function CheckPortAvailability(PerfOptions $options): void {
$ports = Vector {
PerfSettings::HttpPort(),
PerfSettings::HttpAdminPort(),
PerfSettings::BackendPort(),
PerfSettings::BackendAdminPort(),
};
if ($options->useMemcached &&
$options->getTarget()->supportsMemcached()) {
$ports[] = $options->memcachedPort;
}

$busy_ports = Vector {};
foreach ($ports as $port) {
$result = @fsockopen('localhost', $port);
Expand Down
3 changes: 3 additions & 0 deletions targets/mediawiki/LocalSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@
require_once "$IP/extensions/TitleBlacklist/TitleBlacklist.php";
require_once "$IP/extensions/WikiEditor/WikiEditor.php";

# This option should be false if we are not using memcached, otherwise it will incur a significant performance penalty
# source: https://www.mediawiki.org/wiki/Manual:$wgUseDatabaseMessages
$wgUseDatabaseMessages = false;

# End of automatically generated settings.
# Add more configuration options below.
29 changes: 24 additions & 5 deletions targets/mediawiki/MediaWikiTarget.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ protected function getSanityCheckString(): string {
return 'Obama';
}

private function replaceInFile(string $fileName, string $search, string $replace) {
$file = $this->getSourceRoot().'/'.$fileName;
$file_contents = file_get_contents($file);
$file_contents = str_replace($search, $replace, $file_contents);
file_put_contents($file, $file_contents);
}

public function install(): void {
$src_dir = $this->options->srcDir;
if ($src_dir) {
Expand All @@ -41,16 +48,23 @@ public function install(): void {
mkdir($cache_dir);
copy(__DIR__.'/LocalSettings.php', $this->getSourceRoot().'/LocalSettings.php');

$file = $this->getSourceRoot().'/LocalSettings.php';
$file_contents = file_get_contents($file);
$file_contents = str_replace('__DB_HOST__', $this->options->dbHost, $file_contents );
file_put_contents($file, $file_contents);
$this->replaceInFile('LocalSettings.php', '__DB_HOST__', $this->options->dbHost);

file_put_contents(
$this->getSourceRoot().'/LocalSettings.php',
'$wgCacheDirectory="'.$cache_dir.'";',
'$wgCacheDirectory="'.$cache_dir.'";'."\n",
FILE_APPEND,
);
if ($this->options->useMemcached) {
copy(__DIR__.'/Memcached.php', $this->getSourceRoot().'/Memcached.php');
$this->replaceInFile('Memcached.php', '__MEMCACHED_HOST__', '127.0.0.1');
$this->replaceInFile('Memcached.php', '__MEMCACHED_PORT__', (string) $this->options->memcachedPort);
file_put_contents(
$this->getSourceRoot().'/LocalSettings.php',
'require_once "'.$this->getSourceRoot().'/Memcached.php";'."\n",
FILE_APPEND,
);
}
}

<<__Override>>
Expand All @@ -67,4 +81,9 @@ public function postInstall(): void {
public function getSourceRoot(): string {
return $this->options->tempDir.'/'.self::MEDIAWIKI_VERSION;
}

<<__Override>>
public function supportsMemcached(): bool {
return true;
}
}
8 changes: 8 additions & 0 deletions targets/mediawiki/Memcached.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

$wgMainCacheType = CACHE_MEMCACHED;
$wgMemCachedServers = array( "__MEMCACHED_HOST__:__MEMCACHED_PORT__" );

$wgSessionCacheType = CACHE_MEMCACHED;
# Turn this option back on if we use memcached
$wgUseDatabaseMessages = true;