title: Bad FPS in a simple Three.js scene in Safari MacOS
body: <p>I have a simple demo that works fine in Chrome and Firefox. But Safari is lag like hell. If I disable antialising, it increases the FPS but not that much. How can i optimize my code ? Maybe use some caching? I'm new to three.js </p>
  
  <p>It will be nice if it will work in iOs safari too.</p>
  
  <p>Here's the demo: </p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var $container = $('#torus');
  var mouseX = 0,
    mouseY = 0;
  
  var camera, scene, renderer;
  var geometry, material, mesh, config;
  var numTorus = 65;
  var tabTorus = [];
  var windowHalfX = window.innerWidth / 2;
  var windowHalfY = window.innerHeight / 2;
  
  config = {
    speed: 1.3,
    rotation: 1,
    opacity: 1
  }
  
  
  function init() {
  
    camera = new THREE.PerspectiveCamera(100, window.innerWidth / window.innerHeight, 10, 1000);
    camera.position.z = 1;
    scene = new THREE.Scene();
    material = new THREE.MeshNormalMaterial();
    material.transparent = true;
    material.opacity = config.opacity;
    geometry = new THREE.TorusGeometry(130, .5, 120, 100);
    geometry.computeFaceNormals();
    geometry.computeVertexNormals();
    geometry.normalsNeedUpdate = true;
    geometry.verticesNeedUpdate = true;
    geometry.dynamic = true;
  
    for (var i = 0; i &lt; numTorus; i++) {
      tabTorus.push(new Torus(-i * 6));
      scene.add(tabTorus[i].b);
    }
  
    renderer = new THREE.WebGLRenderer({
      antialias: true,
      autoClear: true,
      alpha: true,
    });
    renderer.setSize(window.innerWidth, window.innerHeight);
    $container.append(renderer.domElement);
  
  }
  
  function Torus(f) {
  
    this.b = new THREE.Mesh(geometry, material);
    this.b.position.y = 55 * Math.sin(f);
    this.b.position.x = 55 * Math.cos(f);
    this.b.position.z = f * 2.72;
  }
  
  function onWindowResize() {
  
    windowHalfX = window.innerWidth / 2;
    windowHalfY = window.innerHeight / 2;
  
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
  
    renderer.setSize(window.innerWidth, window.innerHeight);
  }
  
  function onDocumentMouseMove(event) {
    mouseX = (event.clientX - windowHalfX) / 10;
    mouseY = (event.clientY - windowHalfY) / 10;
  }
  
  function update() {
    for (var i = 0; i &lt; numTorus; i++) {
      tabTorus[i].b.position.z += config.speed * 1.5;
      tabTorus[i].b.material.opacity = config.opacity;
      tabTorus[i].b.geometry.parameters.arc = 0.5 + config.opacity * 10;
      if (tabTorus[i].b.position.z &gt; 0) {
        tabTorus[i].b.position.z = -1000;
      }
    }
  }
  
  function animate() {
    requestAnimationFrame(animate);
    camera.position.x += (mouseX - camera.position.x) * .02;
    camera.position.y += (-mouseY - camera.position.y) * .02;
    renderer.render(scene, camera);
    update();
  }
  
  window.addEventListener('resize', onWindowResize, false);
  document.addEventListener('mousemove', onDocumentMouseMove, false);
  
  init();
  animate();</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>body {
    background: black;
  }
  
  #torus {
    position: fixed;
    width: 100%;
    height: 100%;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;div id="torus"&gt;&lt;/div&gt;
  &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"&gt;&lt;/script&gt;
  &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.min.js"&gt;&lt;/script&gt;</code></pre>
  </div>
  </div>
  </p>