Master, forgive me, but I'll have to go all out... Just this once
GENERATING TEST DATA: https://pastebin.com/Duha7ZwG
CODE: https://pastebin.com/nsfVC5nU

> 1.1 GB, 3 million line log file with entries such as the ones described by logtard originally.

RESULTS:
~SCRIPTS time cat ./logs.txt | ./cl-io-bench-test.lisp

Processing HTTP logs from stdin...
Total lines: 3,000,000

Methods:
PATCH: 600,434
DELETE: 599,597
POST: 600,585
GET: 599,017
PUT: 600,367

Status Codes:
401: 249,510
404: 250,013
201: 249,624
204: 250,136
500: 250,247
200: 250,048
301: 250,069
503: 250,208
302: 249,946
403: 249,460
502: 250,422
400: 250,317

Top 10 IPs:
187.78.94.121: 2
121.134.77.202: 2
221.33.54.71: 2
224.150.235.192: 2
171.29.251.220: 2
106.64.20.219: 2
8.20.104.83: 2
127.192.79.233: 2
75.180.73.157: 2
86.73.2.249: 2
Evaluation took:
5.282 seconds of real time
5.278661 seconds of total run time (5.167399 user, 0.111262 system)


For reading file as fast as possible:
#!/usr/bin/env -S sbcl --script

(declaim (optimize (speed 3) (safety 0) (debug 0)))

(defun count-lines ()
(let ((buffer (make-array 65536 :element-type '(unsigned-byte 8)))
(count 0))
(declare (type fixnum count))
(with-open-file (stream "/dev/stdin" :element-type '(unsigned-byte 8))
(loop
(let ((bytes-read (read-sequence buffer stream)))
(when (zerop bytes-read) (return count))
(loop for i from 0 below bytes-read
when (= (aref buffer i) 10)
do (incf count)))))))

(format t "Lines: ~:d~%" (time (count-lines)))


>3 Million lines: 0.490 s
>10 Million lines: 1.658 s

Learned a lot:
>Read bytes, not characters
>NO regex - Direct byte comparisons (73 78 70 79 for "INFO")
>Zero allocations in loops - Reuse fixed buffers, only allocate strings for final results, not intermediate processing
>Chunked read-sequence - 64KB blocks with buffer reuse is optimal