首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >"Javascript heap out of memory“使用Lodash memoize

"Javascript heap out of memory“使用Lodash memoize
EN

Stack Overflow用户
提问于 2018-09-29 04:59:40
回答 1查看 1.8K关注 0票数 4

我试图通过将记忆化应用到递归解决方案中,使用Javascript来解决LeetCode的longest palindromic subsequence问题。下面是递归解决方案longestPalindromicSubsequence.js

代码语言:javascript
复制
function longestPalindromicSubsequence(string, start = 0, end = string.length) {
  if (end < start) { return 0; }
  if (start === end) { return 1; }
  if (string[start] === string[end]) {
    return 2 + longestPalindromicSubsequence(string, start + 1, end - 1);
  }
  return Math.max(
    longestPalindromicSubsequence(string, start + 1, end),
    longestPalindromicSubsequence(string, start, end - 1),
  );
}

module.exports = longestPalindromicSubsequence;

下面是一些Jest测试用例,longestPalindromicSubsequence.test.js

代码语言:javascript
复制
const longestPalindromicSubsequence = require('./longestPalindromicSubsequence');

describe('longest palindromic subsequence', () => {
  test('works for aab', () => {
    expect(longestPalindromicSubsequence('aab')).toBe(2);
  });

  test('works for long string', () => {
    expect(longestPalindromicSubsequence(`${'a'.repeat(50)}bcdef`)).toBe(50);
  });
});

这是可行的,但由于递归调用的数量呈指数级增长,因此速度相当慢。例如,对于长度为~50的字符串,需要9秒:

代码语言:javascript
复制
$ jest longestPalindromicSubsequence.test.js
 PASS  ./longestPalindromicSubsequence.test.js (9.6s)
  longest palindromic subsequence
    ✓ works for aab (3ms)
    ✓ works for long string (9315ms)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        10.039s
Ran all test suites matching /longestPalindromicSubsequence.test.js/i.

为了提高性能,我尝试在更新后的模块longestPalindromicSubsequence2.js中使用_.memoize

代码语言:javascript
复制
const _ = require('lodash');

const longestPalindromicSubsequence = _.memoize(
  (string, start = 0, end = string.length) => {
    if (end < start) { return 0; }
    if (start === end) { return 1; }
    if (string[start] === string[end]) {
      return 2 + longestPalindromicSubsequence(string, start + 1, end - 1);
    }
    return Math.max(
      longestPalindromicSubsequence(string, start + 1, end),
      longestPalindromicSubsequence(string, start, end - 1),
    );
  },
  (string, start, end) => [string, start, end], // resolver function
);

module.exports = longestPalindromicSubsequence;

然而,当我尝试用这个模块运行测试时,我得到了一个"Javascript heap out of memory“错误:

代码语言:javascript
复制
$ jest longestPalindromicSubsequence.test.js

 RUNS  ./longestPalindromicSubsequence.test.js

<--- Last few GCs --->
at[89308:0x104801e00]    15800 ms: Mark-sweep 1379.2 (1401.3) -> 1379.2 (1401.3) MB, 1720.4 / 0.0 ms  (+ 0.0 ms in 5 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 1735 ms) (average mu = 0.128, current mu = 0.057) allocat[89308:0x104801e00]    17606 ms: Mark-sweep 1390.0 (1412.3) -> 1390.0 (1412.3) MB, 1711.7 / 0.0 ms  (+ 0.0 ms in 4 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 1764 ms) (average mu = 0.091, current mu = 0.052) allocat

<--- JS stacktrace --->

==== JS stack trace =========================================

    0: ExitFrame [pc: 0x20b000bdc01d]
Security context: 0x1c189571e549 <JSObject>
    1: /* anonymous */ [0x1c18f7682201] [/Users/kurtpeek/GoogleDrive/LeetCode/longestPalindromicSubsequence2.js:~14] [pc=0x20b0015cd091](this=0x1c18d38893a1 <JSGlobal Object>,string=0x1c18f7682271 <String[55]: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcdef>,start=45,end=45)
    2: memoized [0x1c18f7682309] [/Users/kurtpeek/GoogleDrive/LeetCode/node_...

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
 1: 0x100037733 node::Abort() [/usr/local/bin/node]
 2: 0x1000378d6 node::FatalTryCatch::~FatalTryCatch() [/usr/local/bin/node]
 3: 0x10018e57b v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
 4: 0x10018e51c v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
 5: 0x1004682ee v8::internal::Heap::UpdateSurvivalStatistics(int) [/usr/local/bin/node]
 6: 0x100469ed7 v8::internal::Heap::CheckIneffectiveMarkCompact(unsigned long, double) [/usr/local/bin/node]
 7: 0x1004675cb v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/usr/local/bin/node]
 8: 0x1004663e6 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/local/bin/node]
 9: 0x10046eafc v8::internal::Heap::AllocateRawWithLigthRetry(int, v8::internal::AllocationSpace, v8::internal::AllocationAlignment) [/usr/local/bin/node]
10: 0x10046eb48 v8::internal::Heap::AllocateRawWithRetryOrFail(int, v8::internal::AllocationSpace, v8::internal::AllocationAlignment) [/usr/local/bin/node]
11: 0x10044eb7a v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationSpace) [/usr/local/bin/node]
12: 0x100634916 v8::internal::Runtime_AllocateInTargetSpace(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/local/bin/node]
13: 0x20b000bdc01d 
Abort trap: 6

据我从Node.js heap out of memory了解,Node的标准内存使用量是1.7 be,我认为这应该足够了。有什么想法为什么记忆版本不能工作,以及如何修复它?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-29 05:10:29

通过将解析器函数从(string, start, end) => [string, start, end]更改为(string, start, end) => string + start + end,我设法解决了这个问题

代码语言:javascript
复制
const _ = require('lodash');

const longestPalindromicSubsequence = _.memoize(
  (string, start = 0, end = string.length) => {
    if (end < start) { return 0; }
    if (start === end) { return 1; }
    if (string[start] === string[end]) {
      return 2 + longestPalindromicSubsequence(string, start + 1, end - 1);
    }
    return Math.max(
      longestPalindromicSubsequence(string, start + 1, end),
      longestPalindromicSubsequence(string, start, end - 1),
    );
  },
  (string, start, end) => string + start + end, // resolver function
);

module.exports = longestPalindromicSubsequence;

现在“long string”测试只需要3毫秒:

代码语言:javascript
复制
$ jest longestPalindromicSubsequence.test.js
 PASS  ./longestPalindromicSubsequence.test.js
  longest palindromic subsequence
    ✓ works for aab (3ms)
    ✓ works for long string (3ms)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        1.004s, estimated 10s
Ran all test suites matching /longestPalindromicSubsequence.test.js/i.

似乎使用字符串作为缓存中的键比使用数组更节省内存--也许是因为字符串在Javascript中是不可变的?对这种改进的任何解释都将是受欢迎的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52562611

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档