Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

English

Escolha o caminho

Todo gráfico do Nonius desenha a mesma coisa — uma série de pontos em ordem de tempo —, mas os pontos podem chegar até ele de quatro jeitos. Qual serve depende de duas perguntas: onde estão os pontos agora, e eles param de chegar? (Uma palavra nova — um tile, um resumo — está no glossário.)

Seus pontosCaminhoO que o gráfico guarda
Já estão na página, gerados ou buscados pelo seu próprio códigoEntregue-osTodos
Um histórico fechado, pequeno o bastante para mandar inteiroUm arquivoTodos, buscados uma vez
Um histórico longo demais para mandar, ou que muita gente lêTiles de um servidorSó o que a vista na tela precisa
Chegando agora, conforme acontecemUm feed ao vivoOs mais novos, conforme chegam

E quando não há navegador nenhum — um relatório mandado por e-mail, um programa de desktop, um servidor que responde com uma figura —, o gráfico é desenhado como imagem.

“Pequeno o bastante para mandar inteiro” é questão de conta. Um ponto tem 24 bytes (um tempo, um valor e um peso, 8 bytes cada), então dez milhões de pontos são um arquivo de 240 MB, baixado antes do primeiro quadro e guardado na memória do navegador. Um dia de leituras uma por segundo são 86.400 pontos, 2 MB: o arquivo é a escolha simples. Anos de leituras uma por milissegundo são centenas de gigabytes: só tiles chegam lá.

Entregue-os

Sua página já tem os pontos — calculados, lidos da sua própria API, decodificados do seu próprio formato. Entregue-os ao gráfico em ordem de tempo, quantos quiser de cada vez. O exemplo do pacote do navegador:

const chart = await createChart(canvas);
chart.setScale(2);
chart.push(t, v, w);

t, v e w são colunas de inteiros; Seus dados diz como uma leitura vira esses inteiros, e por que setScale(2).

Um arquivo

Um arquivo de série guarda um histórico fechado no formato do próprio Nonius, o NSB1. O gráfico busca o arquivo inteiro e lê seus bytes onde eles chegam, sem etapa de decodificação, então um arquivo de milhões de pontos é desenhado assim que termina de chegar.

const chart = await createChart(canvas);
await loadNsb(chart, await fetch(url));

O arquivo é escrito uma vez, de onde os dados estiverem: um CSV, um programa em Rust ou .NET, o Node. Seus dados mostra cada um.

Tiles de um servidor

Quando o histórico é longo demais para mandar, um servidor o guarda e manda tiles: pedaços pequenos cortados para a vista na tela, cada um com mais ou menos os bytes dos seus pixels, seja qual for o tamanho do histórico. Com o zoom aberto em dez anos, o gráfico lê resumos; com o zoom num segundo, os pontos daquele segundo. O gráfico busca tiles conforme a pessoa arrasta e dá zoom.

import { attachTiles, createChart, fetchSeries, interact } from "nonius";

// A series on a Nonius server, drawn from its tiles: the chart holds only
// what its views need and fetches the rest as a person moves, however long
// the history. `url` is the series' address, `…/v1/series/{id}`.
export async function fromServer(canvas, url) {
  // Asked for first, so the answer comes while the WebAssembly downloads.
  const meta = fetchSeries(url);
  const chart = await createChart(canvas);
  // Opens the chart on the whole series.
  const tiles = await attachTiles(chart, url, { meta });
  const interaction = interact(chart, canvas, { tiles });
  return { chart, tiles, interaction };
}

Esse é um módulo inteiro. O fetchSeries fica sem await de propósito: o gráfico recebe a promise, e a resposta chega enquanto o WebAssembly baixa. O interact recebe os tiles, para que cada vista para onde a pessoa se move busque os tiles de que precisa. url é o endereço da série no servidor, http://host:porta/v1/series/{id}. O servidor pode ser o nonius-server, a partir de um arquivo de série, ou o seu, falando o protocolo do Nonius. Servir mostra como rodar um.

Um feed ao vivo

Pontos que estão acontecendo agora chegam por um WebSocket, como quadros numerados enviados pelo crate Rust nonius-live. O gráfico acompanha os pontos mais novos; um quadro que a rede perde é notado pelo número e pedido de novo.

const chart = await createChart(canvas);
// A feed's values are integers and carry no scale: say how many decimal
// places they have (2 here: 10_050 is 100.50).
chart.setScale(2);
const stream = streamInto(chart, url);

Uma imagem

O mesmo gráfico, desenhado como PNG na CPU: sem navegador, sem GPU. Um servidor responde a GET /v1/series/{id}/png?from=…&to=…&width=…&height=…; no .NET, a série se desenha:

// Light, for a box of 1200 × 400 CSS pixels at a pixel ratio of 2:
// the size is in device pixels, the ratio in thousandths.
byte[] image = series.StillPng(new Still(first, last + 1, 2400, 800, Theme.Light, RatioPermille: 2000));
File.WriteAllBytes(png, image);

e no Rust, o nonius-render faz isso. A imagem é o quadro que o navegador desenha, pixel por pixel no canvas 2D, então um relatório e uma página concordam. Desenhar mostra cada um.

Na dúvida?

Comece por um arquivo. É uma busca e uma chamada, e o arquivo que ele pede é o que um servidor serve depois: passar para tiles muda como o gráfico é alimentado, não os dados.