in den letzten Tage habe ich mich etwas damit beschäftigt, was denn so passiert, wenn ich einen Code ausführe. Ursprung war ein Python-Code den ich "gefunden" hatte und dem man auch schon ansieht, dass man das so nicht programmieren würde. Ich habe ihn wie er ist einfach mal in eine Funktion gesteckt und die Zeit gemessen.
Code: Alles auswählen
from time import monotonic
def get_prime():
prim_counter = 0
prim_pruefzahl = 0
zahl = 1
prime = []
while prim_counter < 10001:
for teiler in range(1, zahl):
if zahl % teiler == 0:
prim_pruefzahl += 1
if prim_pruefzahl == 1:
prime.append(zahl)
prim_counter += 1
else:
prim_pruefzahl = 0
zahl += 1
return prime
def main():
start = monotonic()
print(get_prime()[-1])
print(f"Dauer {monotonic() - start:.2f} s")
if __name__ == '__main__':
main()
Code: Alles auswählen
[dennis@dennis ~]$ ~/PycharmProjects/Forum/.venv/bin/python ~/PycharmProjects/Forum/cpython.py
104759
Dauer 511.75 s
Wir eine Funktion bei jedem Aufruf erneut übersetzt? Ja oder?
Es gibt `Numba` mit dem Just-in-time-Dekorator. Das wollte ich testen:
Code: Alles auswählen
from time import monotonic
from numba import njit
@njit
def get_prime():
prim_counter = 0
prim_pruefzahl = 0
zahl = 1
prime = []
while prim_counter < 10001:
for teiler in range(1, zahl):
if zahl % teiler == 0:
prim_pruefzahl += 1
if prim_pruefzahl == 1:
prime.append(zahl)
prim_counter += 1
else:
prim_pruefzahl = 0
zahl += 1
return prime
def main():
start = monotonic()
print(get_prime()[-1])
print(f"Dauer {monotonic() - start:.2f} s")
if __name__ == '__main__':
main()
Code: Alles auswählen
[dennis@dennis ~]$ ~/PycharmProjects/Forum/.venv/bin/python ~/PycharmProjects/Forum/njit_test.py
104759
Dauer 17.73 s
Wenn ich davon ausgehe, dass das dynamische an Python der Punkt ist, der viel Zeit braucht, dann war es für mich naheliegend, dass wenn ich eine statische Sprache verwende und direkt den kompilierten Code ausführe, dann müsste ich am schnellsten sein.
Also habe ich den Code stumpf in `Rust` übersetzt:
Code: Alles auswählen
use std::time::Instant;
fn get_prime() -> Vec<i32> {
let mut prim_counter: i32 = 0;
let mut prim_pruefzahl: i32 = 0;
let mut zahl: i32 = 1;
let mut prime: Vec<i32> = Vec::with_capacity(1000);
while prim_counter < 10001 {
for teiler in 1..zahl {
if zahl % teiler == 0 {
prim_pruefzahl += 1;
};
};
if prim_pruefzahl == 1 {
prime.push(zahl);
prim_counter += 1;
} else {
prim_pruefzahl = 0;
};
zahl += 1;
}
prime
}
fn main() {
let start = Instant::now();
let prime = get_prime();
println!("{:?}", prime.last());
println!("Dauer: {:.2?}", start.elapsed());
}
Ergebnis:
Code: Alles auswählen
[dennis@dennis ~]$ ./rust_test/main
Some(104759)
Dauer: 61.26s
Wird der Code eigentlich direkt, egal von welcher Sprache, in Maschinencode übersetzt? Weil ich kann mit `dis` in Python den Assembler Code anschauen, in den der Python Code übersetzt wird. Wird der dann vor der Ausführung noch einmal von `Assembler` übersetzt? So wie ich das verstanden habe, ist `Assembler` die hardwarenähste Sprache, die noch von Menschen lesbar ist.(?)
Ich weis das sind wieder viele Fragen, aber ich finde es einfach so interessant was denn im Detail passiert, wenn ich einen Code ausführe.
Freue mich wenn ihr etwas Zeit für Erklärungen habt.
Danke und Grüße
Dennis