J'utilise cette méthode pour traiter un seul fichier texte d'environ 220 000 lignes. Il faut quelques minutes pour en traiter un, mais j'en ai beaucoup. Y a-t-il des recommandations pour accélérer ce processus?Comment améliorer les performances d'un processus en convertissant un fichier en tableau de hachages?
def parse_list(file_path,import=false)
# Parse the fixed-length fields
if File.exist?(file_path)
result=[]
File.readlines(file_path)[5..-1].each do |rs|
if rs.length > 140
r=rs.strip
unless r==''
filing={
'name' => r[0..50].strip,
'form' => r[51..70].strip,
'type' => r[71..80].strip,
'date' => r[81..90].strip,
'location' => r[91..-1].strip
}
result.push(filing)
end
end
end
return result
else
return false
end
end
Mise à jour:
Au départ, je pensais qu'il y avait des économies de temps massives de l'utilisation Nex et les méthodes de thetinman alors je suis allé à les tester en gardant la méthode d'analyse cohérente.
En utilisant ma méthode originale r[].strip
d'analyse syntaxique, mais avec la méthode des blocs de Nex each_line
et foreach
méthodes de thetinman:
Rehearsal ---------------------------------------------
Nex 8.260000 0.130000 8.390000 ( 8.394067)
Thetinman 9.740000 0.120000 9.860000 ( 9.862880)
----------------------------------- total: 18.250000sec
user system total real
Nex 14.270000 0.140000 14.410000 (14.397286)
Thetinman 19.030000 0.080000 19.110000 (19.118621)
en cours en utilisant à nouveau unpack.map
méthode d'analyse syntaxique de thetinman:
Rehearsal ---------------------------------------------
Nex 9.580000 0.120000 9.700000 ( 9.694327)
Thetinman 11.470000 0.090000 11.560000 (11.567294)
----------------------------------- total: 21.260000sec
user system total real
Nex 15.480000 0.120000 15.600000 (15.599319)
Thetinman 18.150000 0.070000 18.220000 (18.217744)
unpack.map(&:strip)
vs r[].strip
: unpack
avec map
ne semble pas augmenter la vitesse, mais est une méthode intéressante à utiliser A l'avenir.
J'ai trouvé un problème différent: Avec les gains de temps substantiels trouvés, je pensais, j'ai continué à exécuter les méthodes de Nex et thetinman manuellement en utilisant pry. C'est là que j'ai trouvé mon ordinateur suspendu, tout comme mon code d'origine. Alors j'ai continué à tester, mais avec mon code d'origine.
Rehearsal ---------------------------------------------
Original 7.980000 0.140000 8.120000 ( 8.118340)
Nex 9.460000 0.080000 9.540000 ( 9.546889)
Thetinman 10.980000 0.070000 11.050000 (11.042459)
----------------------------------- total: 28.710000sec
user system total real
Original 16.280000 0.140000 16.420000 (16.414070)
Nex 15.370000 0.080000 15.450000 (15.454174)
Thetinman 20.100000 0.090000 20.190000 (20.195533)
Mon code, Nex, et les méthodes de thetinman semblent comparables, avec Nex étant le plus rapide à l'aide de référence. Cependant, Benchmark ne semble pas raconter toute l'histoire, car l'utilisation de pry pour tester le code manuellement prend toutes les méthodes pour prendre beaucoup plus de temps, si longtemps que je m'annule avant d'obtenir le résultat.
J'ai quelques autres questions:
- Y at-il quelque chose de spécifique sur l'exécution quelque chose comme ceci dans IRB/Pry qui produirait ces résultats étranges, ce qui rend le code plus lent exécuter massivement?
- Si je cours
original_method.count
,nex_method.count
, outhetinmans_method.count
, ils semblent tous revenir rapidement. - En raison de problèmes de mémoire et d'évolutivité, thetinman et nex recommandent que la méthode d'origine ne soit pas utilisée. Cependant, à l'avenir, existe-t-il des moyens de tester l'utilisation de la mémoire avec quelque chose comme un benchmark?
Mise à jour pour NEX, en utilisant activerecord-import
:
@nex, est-ce que vous voulez dire? Cela semble être lent pour moi encore, mais je ne suis pas sûr de ce que vous voulez dire quand vous dites:
importer un ensemble de données à l'intérieur de ce bloc.
Comment recommandez-vous de le modifier?
def parse_line(line)
filing={
'name' => line[0..50].strip,
'form' => line[51..70].strip,
'type' => line[71..80].strip,
'date' => line[81..90].strip,
'location' => line[91..-1].strip
}
end
def import_files
result=[]
parse_list_nix(file_path){|line|
filing=parse_line(line)
result.push(Filing.new(filing))
}
Filing.import result #result is an array of new records that are all imported at once
end
Les résultats de la méthode activerecord-import
sont, comme vous pouvez le voir, beaucoup plus lent:
Rehearsal ------------------------------------------
import 534.840000 1.860000 536.700000 (553.507644)
------------------------------- total: 536.700000sec
user system total real
import 263.220000 1.320000 264.540000 (282.751891)
Est-ce que ce processus d'importation lent semble normal?
Cela me semble super lent. J'essaie de comprendre comment accélérer ça, mais je n'ai plus d'idées.
Vous ne nous avez pas donné de données échantillon pour travailler à partir, donc nous n'avons pas une base pour tester avec. Dans vos tests, supprimez tout sauf votre méthode de lecture de fichier et modifiez-la jusqu'à ce qu'elle soit aussi rapide que vos données, en gardant à l'esprit que vous ne voulez PAS tout extraire dans la RAM parce que ce n'est pas évolutif. Puis ajoutez la division et importez et répétez les tests. Vous ne pouvez pas utiliser pry, ou IRB, ou un débogueur, avec Benchmark et attendre des résultats réalistes. Ils gênent la façon dont le script fonctionne comme un effet secondaire des commodités qu'ils offrent et qui se traduit par un code de fonctionnement plus lent. –
Vous n'avez pas dit combien de fichiers vous chargez, mais 5-8 minutes pour charger un tas de fichiers 220K-ligne une fois par jour ne vous inquiétez pas. Si cela semble lent, vous pouvez utiliser des threads pour charger plusieurs fichiers à la fois, ou les traiter et les charger directement, car vous avez besoin de champs de largeur fixe, ce qui chargera probablement tout un chargement plus rapide car il est probablement compilé code spécifique à l'application. –
@thetinman, Il faut environ 6-9 minutes par fichier pour importer (voir le test de performance ci-dessus). J'ai besoin d'importer une vingtaine de fichiers. Vous avez de bonnes suggestions. J'aime votre suggestion d'importer directement dans la base de données. Je vais chercher comment c'est fait. Je n'ai pas appris les processus de filetage, ou de forking, mais j'y penserai aussi. Si vous avez de bons liens, s'il vous plaît envoyez-les moi. Merci encore! – user2012677