NodeJs: недопустимая длина строки [дубликат]

Нет встроенной функции (если вы работаете с поддержкой SQL и поддержкой Hive, вы можете использовать функцию stack , но она не отображается в Spark и не имеет встроенной реализации), но она тривиально сворачивать ваши собственные. Требуемый импорт:

from pyspark.sql.functions import array, col, explode, lit, struct
from pyspark.sql import DataFrame
from typing import Iterable 

Пример реализации:

def melt(
        df: DataFrame, 
        id_vars: Iterable[str], value_vars: Iterable[str], 
        var_name: str="variable", value_name: str="value") -> DataFrame:
    """Convert :class:`DataFrame` from wide to long format."""

    # Create array>
    _vars_and_vals = array(*(
        struct(lit(c).alias(var_name), col(c).alias(value_name)) 
        for c in value_vars))

    # Add to the DataFrame and explode
    _tmp = df.withColumn("_vars_and_vals", explode(_vars_and_vals))

    cols = id_vars + [
            col("_vars_and_vals")[x].alias(x) for x in [var_name, value_name]]
    return _tmp.select(*cols)

И некоторые тесты (на основе доктрин Pandas ):

import pandas as pd

pdf = pd.DataFrame({'A': {0: 'a', 1: 'b', 2: 'c'},
                   'B': {0: 1, 1: 3, 2: 5},
                   'C': {0: 2, 1: 4, 2: 6}})

pd.melt(pdf, id_vars=['A'], value_vars=['B', 'C'])
   A variable  value
0  a        B      1
1  b        B      3
2  c        B      5
3  a        C      2
4  b        C      4
5  c        C      6
sdf = spark.createDataFrame(pdf)
melt(sdf, id_vars=['A'], value_vars=['B', 'C']).show()
+---+--------+-----+
|  A|variable|value|
+---+--------+-----+
|  a|       B|    1|
|  a|       C|    2|
|  b|       B|    3|
|  b|       C|    4|
|  c|       B|    5|
|  c|       C|    6|
+---+--------+-----+

Примечание: для использования с устаревшими версиями Python удалите аннотации типов.

22
задан Hydrothermal 11 June 2014 в 04:04
поделиться

3 ответа

V8 (узел движка JavaScript построен на) до тех пор, пока very не получил жесткий предел размера кучи около 1,9 ГБ .

Узел v0.10 застрял на старой версии V8 (3.14) из-за нарушения изменений API V8 вокруг собственных аддонов. Узел 0.12 будет обновлен до новейшего V8 (3.26), который сломает многие родные модули, но откроет дверь для ограничения уровня кучи 1.9 ГБ.

Итак, поскольку он стоит, процесс с одним узлом может хранить не более 1,9 ГБ кода JavaScript, объектов, строк и т. д. в сочетании . Это означает, что максимальная длина строки меньше 1,9 ГБ.

Вы можете [] обойти это, используя Buffer s, которые хранят данные вне кучи V8 (но все же в куче вашего процесса). 64-битная сборка узла может в значительной степени заполнить всю вашу оперативную память, если у вас никогда не будет более 1,9 ГБ данных в переменных JavaScript.


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

Вы должны задать себе несколько вопросов:

  • Какие данные вы действительно получаете от user?
  • Почему вы хотите сохранить его в формате JSON?
  • Действительно ли это хорошая идея для наполнения гигабайтов в JSON? (Ответ - нет.)
  • Что будет с данными позже, после того, как оно будет сохранено? Будет ли ваш код читать? Что-то еще?

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

Если вы ожидаете, что данные никогда не будут такими большими, просто наведите разумный лимит в 10 МБ или что-то на вход, буферизуйте все это и используйте JSON.stringify.

Если вы планируете больше обрабатывать данные, вам нужно передать поток прямо на диск. Посмотрите на потоки преобразования , если вам нужно обработать / изменить данные перед тем, как перейти на диск. Например, существуют модули, которые связаны с потоковой передачей JSON .

25
ответ дан user2284570 31 August 2018 в 09:55
поделиться

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

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

Любой размер строки более 1 МБ займет у пользователя несколько секунд для загрузки, а 10 мегабайт могут занять несколько минут. После получения запроса сервер займет от нескольких сотен миллисекунд до секунды, чтобы проанализировать структуру данных, что приводит к очень плохому пользовательскому опыту (Parsing JSON очень дорогой)

пропускная способность и время обработки сервера затмевают любые ограничения, которые JSON может иметь на размер строки.

1
ответ дан Martin Konecny 31 August 2018 в 09:55
поделиться

Максимальный размер строки в «ванильном» узле JS (v0.10.28) находится в шаге 1GB.

Если вы спешите, вы можете проверить максимальный поддерживаемый размер строки с помощью строки с удвоением. Системная проверка имеет 8 ГБ ОЗУ, в основном неиспользованные.

x = 'x';
while (1){ 
     x = ''+x+x; // string context
     console.log(x.length);
}

2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
131072
262144
524288
1048576
2097152
4194304
8388608
16777216
33554432
67108864
134217728
268435456
536870912
FATAL ERROR: JS Allocation failed - process out of memory
Aborted (core dumped)

В другом тесте я получил до 1 000 000 000 с одним символом за цикл.

Теперь критик может сказать , «подождите, как насчет JSON. Вопрос о JSON!» и я бы кричал, что в JAVASCRIPT нет JS-типов JS-типов: Object, Array, String, Number и т. д., а поскольку JSON представляет собой представление String, этот вопрос сводится к тому, что является самой длинной допустимой строкой. Но для двойной проверки добавим вызов JSON.stringify для адресации преобразования JSON.

Код

x = 'x';
while (1){ 
     x = ''+x+x; // string context
     console.log(JSON.stringify({a:x}).length);
}

Ожидания: размер строки JSON начнется больше 2 , потому что первый объект будет привязывать к '{"a": "xx"}' для 10 символов. Он не начнет удваиваться, пока строка x в свойстве a не станет больше. Вероятно, он провалится около 256M, так как он, вероятно, делает вторую копию в строчении. Напомним, стробирование не зависит от исходного объекта.

Результат:

10
12
16
24
40
72
136
264
520
1032
2056
4104
8200
16392
32776
65544
131080
262152
524296
1048584
2097160
4194312
8388616
16777224
33554440
67108872
134217736
268435464

Довольно много, как ожидалось ....

Теперь эти ограничения, вероятно, связаны с кодом C / C ++, который реализует JS в проект nodeJS, который в это время я считаю одним и тем же кодом V8, используемым в браузерах Chrome.

Есть данные из сообщений в блогах людей, которые перекомпилируют nodeJS, чтобы обойти ограничения памяти в более старых версиях. Существует также ряд команд командной строки nodejs. Я не проверял эффект от этого.

9
ответ дан Paul 31 August 2018 в 09:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: