LINUX.ORG.RU

Объясните за js

 , ,


1

1

Размещаю не в веб-деве потому, что вопрос касается ресурсов и производительности.

Спрашиваю потому, что понятия не имею как это правильно загуглить.

Собственно есть необходимость создавать сотни тысяч объектов данных. Варианта два — «интерактивные» (не знаю как правильнее выразиться) классы и «тупые» объекты.

Вариант первый:

function myObj(data)
{
    var _internalData = data;
    this.myMethod = function() {
        // что-то делаем с данными
        console.log(_internalData);
    }
}

var obj = new myObj({a: 1, b: 2});
obj.myMethod();

Вариант второй:

function methodForMyObj(obj)
{
    // что-то делаем с данными
    console.log(obj._internalData);
}

var obj = {_internalData: {a: 1, b: 2}};
methodForMyObj(obj);

Вопросы такие:

1) Будет ли для первого варианта «клонироваться» в памяти методы при new myObj()?
2) Как правильно замерить?
3) Есть ли различия в поведении js-движков для вышеописанного контекста?
4) Предполагаю есть еще вариант с прототипами?

З.Ы.: Сейчас используется второй вариант, и при 600к «тупых» объектов данных браузер летает. За первый вариант спрашиваю потому, что если оверхеда нет, то я бы перевел на первый ради инкапсуляции данных и разделения ответственности.

Вариант первый:

ты в каждый из сотен тысяч объектов запихиваешь по функции. негоже.

примерно так:

myObj.prototype.myMethod = function() {
        // что-то делаем с данными
        console.log(_internalData);
}

dib2 ★★★★★ ()

Скрытые классы создаются по мере прогрева и набора статистики. Как создавали объекты - дело десятое. Главное за пределами конструктора не добавлять вагон пропертей.

http://mrale.ph/ - почитай этот бложик и посмотри видео этого перца на ютюбе.

Vit ★★★★★ ()

1) Будет ли для первого варианта «клонироваться» в памяти методы при new myObj()?

в ванильной теории - да. в любом случае перфоманса тебе это не прибавит

2) Как правильно замерить?

на jsperf поковыряйся, там готовых мерялок на тему - хоть пруд пруди

3) Есть ли различия в поведении js-движков для вышеописанного контекста?

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

4) Предполагаю есть еще вариант с прототипами?

именно

dib2 ★★★★★ ()
Ответ на: комментарий от Vit

за пределами конструктора не добавлять вагон пропертей

Ну у меня сейчас ф-ции описаны один раз без прототипов и классов вообще и я просто передаю в них первым аргументом целевые данные с которыми надо поработать.

deep-purple ★★★★★ ()
Ответ на: комментарий от dib2

кстати, стоят мобильные браузеры - в них могут быть приколы

Так может, во избежание приколов, тогда и оставить без прототипов как есть простыми ф-циями с передачей первым параметром целевых данных?

deep-purple ★★★★★ ()
Ответ на: комментарий от deep-purple

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

Быстрее только типизированные массивы гонять и ручками там байты раскладывать. И то не факт.

Vit ★★★★★ ()

1) Будет ли для первого варианта «клонироваться» в памяти методы при new myObj()?

метод будет один. В каждом объекте будет один указатель на метод.

Правильный вариант — использовать массивы примитивных типов и отказаться от хранения сотен тысяч объектов. Впрочем сто тысяч объектов это не так много, можно и не заморачиваться.

Legioner ★★★★★ ()
Ответ на: комментарий от deep-purple

Вполне нормальный подход, если надо скорость как на сях и не впадлу потом такой код потом поддерживать. Только имей в виду, что доступ к полям объекта не совсем бесплатный, хотя и достаточно быстрый.

Vit ★★★★★ ()
Ответ на: комментарий от Vit

если надо скорость как на сях

Тип того.

не впадлу

Оно.

доступ к полям объекта не совсем бесплатный

Собсно как и к данным в классе, которые тоже — объект.

быстрый код под старое говно

Не совсем, просто хочется так, чтобы меньше потом всплыло касяков. Пока есть возможность продумать заранее.

deep-purple ★★★★★ ()
Ответ на: комментарий от Legioner

В каждом объекте будет один указатель на метод

Точно? Посмотри внимательнее код первого варианта. Может ты про методы в прототипе.

deep-purple ★★★★★ ()
Ответ на: комментарий от Vit

доступ к полям объекта не совсем бесплатный

Вот:

for (var i in obj.foo.bar) xxx(obj.foo.bar[i].blah);
будет дороже чем:
var i, bar = obj.foo.bar;
for (i in bar) {
    xxx(bar[i].blah);
}
или не?

deep-purple ★★★★★ ()
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от deep-purple

for (var i in obj.foo.bar)

Это хреновый паттерн. В цикле будет создаваться строковый объект для каждой проперти. Забудь про скорость для такого.

А если тебя скорость такого цикла устраивает - тогда вообще не парься на тему оптимизаций.

Vit ★★★★★ ()
Ответ на: комментарий от deep-purple

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

Почитай бложик по ссылке выше, и посмотри видео.

Vit ★★★★★ ()
Ответ на: комментарий от deep-purple

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

dib2 ★★★★★ ()
Ответ на: комментарий от dib2

варианты?

Массив объектов, и доступ вида a[ i ].bar, например.

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

Надо смотреть по конкретной задаче, как данные организовать. Универсального ответа нет.

Vit ★★★★★ ()
Последнее исправление: Vit (всего исправлений: 1)
Ответ на: комментарий от Vit

Массив объектов

ну эт понятно, а если все-таки хеш? и про hasOwnProperty надо не забыть...
Не доводилось мерить for vs Object.keys + перебор?

dib2 ★★★★★ ()
Ответ на: комментарий от dib2

Не знаю, я такое не использую, когда скорость критична. Но я только парсеры и числомесилки делал, там такое не надо.

Vit ★★★★★ ()
Ответ на: комментарий от dib2

Не доводилось. Я такое сразу отбросил как гарантированную жопу.

Vit ★★★★★ ()
Ответ на: комментарий от Vit

Массив объектов, и доступ вида a[ i ].bar, например

Ну и исходя из твоих слов, надо не «i in a», а «i = 0; i < a.length; i++» иначе «i» будет строкой же.

deep-purple ★★★★★ ()
Ответ на: комментарий от deep-purple

Ну да. Надо четко понимать, что если в горячем пути начать работать со строками, то будет куча неявных созданий объектов. А это очень дорого.

Поэтому и говорю, что надо уметь писать на статических языках - там подобное невозможно. Только если в явном виде создавать какие-нибудь коллекции. А тогда и так понятно что скорость просядет.

Vit ★★★★★ ()

озвучь задачу конкретнее, мутабельны ли объекты, отличаются ли они структурой, и т.п.

тому що если они иммутабельны (например список товаров) может оказаться дешевле все закодировать в строку или один массив и юзать прям оттуда

Deleted ()

1) Будет ли для первого варианта «клонироваться» в памяти методы при new myObj()?

Вероятно.

2) Как правильно замерить?

Встроенные профайлеры, количество съеденной памяти и т.д. и т.п. Так или иначе работа с памятью сильна инкапсулирована, чтобы что-то там конкретное измерить.

3) Есть ли различия в поведении js-движков для вышеописанного контекста?

Есть.

4) Предполагаю есть еще вариант с прототипами?

Если создавать функцию один раз, а не 100, то она гарантировано займет в памяти меньше места чем 100 дубликатов функции. Технически можно установить в свойство объекта ссылку на функцию, а не создавать ее на месте.

ради инкапсуляции данных

Прекратите засирать код.

600к «тупых» объектов данных браузер летает

600к объектов с т.з памяти - херня.

for (var i in obj.foo.bar)

Перебор больших объемов данных должен осуществляться только по индексу массива в котором заполнены все элементы (т.е. без дыр).

special-k ★★★ ()
Последнее исправление: special-k (всего исправлений: 1)
Ответ на: комментарий от special-k

можно установить в свойство объекта ссылку на функцию

Тогда смысл? Ф-ция хоть и в другом месте, но в том же скопе.

Прекратите засирать код

С удовольствием, что не противоречит предыдущей цитате.

без дыр

Ну, с этим то все ок.

600к объектов с т.з памяти - херня

Не херня если все это в DOM-дереве. Но от задрачивания DOM'а я отказался в первую очередь.

deep-purple ★★★★★ ()
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от Deleted

тому що если они иммутабельны

Вообще они типа одинаковые, и так и есть — все лежат в одном массиве. Но мне их надо перебирать в цикле чтобы применить кучу разных калбяков (знаю, коллбеков, но мне нраца слово «калбяки», заразил один чел) на каждый из объектов, прошерстить необходимые св-ва, установить флаги, апдейтнуть значения счетчиков.

deep-purple ★★★★★ ()

Будет ли для первого варианта «клонироваться» в памяти методы при new myObj()?

LOL, само сабой

Как правильно замерить?

LOL, obj1.myMethod===obj2.myMethod

Есть ли различия в поведении js-движков для вышеописанного контекста?

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

Предполагаю есть еще вариант с прототипами?

Да, это самоочевидный для данной задачи вариант. Так и должно быть.

javaQest ()
Ответ на: комментарий от Vit

это полноценные объекты

Какой же бред ты несешь. Как с такими детскими понятиями можно вообще хоть что-то писать? Может ты просто клоун, и никаких проджектов у тебя нет? Это же основы основ, типы данных в JS, ты даже это умудрился про***бать.

javaQest ()
Ответ на: комментарий от Legioner

А как ты в прототипе замыкание сделаешь?

А нахрен оно нужно? Замыкания надо использовать для быдлоязычков, где без них нельзя обойтись. Сравни, варианты,

1 создаешь 1 ф-цию, 1000 объектов.

2 создаешь 1000 ф-ций, 1000 замыканий 1000 объектов

Боишься, кто то твои даные кто-то украдет изменит? Так назови _____$$$$$mylongName$$$____, зашифруй, не надо проблемы со своей инакпсуляцией из пальца высасывать. В Ъ CS под инкапсуляцией понимается несколько другое, вообще то, это не из разряда приват паблик ко-ко-ко.

javaQest ()
Ответ на: комментарий от deep-purple

Ф-ция хоть и в другом месте, но в том же скопе.

Ты, в смысле не понимаешь, что каждый вызов function(){...} создается новый объект данных?

Не херня если все это в DOM-дереве

Что за бред. 600к объектов интерфейса здесь причем. Нелепое сравнение.

special-k ★★★ ()
Ответ на: комментарий от javaQest

даные кто-то украдет изменит

Я думаю, там комплексы. Мол, я пишу на сурьёзном языке с инкапсуляцией.

special-k ★★★ ()
Ответ на: комментарий от special-k

Ты, в смысле не понимаешь, что каждый вызов function(){...} создается новый объект данных?

Не то. Новый (копия) не создается (для второго варианта).

deep-purple ★★★★★ ()
Ответ на: комментарий от javaQest

Это же основы основ, типы данных в JS

Поясни и для меня, кратко, что не так с его фразой про:

var arr = [{a:1},{a:2},{a:3},{a:4}];
for (i in arr) {
    console.log(typeof i); // string
}
for (i = 0; i < arr.length; i++) {
    console.log(typeof i); // number
}

deep-purple ★★★★★ ()
Ответ на: комментарий от deep-purple

В JS строки — это примитивный тип, то что он там лепит, это вообще бред, no_comments. Объект создается только при таком вот создани, new String, да и то, на полноценный объект эта параша не тянет. Ты можешь вызвать строку в «объектном контексте», «foo».something, тогда она отчасти будет вести себя как объект, да и то, только в том смысле, что будет произведен лукап свойства в прототипах. Во всех остальных случаях — это примитив(а жаль:))

javaQest ()
Ответ на: комментарий от deep-purple

Тот «плохой» паттерн, for in — действительно медленней. Но создание мифических «строковых объектов», тут не при чем. Поиск по хешам, вместе с цепочками родителей по любому будет медленней, в общем случае. Но параноить тут тоже не надо.

Самое главное, если используешь объект в качестве хеша, ограничивай поиск hasOwnProperty. то есть

for(i in o){
 if(!o.hasOwnProperty(i)) break/return
 more...
}
а не 
 for(i in o){
  if(o.hasOwnProperty(i)) more...
 }

чуешь разницу? 99% случаев тормозов у тормозов вроде вышеупомянутого, сорри за тавтологию, обусловлено именно этим.

javaQest ()
Ответ на: комментарий от deep-purple

Но для массива, конечно, for in не нужен, за исключением некоторых специфических случаев. Если не нравиться цикл, можешь пользовать forEach. но перформанс в общем случае, у цикла лучше.

javaQest ()
Ответ на: комментарий от javaQest

А... Тут как было, в момент создания треда я еще не определился что у меня там будет, массив массивов или массив объектов )) Но после твоих каментов таки я определился — массив массивов.

deep-purple ★★★★★ ()
Ответ на: комментарий от deep-purple

Перед тем как так делать, подумай почему у этого пейсателя-фантаста аккаунты через день банят :)

Vit ★★★★★ ()
Ответ на: комментарий от deep-purple

А с объявленной в прототипе не будет?

Не будет. Объявление функций в конструкторе сильно замедлит создание. Если у тебя 600К объектов, будет заметно.

Vit ★★★★★ ()
Ответ на: комментарий от Vit

Потому что я ставлю на место юродивых библиотекарей, а они потом стучат юродивым модераторам? Тебе слово симбиоз не на что не намекает? У червей, кстати, такие вещи тоже неплохо получаются.

javaQest ()
Ответ на: комментарий от Vit

Объявление функций в конструкторе сильно замедлит создание

show must go on. В прототипе она создается лишь однажды. Что там замедлять? У тебя они в одном случае создаются, а в другом нет.

PS давно так не ржал. Продолжай. Про кюрринг нам расскажи, а я пока за попкорном селетаю.

javaQest ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.