Não procurei problemas. Não iniciei o processo de criação do Chrome
mil vezes no fim de semana , mas apenas fiz as tarefas mais comuns do século 21 - acabei de escrever um email às 10:30 da manhã. E de repente o Gmail continuou. Continuei imprimindo por alguns segundos, mas nenhum caractere apareceu na tela. De repente, o Gmail cedeu e voltei ao meu e-mail
muito importante . Mas depois tudo se repetiu, só que desta vez o Gmail não respondeu às solicitações por mais tempo.
Isso é estranho ...
É difícil resistir à oportunidade de conduzir uma boa investigação, mas, neste caso, o desafio é especialmente forte. Afinal, estou no Google trabalhando para melhorar o desempenho do Chrome para Windows. Descobrir a causa do congelamento é o meu
trabalho . E, depois de muitas falsas partidas e muito trabalho, ainda consegui descobrir como o Chrome, Gmail, Windows e nosso departamento de TI juntos me impediram de digitar um email. Ao longo do caminho, havia uma maneira de economizar uma quantidade significativa de memória para algumas páginas da web no Chrome.
Havia tantas nuances na investigação que deixarei algumas para
outro artigo , e agora vou explicar completamente as razões das suspensões.
Como de costume, o
UIforETW funciona em meu plano de fundo e monitora os buffers circulares, então eu apenas tive que inserir Ctrl + Win + R - e os buffers foram salvos em disco pelos últimos trinta segundos de atividade do sistema. Fiz o download no
Windows Performance Analyzer (WPA), mas não consegui instalar permanentemente o congelamento.
Quando o programa Windows para de enviar mensagens, os eventos ETW são lançados indicando
exatamente onde isso aconteceu ; portanto, é trivial encontrar esses tipos de interrupções. Mas, aparentemente, o Chrome continuou a enviar mensagens. Procurei um momento em que um dos principais fluxos do Chrome entrou no ciclo ativo ou estava completamente ocioso, mas não encontrou nada explícito. Em alguns lugares, o Chrome permaneceu ocioso, mas mesmo assim todos os principais tópicos continuaram funcionando, portanto, você não podia ter certeza de onde ocorreu o travamento - o Chrome poderia ficar ocioso na ausência de eventos:


O UIforETW possui um keylogger interno, que geralmente é útil na identificação de pontos-chave em um rastreamento. No entanto, por razões óbvias de segurança, por padrão anonimiza as teclas, tratando cada número digitado como "1" e cada letra como "A". Isso torna difícil encontrar o momento exato do congelamento, então mudei o tipo de rastreio de "particular" para "cheio" e estava esperando um congelamento. Por volta das 10h30 da manhã seguinte, o desligamento foi repetido. Salvei os buffers de rastreamento e salvei essa marca no campo de informações de rastreamento do UIforETW:
Ele digitou "adiar para aqueles que têm mais experiência com mergulho" - e o Gmail parou no final da palavra "aqueles" e depois retomou o trabalho na área da palavra "experiência". Guia Gmail com PID 27368.
Esta é uma discussão comum sobre
maneiras de chegar ao escritório , mas é importante que agora haja uma maneira de encontrar um travamento no rastreamento da ETW. Carrego o rastreio, olho para os dados do keylogger no campo Generic Events (os eventos são emitidos pelo próprio UIforETW e cada um é um losango roxo na captura de tela abaixo) - e posso ver imediatamente onde ocorreu o travamento, com o qual a falha no uso da CPU se correlaciona claramente:

Ok, mas por que o Chrome parou? Aqui estão algumas dicas: as capturas de tela não mostram que cada vez que o
WmiPrvSE.exe usa totalmente o hyperthread da CPU. Mas isso não deveria importar. Minha máquina possui 24 núcleos / 48 threads, portanto, consumir um hyper-thread significa que o sistema ainda está 98% gratuito.
Então, cheguei a um período claramente importante em que o Chrome estava ocioso - e observei, em particular, o processo CrRendererMain no chrome.exe (27368), correspondente à guia Gmail.
Nota: Quero agradecer a mim mesmo a partir de 2015 por solicitar à Microsoft que melhore os mecanismos de nomeação de fluxo e obrigado pela Microsoft por implementar todas as sugestões - os nomes dos threads no WPA são ótimos!
O problema foi esclarecido. Durante uma interrupção de 2,81 segundos, esse encadeamento foi iniciado em um agendamento 440 vezes. Normalmente, iniciar a cada 6 ms é suficiente para tornar o programa responsivo, mas por algum motivo isso não aconteceu. Percebi que toda vez que ele acordava, ele estava na mesma pilha. Para simplificar:
chrome_child.dll (stack base)
KernelBase.dll!VirtualAlloc
ntoskrnl.exe!MiCommitVadCfgBits
ntoskrnl.exe!MiPopulateCfgBitMap
ntoskrnl.exe!ExAcquirePushLockExclusiveEx
ntoskrnl.exe!KeWaitForSingleObject (stack leaf)
Chrome VirtualAlloc, “CfgBits” . , Chrome VirtualAlloc 440 , . . Chrome VirtualAlloc — . Chrome , — 439 — Chrome , . , .
Windows
— , , . . .
, Chrome , WmiPrvSE., :
ntoskrnl.exe!KiSystemServiceCopyEnd (stack base)
ntoskrnl.exe!NtQueryVirtualMemory
ntoskrnl.exe!MmQueryVirtualMemory
ntoskrnl.exe!MiUnlockAndDereferenceVad
ntoskrnl.exe!ExfTryToWakePushLock (stack leaf)
WMI ( ), WMI. CPU, , WmiPrvSE.exe ( ):
WmiPerfClass.dll!EnumSelectCounterObjects (stack base)
WmiPerfClass.dll!ConvertCounterPath
pdh.dll!PdhiTranslateCounter
pdh.dll!GetSystemPerfData
KernelBase.dll!blah-blah-blah
advapi32.dll!blah-blah-blah
perfproc.dll!blah-blah-blah
perfproc.dll!GetProcessVaData
ntdll.dll!NtQueryVirtualMemory
ntoskrnl.exe!NtQueryVirtualMemory
ntoskrnl.exe!MmQueryVirtualMemory
ntoskrnl.exe!MiQueryAddressSpan
ntoskrnl.exe!MiQueryAddressState
ntoskrnl.exe!MiGetNextPageTable (stack leaf)
.
NtQueryVirtualMemory,
GetProcessVaData,
Va, , . VirtualScan
NtQueryVirtualMemory , Gmail (10-15 ) — . ?
, .
NtQueryVirtualMemory . « », « » .. Gmail 26 000 , ( ,
WPA) 16 000 , .
- Gmail
vmmap , Gmail (361 836 ) (49 719), — 2 147 483 648 , 2 . ?

, 2
Control Flow Guard (CFG), , “CFG” , Gmail Chrome —
MiCommitVadCfgBits. , CFG !
Control Flow Guard (CFG) . , 128- . , CFG ( 2 ), . CFG
, CFG . 98 24 866 CFG-. :
Scan time, Committed, page tables, committed blocks
Total: 41.763s, 1457.7 MiB, 67.7 MiB, 32112, 98 code blocks
CFG: 41.759s, 353.3 MiB, 59.2 MiB, 24866
vmmap , — vmmap 49 684 , 24 866
, CFG ? CFG , ? .
— VAllocStress, . 64- CFG, , , , . , / , , . VAllocStress:
- :
- :
- 500 ( ).
- VirtualAlloc .
- , VirtualAlloc ~500
- .
. . , . , VirtualScan VAllocStress. , CFG ,
. VAllocStress !
CFG, . !
, JavaScript- v8 CodeRange , CodeRange
128 . , , CFG, .
, CodeRange, , ? CodeRange, Gmail — . ( ) CodeRange. , WorkerThread::Start . :
- Gmail -, , .
- , -.
- CodeRange, JITted- JavaScript 47- .
- CFG 2 .
- CFG .
- NtQueryVirtualMemory CFG ( 1 ) , .
CFG Windows 10 RS4 ( 2018 ), , . , .
CFG — . CFG , . . , CFG ! , . CFG . ,
2 !
, — Gmail 353,3 CFG 59,2 , 400 . - , .
v8 ( JavaScript Chrome) ,
CodeRange, . Microsoft CFG. , - Microsoft CFG , , , . vmmap .
. :
- Gmail.
- Windows 10.
- IT- WMI- .
- .
- .
, , , . , , , , .
, 10:30 , IT- . ,
Control Panel →
Configuration Manager →
Actions,
Hardware Inventory Cycle Run Now.

, VAllocStress VirtualScan
Github.
. ( ), (), ( WMI). vmmap. — —
crbug.com/870054.
UPD.