linux real-time e java real time, um mundo sem delays! por flávio buccianti
TRANSCRIPT
Proibida cópia ou divulgação sem permissão escrita do CMG Brasil.
Linux Real-Time
e
Java Real-Time
um mundo sem delays
Flavio C Buccianti
Agenda
�Introdução ao real-time e Enterprise real-time�Extensões ao Real-Time Linux�o patch CONFIG_PREEMPT_RT�Real-time Java�Conclusão
Definições
� Real-Time Operating Systems (RTOS) são sistemas que garantem o intervalo de tempo entre a ocorrência de um evento e do início da execução do código que está esperando esse evento ocorrer.
� Esse tempo é geralmente chamado de “latência”� Diferentes tipos de latência
– Latência do Scheduler– Latencia da Interrupção
� Hard x Soft Real-time� Sistemas com Hard Real-Time tem a maxima latência previsivel (via
“longest code path analysis”) � Soft Real-Time: latência de “melhor esforço”
Real-Time Tradicional� Geralmente usado em pequenos sistemas embarcados
� Monoprocessado (Sistemas SMP são muito complexos para o max. code path analysis)
� Velocidades de CPU restritas
� Usados para captura de dados e análise “real-time” imediata
� todos querem “hard real-time”
� “Soft Real Time” é geralmente mencionado como “not real-time at all”
� TCP/IP é muito complexo para o max. code path analysis
� RTOS's geralmente não tem suporte a TCP/IP
Os tempos mudaram ........� Os computadores estão mais rápidos
� O Cray-1 (1976) tinha 160MFLOPs e 8MB de memoria– um sistema embarcado modesto para os padrões de hoje.– Não seria capaz de rodar nem o Mozilla ou OpenOffice !
� Hoje é possível rodar muito mais instruções em somente 10us.
� As expectativas são maiores do que antes. TCP/IP é obrigatório.
� Até maquinas embarcadas pequenas precisam de SMP devido a processadores multi-core.
� Mudanças de requerimentos nos softwares empresariais: alta capacidade processamento não é mais suficiente, são necessárias garantias de latência também !
� Arquiteturas complexas multi-tier fazem a latência aumentar
O resultado ?Um novo tipo de real-time
� Vamos chama-lo de “Enterprise real-time” para diferencia-lo das aplicações real-time tradicionais
� Caracteristicas� Suporta grandes sistemas SMP� TCP/IP é requerido� Capacidade de suportar produtos de middleware existentes.
– Databases, Web servers– Certamente sem as caracteristicas de real-time..
� Suportar liguagens de alto nível� Tenha o “hard real-time” à prova de não-determinismo
Escala de tempos de latência
10 s
1 s
100 μs
10 ms
100 ms
1 ms
10 μs
STRATEGY
TACTICS
COORDINATION
ACTUATION
SENSINGMODULATION
SIGNALING CUSTOM HARDWARE
PE
RC
EP
TIO
N R
EA
CT
ION
CO
GN
ITIO
N
Extensões do Real-Time Linux
� Primeiros patches e scripts atualizaram RHEL4U2 32-bit x86
� 2.6.16 Linux kernel
� 2.6.16-rt22 CONFIG_PREEMPT_RT patch (Ingo Molnar)
� interfaces adicionadas ao glibc para suportar priority inheritance
� melhorias nas bibliotecas do PAM para permitir que usuáriosnão-root tenham acesso aos recursos do real-time.
� acesso direto à memória física requerido para estar emconformidade com o RTSJ
� bug fixes e patches de estabilização
Patch CONFIG_PREEMPT_RT
� High-resolution timers
� Kernel e userspace priority inheritance
� Hardware e software interrupt handlers rodam como kernel threads (permitindo o ajuste da prioridade real-time)
� Interrupt e Scheduler com máxima latência de 20us ( medida)
Priority InheritanceEm ambiente de computação Real-Time, priority inheritance é a maneira usada para eliminar possíveis problemas de inversão de prioridade. Usando esse modelo, o algoritimo de scheduling de processos, vai aumentar a prioridade de um processo, para a máxima prioridade sobre qualquer processo que esteja agurdando um recurso que o processo tenha feito o lock de um recurso.
A idéia básica do protocolo de priority inheritance é que quando um processo bloqueia um ou mais processos com prioridade superior, o protocolo ignora a prioridade original do processo e executa sua a parte crítica do código na maior prioridade disponível acima ou igual ao dos processos que ele está bloqueando. Depois de executar a sessão crítica do processo e fazer o unlock do recurso, o processo retorna ao seu nível original de prioridade.
Priority InheritanceConsidere três processos:
Processo Prioridade
A AltaB MediaC Baixa
onde: “A” está bloqueado aguardando algum recurso compartilhado que“C” fez um lock e está utilizando.
O protocolo de priority inheritance fará com que “C” execute sua sessãocritica na prioridade de “A” (alta).
Como resultado “B” vai ser impedido de ganhar o controle sobre “C” e vai ser bloqueado, ou seja, o processo “B” que tem mais alta prioridade, vai ter que esperar que a sessão crítica do processo “C” seja executadaporque “C” agora tem a mesma priodade que “A” (alta).
Quando “C” sai de sua sessão cítica, ele volta a ter sua prioridadeoriginal (baixa) e libera o processamento para “A” que tem prioridademais alta, e pode agora também alocar o recurso que estava bloqueadopor “C”.
sem Priority Inheritance
lock
lockAAlta
BMedia
CBaixa
com Priority Inheritance
lock
lockAAlta
BMedia
CBaixa
unlockX lock unlock
Prioridades de real time via programa
#include <stdio.h>#include <sched.h>
int main() {
struct sched_param sp;
sp.sched_priority = 90;if (sched_setscheduler(0, SCHED_FIFO, &sp) != 0) {
perror("sched_setscheduler");return -1;
}printf("hello real-time!\n");return 0;
}
Criando pthreads real-time#include <pthread.h>
#include <stdio.h>
void * func(void *arg)
{
// coloque seu código aqui...
printf("hello real-time!\n");
return NULL;
}
int main()
{
pthread_t pthread;
pthread_attr_t attr;
struct sched_param param;
int ret;
param.sched_priority = 90;
pthread_attr_init(&attr);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedparam(&attr, ¶m);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
if ((ret = pthread_create(&pthread, &attr, func, NULL))) {
printf("pthread_create failed: %d (%s)\n", ret, strerror(ret));
pthread_attr_destroy(&attr);
return -1;
}
pthread_attr_destroy(&attr);
return 0;
}
Setando prioridade na mão: usando chrt
Uma aplicação normal pode rodar como Real-time:
$ chrt -f -p 90 <PID>
Referências:•http://rt.wiki.kernel.org/index.php/Main_Page
Software Suportado
� Como o ambiente de userspace é RHEL ou SLES com pequenas adiçõesàs bibliotecas de C.
� Qualquer produto de software que tenha sido testado/homologado para o RHEL/SLES (nas mesmas versões disponíveis do RT) e que não dependade módulos binários do kernel deve rodar sem problemas.
� Alguns produtos em produção nos usuários do Real-Time Linux:� Clearcase� Tivoli Storage Manager (TSM) � Tivoli Enterprise Console (TEC) Agent� Etc….
Real-Time Java
http://www-03.ibm.com/press/us/en/pressrelease/21033.wss
USS ZUMWALT, destroyer DDG 1000 da Marinha Americana• Lançado ao mar em outubro de 2013
• Utiliza Linux RT e Java RT para diversos sistemas internos:� Comando e controle� Navegação� Ajuste de Mira� Controle de armas� Sistemas de Radar� Menor tripulação a bordo� Menor complexidade entre sistemas
RTSJ Real-Time Specification for Java� Primeira extensão da linguagem Java
� A arquitetura não define um RT garbage collector
� Define 4 áreas de memória:
1. Scoped memory
2. Physical memory
3. Immortal memory
4. Heap memory
RTSJ Real Time Specification for Java
� Define NonHeapRealTime threads
� NHRT threads podem usar somente scoped e immortal memory� NHRT threads não podem referenciar “Heap” memory, porque a
parada total em caso de mover objetos Java não é aceitável pelas threads real-time.
– Qualquer tentativa de referenciar a memória normal a partir the uma thread NHRT causará um uncatchable exception
– Significa que NHRT não pode usar a maioria das bibliotecas Java a não ser que elas sejam auditadas com cuidado para que não leiam, escrevam ou aloquem objetos no heap. A maioria da bibliotecas Java não são compatíveis com NHRT.
char size = 'L' ;char [ ] sizes = { 'S' , 'M' , 'L' } ;
0
1
2
0x21B08
'S'
'M'
'L'
'L'
sizes [ ]
size
HeapStack
Variáveis primitivas e matrizes
char [ ]
Shirt myShirt = new Shirt ( “Polo”, 'M' ) ;
Shirt [ ] shirts = { new Shirt (“Polo”, 'S') ,new Shirt (“Oxford”, 'M' ) ,
new Shirt (“Polo”, 'L' )} ;
0
1
2
0x23162shirts [ ]
myShirt
Heap
Stack
Variáveis Reference e matrizes
0x0088
0x0432
0x0776
0x73128Polo
M
Polo
Polo
Oxford
S
M
L
Java Real Time
Dois fabricantes produzem o Java Real Time de acordo com o RTSJ e que podem ser executados em ambiente Linux RT:
• IBM (Websphere Real Time)• Oracle (Sun Java Real-Time System)
Features da JVM real-time
� RTSJ: Real-Time Specification for Java
� Metronome: um garbage collector real-time
� AOT: Ahead of Time compilation
Metronome -garbage collector RT� Um garbage collector desenhado por David F. Bacon IBM TJW Research
Center para workloads de real-time.
� Tuning knobs:� Max. time slice “roubado” pelo the GC (ex.: 100us) � Max. % of CPU time usado pelo GC (ex.: 30% sobre 1ms) � O que fazer se a aplicação gera mais garbage do que o GC pode
manusear:– Imprimir uma warning message e fazer um “stop the world” GC– Abortar o programa uma vez que as garantias de real-time não
conseguem ser sustentadas.� Max. heap memory usada pela JVM
– Aumentado-a pode ajudar se a aplicação tem um perfil de gerar garbage collection em formato “burst”
� Nenhuma outra JVM tem essas caracteristicas !
Metronome – um garbage collector real-time
Garbage Collector tradicionall
•Tempos de utilização imprevisível•Latência imprevisivel
Metronome – um garbage collector real-time
Garbage collector com intervalos de 1 ms
Iniciando um programa RT com controle de GC
java -Xrealtime -Xgc:targetUtilization=70 nomeprograma
Metronome – um garbage collector real-time
Metronome GC pré-configurado para 30% de GC e 70% do tempo para aplicação
� POSIX SCHED_OTHER� 40 níveis de prioridade� a JVM RT usa o default Linux priority para threads regulares
� POSIX SCHED_FIFO
� não tem time slice (diferente da SCHED_RR)� executa até ser bloqueada (I/O, etc...)� executa até liberar o controle voluntáriamente� é feito um preempt por uma thread the mais alta prioridade
� 99 prioridades� RTSJ requer 28 níveis numerados de 11 a 38� distribuidas entre as prioridades 11 e 89� a aplicação assinala um dos 28 níveis� não tem ajuste dinâmico de prioridade
Scheduling
Exemplo de uma thread Realtimeimport javax.realtime.RealtimeThread;
import javax.realtime.PriorityParameters;
import javax.realtime.PriorityScheduler;
public class MyThread extends RealtimeThread {
public MyThread() {
this.setName("MyThread");
this.setSchedulingParameters(
new PriorityParameters(
PriorityScheduler.getMinPriority(this)+1));
}
public void run() {
while (true) {
// do work
}
}
}
Exemplo: thread NoHeapRealtimeimport javax.realtime.NoHeapRealtimeThread;
import javax.realtime.PriorityParameters;
import javax.realtime.PriorityScheduler;
import javax.realtime.MemoryArea;
public class MyThread extends NoHeapRealtimeThread {
public MyThread(MemoryArea memArea) {
super(null, memArea);
this.setName("MyThread");
this.setSchedulingParameters(
new PriorityParameters(
PriorityScheduler.getMinPriority(this)+1));
}
public void run() {
// do work
}
}
• Heap memory – Heap tradicional porém gerenciada pelo Metronome Garbage Collector.
• Scoped memory – as aplicações podem usar e requisitar, porémsomente pode ser usada por real-time threads. Tem um contador de utilização que quando chega a zero é liberada.
• Immortal memory – usada para carga de classes e inicializaçãoestática mesmo que a aplicação não faça uso especifico dela.
Representa uma área de memória contendo objetos que podemser referenciados por qualquer schedulable object incluindo no-heap real-time threads e no-heap asynchronous event handlers., sem excessões ou delays de garbage collection.
• Physical memory – premite que objetos sejam criados em regiõesespecíficas da memória real que tenham características únicas e importantes tal como memória que tenha um acesso mais rápido.Em geral é pouco usado e não afeta o usuario normal de JVM.
O Java RT implementa 4 tipos de memória:
Immortal memory
A Immortal Memory é um recurso de memoria compartilhado entretodos os objetos e threads “esqueduláveis” numa aplicação.
Os objetos alocados na Immortal memory estão sempre disponíveispara as non-heap threads e para os assichronous event handlers,esses objetos não estão sujeitos aos delays causados pelo processode garabage collection.
Esses objetos são liberados pelo sistema quando o programatermina.
Parâmetro para definir a Immortal Memory:
-Xgc:immortalMemorySize=20m sets 20 MB
Exemplo de uso de ImmortalMemoryimport javax.realtime.MemoryArea;
public class MyObject {
Object obj;
public MyObject(MemoryArea memArea) {
memArea.enter(new Runnable() {
public void run() {
// do something
}
});
}
}
import javax.realtime.RealtimeThread;
import javax.realtime.PriorityParameters;
import javax.realtime.PriorityScheduler;
import javax.realtime.HeapMemory;
import javax.realtime.ImmortalMemory;
public class MyThread extends RealtimeThread {
public MyThread() {
this.setName("MyThread");
this.setSchedulingParameters(
new PriorityParameters(
PriorityScheduler.getMinPriority(this)+1));
}
public void run() {
final MyObject myObject =
new MyObject(HeapMemory.instance());,
ImmortalMemory.instance().enter(new Runnable() {
public void run() {
// do work in immortal heap
}
});
}
}
Scoped memory
• O padrão RTSJ introduziu o conceito de scoped memory.
• Ele pode ser usado por objetos que tenham uma duração bem definida.
• Um scope pode ser definido explicitamente ou ele pode ser anexado à um schedulable object (uma thread real-time ou à um asynchronous event handler) que efetivamente cria o scope antes que ele execute o método run() do objeto.
• Cada scope tem um contador de referência e quando ele chega a zero, os objetos que residem nesse scope podem ser fechados (finalizados) e a memória associada a esse scope é liberada.
• O re-uso do scope fica bloqueado até que finalização esteja completa.
• Parâmtero para definir scoped memory:
• -Xgc:scopedMemoryMaximumSize (default 8 MB)
Exemplo de uso de ScopedMemoryimport javax.realtime.RealtimeThread;
import javax.realtime.PriorityParameters;
import javax.realtime.PriorityScheduler;
import javax.realtime.LTMemory;
import javax.realtime.ScopedMemory;
import javax.realtime.SizeEstimator;
public class MyThread extends RealtimeThread {
static final int load = 1000000;
public MyThread() {
this.setName("MyThread");
this.setSchedulingParameters(
new PriorityParameters(
PriorityScheduler.getMinPriority(this)+1));
this.setDaemon(true);
}
public void run() {
SizeEstimator size = new SizeEstimator();
/**
* Calulate the memory footprint of all objects
*/
size.reserve(long[][].class, load);
size.reserve(long[].class, load * 50);
ScopedMemory memArea = new LTMemory(size);
while (true) {
/* A scoped memory area is being used. Normally the garbage collector would have to deal with the
* unused classes, but with scoped memory we are throwing away all of the objects in the scope when
* we exit the enter() method. This will put much less load on the garbage collector. */
memArea.enter(new Runnable() {
public void run() {
int count = 0;
long[][] array = new long[load][];
for (int n = 0; n < array.length; n++) {
array[count] = new long[50];
}
});
}
}}
AOT – compilação Ahead of Time
� Reduz a pausa causada pelo compilador JIT
� Dificil pois o Java tem features da linguagem que requerem o compiladorJIT por questões de performance.
� sx.: subclasses definindo “new types” podem ser carregadasdinamicamente no tempo de execução.
� A performance obtida pelo uso do AOT é uma alternativa entre o codigointerpretado e código totalmente otimizado gerado pelo JIT.
Ahead-of-time (AOT)
� Compila os programas (classes) antes de ser executado
� AOT evita o problema do JIT não compilar o codigo antes que ele sejarequerido para execução.
Just-InTime (JIT)
� JIT NÃO causa delays indesejados em código real time.
� JIT é executado como uma thread de alta prioridade (SCHED_OTHER) � roda acima das threads normais do Java
� roda abaixo das threads real-time
� O trabalho de alta-prioridade não é interrompido pelo trabalho do JIT
� O trabalho real-time é executado em tempo porém o trabalho real-time pode acabar tendo que interpretar bytecodes porque o JIT nãoconseguiu compilar em tempo os métodos que estavam na fila.
AOT e JIT
Pode-se controlar quando e como o compilador JIT opera, usando a classe java.lang.Compiler fornecida com o SDK standard.
A JVM suporta os métodos:
Compile.compileClass()
Compiler.enable()
Compiler.disable()
Sem Metronome e AOT
10 s
1 s
100 μs
10 ms
100 ms
1 ms
10 μs
RealTimeThread com Heap
NoHeapRealTimeThreadcom Scopes
Com Metronome e AOT
10 s
1 s
100 μs
10 ms
100 ms
1 ms
10 μs
RealTimeThread com Heap
NoHeapRealTimeThreadcom Scopes
Scoped memory
Parâmetro:
-Xgc:scopedMemoryMaximumSize (default 8 MB)
Immortal memory
Parâmetro:
-Xgc:immortalMemorySize=20m (seta 20 MB)
Porque Real-time Java ?� Para fornecedores dos orgãos de defesa e militares , o Java é o novo ADA
� É difícil de encontrar programadores ADA...� Sistemas de defesa
– precisam de real-time– estão cada vez mais integrados outros sistemas e mais complexos.
� Setor Financeiro� Aplicações automatizadas de compra/venda tem necessidade de real-time.
� Web sites com tempo de resposta garantido� Numa arquitetura muti-tier onde orequerimento de tempo de resposta de
milisegundos para satisfazer o requisito de um page-load abaixo de 1 segundo.
Conclusão� Enterprise Real-Time: uma nova maneira de “pensar”real-time
� Mais poderoso e com mais features do que o tradicional “hard real-time”
� Melhor determinismo do que o esperado pelo soft real-time
� Java Real Time e Real-Time Linux Extensions
� Implementação do conceito de enterprise real-time
� Disponível para os “lead adopters”
� Metronome GC e AOT tornam o uso do de programas real-time em Java mais fáceis e “mais saborosos”.
Algumas referências:
http://www.ibm.com/developerworks/java/jdk/linux/download.html
http://pic.dhe.ibm.com/infocenter/realtime/v3r0m0/index.jsp
http://docs.oracle.com/javase/realtime/doc_2.2/release/JavaRTSInstallation.html
http://www.research.ibm.com/journal/sj47-2.html
http://www.oracle.com/technetwork/articles/javase/index-138577.html
https://blogs.oracle.com/delsart/entry/real_time_java_programming_rt
http://docs.oracle.com/javase/realtime/doc_2.2u1/release/JavaRTSGarbageCollection.html
http://www.ibm.com/developerworks/java/library/j-devrtj1/index.html?ca=dat-
Demonstração:
Harmonicon:
http://www.youtube.com/watch?v=jid4WaILPBk
- Sintetizador MIDI escrito em Java RT
- Música em real-time mesmo com a máquina sobrecarregada
http://www.youtube.com/watch?v=AKfmBMTx0gM
- Explicação geral sobre features e funcionamento
Proibida cópia ou divulgação sem permissão escrita do CMG Brasil.
Flavio C Buccianti
OBRIGADO !