I made something like tail that displays the last n lines of a file in Ruby
I will try to imitate.
tail_simple.rb
file_path = ARGV[0]
row_limit = ARGV[1].to_i
buffer = []
File.foreach(file_path) do |line|
  buffer << line
  buffer.shift if buffer.size > row_limit
end
puts buffer
First, from the comment section of the original article. If you do it in Ruby, this is fine. This feature is
Such. It's surprisingly fast when I try it.
tail_buffered.rb
def reverse_chunks(file, size)
  n = file.size / size
  n -= 1 if file.size == n * size
  len = file.size - n * size
  until n < 0
    file.seek(n * size)
    yield file.read(len)
    n -= 1
    len = size
  end
end
def offset_of_nth_chr_from_tail(file, count, target)
  offset = 0
  reverse_chunks(file, 1024*16) do |chunk|
    chunk.size.times do |i|
      chr = chunk[chunk.size - i - 1]
      if chr == target || (offset == 0 && i == 0 && chr != target)
        count -= 1
        if count < 0
          offset += i
          return offset
        end
      end
    end
    offset += chunk.size
  end
  offset
end
def tail(fname, n_lines)
  open(fname) do |file|
    offset = offset_of_nth_chr_from_tail(file, n_lines, "\n")
    file.seek(file.size - offset)
    print file.read
  end
end
tail(ARGV[0], ARGV[1].to_i)
Next, I wrote a tail by Ruby. A method of dividing a file into chunks of a certain size and counting the number of line breaks from the back of the trailing chunk.
Not too early.
Next is the implementation that if you are told to write tail, it will be in this direction.
tail_mmap.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
void tail(char *fname, int n_lines) {
  int fd = open(fname, O_RDONLY);
  struct stat st;
  fstat(fd, &st);
  int fsize = st.st_size;
  char *map = mmap(0, fsize, PROT_READ, MAP_PRIVATE, fd, 0);
  char *cursor = map+fsize;
  if (fsize > 0 && cursor[-1] != '\n') n_lines--;
  for (int i = 0; i < fsize; i++){
    cursor--;
    if (*cursor == '\n') n_lines--;
    if (n_lines < 0){
      cursor++;
      break;
    }
  }
  write(1, cursor, fsize-(cursor-map));
  munmap(map, fsize);
  close(fd);
}
int main(int argc, char *argv[]){
  if(argc != 3)  exit(EXIT_FAILURE);
  tail(argv[1], atoi(argv[2]));
  exit(EXIT_SUCCESS);
}
A method of counting from the back using mmap.
There are many merits. It's really fast. Faster than the original tail.