Estoy evaluando la expresión 6^6^6
usando python
y por bc
separado.
El contenido del archivo python es print 6**6**6
. Cuando ejecuto time python test.py
, obtengo la salida como
real 0m0.067s
user 0m0.050s
sys 0m0.011s
Y luego, ejecuté el comando time echo 6^6^6 | bc
que me dio el siguiente resultado
real 0m0.205s
user 0m0.197s
sys 0m0.005s
A partir de estos resultados, está claro que el tiempo del sistema tomado por python y bc fue de 11 ms y 5 ms respectivamente. El comando bc superó a Python en el nivel de tiempo del sistema, pero en lo que respecta al usuario y a Python en tiempo real fue casi 4 veces más rápido que bc . Lo que pudo haber ido allí. No he dado ninguna prioridad a los procesos como tal. Estoy tratando de entender esta situación.
python
performance
process-management
bc
ganessh
fuente
fuente
echo | bc
implica el lanzamiento de una subshell debido a la canalización, de ahí es probable que provenga parte de su tiempo de usuario adicional. Para hacer de esto una prueba equitativa, el script de Python debe leer de stdin para que puedatime echo 6**6**6 | whatever.py
.echo 6^6^6 | time bc
.6**6**6
expresión se calcula en tiempo de compilación . Sin embargo, dado que está iniciando el archivo directamente en lugar de importarlo desde un módulo, esto no debería importar. Para ver la diferencia puesta10**12345678
en una.py
archivo e intentar importarlo desde el intérprete interactivo. Luego cierre el intérprete, reinícielo e importea
nuevamente. La primera vez debería llevar una cantidad de tiempo notable (porque Python está compilando el módulo), mientras que la segunda vez carga el.pyc
, que debería ser instantáneo,Respuestas:
Python importa una gran cantidad de archivos al inicio:
Cada uno de estos requiere un número aún mayor de intentos de abrir un archivo Python, porque hay muchas formas de definir un módulo:
Cada "intento", excepto los que están integrados, requiere un nivel de sistema operativo / llamadas al sistema, y cada "importación" parece desencadenar alrededor de 8 mensajes de "intento". (Hubo formas de reducir esto usando zipimport, y cada ruta en su PYTHONPATH puede requerir otra llamada).
Esto significa que hay casi 200 llamadas al sistema de estadísticas antes de que Python se inicie en mi máquina, y "time" asigna eso a "sys" en lugar de "usuario", porque el programa de usuario está esperando que el sistema haga las cosas.
En comparación, y como dijo terdon, "bc" no tiene ese alto costo inicial. Al observar la salida de dtruss (tengo una Mac; "strace" para un sistema operativo basado en Linux), veo que bc no hace ninguna llamada al sistema open () o stat (), excepto para cargar algunas compartidas las bibliotecas son el comienzo, que por supuesto Python también lo hace. Además, Python tiene más archivos para leer, antes de que esté listo para procesar cualquier cosa.
Esperar el disco es lento.
Puede tener una idea del costo de inicio de Python haciendo:
Son 0.032s en mi máquina, mientras que 'print 6 ** 6 ** 6' es 0.072s, por lo que el costo de inicio es 1 / 2rd del tiempo total y el cálculo + conversión a decimal es la otra mitad. Mientras:
toma 0.005s, y "6 ^ 6 ^ 6" toma 0.184s por lo que la exponenciación de bc es 4 veces más lenta que la de Python a pesar de que es 7 veces más rápido para comenzar.
fuente
Encontré una buena respuesta en SO que explica los diferentes campos:
Entonces, en su ejemplo específico, la versión de Python es más rápida en términos del tiempo real que lleva completar. Sin embargo, el enfoque de Python pasa más tiempo en el espacio del núcleo, haciendo llamadas a las funciones del núcleo. El
bc
comando no pasa esencialmente tiempo en el espacio del kernel y todo su tiempo se gasta en el espacio del usuario, presumiblemente ejecutandobc
código interno .Esto no hace ninguna diferencia para usted, la única información que realmente le importa es
real
cuál es el tiempo real transcurrido entre el lanzamiento del comando y la obtención de su salida.También debe tener en cuenta que estas pequeñas diferencias no son estables, también dependerán de la carga de su sistema y cambiarán cada vez que ejecute el comando:
fuente
Lo explicaré desde otra perspectiva.
Para ser justos,
bc
tiene ventaja ya que no tiene que leer nada del disco y solo necesita sus blob / binarios, mientras que python tiene que importar una serie de módulos + leer un archivo. Entonces su prueba puede estar sesgada haciabc
. Para probarlo realmente debes usarbc -q file
wherefile
contiene:Cambiar solo eso modificó el tiempo de uso
echo
:Para usar el archivo:
(deberá usar el método de terdon para notar mayores diferencias, pero al menos sabemos que lo son)
Ahora, desde la perspectiva de Python, Python necesita leer desde el disco, compilar y ejecutar cada vez que el archivo, además de cargar módulos como señala Andrew , lo que hace que el tiempo de ejecución sea más lento. Si compila el código de bytes del script de Python, notará que se necesita un 50% menos de tiempo total para ejecutar el código:
compilado:
Como puede ver, hay varios factores que pueden afectar la ejecución del tiempo entre diferentes herramientas.
fuente
He tenido el beneficio de leer las otras respuestas. Para empezar la gente como yo deben saber la razón por la que estamos tratando con un enorme número entero tal aquí es que tanto
Python
ybc
hacer asociativo por la derecha expansión exponencial, lo que significa que este no es6^36
que estamos evaluando, sino6^46656
que es considerablemente más grande. 1Usando variaciones en los siguientes comandos, podemos extraer un promedio para un elemento específico de la salida de la
time
palabra reservada y el comando:Es posible ir a otra ruta y eliminar el archivo por completo de la comparación. Además, podemos comparar el tiempo de bc con algo como el
dc
comando, ya que históricamente el primero es un "procesador frontal" para el segundo. Los siguientes comandos fueron cronometrados:Tenga en cuenta que el
dc
comando es asociativo a la izquierda para exponenciación. 2Tenemos algunos resultados con
time
(bash) para 1000 iteraciones (en segundos):bc
ydc
ofrecer un rendimiento comparable en este contexto.Resultados menos precisos 3,
/usr/bin/time
es decir,time
comando GNU (la precisión de la escala no es válida aquí pero los resultados son similares):Una ventaja de esto
/usr/bin/time
es que ofrece la-v
opción que produce mucha más información que podría ser útil eventualmente.También es posible evaluar esto internamente, por así decirlo con el
timeit
módulo Python:Eso es un poco más rápido de lo que vimos antes. Probemos con el propio intérprete:
Eso es lo más rápido que he visto.
Si evaluamos una exponenciación menor
6^6
, entonces el comando de tiempo arroja resultados sorprendentes: usando los mismosfor
comandos de bucle que usamos ahora tenemos:Entonces, ¿con un número entero más pequeño
bc
es de repente mucho más rápido? Desde el reinicio del sistema hasta la segunda ejecución no hay diferencia. Sin embargo, al mismo tiempo, si usamostimeit
para Python, obtenemos:Esto es microsegundos , no milisegundos, por lo que esto no coincide con los resultados mucho más lentos utilizando el
for
bucle. Tal vez se requieran otras herramientas para probar esto más y, como otros han explicado, hay más de lo que parece a simple vista. Parece que Python fue más rápido en el escenario de la pregunta, pero no está claro si se pueden sacar conclusiones más allá de eso ...1. No hace falta decir que está más allá del alcance de algo como la expansión aritmética del eco, es decir
echo $((6**6**6))
,bash
también resulta ser una asociación correcta para eso6^6^6 = 6^(6^6)
.2. Comparar con esto:
6 6 ^ 6 ^ p
.3. Es posible que el comando de tiempo de GNU proporcione más información cuando se ejecuta en BSD UNIX (documento de información de tiempo de GNU): la mayor parte de la información mostrada por 'tiempo' se deriva de la llamada al sistema 'wait3'. Los números son tan buenos como los devueltos por 'wait3'. Muchos sistemas no miden todos los recursos sobre los que puede informar el "tiempo"; esos recursos se informan como cero. Los sistemas que miden la mayoría o la totalidad de los recursos se basan en 4.2 o 4.3BSD. Las versiones posteriores de BSD utilizan un código de administración de memoria diferente que mide menos recursos. - En los sistemas que no tienen una llamada 'wait3' que devuelve información de estado, en su lugar se usa la llamada del sistema 'times'. Proporciona mucha menos información que 'wait3', por lo que en esos sistemas el 'tiempo' informa que la mayoría de los recursos son cero.
fuente