Was ist schneller: /proc/self/status oder /proc/$$/status...

Alles, was nicht direkt mit Python-Problemen zu tun hat. Dies ist auch der perfekte Platz für Jobangebote.
Antworten
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Wollte mal wissen, was das für einen Unterschied macht:

Code: Alles auswählen

#!/usr/bin/python
# coding: utf-8

import os

def test_self():
    f = open("/proc/self/status")
    c = f.read()
    f.close()


def test_pid1():
    f = open("/proc/%s/status" % os.getpid())
    c = f.read()
    f.close()

path = "/proc/%s/status" % os.getpid()
def test_pid2():
    f = open(path)
    c = f.read()
    f.close()

if __name__ == '__main__':
    from timeit import Timer

    def timeit(name, number):
        t = Timer("test_%s()" % name, "from __main__ import test_%s" % name)
        print "%s:" % name,
        print "%.3fsec" % t.timeit(number)

    number = 300000
    timeit("self", number)
    timeit("pid1", number)
    timeit("pid2", number)
Ergebnis:

Code: Alles auswählen

self: 5.794sec
pid1: 5.815sec
pid2: 5.613sec
Also es ist geringfügig schneller direkt die Nummer zu verwenden, aber nicht, wenn man sie selbst ermitteln muß.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Hm,

wenn ich das hier:

Code: Alles auswählen

def test_self():
    f = open("/proc/self/status")
    c = f.read()
    f.close()
durch das hier

Code: Alles auswählen

path = "/proc/self/status"
def test_self():
    f = open(path)
    c = f.read()
    f.close()
ersetze (damit es mit test_pid2()) vergleichbar ist, dann gleichen sich die Zeiten stark an.

Es scheint also weniger an /proc zu liegen, als an der Implementierung deiner Funktionen. Da "self" in /proc aber ein Symlink auf die entsprechende PID ist, würde ich jetzt mal vermuten, dass da aber ein kleiner "Mehraufwand" besteht. Wobei ich keine Ahnung habe, in wie weit das bei dem virtuellen /proc-System überhaupt eine Rolle spielt - da reicht mein Wissen schlicht nicht aus :)
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Genau den Fall hatte ich doch auch getestet.

Ich hab aber nochmal eine Variante hinzu gefügt:

Code: Alles auswählen

#!/usr/bin/python
# coding: utf-8

import os

def test_self():
    f = open("/proc/self/status")
    c = f.read()
    f.close()


def test_pid1():
    f = open("/proc/%s/status" % os.getpid())
    c = f.read()
    f.close()

pid = os.getpid()
def test_pid2():
    f = open("/proc/%s/status" % pid)
    c = f.read()
    f.close()

path = "/proc/%s/status" % os.getpid()
def test_pid3():
    f = open(path)
    c = f.read()
    f.close()

if __name__ == '__main__':
    from timeit import Timer

    def timeit(name, number):
        t = Timer("test_%s()" % name, "from __main__ import test_%s" % name)
        print "%s:" % name,
        print "%.3fsec" % t.timeit(number)

    number = 300000
    timeit("self", number)
    timeit("pid1", number)
    timeit("pid2", number)
    timeit("pid3", number)
Ergebnis:

Code: Alles auswählen

self: 5.784sec
pid1: 5.824sec
pid2: 5.757sec
pid3: 5.718sec

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Und jetzt der Realitaetscheck: Der Unterschied pro Operation zwischen der schnellsten und der langsamsten Variante liegt im unteren Mikrosekundenbereich.
lunar

@jens: Das einzige, was Du damit wirklich verlässlich misst, sind die Kosten des Aufrufs von "os.getpid()" im "pid1"-Test im Unterschied zu den anderen Testfällen. Die Differenzen zwischen diesen anderen Testfällen selbst würde ich persönlich auf Caching, Scheduling und diverse andere Nebenwirkungen im Kernel schieben. Der tatsächliche Unterschied liegt – wie cofi schon festgestellt hat – wohl eher weit unterhalb der Relevanzgrenze, wahrscheinlich sogar weit unterhalb dessen, was man mit Python und der ganzen Laufzeitumgebung dahinter überhaupt zuverlässig messen kann.

Und im Allgemeinen ist es eine ganz blöde Idee, die PID auf Modul-Ebene zu speichern.
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Hallo,

> Genau den Fall hatte ich doch auch getestet

Ne, was ich meinte war, dass es einen Unterschied macht, ob man einen String wie "/proc/self/status" bei jedem Funktionsaufruf erzeugt (wird das egtl. irgendwie gecacht?) oder ob man eine Variable verwendet.

Wenn es stimmt, dass das String-Objekt jedes Mal neu erzeugt werden muss, könnte die derzeitig schnellste Variante auch deshalb so schnell sein, weil da nur eine Variable ausgelesen werden muss und bei allen anderen Varianten jeweils String-Objekte erzeugt werden.

Wie Lunar und Cofi erscheinen mir diese Messungen ohnehin nicht ganz zuverlässig. Aber wenn du /proc/self gegenüber /proc/$$ vergleichen möchtest, solltest du schon darauf achten, dass du entweder in jeder Funktion eine Variable ausliest oder in jeder Funktion einen String erzeugst. So wie du das jetzt machst, hast du ja zwei "Variablen": Einmal "/proc/self/status" vs. "/proc/$$/status" und einmal "String erzeugen" vs. "Variable path auslesen".

Momentan lassen deine Ergebnisse nicht notwendig den Schluss zu, dass "/proc/$$/status" schneller ist, theoretisch könnte ich ja noch immer behaupten, dass "/proc/self/status" schneller ist und nur darum schlechter abschneidet, weil du da in der Funktion zusätzlich jedes Mal einen String erzeugst.

Sorry, etwas viel blabla. Wollte nur verdeutlichen, was ich meinte :)
Antworten