Действительно простая проблема: у вас есть один миллиард (1e + 9) 32-разрядных целых чисел без знака, которые хранятся в виде десятичных строк ASCII в файле TSV (значения, разделенные табуляцией). Преобразование с использованием int()
ужасно медленное по сравнению с другими инструментами, работающими с тем же набором данных. Зачем? И что еще важнее: как сделать это быстрее?
Поэтому вопрос: какой самый быстрый способ преобразовать строку в целое число в Python?
То, о чем я на самом деле думаю, - это некоторая полузакрытая функциональность Python, которая (ab) может использоваться для этой цели, мало чем отличается от использования Гвидо array.array
в его «Оптимизационном анекдоте» .
Пример данных (с расширенными до пробелов табуляциями)
38262904 "pfv" 2002-11-15T00:37:20+00:00
12311231 "tnealzref" 2008-01-21T20:46:51+00:00
26783384 "hayb" 2004-02-14T20:43:45+00:00
812874 "qevzasdfvnp" 2005-01-11T00:29:46+00:00
22312733 "bdumtddyasb" 2009-01-17T20:41:04+00:00
Время, затрачиваемое на чтение данных, здесь неактуально, обработка данных является узким местом.
Microbenchmarks
Все перечисленные ниже языки являются интерпретированными. На хосте установлена 64-битная версия Linux.
Python 2.6.2 с IPython 0.9.1, ~ 214 тыс. Преобразований в секунду (100%):
In [1]: strings = map(str, range(int(1e7)))
In [2]: %timeit map(int, strings);
10 loops, best of 3: 4.68 s per loop
REBOL 3.0 Версия 2.100.76.4.2, ~ 231 кбит / с (108%):
>> strings: array n: to-integer 1e7 repeat i n [poke strings i mold (i - 1)]
== "9999999"
>> delta-time [map str strings [to integer! str]]
== 0:00:04.328675
REBOL 2.7.6.4.2 (15 марта 2008 г.), ~ 523 кбит / с (261%):
Как отметил Джон в комментариях, эта версия не создает список преобразованных целых чисел, поэтому приведенное соотношение скоростей относительно времени выполнения Python 4,99 for str in strings: int(str)
.
>> delta-time: func [c /local t] [t: now/time/precise do c now/time/precise - t]
>> strings: array n: to-integer 1e7 repeat i n [poke strings i mold (i - 1)]
== "9999999"
>> delta-time [foreach str strings [to integer! str]]
== 0:00:01.913193
KDB + 2,6 т 2009.04.15, ~ 2016 кбит / с (944%):
q)strings:string til "i"$1e7
q)\t "I"$strings
496