[RUBY] Mettre en œuvre la queue

J'ai créé quelque chose comme tail qui affiche les n dernières lignes d'un fichier en Ruby

J'essaierai d'imiter.

Version simple

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

Tout d'abord, à partir de la section des commentaires de l'article original. Si vous le faites avec Ruby, cela fait du bien. Cette fonction est

Tel. C'est étonnamment rapide quand je l'essaye.

Version du tampon

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)

Ensuite, j'ai écrit une queue de Ruby. Méthode de division d'un fichier en morceaux d'une certaine taille et de comptage du nombre de sauts de ligne à partir de l'arrière du morceau de fin.

Pas trop tôt.

version mmap

Vient ensuite l'implémentation selon laquelle si on vous dit d'écrire tail, ce sera dans cette 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);
}

Une méthode de comptage à partir de l'arrière en utilisant mmap.

Il y a de nombreux avantages. C'est vraiment rapide. Plus rapide que la queue d'origine.

Recommended Posts

Mettre en œuvre la queue
Implémenter la pagination des rails
Implémentons Lexer (1)
Implémentons Lexer (2)
Implémentons EAM