Неэффективно ли использовать неявное создание массива (сокращенное или буквенное обозначение) в циклах или параметрах функций?

(Это своего рода продолжение моего предыдущего вопроса о структурах)

Будет ли это:

<cfset myArray = ArrayNew(1)>
<cfloop query="myQuery">
    <cfset myArray[1] = queryCol1>
    <cfset myArray[2] = queryCol2>
    <cfset myArray[3] = queryCol3>
    <cfset funcionWithArrayParam(myArray)>
</cfloop>

... использовать системные ресурсы более эффективно, чем это:

<cfloop query="myQuery">
    <cfset functionWithArrayParam([queryCol1, queryCol2, queryCol3])>
</cfloop>

?

И чтобы сохранить фокус, предположим, что массив в первом примере не служит никакой другой цели, кроме подачи функции. Кроме того, предположим, что данные запроса и / или столбца достаточно велики, чтобы сделать целесообразным рассмотрение эффективности.

Второй метод заманчив из-за его компактности, но меня беспокоит то, что я не уверен, сколько новых массивов он создает на каждой итерации. Первый метод создает один, я полагаю, из-за того, что массивы передаются по значению в CF. Но значит ли это, что второй метод создает два массива (неявно созданный и его копию для использования в функции)?

Также было бы интересно узнать, как сокращенная запись сравнивает по производительности несколько операторов cfset для заполнения массива. Я понимаю, что это не яблоки с яблоками, так как первый также создает массив, но все же... Я полагаю, я мог бы легко проверить это сам.

3 ответа

Решение

Адам Кэмерон технически ответил на мой вопрос в одном из своих комментариев, но, поскольку это не был его "официальный" ответ, я приведу свой (вместе с небольшой перспективой).

Ответ: ДА. Фактически, неэффективно использовать неявное создание массива способом, продемонстрированным в моем втором примере. Означает ли это, что вы не сможете сойти с рук большую часть времени? Конечно, нет! Но я представил два метода выполнения одной и той же операции, второй из которых вдвое менее эффективен по сравнению с первым с точки зрения использования памяти (и даже чуть-чуть медленнее)- в моем мире об этом стоит знать! Если вы по-прежнему будете настаивать на использовании неявного создания массива в такой ситуации, не помешает спросить себя, почему. Это потому, что вы думаете, что сжатие кода в одну строку впечатляет девушек-программистов? Я думаю, это что-то. "Читаемость" кажется наиболее популярным оправданием (в конце концов, это единственная мера, по которой неявное создание массива / структуры объективно не уступает явному). Если, как и я, вы находите читабельность неоднозначной, движущейся цель, нет ничего плохого в том, чтобы позволить эффективности влиять на то, как вы кодируете. Если вы знаете, как написать эффективный алгоритм, не позволяйте популярной гиперболе с "преждевременной оптимизацией" напугать вас до написания неэффективного алгоритма. Это демонстрирует отсутствие перспективы так же, как преждевременная оптимизация.

С точки зрения производительности разница будет незначительной, но неявное создание, как правило, немного медленнее, но неявное создание гораздо более читабельно, что более важно в долгосрочной перспективе, если только вы не столкнулись с какой-то проблемой масштабирования.

Изменить: Написал быстрый тестовый скрипт, и я получаю совершенно разные результаты. Я бы сказал, что оба настолько близки, что это не должно иметь значения, но запустите тест на вашей системе. Я использую это на Macbook Pro с CF10, это может варьироваться в зависимости от вашей конкретной реализации. Возможно, полученный вывод Java-байта может выявить какие-либо структурные различия между этими двумя методами.

<cfset iterations = 1000000>

<cfset start = getTickCount()>

<cfloop from="1" to="#iterations#" index="x">
    <cfset a[x] = arrayNew(1)>
    <cfset a[x][1] = x>
    <cfset a[x][2] = x>
    <cfset a[x][3] = x>
</cfloop>
<cfoutput>Explicit Array took: #getTickCount()-start#ms</cfoutput><br>

<cfset start = getTickCount()>
<cfloop from="1" to="#iterations#" index="y">
    <cfset b[y] = [y, y, y]>
</cfloop>

<cfoutput>Implicit Array took: #getTickCount()-start#ms</cfoutput><br>

Спектакль? Не беспокойся об этом. Любой тест, в котором вам необходимо выполнить петлевую петлю, чтобы увеличить продолжительность тестируемой операции, чтобы указанная продолжительность была измеряемой, по сути, демонстрирует, что соображения производительности незначительны.

Что касается того, сколько массивов создается? В каждом примере в вызывающем коде создается один массив, затем он в основном дублируется при передаче в функцию. Так что никакой реальной разницы нет.

Все сводится к тому, что вы считаете более понятным (мы, вероятно, закорачиваем последующие вопросы, которые могут у вас возникнуть, указав, что это всегда будет ответом).

Лично я думаю, что иметь отдельные операторы для установки каждого элемента массива немного неуклюже, когда можно сделать это одним ударом.

Другие вопросы по тегам