Как уже заметили коллеги - первое что нужно выяснить - что тормозит.
Спойлер: 90% что проблема в запросах к бд, так как сам по себе код в большинстве случаев банально отсылает запросы и принимает их результат, выводя его пользователю в несложных действиях. В редких случаях - запросы идут к внешним тормозящим сервисам, например к фейсбуку или другим СС. И крайне редко тормозит сам код, но тут уже опять же - 90% что это некомпетентность разраба, например, не способного построить нормальный запрос и сортирующий данные от бд в коде...
Что конкретно надо делать:
1) Взять за шкирку самого разбирающегося в коде (если таковой существует в проекте), и дать задание описать базовый стек вызовов, если это какой-то самопис, или сразу расставить код замера времени с метками в случае понятной архитектуры. Что то типа такого(класс - древний костыль, но работает, так что матом не ругаться):
Class Timer.php:
class Timer {
static $start;
static $end;
static $marks = [];
static $formats = [1=>''];
static function init(){
if(empty(self::$start)) self::$start = microtime(true);
}
static function setMark($markName = ''){
$time = microtime(true);
if($markName == '')$markName = $time;
$data['name'] = $markName;
$data['time'] = $time;
$res['time'] = $time;
if(count(self::$marks) > 1)$res['diff'] = $time - self::$marks[count(self::$marks)-2]['time'];
else $res['diff'] = 0;
$data['diff'] = $res['diff'];
self::$marks[] = $data;
return $res;
}
static function timeFormat($number,$format = ''){
if(empty($format)) $format = 3;
return number_format ($number,$format,'.','');
}
static function report(){
self::$end = microtime(true);
self::$marks['start'] = self::$start;
self::$marks['end'] = self::$end;
self::$marks['all_time'] = self::$end - self::$start;
if(!empty(self::$marks)) return self::$marks;
}
}
In code:
\Timer::init()
//some code block 1
\Timer::setMark('after block 1');
//some code block 2
\Timer::setMark('after block 2');
...
//some code block n
\Timer::setMark('after block n');
//near end of code
\Timer::setMark('end');
var_dump(\Timer::report());
exit;
2) Смотрите на блоки жрущие время, делите их до атомарных операций путем деления блоков пополам таймерами.
3) Смотрите что там происходит - оптимизируете*. И так по кругу.
4) Профит.
* Оптимизация
Запросы:
1) Смотреть план запроса (use explain, Luke!).
2) Расставить индексы которых явно не хватает
3) Смотреть не вызывается ли 50 запросов в цикле? Если да - выписать пенделя писавшему, затем переписать в 1 запрос с нормальным джоином.
Код:
Иногда запрос сложно оптимизировать, он вытаскивает много данных, хотя эти данные не часто обновляются. Такие запросы нужно кешировать, для чего используют быстрые ин-мемори хранилища типа редис или мемкеш. В крайнем случае в файлах...
Чаще всего код тормозит на регулярках, хотя "хороший" программист может придумать и более креативные способы погреть процессор.
Что нужно сделать обязательно кроме тестов и как тогда лучше спрашивать с разработчиков, если они предлагают размытые предложения? Хочется понять в какую сторону копать
Бить палкой не вариант? Тогда берите других, эти испортились. Если разработчик не знает как выявить узкие места кода - нахрена он нужен? Код написать сегодня любой чат может... Ну, на крайняк дайте им вышеприведенный вариант решения проблемы...
PS: Кстати, сервер может банально не выдерживать наплыв сетевых соединений, пните адимна, пусть глянет логи.
PPS:
достаточно 2000-4000 человек, заходящих в течение 20 минут на сайт
это равномерные 3-4 рпс, ну или пусть в пике 50 рпс, должно держать даже на несложной конфигурации... Копайте код.