data === []) { return; } $this->waitForBroadcastInterval(); event(new PerceptronTrainingIteration($this->data, $this->sessionId, $this->trainingId)); $this->lastBroadcastAt = microtime(true); $this->data = []; } public function addIteration(int $epoch, int $exampleIndex, float $error, array $synaptic_weights): void { $iteration = [ 'epoch' => $epoch, 'exampleIndex' => $exampleIndex, 'error' => $error, 'weights' => $synaptic_weights, ]; $this->data[] = $iteration; if ($this->data !== [] && $this->payloadExceedsLimit()) { $lastIteration = array_pop($this->data); $this->flush(); $this->data[] = $lastIteration; } if (count($this->data) >= config('perceptron.broadcast_iteration_size')) { $this->flush(); } } private function payloadExceedsLimit(): bool { return strlen(json_encode([ 'iterations' => PerceptronTrainingIteration::normalizeForJson($this->data), 'trainingId' => $this->trainingId, ], JSON_THROW_ON_ERROR)) > config('broadcasting.broadcast_max_payload_size'); } private function waitForBroadcastInterval(): void { if ($this->lastBroadcastAt === null) { return; } $minimumInterval = config('perceptron.broadcast_minimum_interval_ms') / 1000; $remainingInterval = $minimumInterval - (microtime(true) - $this->lastBroadcastAt); if ($remainingInterval > 0) { usleep((int) ceil($remainingInterval * 1_000_000)); } } }