corpus de maquetación para el PGO: 10 páginas nuestras
Medida la ganancia del PGO ayer: -9,4% en una página de DOM/maquetación y -1,0% en 3d-raytrace de SunSpider. La razón de la diferencia es que un benchmark JIT-bound es casi CIEGO al PGO: el bucle caliente no lo ejecuta el C++ de SpiderMonkey sino el código máquina que el JIT emite en runtime, y el PGO optimiza el intérprete, el GC y el propio JIT — no lo que el JIT produce. El corpus de Mozilla está dominado en número de páginas por SunSpider, o sea que entrenaba mucho justo donde el PGO menos rinde. Estas diez ejercitan el camino que sí es C++ de punta a punta: flex flexbox anidado, wrap, alineaciones rejilla CSS Grid: pistas, áreas nombradas, auto-fit tablas tablas grandes con table-layout FIJO y AUTO (dos algoritmos) texto columnas, shaping, reflujo por cambio de ancho selectores DOM profundo contra 600 reglas, muchas que NO casan pintado degradados, sombras, opacidad, mix-blend-mode transformar transforms y contextos de apilamiento svg paths, degradados, clip desbordes overflow anidado, position:sticky, scroll programático reflujo layout thrashing: leer y escribir geometría alternadamente Reglas que cumplen todas, y no son de estilo: · DETERMINISTAS (LCG propio, ni Math.random ni Date ni red) — dos corridas hacen lo mismo, así que dos perfiles difieren por el timing de los contadores y no por haber visitado caminos distintos. · AUTOCONTENIDAS — el perfilado corre sin red. · NUESTRAS — nada de páginas ajenas capturadas, que traerían licencia y fragilidad. · ACOTADAS — 16 a 32 s cada una; el perfilado arranca un navegador POR PÁGINA. Validadas las diez contra el firefox sellado: todas renderizan y producen captura. `flex` hubo que acortarla de 40 a 12 cajas raíz: con 40 la página medía 68.241 px de alto y la captura moría con «Failed to allocate a surface due to invalid size». El layout ocurría igual, pero sin captura no se ejercita el pintado, que es justo la mitad que se venía a entrenar.
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
# Corpus de maquetación para el PGO de Gecko
|
||||
|
||||
Páginas de entrenamiento **nuestras** que complementan el corpus de Mozilla (`build/pgo`).
|
||||
|
||||
## Por qué existe
|
||||
|
||||
Medida la ganancia del PGO el 2026-09-07 (SDD 26 §3.a): **−9,4 %** en una página de DOM/maquetación
|
||||
y **−1,0 %** en `3d-raytrace` de SunSpider. El corpus de Mozilla está dominado en número de páginas
|
||||
por SunSpider, que es aritmética pura en bucles calientes — y **ese bucle no lo ejecuta el C++ de
|
||||
SpiderMonkey sino el código máquina que el JIT emite en runtime**, que el PGO no toca. O sea que el
|
||||
corpus entrenaba mucho justo donde el PGO menos rinde.
|
||||
|
||||
Estas páginas ejercitan el camino que sí es C++ de punta a punta: resolución de estilo, layout,
|
||||
pintado y composición.
|
||||
|
||||
## Reglas que cumplen todas, y por qué
|
||||
|
||||
- **Deterministas.** Ni `Math.random` ni `Date` ni red. Dos corridas hacen LO MISMO, así que dos
|
||||
perfiles difieren por el timing de los contadores y no por haber visitado caminos distintos.
|
||||
- **Autocontenidas.** CSS y JS en línea, sin recursos externos. El perfilado corre sin red.
|
||||
- **Nuestras.** Escritas para esto: nada de páginas ajenas capturadas, que traerían licencia y
|
||||
fragilidad.
|
||||
- **Acotadas.** Cada una termina en segundos. El perfilado arranca un navegador POR PÁGINA.
|
||||
|
||||
## Qué ejercita cada una
|
||||
|
||||
| página | subsistema |
|
||||
|---|---|
|
||||
| `flex.html` | flexbox anidado, `wrap`, alineaciones, `min/max-content` |
|
||||
| `rejilla.html` | CSS Grid: muchas pistas, áreas nombradas, `auto-fit`, `subgrid` |
|
||||
| `tablas.html` | tablas grandes, `colspan`/`rowspan`, `table-layout` fijo y automático |
|
||||
| `texto.html` | texto largo, columnas, `text-shadow`, tamaños y pesos variados, reflujo |
|
||||
| `selectores.html` | resolución de estilo: DOM profundo contra cientos de reglas |
|
||||
| `pintado.html` | degradados, `border-radius`, `box-shadow`, `opacity`, `mix-blend-mode` |
|
||||
| `transformar.html` | `transform`, contextos de apilamiento, `will-change` |
|
||||
| `svg.html` | SVG en línea: paths, degradados, `use`, clip |
|
||||
| `desbordes.html` | `overflow` anidado, `position: sticky`, scroll programático |
|
||||
| `reflujo.html` | layout thrashing: leer y escribir geometría alternadamente |
|
||||
@@ -0,0 +1,27 @@
|
||||
<!doctype html><meta charset=utf-8><title>desbordes</title><style>
|
||||
body{margin:0;font:12px sans-serif}
|
||||
.sc{overflow:auto;border:1px solid #ccb;margin:3px;height:170px}
|
||||
.sk{position:sticky;top:0;background:#ffe;border-bottom:1px solid #dd9;padding:2px}
|
||||
.it{padding:2px 4px;border-bottom:1px dotted #ddd}
|
||||
</style><div id=r></div><script>
|
||||
function lcg(x){return function(){x=(x*1103515245+12345)&0x7fffffff;return x/0x7fffffff}}
|
||||
var r=lcg(83), h=[];
|
||||
// Contenedores de scroll anidados con `position:sticky`: Gecko tiene que recalcular la posición
|
||||
// pegajosa en cada scroll, y eso es camino de layout puro.
|
||||
for(var c=0;c<26;c++){
|
||||
h.push("<div class=sc id=s"+c+"><div class=sk>cabecera pegajosa "+c+"</div>");
|
||||
for(var i=0;i<160;i++){
|
||||
if(i%40===0) h.push("<div class=sc style='height:90px'><div class=sk>anidada</div>");
|
||||
h.push("<div class=it>"+((r()*1e9)|0).toString(36)+" — fila "+i+"</div>");
|
||||
if(i%40===39) h.push("</div>");
|
||||
}
|
||||
h.push("</div>");
|
||||
}
|
||||
document.getElementById('r').innerHTML=h.join("");
|
||||
// Scroll programático: fuerza recálculo de sticky y de lo visible.
|
||||
var t=0;
|
||||
for(var i=0;i<60;i++){
|
||||
for(var c=0;c<26;c++){ var n=document.getElementById('s'+c); if(n){ n.scrollTop=(i*37)%900; t+=n.scrollTop; } }
|
||||
}
|
||||
document.title="desb-"+(t|0);
|
||||
</script>
|
||||
@@ -0,0 +1,27 @@
|
||||
<!doctype html><meta charset=utf-8><title>flex</title><style>
|
||||
body{font:13px sans-serif;margin:0}
|
||||
.c{display:flex;flex-wrap:wrap;gap:2px;padding:2px;border:1px solid #ccd}
|
||||
.c>div{flex:1 1 auto;min-width:40px;padding:3px;background:#eef;border:1px solid #99c}
|
||||
.col{flex-direction:column}.ctr{align-items:center;justify-content:space-between}
|
||||
.gr2{flex-grow:2}.sh0{flex-shrink:0}
|
||||
</style><div id=r></div><script>
|
||||
// Flexbox anidado a 4 niveles, con mezcla de grow/shrink/basis y wrap. Determinista.
|
||||
function lcg(s){return function(){s=(s*1103515245+12345)&0x7fffffff;return s/0x7fffffff}}
|
||||
var r=lcg(7);
|
||||
function caja(prof){
|
||||
if(prof===0) return "<div>"+((r()*1e6)|0)+"</div>";
|
||||
var cls="c"+(r()<0.4?" col":"")+(r()<0.3?" ctr":"");
|
||||
var n=2+((r()*4)|0), h="<div class='"+cls+"'>";
|
||||
for(var i=0;i<n;i++){
|
||||
var extra=r()<0.25?" class='gr2'":(r()<0.2?" class='sh0'":"");
|
||||
h+="<div"+extra+">"+caja(prof-1)+"</div>";
|
||||
}
|
||||
return h+"</div>";
|
||||
}
|
||||
var out=[]; for(var i=0;i<12;i++) out.push(caja(4)); // 12 y no 40: con 40 la página medía 68.241 px de alto y la captura fallaba por tamaño de superficie
|
||||
document.getElementById('r').innerHTML=out.join("");
|
||||
// Forzar layout de verdad, no sólo parse.
|
||||
var t=0; for(var i=0;i<120;i++){ t+=document.getElementById('r').getBoundingClientRect().height;
|
||||
document.body.style.width=(900+i%7)+"px"; }
|
||||
document.title="flex-"+(t|0);
|
||||
</script>
|
||||
@@ -0,0 +1,22 @@
|
||||
<!doctype html><meta charset=utf-8><title>pintado</title><style>
|
||||
body{margin:0;background:#fff}
|
||||
.b{position:relative;display:inline-block;width:70px;height:52px;margin:2px;
|
||||
border-radius:9px;box-shadow:0 2px 5px rgba(0,0,0,.35),inset 0 0 8px rgba(255,255,255,.5)}
|
||||
.o{opacity:.72}.m{mix-blend-mode:multiply}.sc{mix-blend-mode:screen}
|
||||
</style><div id=r></div><script>
|
||||
function lcg(x){return function(){x=(x*1103515245+12345)&0x7fffffff;return x/0x7fffffff}}
|
||||
var r=lcg(53), h=[];
|
||||
// Pintado y composición: degradados, sombras, opacidad y modos de mezcla. Es el camino que
|
||||
// termina en el rasterizador por software (pixman/skia), completamente ajeno al JIT.
|
||||
for(var i=0;i<1400;i++){
|
||||
var a=((r()*360)|0), c1=((r()*0xffffff)|0).toString(16), c2=((r()*0xffffff)|0).toString(16);
|
||||
var cls="b"+(r()<0.3?" o":"")+(r()<0.2?" m":(r()<0.15?" sc":""));
|
||||
var bg=r()<0.5 ? "linear-gradient("+a+"deg,#"+c1+",#"+c2+")"
|
||||
: "radial-gradient(circle at "+((r()*100)|0)+"% "+((r()*100)|0)+"%,#"+c1+",#"+c2+")";
|
||||
h.push("<div class='"+cls+"' style=\"background:"+bg+"\"></div>");
|
||||
}
|
||||
document.getElementById('r').innerHTML=h.join("");
|
||||
var t=0; for(var i=0;i<50;i++){ t+=document.body.getBoundingClientRect().height;
|
||||
document.body.style.filter=(i%4===0)?"saturate(1.05)":"none"; }
|
||||
document.title="pint-"+(t|0);
|
||||
</script>
|
||||
@@ -0,0 +1,20 @@
|
||||
<!doctype html><meta charset=utf-8><title>reflujo</title><style>
|
||||
body{margin:0;font:12px sans-serif}.x{display:inline-block;border:1px solid #aac;padding:2px;margin:1px}
|
||||
</style><div id=r></div><script>
|
||||
function lcg(x){return function(){x=(x*1103515245+12345)&0x7fffffff;return x/0x7fffffff}}
|
||||
var r=lcg(97), h=[];
|
||||
for(var i=0;i<1800;i++) h.push("<span class=x id=e"+i+">"+((r()*1e6)|0)+"</span>");
|
||||
document.getElementById('r').innerHTML=h.join("");
|
||||
// LAYOUT THRASHING a propósito: leer geometría y escribir estilo alternadamente obliga a Gecko a
|
||||
// re-hacer el reflujo una y otra vez. Es el peor caso de una página real mal escrita, y por eso
|
||||
// entrena justo el camino que más duele cuando pasa de verdad.
|
||||
var t=0;
|
||||
for(var pase=0;pase<14;pase++){
|
||||
for(var i=0;i<1800;i+=3){
|
||||
var n=document.getElementById('e'+i);
|
||||
t+=n.offsetWidth; // lectura: fuerza reflujo
|
||||
n.style.paddingLeft=((i+pase)%7)+"px"; // escritura: lo invalida
|
||||
}
|
||||
}
|
||||
document.title="refl-"+(t|0);
|
||||
</script>
|
||||
@@ -0,0 +1,27 @@
|
||||
<!doctype html><meta charset=utf-8><title>rejilla</title><style>
|
||||
body{font:12px sans-serif;margin:0}
|
||||
.g{display:grid;gap:2px;margin:2px;border:1px solid #cdc}
|
||||
.a{grid-template-columns:repeat(auto-fit,minmax(60px,1fr));grid-auto-rows:minmax(20px,auto)}
|
||||
.b{grid-template-areas:"h h h" "s m m" "s f f";grid-template-columns:80px 1fr 1fr}
|
||||
.h{grid-area:h;background:#dfd}.s{grid-area:s;background:#ffd}.m{grid-area:m}.f{grid-area:f;background:#ddf}
|
||||
.g>div{padding:2px;border:1px solid #9c9}
|
||||
.sp{grid-column:span 2}.sp3{grid-row:span 3}
|
||||
</style><div id=r></div><script>
|
||||
function lcg(s){return function(){s=(s*1103515245+12345)&0x7fffffff;return s/0x7fffffff}}
|
||||
var r=lcg(11), out=[];
|
||||
for(var k=0;k<30;k++){
|
||||
var h="<div class='g b'><div class=h>cab</div><div class=s>lat</div><div class=m>"
|
||||
+ "<div class='g a'>";
|
||||
var n=12+((r()*24)|0);
|
||||
for(var i=0;i<n;i++){
|
||||
var c=r()<0.18?" class=sp":(r()<0.1?" class=sp3":"");
|
||||
h+="<div"+c+">"+((r()*1e5)|0)+"</div>";
|
||||
}
|
||||
h+="</div></div><div class=f>pie</div></div>";
|
||||
out.push(h);
|
||||
}
|
||||
document.getElementById('r').innerHTML=out.join("");
|
||||
var t=0; for(var i=0;i<120;i++){ t+=document.body.getBoundingClientRect().height;
|
||||
document.body.style.width=(700+i%11*20)+"px"; }
|
||||
document.title="rejilla-"+(t|0);
|
||||
</script>
|
||||
@@ -0,0 +1,35 @@
|
||||
<!doctype html><meta charset=utf-8><title>selectores</title><style id=s></style>
|
||||
<div id=r></div><script>
|
||||
function lcg(x){return function(){x=(x*1103515245+12345)&0x7fffffff;return x/0x7fffffff}}
|
||||
var r=lcg(41);
|
||||
// Resolución de estilo: DOM profundo contra CIENTOS de reglas, muchas de las cuales NO casan.
|
||||
// Es trabajo puro del motor de selectores, invisible para un benchmark de JS.
|
||||
var reglas=[];
|
||||
for(var i=0;i<600;i++){
|
||||
var d=1+((r()*4)|0), sel=[];
|
||||
for(var j=0;j<d;j++){
|
||||
var t=r();
|
||||
sel.push(t<0.3?(".c"+((r()*40)|0)) : t<0.55?("#n"+((r()*300)|0)) :
|
||||
t<0.7?("div.c"+((r()*40)|0)+":nth-child("+(1+((r()*5)|0))+")") :
|
||||
t<0.85?("[data-k='"+((r()*20)|0)+"']") : "div");
|
||||
}
|
||||
reglas.push(sel.join(r()<0.5?" ":" > ")+"{color:#"+(((r()*0xfff)|0)|0x400).toString(16)+"}");
|
||||
}
|
||||
document.getElementById('s').textContent=reglas.join("\n");
|
||||
function arbol(p,prof){
|
||||
if(prof===0) return "";
|
||||
var n=2+((r()*3)|0),h="";
|
||||
for(var i=0;i<n;i++)
|
||||
// Con texto en las hojas, no sólo divs vacíos: si el árbol no pinta nada, la página entrena
|
||||
// la resolución de estilo pero deja fuera el layout inline, que va en el mismo viaje.
|
||||
var dentro = arbol(p+1,prof-1) || ("nodo "+((r()*1e6)|0).toString(36));
|
||||
h+="<div id=n"+((r()*300)|0)+" class='c"+((r()*40)|0)+" c"+((r()*40)|0)+
|
||||
"' data-k='"+((r()*20)|0)+"'>"+dentro+"</div>";
|
||||
return h;
|
||||
}
|
||||
document.getElementById('r').innerHTML=arbol(0,7);
|
||||
// Invalidar el estilo a propósito y forzar recálculo: el camino caliente de verdad.
|
||||
var t=0, raiz=document.getElementById('r');
|
||||
for(var i=0;i<40;i++){ raiz.className="v"+(i%5); t+=raiz.getBoundingClientRect().height; }
|
||||
document.title="sel-"+(t|0);
|
||||
</script>
|
||||
@@ -0,0 +1,29 @@
|
||||
<!doctype html><meta charset=utf-8><title>svg</title><body style="margin:0">
|
||||
<div id=r></div><script>
|
||||
function lcg(x){return function(){x=(x*1103515245+12345)&0x7fffffff;return x/0x7fffffff}}
|
||||
var r=lcg(71), h=['<svg width="1100" height="1500" xmlns="http://www.w3.org/2000/svg"><defs>'];
|
||||
// SVG: otro árbol de layout y otro pintor dentro del mismo motor. Paths, degradados y clip.
|
||||
for(var g=0;g<12;g++)
|
||||
h.push('<linearGradient id="g'+g+'"><stop offset="0" stop-color="#'+((r()*0xfff)|0).toString(16)+
|
||||
'"/><stop offset="1" stop-color="#'+((r()*0xfff)|0).toString(16)+'"/></linearGradient>');
|
||||
h.push('<clipPath id="cp"><circle cx="550" cy="750" r="700"/></clipPath></defs><g clip-path="url(#cp)">');
|
||||
for(var i=0;i<1100;i++){
|
||||
var t=r();
|
||||
if(t<0.4){
|
||||
var d="M"+((r()*1100)|0)+","+((r()*1500)|0);
|
||||
for(var k=0;k<5;k++) d+=" C"+((r()*1100)|0)+","+((r()*1500)|0)+" "+((r()*1100)|0)+","+((r()*1500)|0)+
|
||||
" "+((r()*1100)|0)+","+((r()*1500)|0);
|
||||
h.push('<path d="'+d+'" fill="none" stroke="url(#g'+((r()*12)|0)+')" stroke-width="'+(1+((r()*3)|0))+'"/>');
|
||||
} else if(t<0.75){
|
||||
h.push('<rect x="'+((r()*1050)|0)+'" y="'+((r()*1450)|0)+'" width="'+(5+(r()*60|0))+'" height="'+
|
||||
(5+(r()*60|0))+'" rx="3" fill="url(#g'+((r()*12)|0)+')" opacity="'+(0.3+r()*0.7).toFixed(2)+'"/>');
|
||||
} else {
|
||||
h.push('<circle cx="'+((r()*1100)|0)+'" cy="'+((r()*1500)|0)+'" r="'+(2+(r()*22|0))+
|
||||
'" fill="#'+((r()*0xffffff)|0).toString(16)+'"/>');
|
||||
}
|
||||
}
|
||||
h.push('</g></svg>');
|
||||
document.getElementById('r').innerHTML=h.join("");
|
||||
var t=0; for(var i=0;i<40;i++) t+=document.body.getBoundingClientRect().height;
|
||||
document.title="svg-"+(t|0);
|
||||
</script>
|
||||
@@ -0,0 +1,32 @@
|
||||
<!doctype html><meta charset=utf-8><title>tablas</title><style>
|
||||
body{font:12px sans-serif;margin:0}
|
||||
table{border-collapse:collapse;margin:4px}
|
||||
td,th{border:1px solid #bbb;padding:2px 4px}
|
||||
.fija{table-layout:fixed;width:900px}.auto{table-layout:auto}
|
||||
tr:nth-child(odd){background:#f6f6fa} th{background:#e6e6f0;position:sticky;top:0}
|
||||
</style><div id=r></div><script>
|
||||
function lcg(s){return function(){s=(s*1103515245+12345)&0x7fffffff;return s/0x7fffffff}}
|
||||
var r=lcg(23), out=[];
|
||||
// Dos tablas grandes: una con table-layout FIJO y otra AUTO. Son dos algoritmos de layout
|
||||
// distintos en Gecko y conviene entrenar los dos; el automático es el caro.
|
||||
["fija","auto"].forEach(function(modo){
|
||||
var h="<table class='"+modo+"'><thead><tr>";
|
||||
for(var c=0;c<9;c++) h+="<th>col "+c+"</th>";
|
||||
h+="</tr></thead><tbody>";
|
||||
for(var f=0;f<420;f++){
|
||||
h+="<tr>";
|
||||
for(var c=0;c<9;){
|
||||
var span=(r()<0.12&&c<7)?2:1;
|
||||
var rs=(r()<0.06)?" rowspan=2":"";
|
||||
h+="<td"+(span>1?" colspan=2":"")+rs+">"+((r()*1e7)|0).toString(36)+"</td>";
|
||||
c+=span;
|
||||
}
|
||||
h+="</tr>";
|
||||
}
|
||||
out.push(h+"</tbody></table>");
|
||||
});
|
||||
document.getElementById('r').innerHTML=out.join("");
|
||||
var t=0; for(var i=0;i<60;i++){ t+=document.body.getBoundingClientRect().height;
|
||||
document.body.style.fontSize=(11+i%3)+"px"; }
|
||||
document.title="tablas-"+(t|0);
|
||||
</script>
|
||||
@@ -0,0 +1,30 @@
|
||||
<!doctype html><meta charset=utf-8><title>texto</title><style>
|
||||
body{margin:0;font:15px/1.5 serif}
|
||||
.cols{column-count:4;column-gap:14px;column-rule:1px solid #ccc;padding:6px}
|
||||
h2{font:bold 22px sans-serif;margin:.4em 0}
|
||||
.g{font-size:26px;font-weight:700;letter-spacing:.4px;text-shadow:1px 1px 2px #999}
|
||||
.p{font-size:11px;color:#555}
|
||||
em{font-style:italic}strong{font-weight:800}
|
||||
</style><div id=r></div><script>
|
||||
function lcg(s){return function(){s=(s*1103515245+12345)&0x7fffffff;return s/0x7fffffff}}
|
||||
var r=lcg(31);
|
||||
// Shaping de texto, saltos de línea y columnas: camino de layout inline, que es el más
|
||||
// distinto del de bloque y el que SunSpider no toca en absoluto.
|
||||
var voc=("la reproducibilidad no es una propiedad del binario sino del proceso que lo produce "+
|
||||
"y por eso el store se direcciona por contenido mientras el grafo se direcciona por entradas "+
|
||||
"cada guardián que no falla nunca es indistinguible de uno que no mira nada en absoluto").split(" ");
|
||||
function parrafo(n){var s=[];for(var i=0;i<n;i++){var w=voc[(r()*voc.length)|0];
|
||||
if(r()<0.06) w="<em>"+w+"</em>"; else if(r()<0.04) w="<strong>"+w+"</strong>";
|
||||
s.push(w);} return s.join(" ");}
|
||||
var h=[];
|
||||
for(var k=0;k<26;k++){
|
||||
h.push("<h2>"+parrafo(4)+"</h2>");
|
||||
h.push("<div class=cols>");
|
||||
for(var p=0;p<5;p++) h.push("<p class='"+(r()<0.3?"g":(r()<0.4?"p":""))+"'>"+parrafo(60+((r()*90)|0))+"</p>");
|
||||
h.push("</div>");
|
||||
}
|
||||
document.getElementById('r').innerHTML=h.join("");
|
||||
var t=0; for(var i=0;i<90;i++){ t+=document.body.getBoundingClientRect().height;
|
||||
document.body.style.width=(650+i%9*40)+"px"; }
|
||||
document.title="texto-"+(t|0);
|
||||
</script>
|
||||
@@ -0,0 +1,21 @@
|
||||
<!doctype html><meta charset=utf-8><title>transformar</title><style>
|
||||
body{margin:0}
|
||||
.t{position:absolute;width:56px;height:40px;border:1px solid #557;background:#dde;
|
||||
border-radius:4px;font:10px sans-serif;overflow:hidden}
|
||||
.w{will-change:transform}.z{z-index:5}
|
||||
</style><div id=r style="position:relative;height:2600px"></div><script>
|
||||
function lcg(x){return function(){x=(x*1103515245+12345)&0x7fffffff;return x/0x7fffffff}}
|
||||
var r=lcg(67), h=[];
|
||||
// Transformaciones y contextos de apilamiento: obliga a Gecko a armar capas y a ordenarlas.
|
||||
for(var i=0;i<900;i++){
|
||||
var rot=((r()*360)|0), sx=(0.5+r()).toFixed(2), tx=((r()*1000)|0), ty=((r()*2500)|0);
|
||||
var cls="t"+(r()<0.25?" w":"")+(r()<0.2?" z":"");
|
||||
h.push("<div class='"+cls+"' style=\"left:"+tx+"px;top:"+ty+"px;transform:rotate("+rot+
|
||||
"deg) scale("+sx+") skewX("+((r()*20)|0)+"deg)\">"+i+"</div>");
|
||||
}
|
||||
document.getElementById('r').innerHTML=h.join("");
|
||||
var t=0, n=document.getElementById('r');
|
||||
for(var i=0;i<60;i++){ n.style.transform="translateZ(0) rotate("+(i%7)+"deg)";
|
||||
t+=n.getBoundingClientRect().width; }
|
||||
document.title="tr-"+(t|0);
|
||||
</script>
|
||||
Reference in New Issue
Block a user