2017-03-02 4 views
1

Was ist das Zeitachsenverhalten der TCL mit hoher Auflösung "exec"? Ich verstehe, dass ein "Gabel" -Befehl verwendet wird, der zunächst eine Kopie des Speicherabbilds des Prozesses erstellt und dann fortfährt.Zeitaufgelöster Speicherbedarf der TCL exec

Hier ist die Motivation für meine Frage:

Ein Benutzer mich Beobachtung nach gab. Eine 64-GB-Maschine verfügt über eine TCL-basierte Werkzeugschnittstelle mit 60 GB Speicher. (Nehmen wir an, der Tausch ist klein). An der TCL-Eingabeaufforderung gibt er "Exec ls" und der Prozess stürzt mit einem Speicherfehler ab.

Sie Einblick wird sehr geschätzt. Danke, Gert

+0

Gute Frage! _Tricky_ Frage auch. –

Antwort

1

Der exec Befehl wird den fork() Systemaufruf intern nennen. Dies ist normalerweise in Ordnung, aber es kann sein, dass der Arbeitsspeicher erschöpft ist, wenn das Betriebssystem so konfiguriert ist, dass es nicht vertauscht wird und der ursprüngliche Tcl-Prozess sehr groß ist (oder wenn nur sehr wenig Speicherplatz zur Verfügung steht; abhängig von der tatsächlichen Situation).

Die Ideen, die ich für die Verringerung der Speichernutzung haben, sind entweder vfork() mit (von tclUnixPipe.c Patchen, man USE_VFORK in der Make-Datei, das zu ermöglichen, definieren kann, und ich weiß nicht, warum das nicht mehr weit verbreitet ist) oder durch Erstellen eines Hilfsprozesses früh (vor viel Speicher verwendet wird), die die exec s im Namen Ihres Hauptprozesses tun wird. Hier ist, wie die letztere Option zu tun:

# This is setup done at the start 
set forkerProcess [open "|tclsh" r+] 
fconfigure $forkerProcess -buffering line -blocking 0 
puts $forkerProcess { 
    fconfigure stdout -buffering none 
    set tcl_prompt1 "" 
    set tcl_prompt2 "" 
    set tcl_interactive 0 
    proc exechelper args { 
     catch {exec {*}$args} value options 
     puts [list [list $value $options]] 
    } 
} 
# TRICKY BIT: Yield and drain anything unwanted 
after 25 
read $forkerProcess 

# Call this, just like exec, to run programs without memory hazards 
proc do-exec args { 
    global forkerProcess 
    fconfigure $forkerProcess -blocking 1 
    puts $forkerProcess [list exechelper {*}$args] 
    set result [gets $forkerProcess] 
    fconfigure $forkerProcess -blocking 0 
    while {![info complete $result]} { 
     append result \n [read $forkerProcess] 
    } 
    lassign [lindex $result 0] value options 
    return -options $options $value 
} 
+0

Dieser Kommentar wurde gefunden: "Bei den meisten aktuellen Kerneln, einschließlich Linux, ist der Hauptvorteil von vfork aufgrund der Implementierung von fork verschwunden. Anstatt das gesamte Image zu kopieren, wenn fork ausgeführt wird, werden Copy-on-Write-Techniken verwendet . " Also kommt es in gewissem Umfang auf das Betriebssystem an. –

+0

@BradLanam Das würde man meinen, aber es stellt sich heraus, dass die tatsächlichen Duplizierungskosten immer noch ein wesentliches Problem sind. Ich sehe das mehr mit Java-Anwendungen (wo das Arbeiten mit Pipes _seriously nervig ist_), aber die Symptome sind ziemlich klar. OTOH, das Problem mit Vfork ist, dass der Elternprozess heutzutage viel weniger wahrscheinlich ist, zu stoppen und zu warten, aufgrund des weit verbreiteten Threads. –

+0

Ein Aufruf von fork() schlägt fehl, wenn das System nicht festlegt, dass Speicher für die Copy-on-Write-Seiten verfügbar ist. Die Verwendung von Copy-on-Write hilft bei der Leistung, nicht aber bei der Größe. Wenn Overcommit aktiviert ist, wird Linux mehr Speicher bereitstellen (DRAM + Swap) als wirklich beendet. Wenn es jedoch ausgeht, wird der Manager für nicht genügend Arbeitsspeicher wie ein Sicherheitsbeamter auf einem United-Flug erscheinen und einen laufenden Prozess entfernen. –

Verwandte Themen