Je comprends que Java et Perl s'essayent tout à fait difficile de trouver une taille unique de tampon par défaut lors de la lecture dans les fichiers, mais je trouve leurs choix à être de plus en plus prétendu et que j'ai un problème de modification du choix par défaut lorsque Cela vient à Perl.
Dans le cas de Perl, que je crois utiliser tampons 8K par défaut, Semblable au choix de Java, je ne trouve pas de référence à l'aide du moteur de recherche de sites Web Perldoc (vraiment Google) sur la manière d'augmenter la taille de la mémoire tampon d'entrée par défaut de fichier à dire, 64k. p>
de la liaison ci-dessus, à Montrez comment les tampons de 8k ne font pas échelle: p>
Si des lignes ont généralement environ 60 caractères chacune, le fichier de 10 000 lignes compte environ 610 000 caractères. La lecture du fichier ligne-ligne avec la mémoire tampon nécessite uniquement 75 appels système et 75 attend le disque, au lieu de 10 001. P> BlockQuote>
Ainsi, pour un fichier de 50 000 000 lignes avec 60 caractères par ligne (y compris la nouvelle ligne à la fin), avec un tampon 8K, il s'agit de faire des appels système 366211 pour lire un fichier 2.8GIB. De côté, vous pouvez confirmer ce comportement en regardant le delta de lecture de disque Lire le Delta (sous Windows au moins, Top In * Nix montre la même chose que je suis aussi sûr que je suis sûr) dans la liste des processus du gestionnaire de tâches comme programme PERL. Prend 10 minutes pour lire dans un fichier texte :) P>
Quelqu'un a posé la question de l'augmentation de la taille de la mémoire tampon d'entrée Perl sur Perlmonks, une personne a répondu ici que vous pourriez augmenter la taille de" $ / "et augmenter ainsi la taille de la mémoire tampon, cependant du Perldoc: P>
Réglage $ / à une référence à un entier, scalaire contenant un entier, ou scalaire convertible vers un entier tentera de lire des enregistrements au lieu de lignes, la taille d'enregistrement maximale étant l'entier référencé. P> blockQuote>
alors je suppose que cela n'augmente pas réellement la taille du tampon que Perl utilise pour lire à l'avance sur le disque lors de l'utilisation de la ligne Typique: P>
import java.io.BufferedReader; [...] reader = new BufferedReader(new InputStreamReader(fileInputStream, "UTF-8"), 65536); [...] while (true) { String line = reader.readLine(); if (line == null) { break; } /* do something with the line here */ foo(line); }
4 Réponses :
Non, il n'y a pas (à court de recompiler une perl modifiée), mais vous pouvez lire l'ensemble du fichier en mémoire, puis la ligne de travail par ligne à partir de celle-ci: Notez que Perl avant 5.10 Fait défaut à l'aide des tampons Stdio dans la plupart des endroits (mais trichent souvent et accédant directement aux tampons directement, pas à travers la bibliothèque Stdio), mais dans
5.10 et ultérieure par défaut à son propre système de couche de Perlio. Ce dernier semble utiliser un 4k
tampon par défaut, mais écrire un calque permettant de configurer cela devrait être trivial
(Une fois que vous avez compris comment écrire un calque: voir Perldoc Perliol ). P> p>
AVERTISSEMENT, le code suivant n'a été testé que par la lumière. Le code ci-dessous est un premier coup sur une fonction qui vous permettra de traiter une ligne de fichier par ligne (d'où le nom de la fonction) avec une taille de tampon définissable par l'utilisateur. Il faut jusqu'à quatre arguments:
stdin code>) li>
- une taille de tampon (par défaut est 4K) li>
- Une référence à une variable pour stocker la ligne dans (par défaut est
$ _ code>) li>
- Un sous-programme anonyme pour appeler le fichier (la valeur par défaut imprime la ligne). LI>
OL>
Les arguments sont positionnels à l'exception de l'exception que le dernier argument peut toujours être le sous-programme anonyme. Les lignes sont auto-châchées. P>
bugs probables: p>
- peut ne pas fonctionner sur des systèmes où l'alimentation en ligne est le caractère final de la ligne li>
- échouera probablement quand combiné avec un
_ code> (introduit dans Perl 5.10) li>
ul> Vous pouvez voir à partir d'un strace code> qu'il lit le fichier avec la taille de la mémoire tampon spécifiée. Si j'aime comment tester le test, vous pouvez voir ceci sur CPAN bientôt. P> #!/usr/bin/perl
use strict;
use warnings;
use Scalar::Util qw/reftype/;
use Carp;
sub line_by_line {
local $_;
my @args = \(
my $fh = \*STDIN,
my $bufsize = 4*1024,
my $ref = \$_,
my $coderef = sub { print "$_\n" },
);
croak "bad number of arguments" if @_ > @args;
for my $arg_val (@_) {
if (reftype $arg_val eq "CODE") {
${$args[-1]} = $arg_val;
last;
}
my $arg = shift @args;
$$arg = $arg_val;
}
my $buf;
my $overflow ='';
OUTER:
while(sysread $fh, $buf, $bufsize) {
my @lines = split /(\n)/, $buf;
while (@lines) {
my $line = $overflow . shift @lines;
unless (defined $lines[0]) {
$overflow = $line;
next OUTER;
}
$overflow = shift @lines;
if ($overflow eq "\n") {
$overflow = "";
} else {
next OUTER;
}
$$ref = $line;
$coderef->();
}
}
if (length $overflow) {
$$ref = $overflow;
$coderef->();
}
}
my $bufsize = shift;
open my $fh, "<", $0
or die "could not open $0: $!";
my $count;
line_by_line $fh, sub {
$count++ if /lines/;
}, $bufsize;
print "$count\n";
J'ai commencé à jouer avec sysdread code> en réponse à cette question, mais je ne pouvais pas m'appuyer sur la façon d'analyser lignes i> après cela. Cela semble prometteur, mais je me demande s'il ne se révélera toujours plus lentement que la mise en œuvre intégrée de Perl (soumissionnaire nonobstant).
Hé, je n'ai jamais réclamé que cela allait être rapide b>, juste pour que cela lirait les fichiers avec la taille de la mémoire tampon spécifiée. Cela dit, je vais le comparer à l'idiome commun et les résultats feront partie des documents.
Vous pouvez affecter la mémoire tampon si vous utilisez un système d'exploitation qui prend en charge isif vous utilisez perl v5.10 ou plus tard, alors il n'y a pas besoin
Pour créer explicitement un objet SETVBUF code>; Voir le Documentation pour
IO :: Poignée Code> < /a>.
io :: gérer code> comme décrit dans la documentation, car toutes les poignées de fichier sont implicitement bénies dans
io :: gérer code> objets depuis cette sortie. P>
Il serait agréable de poster un lien vers des informations supplémentaires sur les poignées Perl 5.10.
La seule chose différente des versions antérieures est que les poignées sont bénies dans le paquet IO :: Handin. C'est la / seule / différence. En particulier, l'ouverture d'un fichier ne signifie pas que vous pouvez invoquer des méthodes sur la poignée. Vous devez "utiliser io :: gérer" afin que les méthodes soient définies.
Ce n'est pas nouveau dans 5.10; Les titres ont été bénis dans l'IO :: Poignée pendant une longue période (ou, pour la compatibilité à l'envers, dans le fichier de fichiers si cela était chargé). Mais comme elliot dit, les méthodes ne sont pas définies à moins que vous n'utilisiez pas IO :: Poignée.
Le perldelta code> pour v5.13.8 dit "lorsqu'un procédé d'appel sur un fichier de fichiers mourrait car la méthode ne peut pas être résolue, et
io :: fichier code> a Pas été chargé, Perl est maintenant chargé
io :: Fichier Code> via
Exiger code> et tente à nouveau la résolution de la méthode " i> b>.
io :: fichier code> est une sous-classe de
io :: poignée code>, donc les deux sont chargées à la demande (ainsi que
io :: désapproprié code>) et Leurs méthodes peuvent être utilisées sans une instruction code> explicite code>. La première libération publique avec cette installation est PERL V5.14.0 en 2011.
Je suis nécroposting depuis que cela est venu sur Ce fil perlmonks
Ce n'est pas possible Pour utiliser SETVBUF sur Perls à l'aide de Perlio, quelle valeur par défaut depuis la version 5.8.0. Cependant, il y a le Perlio :: Tampersize module sur CPAN qui vous permet de définir le Taille du tampon lors de l'ouverture d'un fichier: P>
use open ':buffersize(65536)';