Xterm.js: Terminal não renderiza true color

Criado em 16 jan. 2017  ·  20Comentários  ·  Fonte: xtermjs/xterm.js

Comentários muito úteis

Olá. Alguma atualização sobre isso? Mal posso esperar para fazer isso funcionar 😃

Todos 20 comentários

Mal posso esperar por isso. Eu tenho invadido o hterm tentando obter suporte truecolor, mas acho que esta é uma opção muito melhor.

A implementação deve ser feita aqui https://github.com/sourcelair/xterm.js/blob/365a9f949cc1acfb6c4649ee1d85da3bbc60f928/src/InputHandler.ts#L1276

A parte complicada é determinar como armazenamos as cores em relação aos caracteres e, em seguida, como renderizá-los (provavelmente style atributos em linha). Algo como https://github.com/sourcelair/xterm.js/pull/450 provavelmente simplificaria a adição dos atributos.

Posso dar uma olhada quando tiver algum tempo, mas não posso dizer que estou muito familiarizado com as sequências de controle.

Dei uma olhada em http://invisible-island.net/xterm/ctlseqs/ctlseqs.html, mas não consegui encontrar nada sobre true color ou cor de 24 bits. Estou faltando alguma coisa ou há algum outro recurso que cobre isso?

@cnsumner xterm atualmente não pode exibir true color, mas tem suporte para uma das sequências de escape propostas. Você pode ler mais sobre isso aqui: https://gist.github.com/XVilka/8346728
BTW, isso é parcialmente especificado no padrão ECMA-48.

Monte uma prova de conceito confusa para ter uma ideia melhor do que precisamos fazer aqui https://github.com/Tyriar/xterm.js/tree/484_truecolor

image

Coisas que precisam ser feitas:

  • O ramo atualmente adiciona outro número para cada caractere que representa sua 'truecolor' no formato 0x1RRGGBB (fg) ou 0x0RRGGBB (bg), que cabe em um inteiro de 32 bits
  • Ele precisa ser compatível com as cores fg e bg e ser capaz de misturar truecolor com cores regulares
  • curTrueColor é super feio
  • Suporte inverso
  • Sinalizadores de cores precisam ser apagados quando as células são reutilizadas
  • Pode ser hora de repensar como os caracteres são codificados, o formato atual é:

    [attribute, character, width]
    
    • attribute : um inteiro de 32 bits que contém ascii fg, ascii bg e sinalizadores (negrito, sublinhado, piscar, inverso, invisível), nem todos os bits são usados
    • char : A string vazia (para caracteres de largura 0 que preenchem caracteres largos) ou uma string Unicode de caractere único
    • width : a largura do caractere, atualmente, pode ser 0, 1 ou 2, mas pode incluir mais para suportar guias adequadamente https://github.com/sourcelair/xterm.js/issues/734
  • A solução eventual deve ser compacta para a memória e também rápida para acessar, ficar com um array, sinalizadores binários e deslocamento de bits para dados é provavelmente a melhor ideia.

@Tyriar
Sim, o uso de memória explodirá se não for otimizado para baixo consumo. Talvez ele possa ser empacotado junto com width , este campo é improvável que fique maior que 16 consumindo apenas 4 bytes (o padrão da guia é 4 ou 8 normalmente). Isso deixa espaço para uma definição RGB * (assumindo que width é um inteiro de 32 bits). Não tenho certeza de quantos bits estão livres em attribute , talvez possa ir a segunda definição RGB .

Parece que os atributos atualmente consomem 9 bytes para bg, 9 bytes para bg e 5 bytes para sinalizadores, deixando bastante espaço para espremer largura no final. As definições RGB precisam de 24 bytes (8 * 3) cada.

Aqui está a abordagem (um pouco complicada) de economia de espaço que acho que você está sugerindo:

[char, attr1, attr2]

Onde attr1 é (29 bits):

  • largura: 4 bits
  • é de 256 cores ou bandeira truecolor: 1 bit
  • cor bg: 24 bits

E attr2 é (30 bits):

  • sinalizadores: 5 bits
  • é de 256 cores ou bandeira truecolor: 1 bit
  • cor fg: 24 bits

Uma abordagem mais simples usaria um número especificamente para atributos:

[char, attr, truecolorBg, truecolorFg]

Onde attr está:

  • largura: 4 bytes
  • sinalizadores: 5 bytes
  • 256 bg color: 9 bytes
  • 256 fg color: 9 bytes

Quero tanto encapsular esses detalhes, pois eles realmente complicam as coisas, que me pergunto se o texto digitado nos permitirá colocar getters em um array de alguma forma. Usar um objeto era 20x mais lento do que um array baseado em um micro benchmark que eu fiz no jsperf, eu sei que eles nem sempre são confiáveis, mas isso é o que eu esperava como sobrecarga para criar um objeto baseado em um protótipo.

Faça o que fizermos, o formato precisa ser muito bem documentado. Agora você tem que descobrir sozinho olhando para InputHandler.charAttributes .

Mais algumas idéias sobre economia de memória:

  • Se um caractere tem largura> 1, não precisamos armazenar nenhum dado para os caracteres a seguir. Os "caracteres vazios" existem como uma solução alternativa e provavelmente funcionariam bem sendo null .
  • Normalmente, um conjunto de caracteres é estilizado, o que significa que os atributos podem ser compartilhados entre uma sequência de caracteres.
  • Os atributos podem ser armazenados em cache e cada char usa um ponteiro para um dos valores armazenados em cache,

Sim, acho que na maioria dos arrays de mecanismos JS com acesso de índice ainda são mais rápidos do que objetos e sua resolução de propriedade. O V8 tem algumas otimizações extras para objetos. Em termos de construção e GC, um array é mais rápido devido ao layout de memória muito mais simples (esta desvantagem pode ser omitida reutilizando objetos existentes).

Não tenho ideia sobre o layout correto aqui, o problema é que qualquer coisa muito compactada aumentará a penalidade de tempo de execução devido às transformações necessárias. (Esta é uma razão para não usar campos de bits em C se a memória não for problema - as operações de deslocamento necessárias poluirão o cache de instruções levando a erros de cache - o código roda muito mais devagar).
Apenas os testes Imho mostrarão o que funciona melhor aqui.

@jerch interessante, eu tenho uma versão de 4 números para simplificar agora em https://github.com/sourcelair/xterm.js/pull/756.

Portanto, espera-se que a memória aqui seja em torno de: 5 * (1000 scrollback) * (8 bytes na máquina de 64 bits) * 80 = 3.2mb (antes do overhead do array js). A largura real de um terminal VS Code típico teria o dobro se mantivéssemos o formato atual. Parece muito íngreme agora que vejo, especialmente porque os usuários geralmente terão mais de 1000 scrollback e vários terminais ativos. O espaço em branco à direita que realmente não acrescenta muito e poderia facilmente ser nulo, o que provavelmente seria uma grande vitória.

A ideia de cache de conjunto de atributos / cores também parece promissora, contanto que haja uma boa maneira de acesso rápido. Uma estrutura leve em forma de árvore splay seria ideal (acesso rápido para atributos usa com mais freqüência).

Também pode valer a pena reutilizar matrizes de dados de linha quando forem aparadas, em vez de apenas descartá-las ( por exemplo, aqui ).

Sim, e com a sobrecarga do mecanismo em mente, ele fica ainda maior - tudo em um array ou objeto é armazenado como uma referência, basicamente um ponteiro para o conteúdo. Os js-arrays densos têm uma pequena vantagem aqui, eles são formados como um array do tipo C em algum lugar no caminho (bem, na verdade, ArrayLists). Matrizes esparsas e outros objetos são construídos com alguma magia de árvore para resolver a resolução da propriedade.
Portanto, para 64 bits, a referência adiciona 5 * 8 bytes a mais por célula (basicamente dobra o cálculo acima - 6,4 MB). O conteúdo pode adicionar ainda mais bytes além do "conteúdo real", mas isso depende da implementação real do tipo Inteiro e String.

Talvez um TypedArray possa resolver isso. Nesse caso, o material inteiro pode residir diretamente na posição do índice na memória, sem um direcionamento adicional. asm.js basicamente opera apenas nesses.

Aqui está um micro benchmark rápido para comparar TypedArray e js-Array para criação e inserção de dados: http://jsbench.github.io/#af3ea1056a70df2aa6775699d174df0d

O TypedArray roda 10 vezes mais rápido com FF e Chrome na minha máquina. Isso pode ser devido à pré-alocação, não testei isso com js-Array, pois não é recomendado. Não tenho certeza se os JITs detectam o fato de que o valor apenas aumenta em 1 a cada 8 bytes e até otimiza isso. Então, o benchmark é totalmente inútil.

O acesso é um pouco pior para um TypedArray (talvez devido à conversão de Number ), o consumo de memória é muito melhor com um TypedArray.

A desvantagem de um TypedArray é o bloco estático de memória quando se trata de dados sobressalentes (truques para evitar dados não funcionam aqui, a memória é "perdida" de qualquer maneira) ou redimensionamento com quebra de conteúdo. É difícil acertar e provavelmente envolverá a cópia repetida de grandes blocos de dados.

Olá. Alguma atualização sobre isso? Mal posso esperar para fazer isso funcionar 😃

Alguém está trabalhando ativamente neste problema? Está sendo discutido em algum outro lugar? @chabou @Tyriar? A Microsoft está ajudando devido ao uso do VS Code?

Este é o último problema de atraso no uso de hyper em WSL no Windows 10 para fornecer um fluxo de trabalho dev CLI decente com suporte a tmux e vim / neovim. Outros emuladores de terminal disponíveis para uso com WSL simplesmente não são agradáveis ​​de se olhar, wsltty está perto, mas o suporte a guias e plug-in está faltando ...

@vastbinderj Por que o suporte a true color ausente não oferece um fluxo de trabalho dev CLI decente? Pergunta honesta.

@szmarczak e @vastbinderj
Este problema ainda está na agenda, mas meio bloqueado devido ao alto uso de memória que irá introduzir com o design de buffer de terminal atual. Ele receberá mais atenção quando o # 791 nos trouxer um layout de buffer mais eficiente.

@rfgamaral simple - Eu trabalho em muitos servidores unix / linux diferentes por dia em sistemas corporativos muito grandes com muitos microsserviços e não ter suporte de cores decente no host principal é perturbador. Lidar com as cores não sendo iguais, esteja eu no rhel, no centos ou no debian, é doloroso. Além disso, sentar-se para ajudar um jr ou desenvolvedor par no Windows significa que tenho que mudar de contexto se as coisas não funcionarem de maneira uniforme. No entanto, estou super impressionado com o quão longe o wsl chegou tão rapidamente com as melhorias lançadas quase que mensalmente e o mesmo com o VS Code, é excelente.

@jerch Obrigado pela atualização, esperarei pacientemente até que # 791 seja resolvido ...

Estou muito ansioso por isso também.

É importante lembrar que os números JavaScript podem representar inteiros exatos de até 53 bits. Portanto, você tem 21 bits além dos 32 bits "convenientes". Você pode adicionar "ou" um pouco por simples adição, se ainda não estiver definido. Para ler os bits de alta ordem, basta dividir por um inteiro com potência de dois adequado e, em seguida, usar as operações regulares de bits.

É claro que há um pouco mais de overhead trabalhando com bits de ordem superior, mas em CPUs modernas a divisão por potência ou dois é relativamente barata - mais barata do que acessos à memória.

Eu sugiro usar um único número com 50 bits: 25 bits cada para primeiro plano e segundo plano. Um bit se definido indica que estamos usando uma cor "verdadeira" de 24 bits; se não for definido, usaremos cores "lógicas" (temáticas) ou de 8 bits. Os bits indicadores devem ser os 2 bits de ordem inferior; se não estiver definido, as cores lógicas / de 8 bits podem estar nos próximos 30 bits, portanto, só usamos os bits 32-50 se estivermos realmente usando true-color.

@PerBothner Decidimos usar um Uint32Array para o novo buffer e, por conveniência, colocar as cores nesse array também. Isso ainda não foi feito, pois queremos higienizar o novo impl antes de oferecer suporte ao truecolor.

Também fiz alguns testes / cálculos sobre possíveis layouts (consulte https://gist.github.com/jerch/27c2cf91ad313a25415873e4047b2900). Resumindo a história - as ideias são sobre a troca de economia de memória versus penalidade de tempo de execução. A transição para a matriz digitada já proporcionou uma grande economia de memória (atualmente implementa a segunda ideia acima, embora os valores da cor verdadeira ainda não tenham sido aplicados).

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

jerch picture jerch  ·  3Comentários

Tyriar picture Tyriar  ·  4Comentários

tandatle picture tandatle  ·  3Comentários

goxr3plus picture goxr3plus  ·  3Comentários

fabiospampinato picture fabiospampinato  ·  4Comentários