2014-11-01 87 views
2

我正在尝试通过HTTP使用Oboe.js,MongoDB和Express.js进行JSON流式传输。使用Oboe.js,MongoDB和Express.js进行JSON流式传输

关键是要做好MongoDB查询(Node.js的的MongoDB的本地驱动器),管它(一个JavaScript数组)Express.jsOboe.js解析它在浏览器中。

我在两个MongoDB查询服务器端和客户端的JSON解析中都比较了streamingblocking的基准。

这是两个基准的源代码。 first number1000 queries的毫秒数,100 items(分页)在10 million documents collectionsecond number括号之间,表示在解析MongoDB结果数组中的第一项之前的毫秒数。

的流基准服务器端:

// Oboe.js - 20238 (16.887) 
// Native - 16703 (16.69) 

collection 
.find() 
.skip(+req.query.offset) 
.limit(+req.query.limit) 
.stream() 
.pipe(JSONStream.stringify()) 
.pipe(res); 

阻塞基准服务器端:

// Oboe.js - 17418 (14.267) 
// Native - 13706 (13.698) 

collection 
.find() 
.skip(+req.query.offset) 
.limit(+req.query.limit) 
.toArray(function (e, docs) { 
    res.json(docs); 
}); 

这些结果真的让我感到吃惊,因为我本来认为:

  1. Streaming每次都会比blocking更快。
  2. Oboe.js与原生JSON.parse方法相比,解析整个JSON数组会更快。
  3. Oboe.js比解析本地JSON.parse方法更快地解析数组中的第一个元素。

有没有人有解释? 我在做什么错?

以下是两个客户端基准测试的源代码。

流媒体标杆客户端:

var limit = 100; 
var max = 1000; 

var oboeFirstTimes = []; 
var oboeStart = Date.now(); 

function paginate (i, offset, limit) { 
    if (i === max) { 
     console.log('> OBOE.js time:', (Date.now() - oboeStart)); 
     console.log('> OBOE.js avg. first time:', (
      oboeFirstTimes.reduce(function (total, time) { 
       return total + time; 
      }, 0)/max 
     )); 
     return true; 
    } 

    var parseStart = Date.now(); 
    var first = true; 
    oboe('/api/spdy-stream?offset=' + offset + '&limit=' + limit) 
    .node('![*]', function() { 
     if (first) { 
      first = false; 
      oboeFirstTimes.push(Date.now() - parseStart); 
     } 
    }) 
    .done(function() { 
     paginate(i + 1, offset + limit, limit); 
    }); 
} 

paginate(0, 0, limit); 

阻塞标杆客户端:提前

var limit = 100; 
var max = 1000; 

var nativeFirstTimes = []; 
var nativeStart = Date.now(); 

function paginate (i, offset, limit) { 
    if (i === max) { 
     console.log('> NATIVE time:', (Date.now() - nativeStart)); 
     console.log('> NATIVE avg. first time:', (
      nativeFirstTimes.reduce(function (total, time) { 
       return total + time; 
      }, 0)/max 
     )); 
     return true; 
    } 

    var parseStart = Date.now(); 
    var first = true; 

    var req = new XMLHttpRequest(); 
    req.open('GET', '/api/spdy-stream?offset=' + offset + '&limit=' + limit, true); 

    req.onload = function() { 
     var json = JSON.parse(req.responseText); 
     json.forEach(function() { 
      if (first) { 
       first = false; 
       nativeFirstTimes.push(Date.now() - parseStart); 
      } 
     }); 
     paginate(i + 1, offset + limit, limit); 
    }; 

    req.send(); 
} 

paginate(0, 0, limit); 

谢谢!

回答

1

我在Oboe doc的“为什么是双簧管”结尾处发现了这些评论?部分:

因为它是纯粹的JavaScript解析器,所以Oboe.js比JSON.parse需要更多的CPU时间。对于加载非常快的小型消息,Oboe.js稍微慢一点,但对于大多数真实世界中使用I/O的情况,Oboe.js有效地节省了CPU时间。 SAX解析器比Oboe的基于模式的解析模型需要更少的内存,因为它们不构建解析树。请参阅Oboe.js与SAX与DOM的比较。 如果有疑问,基准,但不要忘记使用包括手机在内的真实互联网,并考虑感知性能。