[Off-Topic] Multi-Tasking no iPhone OS 4

2010 April 09, 14:05 h - tags: apple obsolete

Acho que todos assistiram ontem a apresentação do iPhone OS 4, com “100 novas funcionalidades” e “7 grandes pilares”. No fundo mesmo o principal são 2 pontos: iAd e MultiTasking. iAd não me interessa muito agora, então vou pular.

Os pundits de plantão não páram de perturbar com os “ahhhhh … mas o iPhone não roda mais de uma aplicação ao mesmo tempo”. Ou, se ele é um iniciante de computação usa os jargões erroneamente “ahhhhh … mas o iPhone não tem multi-tasking”, sendo que o cidadão sequer sabe o que é multi-tasking.

Apesar que isso poderia ser atribuído à falta de entender inglês aqui no Brasil. Quando se fala “multi-tasking”, penso em duas traduções para isso: a normal e a técnica. A técnica significa:

“Simular a capacidade de executar mais de um programa ao mesmo tempo”.

Já a tradução normal significa;

“A capacidade de permitir executar mais de uma tarefa ao mesmo tempo”.

E nesse caso “tarefa” no sentido não-técnico da palavra, assim como lavar roupa, tirar o lixo são “tarefas”.

O iPhoneOS é o sistema operacional que roda no iPhone, iPod Touch e agora no iPad. Ele é uma variante mais leve e otimizada de seu irmão maior, o Mac OS X. Por sua vez ele foi baseado no venerado NeXTStep, um sistema avançado demais para sua época que foi baseada na plataforma BSD-UNIX, usando uma kernel Mach batizada em XNU. Essa plataforma Unix do Mac é conhecida como Darwin. A soma dela com outras tecnologias de usuário como Aqua, Core Foundation e tudo mais forma o Mac OS X e por sua vez o iPhoneOS.

Se você está rodando um iPhone, você tem DNA nobre dessa era espalhada em algum lugar. Sistemas Unix praticamente inventaram o que chamamos hoje de “multi-tasking” que é a capacidade de dividir tempo do processador para cada aplicação em execução para simular a “impressão” de que estão rodando ao mesmo tempo em paralelo.

Portanto, dizer que o iPhoneOS não suporta “multi-tasking”, no sentido de “time-sharing de CPU, não faz sentido. Mas é perdoável se você é leigo em informática.

Porém, o iPhoneOS de fato não suporta “multi-tasking” no sentido cotidiano, ou seja, se você estava dirigindo com um navegador via GPS como o TomTom e de repente recebeu um SMS e resolveu atender, o aplicativo do TomTom é completamente fechado para que o leitor de SMS possa abrir. A Apple conscientemente, por decisão própria, incluiu código extra no sistema operacional para que aplicativos de terceiros não funcionem em paralelo.

É importante salientar o “aplicativos de terceiros” porque você pode ouvir música no iPod, ficar recebendo e-mails, navegar no Safari, tudo em paralelo. Até onde sei, tirando os processos específicos de telefonia, só o Safari, Mail.app e iPod conseguem funcionar em paralelo sem fechar quando se muda de aplicação.

Por que?

Mas por que a Apple resolveu fazer isso? Foi uma escolha de prioridades. Estamos falando de uma nova plataforma aqui, não de um sistema operacional tradicional genérico. O iPhone foi uma oportunidade única de redefinir muitos dos paradigmas que estão estabelecidos na indústria há mais de 30 anos.

Quando o Apple II foi lançado no fim dos anos 70, o público alvo era o nicho dos geeks, dos ávidos por eletrônica e programação. Era uma época onde o cidadão comum não tinha o menor interesse em equipamentos eletrônicos muito mais “estranhos” do que uma TV ou um rádio de pilha.

Rolando a fita até 2007, o lançamento do iPhone não é mais para esse público e sim para o cidadão comum, para minha mãe, para seu pai, para professores. O maior problema de computadores é que a maioria das pessoas não sabe gerenciar programas. Eles não entendem bem o que significa “fechar um programa”. Para eles o computador está executando um programa: aquele que ele está usando no momento – e normalmente maximizado – seja um navegador ou leitor de e-mail. Só geeks efetivamente ficam mudando de programas o tempo todo, suando as teclas alt-tab.

Pior, um smartphone tem recursos muito limitados. Um desktop conta com 4Gb de RAM, discos rígidos com 320Gb ou mais. Mas há uma herança da época onde recursos eram escassos: memória virtual. Windows, Linux e Macs usam esse recurso. Em um sistema operacional de 32-bits, cada programa poderia teoricamente pedir ao sistema até 4Gb de memória. Porém, até pouco tempo, não era comum nem mesmo ter 1Gb de RAM. Ou seja, em pouco tempo esse limite físico seria um problema. Para um meio termo, o sistema operacional reserva uma parte do espaço em disco rígido (que é mais lento, mas mais barato que RAM) para usar quando falta RAM.

Claro, a história é bem mais complicada que isso, mas é só para dar uma idéia. Mas nos smartphones temos um problema: temos menos RAM ainda do que o normal e não temos memória virtual. Ou seja, memória é um recurso muito escasso. Mesmo o iPad, hoje tem apenas 256Mb. E a solução não é simplesmente “ahhhh … mas meu smartphone XPTO terá 1Gb de RAM, isso é pensar com os músculos e não com o cérebro.

Fonte: Why iPad and iPhone don’t support multitasking

Tudo isso pode parecer uma desculpa esfarrapada para não implementar alguma coisa, mas aqui estamos falando o contrário: quem está criticando é que está ignorando os fatos, se super-estimando mais do que devia e ignorando o fato que o iPhoneOS inerentemente suporta multi-tasking por causa de seu DNA Unix. Ou seja, estão chovendo no molhado. Pense no que significa, em menos de 128Mb de RAM, subir múltiplas aplicações – pior ainda, muitas delas intensivas de dados já que estamos na era online onde baixamos dados o tempo todo – e ainda pedir para o sistema operacional ser super responsivo?

Não dá. Existem truques para isso, por exemplo, fazer o sistema operacional ficar checando quanto de memória ainda tem sobrando e ficar matando os programas mais antigos, ou mesmo adicionar memória virtual nos cartões de memória Flash. Nenhuma dessas soluções dá certo e a prova é que um dos aplicativos mais instalados em smartphones Android justamente é um “Gerenciador de Tarefas” para que você possa ficar matando programas. Geeks se sentem confortáveis com isso, meu pai nunca vai saber o que é e nem se interessa.

Então, há solução?

Solução 1

A Apple, na melhor maneira ágil, está consistentemente fazendo iterações e lançando novas funcionalidades à medida que elas são necessárias, lançando o que é prioritário primeiro e depois incrementando, num movimento de melhoria contínua. Está correto. Seria melhor do que ela estar lançando o iPhone só em 2009 em vez de 2007.

Dado que a prioridade era tornar a computação mais simples para usuários leigos, multi-tasking não era prioridade mesmo. Em 2007 sequer existia tantos aplicativos assim para se querer trabalhar ao mesmo tempo. O paradigma de uma aplicação focada de cada vez funcionou muito bem. Ninguém reclama de sistema ficando lento, tudo sempre está rápido e responsivo como se tivesse acabado de ligar.

Hoje temos mais de 150 mil aplicativos, das mais diferentes categorias. O iPhone cresceu e ganhou GPS, 3G, bússola, serviços de localização. Mas agora realmente queremos ouvir música via internet no Pandora, ao mesmo tempo que dirigimos na rua usando o TomTom GPS, e ainda com um instant messenger recebendo mensagens no fundo.

Por outro lado, não queremos perder essa responsividade, não queremos ter que ficar gerenciando e matando programas o tempo todo. Então a questão é: como adicionar a capacidade de dividir tempo do processador para múltiplas aplicações de terceiros sem perder os benefícios que já temos hoje, ou seja, como não fazer um bloatware?

A primeira solução foi a criação do Push Notification Services. Esse tipo de sistema funcionou para alguns poucos tipos de aplicativos como instant messengers. A “grosso” modo eu imagino que um aplicativo como o AIM se conecta a um servidor da Apple que, por sua vez, se conecta a um servidor do AIM. Daí quando a aplicação fecha, a conta da Apple pro AIM continua aberta. Se uma nova mensagem é enviada, o servidor da Apple recebe e redireciona para o iPhone, que tem um serviço escutando mensagens. Quando ele recebe essa mensagem, ele sabe qua aplicativo abrir e passar a mensagem recebida. Esse é o truque para um AIM, Meebo, Palringo e alguns outros funcionarem.

Mas isso foi muito pouco.

Solução 2

Hora da segunda iteração e desta vez eles conseguiram o melhor dos dois mundos.

Para os puristas, o cenário é que o “multi-tasking” de aplicativos de terceiros continua bloqueado, ou seja, você não vai conseguir rodar aplicativos em paralelo de verdade. Portanto os benefícios que mencionei antes continuam existindo. Um efeito colateral, inclusive, é que vírus e outros tipos de malware, que rodariam em paralelo sem você perceber, também não vão conseguir executar.

A primeira parte importante é App Switching, ou seja, em vez de apenas “fechar” a aplicação, o sistema operacional tira uma fotografia do conteúdo relevante em memória dele e salva no Flash drive interno dele, como qualquer arquivo. Ou seja, o aplicativo fechou mas deixou esse estado gravado.

Agora, quando a aplicação for reaberta e existir esse “arquivo” salvo, o sistema operacional pode recuperá-lo e, na prática, será como se a aplicação nunca tivesse fechado. Se você já usou o recurso de “hibernar” do seu computador, onde ele grava o conteúdo da RAM num arquivo em disco e desliga tudo, é a mesma coisa.

O desafio é fazer isso ser rápido, ou seja, quando uma aplicação fechar ela não pode parecer que “travou” enquanto grava esse estado. Portanto devem existir guias bem restritos de como fazer isso funcionar. Existem alguns tipos de dados que devem ser salvos e outros tipos que podem ser recarregados a posteriori. O mesmo vale para abrir uma aplicação, onde não pode aparecer uma “ampulhetinha” ou o “beach-ball” com a mensagem de “Loading …” para recarregar o estado gravado. Ou seja, a chave é fazer App Switching ser rápido.

Se isso está resolvido, agora o problema é como simular que uma aplicação de música como o Pandora, parece que continua rodando mesmo estando fechada?

Para isso a Apple incluiu no sistema operacional 5 serviços. Um de música, outro de VoIP, Push Notifications, Local Notifications, Location, Task Completion.

Com o primeiro, quando o Pandora vai fechar, ele delega a música para esse serviço do sistema operacional. O Pandora fecha, mas a música continua rodando. Quando o Pandora reabre e recarrega seu estado, ele volta a controlar a música.

A mesma coisa com o Skype, que pode usar fechar e delegar o recebimento de chamadas para esse serviço de VoIP, que por sua vez reabre o Skype e ele volta a ter controle.

E assim por diante: o truque é fechar de fato a aplicação e delegar suas tarefas a um serviço do sistema operacional, estes sim, rodando em multi-tarefa preemptiva. Ou seja, o “multi-tasking” continua sendo bloqueado para processos de terceiros, mas habilitado para serviços da Apple.

O cuidado que eles precisam ter é para não sobrecarregar esses serviços. Porque não adianta nada fechar as aplicações, mas digamos num caso ruim, que você tenha 10 aplicativos que façam download de podcasts via internet. Você abre cada um deles, manda fazer o download em cada um e vai fechando cada aplicação. O download pode ser delegado para o serviço Task Completion. Mas agora são efetivamente 7 downloads acontecendo em paralelo e isso pode tornar o sistema todo mais lento e não-responsivo, exigindo provavelmente um reboot do sistema operacional. Uma saída para isso é colocar um teto de limite de processamento, por exemplo, dizer que cada serviço não pode consumir mais do que 10% do CPU nem mais que 10% da memória RAM disponível, rodando sob baixa prioridade. Esta parte não ficou muito clara, mas precisa ser limitada.

Obs: Um detalhe importante é que eu estou especulando parte desse processo. Como eu disse, eu tinha preocupações que parecem que não são problemas na implementação. A forma “ingênua” que é simplesmente fazer um dump da memória do aplicativo para fechá-lo não é trivial. Por exemplo, se a aplicação está usando 30Mb de memória e a velocidade de escrita no Flash drive é de 30Mb/s, ainda assim vai levar 1 segundo para hibernar a aplicação. Não deve ser assim que estão fazendo porque pelos demos é praticamente instantâneo. Também não imagino que o processo esteja apenas sendo suspenso para não gastar CPU porque mesmo assim a RAM continuaria sendo consumida. Portanto o detalhes devem ser elucidados nas próximas semanas.

Conclusão

Como eu sempre digo: produtos precisam ser bem pensados e não simplesmente atirar nele tudo que pedem. Se a Apple fosse adepta de “focus groups”, ela poderia ter implementado o “multi-tasking” da maneira como todo mundo estava pedindo. Mas as pessoas estavam pedindo da forma errada porque não tinham parado para pensar em alternativas nem nas premissas e objetivos. Novamente, só pensaram no “Como”, no “How To” mas não pensaram no “Porque”.

Não quer dizer que esta é a melhor alternativa, mas pelo menos é a melhor que eu posso imaginar. Alguns meses atrás quando estávamos discutindo a respeito com amigos, chegamos à mesma conclusão. Minha preocupação na época era se gravar/restaurar o estado das aplicações não seria lento e se rodar múltiplos serviços (daemons) em paralelo não iria eventualmente deixar o sistema lento de qualquer forma.

Se a Apple lançou, obviamente ela resolveu pelo menos essas duas preocupações que eu tinha, mas agora só testando para saber. De qualquer forma, eu imagino que a polêmica do “multi-tasking” (no sentido normal de “múltiplas tarefas” mesmo) está resolvido com a simulação de uma “multi-tasking” (agora no sentido técnico de “time-sharing de CPU”) via gravar/restaurar estado e delegação/notificação para serviços.

Porém, isso só vai funcionar nos iPhone 3GS e iPod Touch Terceira Geração e não vai funcionar nos iPhone 3G e 2G nem nos iPod Touch mais antigos. Minha única explicação é porque eles tem metade da RAM do 3GS, metade do cache L1, não tem cache L2, tem 30% menos clock de CPU. Se um serviço vai funcionar mal, é melhor não funcionar mesmo. Portanto faz sentido.

Mas só vamos ter um veredicto mais para o meio do ano. Vamos ver, mas imagino que se demorou tudo isso, é porque a coisa foi bem implementada, como de costume.

Comments

comentários deste blog disponibilizados por Disqus