Escribí el siguiente script para probar la velocidad de la funcionalidad de clasificación de Python:
from sys import stdin, stdout
lines = list(stdin)
lines.sort()
stdout.writelines(lines)
Luego comparé esto con el sortcomando coreutils en un archivo que contiene 10 millones de líneas:
$ time python sort.py <numbers.txt >s1.txt
real 0m16.707s
user 0m16.288s
sys 0m0.420s
$ time sort <numbers.txt >s2.txt
real 0m45.141s
user 2m28.304s
sys 0m0.380s
El comando incorporado usó las cuatro CPU (Python solo usó una) pero tardó aproximadamente 3 veces más en ejecutarse. ¿Lo que da?
Estoy usando Ubuntu 12.04.5 (32 bits), Python 2.7.3 y sort8.13

--buffer-sizepara especificar quesortuse toda la memoria física disponible y ver si eso ayuda?Respuestas:
El comentario de Izkata reveló la respuesta: comparaciones específicas de la localidad. El
sortcomando usa la configuración regional indicada por el entorno, mientras que Python tiene por defecto una comparación de orden de bytes. Comparar cadenas UTF-8 es más difícil que comparar cadenas de bytes.Qué hay sobre eso.
fuente
locale.strxfrmpara ordenar, el script tardó ~ 32 segundos, aún más rápidosortpero mucho menos.cut, y otros también. En varias máquinas que ahora tengoexport LC_ALL=Cen.bashrc. Pero cuidado: esto esencialmente se rompewc(exceptowc -l), solo por nombrar un ejemplo. Los "bytes incorrectos" no se cuentan en absoluto ...grep: puede obtener una mejora sustancial en el rendimiento al agrupar archivos de gran tamaño deshabilitando UTF-8, especialmente cuando se hacegrep -iEsto es más un análisis adicional que una respuesta real, pero parece variar según los datos que se ordenan. Primero, una lectura base:
OK, Python es mucho más rápido. Sin embargo, puede hacer que los coreutils sean
sortmás rápidos diciéndole que ordene numéricamente:Eso es mucho más rápido, pero Python aún gana por un amplio margen. Ahora, intentemos de nuevo pero con una lista no ordenada de números 1M:
Coreutils
sort -nes más rápido para datos numéricos sin clasificar (aunque es posible que pueda modificar elcmpparámetro de ordenación de Python para hacerlo más rápido). Coreutilssortsigue siendo significativamente más lento sin la-nbandera. Entonces, ¿qué pasa con los caracteres aleatorios, no con los números puros?Python aún supera a los coreutils pero por un margen mucho menor que el que muestra en su pregunta. Sorprendentemente, aún es más rápido cuando se observan datos alfabéticos puros:
También es importante tener en cuenta que los dos no producen la misma salida ordenada:
Por extraño que parezca, la
--buffer-sizeopción no parecía hacer mucha (o ninguna) diferencia en mis pruebas. En conclusión, presumiblemente debido a los diferentes algoritmos mencionados en la respuesta de goldilock, pythonsortparece ser más rápido en la mayoría de los casos, pero GNU numérico losortsupera en números no ordenados 1 .El OP probablemente ha encontrado la causa raíz, pero en aras de la exhaustividad, aquí hay una comparación final:
1 Alguien con más python-fu del que debería intentar probar los ajustes
list.sort()para ver que se puede lograr la misma velocidad especificando el método de clasificación.fuente
sortparece estar haciendo un poco de trabajo extra para las comparaciones en mayúsculas / minúsculas.stdinentrada sin formato. La conversión de los números de (lines = map(int, list(stdin))) y de vuelta (stdout.writelines(map(str,lines))) hace que toda la clasificación ir más lento, hasta de 0.234s real para 0.720s en mi máquina.Ambas implementaciones están en C, por lo que hay igualdad de condiciones allí. Coreutils
sortaparentemente usa el algoritmo mergesort . Mergesort realiza un número fijo de comparaciones que aumenta logarítmicamente al tamaño de entrada, es decir, O grande (n log n).La clasificación de Python utiliza una combinación híbrida / inserción híbrida única, timsort , que realizará un número variable de comparaciones con el mejor de los casos de O (n), presumiblemente, en una lista ya ordenada, pero generalmente es logarítmica (lógicamente, usted no puede ser mejor que logarítmico para el caso general al ordenar).
Dados dos tipos logarítmicos diferentes, uno podría tener una ventaja sobre el otro en algún conjunto de datos en particular. Un tipo de fusión tradicional no varía, por lo que realizará el mismo independientemente de los datos, pero, por ejemplo, la clasificación rápida (también logarítmica), que varía, funcionará mejor en algunos datos pero peor en otros.
Sin
sortembargo, un factor de tres (o más de 3, ya que está en paralelo) es bastante, lo que me hace preguntarme si no hay alguna contingencia aquí, comosortcambiar a disco (la-Topción parece implicar que sí lo hace). Sin embargo, su bajo tiempo de sistema vs. usuario implica que este no es el problema.fuente