ID3 Tags auslesen zu langsam

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
JonasR
User
Beiträge: 251
Registriert: Mittwoch 12. Mai 2010, 13:59

Hey leute,

ich habe mich mal dran versucht ID3 Tags von den MP3s auf meiner Platte auszulesen. Das ganze klappt an sich ganz gut nur ist es für mich zu langsam :-/
Gibts da noch irgendetwas das ich optimieren kann? Für 175 Lieder brauche ich ca 3,3 Sekunden... Da ich 12k Songs habe und das fertige programm mit GUI etc gerne veröffentlichen würde wäre es cool wenn es schneller gehen würde.

Ist nur die Frage ob es eine Softwareseitige oder Hardwareseitige Limitierung der Geschwindigkeit ist.

Hardwarespecs:
CPU: Core2Duo E8400@2x3Ghz
RAM: 6GB DDR2
Festplatten: 2x WD Caviar Black im Raid0 =)

An sich sollte man meinen das sollte ein bisschen was wegschaffen also was meint ihr?

Code: Alles auswählen

# -*- coding: utf-8 -*-
import time, os
import mimetypes
from mutagen.id3 import ID3
from mutagen.id3 import ID3NoHeaderError

# Starte Timer für die Zeitmessung
start = time.time()

def get_dirs(basedir):
    for root, dirs, files in os.walk(basedir):
        def file_assign_type(file):
            file_path = os.path.join(root, file)
            if "audio" in str(mimetypes.guess_type(file_path)[0]):
                try:
                    audio = ID3(file_path)
#                    print "##################################"
#                    print "Album : %s" % audio["TALB"].text[0]
#                    print "Titelnummer : %s" % audio["TRCK"]
#                    print "Genre : %s" % audio["TCON"]
#                    print "Artist: %s" % audio['TPE1'].text[0]
#                    print "Track: %s" % audio["TIT2"].text[0]
#                    print "Release Year: %s" % audio["TDRC"].text[0]
                except KeyError:
                    pass
                except ID3NoHeaderError:
                    pass
            elif "image" in str(mimetypes.guess_type(file_path)[0]):
                pass
            else:
                pass

        map(file_assign_type, files)

start_time = time.time()

base_dir = os.path.join("X:\\", "Music")
get_dirs(base_dir)

print "Used time: %f" % (time.time() - start_time)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Bastel doch einen Dialog, indem der Fortschritt angezeigt wird. Also in der Art:
"Lese Song xyz aus, bisher (XYZ Stück gelesen)"

Das "map(file_assign_type, files)" ist unschön; du wirfst die Liste ja sofort wieder weg. Schreib da lieber eine for-Schleife.

Die Namensgebung halte ich auch für wenig eingängig. get_dirs() verarbeitet ja doch schon Audio-Dateien und generiert kein Iterable, welches Verzeichnispfade enthält. Genau das würde ich bei dem Namen erwarten ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
JonasR
User
Beiträge: 251
Registriert: Mittwoch 12. Mai 2010, 13:59

Hehe Namen habe ich eben sinnvoller gestaltet :P Dachte immer map ist schneller als ne for schleife... Ist das nicht so?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

JonasR hat geschrieben:Dachte immer map ist schneller als ne for schleife... Ist das nicht so?
Wie kommst Du darauf? Vor allem erzeugt map() eine Liste - damit verbrauchst Du erst einmal Speicher, den Du ja eigentlich nicht nutzt.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
JonasR
User
Beiträge: 251
Registriert: Mittwoch 12. Mai 2010, 13:59

Ich weiß nicht irgendwie ist mir so als hätte ich es mal gelesen :D Naja ist jetzt zu einer "for" Schleife geworden ;) Sonst gibts da nichts das ich beschleunigen könnte?
deets

Ein paar Anmerkungen:

- deine file_assign_type-Funktion definierst du immer wieder neu. Das ist voellig unnoetig, und erschwert im uebrigen das verstaendnis

- dein gesamter code ist ja hochgradig trivial. wenn der also so langsam laeuft, dann liegt es wohl nicht daran, sondern an was anderem.

Um dem auf die Schliche zu kommen, musst du variablen aus der Gleichung nehmen. Um mal die reine Platten-Performance zu testen, wuerde ich statt dem ID3(file_path) ein open(file_path).read() machen. Unter Umstaenden sogar eher sowas wie open(file_path).read(mp3_header_size), falls die ID3-Lib das auch nur so macht.

Damit solltest du dann sozusagen die reine System-Performance testen koennen. Wenn die im selben Bereich liegt, dann ist das halt so, und du musst damit leben.

Wenn's schneller ist, dann liegt das ganze an der ID3-Lib. Da musst du dann schauen, was man da machen kann. Uu koennte man Dinge parallelisieren mittels threading, um IO-Wartezeiten zu eliminieren. Das bringt aber nur beschraenkt viel, wenn wie gesagt die Platten-IO schnell genug ist.

Und sonst bleibt noch multi-processing. Und natuerlich profiling.

Jetzt, wo ich den ganzen Rums geschrieben habe, wuerde ich am liebsten alles loeschen und einfach nur den letzten Satz schreiben ;) Profiling it is. Benutz den Python-Profiler, damit lernst du, was wie lange dauert. Wenn es die file-OPs sind, dann hast du Pech. Wenn nicht, dann kannst du optimieren.
deets

JonasR hat geschrieben:Ich weiß nicht irgendwie ist mir so als hätte ich es mal gelesen :D Naja ist jetzt zu einer "for" Schleife geworden ;) Sonst gibts da nichts das ich beschleunigen könnte?
Das war irgendwann mal so, und vielleicht ist es das sogar immer noch ein gaaaaanz kleines bisschen. Aber da reden wir ueber Microsekunden, bei deinen 175 Iterationen kommst du da noch nicht mal auf einen Liedschlag.
JonasR
User
Beiträge: 251
Registriert: Mittwoch 12. Mai 2010, 13:59

Hey deets,

Die file_assign_type-Funktion habe ich ja bereits gegen eine for Schleife ersetzt.
Mir ist nicht bewusst wie ich meinen Code... komplexer machen soll bzw was man an den par Zeilen überhaupt so viel anders machen kann. Aber genau das war ja auch teilweise der Sinn des Threads dies heraus zu finden.
Für die 175 Datein brauche ich inzwischen nur noch ca 0,14 Sekunden für alle 12k ca 220 Sekunden.
Eigentlich ganz gute Werte :D mal schauen ob man da trotzdem etwas drehen kann.
Ich werde mich mal an das von dir genannte Profiling setzen.

Danke euch beiden schon mal

€ Achja mit open(file_path).read() dauern 175 Songs 20 Sekunden
deets

Verstehe ich nicht - was genau hast du denn geaendert? Nur die for-schleife statt map? Das erklaert den Geschwindigkeitzuwachs nicht.

Aber wenn's jetzt schnell ist, super. Und offensichtlich macht ID3 nix idiotisches, wenn das lesen laenger dauert.
Antworten