2014-10-16 2 views
2

Мне нужно отправить большую строку, представляющую число по проводу клиенту, написанному на Java Script. Теоретически это поток 0s и 1s, например: 011101011101101..., но он может быть очень, очень большим (миллионы бит в длину). Разумеется, моя цель - минимизировать необходимую обработку и накладные расходы. Я думал об изменении базового номера этой строки, так что он использует HEX или больший радиус, который значительно уменьшил бы объем данных, которые нужно отправить. JavaScript имеет встроенные функции для преобразования в и из разных систем нумерации, поэтому он выглядел как способ. Тем не менее, максимальный поддерживаемый радиус составляет всего 36. Мои вычисления показывают, что при потоке 50 миллионов бит и использовании 36 оснований вам все равно нужно отправить 1,388,888 символов - слишком много.Эффективный способ отправки большого битового потока в HTTP-ответе

Мой вопрос: знаете ли вы, каким образом это поможет достичь моей цели? Некоторые ограничения:

  • Решение должно работать для потоков произвольной длины
  • битовые потоки могут быть как биты 50 млн
  • Хорошая производительность должна быть гарантирована длиной около 1-10mln бит. Для больших потоков оно должно работать, однако он не должен расширять линейно
  • Я бы уделять больше внимания оптимизации объема данных, который должен быть отправлен, не обязательно на снижение нагрузки на процессор
+0

я что-то вроде этого какое-то время назад, я использовал типизированные массивы (без устаревших поддержка браузера) и jquery. Какой серверный язык вы используете? Я мог бы опубликовать либо клиентский скрипт, либо оба примера клиента + сервера. И это не ракетостроение, я не уверен, что это супер правильный способ сделать это, но он отлично поработал для нас. Это отправит данные в двоичном формате, например. вам не нужно кодировать/декодировать номера в/из строк – Snellface

+0

Вы думали о том, чтобы ввести какое-то простое сжатие? Например, вместо отправки 111100000 вы можете отправить 1405, где число после 0/1 представляет количество вхождений. –

+0

@MiljenMikic Я попробовал сжатие LZ77 на двоичных строках, но он только уменьшил поток 64k до примерно 36k. Это даже не половина :( –

ответ

0

Вы могли бы сделать что-то вроде этого (демо было написано без возможности его тестирования, но оно должно «работать», вот скрипка для тех, кто хочет скопировать/вырезать/вставить: http://fiddle.jshell.net/sywz3aym/2/
Обратите внимание на скрипку не могу работать, я намеревался написать ответчика, но я не могу сейчас бояться.

В нижней части области ввода javascript У меня есть раздел комментариев о том, как может выглядеть ответчик asp.net, он использует файл «Generic Handler (.ashx)», если вы используете визуальную студию, если вы используете какой-либо другой язык, вам придется использовать эквивалентные варианты там. Вам нужен запрос-ответчик, который вы можете настроить для возврата двоичных данных, вам нужно установить Content-Type в «application/octet-stream» (октет для тех, кто не знает = «группа из 8», например, байт:))

а вот JavaScript + комментарий, как в славной стене формата текст:

$(document).ready(function() { 
    var url = 'your handler URL'; 
    var oReq = new XMLHttpRequest(); 
    oReq.open('GET', url, true); 
    oReq.responseType = 'arraybuffer'; 

    oReq.onload = function (oEvent) { 
     var buffer = oReq.response; 
     var yourData = ExtractData(buffer); 
    } 
    oReq.send(null); 
}); 

function ExtractData(buffer) { 
    var dataReader = { 
     dataView: new DataView(buffer), 
     readPtr: 0, 

     littleEndian: (function() { 
      var buffer = new ArrayBuffer(2); 
      new DataView(buffer).setInt16(0, 256, true); 
      return new Int16Array(buffer)[0] === 256; 
     })(), 

     setReadPtrOffset: function (byteIndex) { 
      this.readPtr = byteIndex; 
     }, 

     nextInt8: function() { 
      var data = this.dataView.getInt8(this.readPtr); 
      this.readPtr += 1; // Sizeof int 
      return data; 
     }, 
     nextUint8: function() { 
      var data = this.dataView.getUint8(this.readPtr); 
      this.readPtr += 1; // Sizeof int8 
      return data; 
     }, 

     nextInt32: function() { 
      var data = this.dataView.getInt32(this.readPtr, this.littleEndian); 
      this.readPtr += 4; // Sizeof int32 
      return data; 
     }, 
     nextUint32: function() { 
      var data = this.dataView.getUint32(this.readPtr, this.littleEndian); 
      this.readPtr += 4; // Sizeof uint32 
      return data; 
     }, 

     nextFloat32: function() { 
      var data = this.dataView.getFloat32(this.readPtr, this.littleEndian); 
      this.readPtr += 4; // Sizeof float 
      return data; 
     }, 
     nextFloat64: function() { 
      var data = this.dataView.getFloat64(this.readPtr, this.littleEndian); 
      this.readPtr += 8; // Sizeof double 
      return data; 
     }, 

     nextUTF8String: function (length) { 
      var data = String.fromCharCode.apply(null, new Uint8Array(this.dataView.buffer, this.readPtr, length)); 
      this.readPtr += length; // Sizeof int 
      return data; 
     }, 
    } 

    var numberOfInt32ToRead = dataReader.nextInt32(); // First data could be, for example, the number of ints to read. 
    for(var i = 0; i < numberOfInt32ToRead; i++){ 
     var someInt = dataReader.nextInt32(); 
     // doStuffWithInt(someInt); 
    } 
} 

/* 
Serverside code looks kind of like this (asp.net/c#): 

    public class YourVeryNiceDataRequestHandler : IHttpHandler 
    { 
     public void ProcessRequest(HttpContext context) 
     { 
      context.Response.ContentType = "application/octet-stream"; // <- very important 
      List<int> data = SomeMethodWithGivesYouData(); 
      context.Response.BinaryWrite(BitConverter.GetBytes((int)data.Count)); // Explicit type casting only to help me get an overview of the data being sent, in this case it has no functional meaning other then to help me debug 
      foreach(int i in data) 
      { 
       context.Response.BinaryWrite(BitConverter.GetBytes((int)i)); 
      } 
      // You could send structs as well, either with the help of a binary formatter, or you can do like i did here and use BitConverter.GetBytes, be carefull when sending strings/chars since they are by default (usually) in a widechar format (1 char = 2 bytes), since i only use english for this i can convert it to a UTF8 char (1 byte):       context.Response.BinaryWrite(System.Text.Encoding.UTF8.GetBytes(new char[] { (motion.Phase == Phases.Concentric ? 'C' : 'E') })); // Phase (as single char) 

     } 
    } 
*/ 

Я надеюсь, что это либо поможет вам непосредственно, либо направить вас в правильном направлении.
Обратите внимание: это ОЧЕНЬ зависит от ваших типов данных, которые используют ваш сервер, и может не попасть в категорию «ОТДЫХ», однако вы указали, что хотите оптимизировать размер потока, и этот афайк - лучший способ сделать что, за исключением добавления сжатия данных
Javascript типизированных массивы "подражает" тип данные C-стиль, как те, которые используются в C, C++, C#, Java и т.д.

Юридической информация:
у меня есть не пробовал это с данными> 1 МБ, однако он сократил общий размер данных, отправляемых с сервера на клиента с 2 МБ до нескольких 10-100 КБ, и i т на сумму данных я отправить/чтение время выполнения были «не по-человечески измеримое» другой, то туда и обратно время для дополнительного запроса, так как это испрашивается ПОСЛЕ загрузки страницы в браузере

заключительное слово предупреждение: любая ручная сериализация/десериализация битов вручную должна выполняться с осторожностью, так как очень легко сделать ошибку, забыв, что вы что-то изменили как на стороне клиента, так и на стороне сервера, и это даст вам отлаживаемый мусор, если вы читаете или пишете байта слишком много/слишком мало на обоих концах, поэтому я добавляю явное наследование типов в своем серверном коде, таким образом я могу открыть как код сервера, так и код клиента бок о бок и сопоставить readInt32 с Write ((целое) ...).
Не забавная работа, но она делает вещи очень компактными и очень быстрыми (как правило, я буду читать, но некоторые задачи должны работать быстрее, чем читаемый код).

типизированные массивы не могут быть использованы в любом браузере, однако, но caniuse состояние, что 85% Интернета может использовать их: http://caniuse.com/#feat=typedarrays

Смежные вопросы