Мне нужно создать CSV-файл 50 миллионов строк со случайными данными: как оптимизировать эту программу? - PullRequest
0 голосов
/ 04 мая 2010

Программа ниже может генерировать случайные данные в соответствии с некоторыми спецификациями (пример здесь для 2 столбцов)

Он работает с несколькими сотнями тысяч строк на моем ПК (зависит от оперативной памяти). Мне нужно масштабировать до десятка миллионов строк.

Как я могу оптимизировать программу для записи прямо на диск? С другой стороны, как я могу «кэшировать» выполнение правила синтаксического анализа, поскольку это всегда один и тот же шаблон, повторяемый 50 миллионов раз?

Примечание: чтобы использовать приведенную ниже программу, просто введите generate-blocks, и выходные данные для блоков сохранения будут db.txt

Rebol[]

specs: [
    [3 digits 4 digits 4 letters]
    [2 letters 2 digits]
]

;====================================================================================================================


digits: charset "0123456789"
letters: charset "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
separator: charset ";"

block-letters: [A B C D E F G H I J K L M N O P Q R S T U V W X Y Z]

blocks: copy []

generate-row: func[][
    Foreach spec specs [

        rule: [

            any [

                [
                    set times integer! [['digits (                          
                                repeat n times [                    
                                block: rejoin [block random 9]                          
                            ]

                            )
                            | 
                            'letters (repeat n times [                  
                                block: rejoin [ block to-string pick block-letters random 24]                       
                            ]

                            )
                        ]
                        |
                        [
                            'letters (repeat n times [block: rejoin [ block to-string pick block-letters random 24]                     
                            ]

                            )       
                            | 
                        'digits (repeat n times [block: rejoin [block random 9]]

                        )   
                        ]
                    ]
                    |
                    {"} any separator {"}
                ]

            ]

            to end

        ]
        block: copy ""
        parse spec rule
        append blocks block
    ]
]

generate-blocks: func[m][
  repeat num m [  
    generate-row
  ]
]

quote: func[string][
    rejoin [{"} string {"}]
]

save-blocks: func[file][
    if exists? to-rebol-file file [
        answer: ask rejoin ["delete " file "? (Y/N): "]
        if (answer = "Y") [
            delete %db.txt
        ]
    ]
    foreach [field1 field2] blocks [
        write/lines/append %db.txt rejoin [quote field1 ";" quote field2]
    ]
]

1 Ответ

2 голосов
/ 05 мая 2010

Используйте open с / direct и / lines уточнение для прямой записи в файл без буферизации содержимого:

file: open/direct/lines/write %myfile.txt
loop 1000 [
  t: random "abcdefghi"
  append file t
]
Close file

Это напишет 1000 случайных строк без буферизации. Вы также можете подготовить блок строк (скажем, 10000 строк), а затем записать его непосредственно в файл, это будет быстрее, чем запись построчно.

file: open/direct/lines/write %myfile.txt
loop 100 [
  b: copy []
  loop 1000 [append b random "abcdef"]
  append file b
]
close file

это будет намного быстрее, 100000 строк меньше секунды. Надеюсь, это поможет.

Обратите внимание, что вы можете изменить число 100 и 1000 в зависимости от ваших потребностей в памяти вашего компьютера и использовать b: make block! 1000 вместо b: copy [], это будет быстрее.

...