LoginSignup
0
0

setTimeout(fn,0)より高速なsetImmediateもどき集

Last updated at Posted at 2024-01-24

激重loopのCPUの負担を抑えたい場合に、よくsetTimeout(fn,0)を連呼するかどうかは定かではないかもしれませんが、それではいささか低速過ぎるという事態に直面しかねません。そういうprogramにおすそ分けする技法を紹介します。

//XMLHttpRequest法
(function(F){
	var x=new XMLHttpRequest;
	x.onload=function a(){F[0]&&F.shift()()};
	this.wait0=function(f){F[F.length]=f;x.send(x.open("GET","data:,"))}
})([])
//script法
(function(F){
	function a(e){
		F[0]&&F.shift()();
		h.removeChild(this);
		e.target=null
	}
	var u="data:,",h=document.getElementsByTagName("head")[0];
	this.wait0=function(f){
		F[F.length]=f;
		f=document.createElement("script");
		f.onload=a;f.src=u;h.appendChild(f)
	}
})([])
//Blob法
(function(F){
	function a(){F[0]&&F.shift()()}
	var b=new Blob([]);
	this.wait0=function(f){b.text(F[F.length]=f).then(a)}
})([])
//File法
(function(F){
	function a(){F[0]&&F.shift()()}
	var b=new File([],"");
	this.wait0=function(f){b.text(F[F.length]=f).then(a)}
})([])
//FileReader法
(function(F){
	function a(){F[0]&&F.shift()()}
	var b=new Blob([new Uint8Array(0)]);
	this.wait0=function(f){
		F[F.length]=f;f=new FileReader;
		f.onload=a;f.readAsArrayBuffer(b)}
})([])
//FileReader法2
(function(F){
	var b=new Blob([new Uint8Array(0)]),r=new FileReader;
	r.onload=a=>{
		F[0]&&F.shift()();delete r.result
	}
	this.wait0=function(f){
		F[F.length]=f;r.readAsArrayBuffer(b)
	}
})([])
//FileReader法3
(function(F){
	function a(){F[0]&&F.shift()()}
	var b=new Blob([""]);
	this.wait0=function(f){
		F[F.length]=f;f=new FileReader;
		f.onloadstart=a;f.readAsArrayBuffer(b)}
})([])
//Image法
(function(F){
	function a(){F[0]&&F.shift()()}
	var s="data:image/gif;base64,R0lGODdhAQABAAAAAAA";
	this.wait0=function(f){
		F[F.length]=f;f=new Image;
		f.onload=a;f.src=s
	}
})([])
//Image法2
(function(F){
	var i=new Image,s="data:image/gif;base64,R0lGODdhAQABAAAAAAA";
	i.onload=function(){
		F[0]&&F.shift()();delete i.src
	};
	this.wait0=function(f){F[F.length]=f;i.src=s}
})([])
//postMessage法
(function(a){
	var F=[],hit="\0";
	a.wait0=function(f){
		F[F.length]=f;a.postMessage(hit,"*")
	};
	a.onmessage=function(e){
		if(e.source===a&&e.data===hit)
			e.stopPropagation(),F[0]&&F.shift()()
	}
})(this);
//MessageChannel法
(f=>{var c=new MessageChannel,p={},o=p;
	c.port1.onmessage=f=>{p=p.p;p.f();delete p.f};
	f.wait0=f=>{o=o.p={f:f};c.port2.postMessage(0)}
})(this);

いずれもwait0(function(){...}) のように使います(setTimeout(function(){...},0) のようなもの)。 速度を比較すると以下のような感じになるかも
MessageChannel >> postMessage > Image >>> File, FileReader > script > XMLHttpRequest

var start=+new Date,times=[];

wait0(function run(){
	times.push(Date.now()-start); // 前の呼び出しからの遅延を覚える
	if(start+100<Date.now())document.write(times.length," ",times.join(" ")); // 100ms 後に遅延を表示
	else wait0(run,0)// もしくは再schedule
},0)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0