LINUX.ORG.RU

Про передачу строк в функцию и про память

 , , ,


1

1

Привет. Программирую на nodejs

ситуация:

function a(){
 var s = "очень длинная строка"
 func_b(s)
}

Функция b читает переменную s, но не модифицирует её

вопрос: При передаче переменной s в функцию func_b, интерпретатор произведёт копирование строки в другую ячейку памяти или же будет передана ссылка?

Интересует именно что фактически происходит в памяти на низком уровне, так как копирование строки было бы неоптимальным решением с точки зрения производительности

При создании строки она попадает в пул, передают ссылки на пул. Строки иммутабельные плюс там всякие оптимизации при repeat и соединении строк. Т.е. если сделать «str».repeat(100500) в памяти не появится 100500 «str». Со склейкой надо смотреть, но по-моему там сделали так, чтобы можно было обходиться без костылей типа StringBuilder'а явы. Когда строки сравнивают, никто не делает побайтовое сравнение, сравнивают уже вычисленные хеши, так что можно не задрачивать enum'ы как в си.

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 3)

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

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

а что тут не соглашаться, это поведение языка, да есть оптимизации в зависимости от реализации, но на них закладываться не стоит. Проще тогда обернуть строку в объект и передавать его гарантированно по ссылке.

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

В таких языках отказались от мутабильных строк давным давно. Когда строку меняешь создаётся новая. Смысл копировать её при передачи?

crutch_master ★★★★★
()

Не интерпретатор, а виртуальная машина. С компилятором и прочим. Память выделится под другую строку, только если ты эту строку в другой функции изменишь. Ты задумываешься о тех вещах, о которых думать не нужно. О них думают разработчики v8 на c++

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

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

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

Вопрос ТСа про nodejs, а не любую реализацию. Так что более правильный ответ дал не ты.

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

+ ко всему, кроме стрингбилдера

Стрингбилдер нужен в некоторых случаях. Для того, чтобы не прострелить себе ногу из-за особенностей хранения строк в виде цепочки, и на жс выглядит как const x = []; x.push(chunk); return x.join('').

Сравни:

function makeString1(size) {
  let x = ''
  for (let i = 0; i < size; i++)
    x += String.fromCharCode(Math.floor(Math.random() * 256))
  return x
}

function makeString2(size) {
  let x = []
  for (let i = 0; i < size; i++)
    x.push(String.fromCharCode(Math.floor(Math.random() * 256)))
  return x.join('')
}

const size = 3e7
console.time()
const y = makeString1(size)
//const y = makeString2(size)
console.timeEnd()
console.log(process.memoryUsage().rss / 2**20)

memoryUsage там пальцем в небо, потому что надо пиковый мерять, конечно. Лучше с --trace-gc запустить и увидишь, что будет.

А ещё можешь size покрутить.

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

думать не нужно

Смелое заявление. нука, ради опыта, не думая просто возьмите и загрузите в переменную целиком 100гб файл (могу ссылку дать), при условии что озу+swap в сумме меньше по объёму. Как думаете, что произойдёт?

я вот тоже раньше не думал, но когда приложение стало падать из-за нехватки памяти задумался.

Вообще, я считаю что это гиблая идея верить что можно кодить не понимая что под капотом творится

russian-turist-2019
() автор топика
Последнее исправление: russian-turist-2019 (всего исправлений: 1)
Ответ на: комментарий от russian-turist-2019

разумеется можно кодить, если ты кодишь мелкие POC для код гольфа на лишпе…

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

Стрингбилдер нужен в некоторых случаях.

Да, без него походу никак, хотя от += оно не падает, что говорит о том, что там не совсем всё тупо.

memoryUsage там пальцем в небо, потому что надо пиковый мерять

Ну, почему. В первом варианте - строка с мусором занимает 1 гб, во втором 500 мб, если вычитать из файла - 100 мб, размер файла - ~50 мб. Даже так понятно, что любом из двух вариантов творится задница.

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

Загрузка 100 гигов в буффер и передача очень длинной строки из одной области в другую - не одно и то же, и то - за тс уже всё оптимизировано

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

Что будет копироваться? Строка - это не примитив.

cdshines ★★★★★
()

Будет передаваться ссылка на строку.

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