Ответ 1
Ваш код почти наверняка быстрее из-за того, что строки связаны в CF. Хотя я не знаю точную внутренность CF, я подозреваю, что Strings является неизменным. Это означает, что каждый раз, когда вы присоединяете дополнительную переменную к String с помощью &, она создаст новую String, содержащую как старую строку, так и новую строку в конце. Для этого ему придется выделять память, а по мере роста строки - все больше и больше памяти.
В строку добавляется 8 переменных, каждая из которых проходит цикл, включая предыдущую версию String, поэтому вы выделяете строки ~ 4800 * 8 во время цикла.
Предполагая, что каждая строка имеет длину 35 символов, конечный размер строки будет 168k. Это означает, что его средний размер во время пробега составляет половину этого: 84k. Теперь, учитывая, что вы назначаете строку 4800 * 8 раз, вы используете целых 3 GIG (4800 * 8 * 8400) памяти для создания 168k вывода. Это будет означать, что Java должна делать целую кучу коллекции мусора и дополнительную работу для обслуживания вашего кода.
Ваш обновленный код работает над LocalTextString 7 раз из 8, что будет крошечным по сравнению, поэтому вы получите значительное улучшение скорости.
Попробуйте эту версию:
<cfset buffer=ArrayNew()>
<cfset crlf=CarriageReturn & LineFeed />
<cfloop>
<cfset ArrayAppend(buffer,DriverID)>
<cfset ArrayAppend(buffer,TabChar)>
<cfset ArrayAppend(buffer,LocalSSN)>
<cfset ArrayAppend(buffer,TabChar)>
<cfset ArrayAppend(buffer,FirstName)>
<cfset ArrayAppend(buffer,crlf)>
</cfloop>
<cfoutput arrayToList(buffer, "")/>
Он создает массив строк, а затем превращает их в одну строку в конце. Вы также можете посмотреть StringBuffer с Java, что делает то же самое. Когда я в последний раз смотрел на него, метод Array/List выше был самым быстрым, но это было несколько версий CF назад.
Update
Я не был доволен количеством догадок в своем ответе, поэтому у меня была популярность при воспроизведении проблемы. Я использовал 5-летний Mac с CF10 для тестирования.
- Оригинальный код: 8100мс
- Улучшенный исходный код: 750 мс
- Метод ArrayAppend: ~ 15 мс
Если я подключу VisualVM к процессу ColdFusion, пока он запускает тесты, я вижу, что исходный код пережевывается через несколько сотен мегабайт памяти во время прогона. Не так плохо, как предложили мои первоначальные математические соображения; Я подозреваю, что это только создание большой строки один раз за один проход по циклу, не один раз за отдельную конкатенацию. Он запускает 2-3 мелкие коллекции мусора во время каждого прогона, хотя это и приводит к снижению производительности. Он также использует 100% процессор на ядре, на котором он работает.
Код ArrayAppend не запускает никаких GC в среднем, и вы вряд ли сможете увидеть используемую память.
Я не понимаю, почему исходный код занял довольно много времени, но другие факторы - это скорость процессора, свободная память, доступ к базе данных (я использовал MySQL5), версию CF и т.д.