셀 소모를 최소화하기 위한 배치 요청
이 기사는 최근 HackerNews의 톱을 장식했습니다. http://highscalability.com/blog/2013/9/18/if-youre-programming-a-cell-phone-like-a-server-youre-doing.html #
다음과 같이 표시됩니다.
핸드폰 라디오는 전화기의 가장 큰 배터리 소모량 중 하나입니다.데이터를 보낼 때마다 아무리 작은 것이라도 라디오의 전원은 20-30초 동안 켜집니다.모든 결정은 무선 전원이 켜지는 횟수를 최소화하는 것에 기초해야 합니다.앱이 데이터 전송을 처리하는 방식을 변경하여 배터리 수명을 크게 향상시킬 수 있습니다.사용자들은 지금 데이터를 원하고 있습니다. 중요한 것은 사용자 경험과 데이터 전송의 균형을 맞추고 전력 사용을 최소화하는 것입니다.앱이 모든 반복 및 간헐적 전송을 신중하게 번들링한 다음 간헐적 전송을 공격적으로 프리페치함으로써 균형을 유지할 수 있습니다.
는 수하고싶다를 수정하고 .$.ajax"지금 당장 수행할 필요가 없습니다. 다른 요청이 시작되면 이 요청만 수행하십시오."와 같은 옵션을 추가합니다.이것에 대해 어떤 방법이 좋을까요?
저는 이것으로 시작했습니다.
(function($) {
var batches = [];
var oldAjax = $.fn.ajax;
var lastAjax = 0;
var interval = 5*60*1000; // Should be between 2-5 minutes
$.fn.extend({batchedAjax: function() {
batches.push(arguments);
}});
var runBatches = function() {
var now = new Date().getTime();
var batched;
if (lastAjax + interval < now) {
while (batched = batches.pop()) {
oldAjax.apply(null, batched);
}
}
}
setInterval(runBatches, interval);
$.fn.ajax = function() {
runBatches();
oldAjax.apply(null, arguments);
lastAjax = now;
};
})(jQuery);
종이의 문구로는 알 수가 없고, 좋은 배치의 "간격"은 2-5분인 것 같아서 그냥 5개를 사용했습니다.
이것이 좋은 구현입니까?
어떻게 하면 이것을 단지의 진정한 수정으로 만들 수 있습니까?
ajax소드를, 추가통을{batchable:true}방법에 대한 옵션?저도 그것을 잘 이해하지 못했습니다.있습니까?
setInterval또한 항상 전화기를 깨어있게 합니까?그것이 나쁜 일입니까?그렇게 하지 않는 더 좋은 방법이 있습니까?배터리가 더 빨리 소모될 수 있는 다른 것들이 있습니까?
이런 접근법이 가치가 있을까요?현대의 스마트폰에는 한 번에 많은 일들이 일어나고 있기 때문에 만약 내 앱이 셀을 사용하지 않는다면, 다른 앱도 마찬가지입니다.Javascript는 셀이 켜져 있는지 여부를 감지할 수 없는데, 왜 귀찮게 하나요?신경 쓸 가치가 있습니까?
옵션을 추가하는 것에 대해 약간의 진전이 .$.ajax질문을 편집하기 시작했고 답변으로 더 낫다는 것을 깨달았습니다.
(function($) {
var batches = [];
var oldAjax = $.fn.ajax;
var lastAjax = 0;
var interval = 5*60*1000; // Should be between 2-5 minutes
var runBatches = function() {
var now = new Date().getTime();
var batched;
if (lastAjax + interval < now) {
while (batched = batches.pop()) {
oldAjax.apply(null, batched);
}
}
}
setInterval(runBatches, interval);
$.fn.ajax = function(url, options) {
if (options.batchable) {
batches.push(arguments);
return;
}
runBatches();
oldAjax.apply(null, arguments);
lastAjax = now;
};
})(jQuery);
그것은 사실 꽤 간단했습니다.하지만 더 나은 답을 보는 것이 좋습니다.
- setInterval도 전화기를 항상 절전 모드로 유지합니까?그것이 나쁜 일입니까?그렇게 하지 않는 더 좋은 방법이 있습니까?
iPhone 4, iOS 6.1.0 Safari 환경에서:
A는 요소의 텍스트를 1초 간격으로 업데이트하는 카운트다운 타이머가 있는 앱을 작성했습니다.DOM 트리는 중간 정도의 복잡성을 가지고 있었습니다.그 앱은 AJAX를 전혀 하지 않는 비교적 간단한 계산기였습니다.하지만, 저는 항상 초당 한 번의 리플로우가 저를 죽이고 있다는 은근한 의심을 가지고 있었습니다.앱의 웹 페이지에서 Safari를 사용하여 테이블에 배터리를 켜둘 때마다 배터리가 다소 빠르게 소모되는 것 같았습니다.
그리고 그 앱에는 두 개의 타임아웃만 있었습니다.시간 초과로 인해 배터리가 소모되었다는 정량화 가능한 증거는 없지만, 이 멍청한 계산기에서 45분마다 약 10%씩 손실되는 것은 약간 불안했습니다. (하지만 백라이트 때문일 수도 있습니다.)
그 점에 관하여:주기적으로 AJAX를 수행하는 테스트 앱이나 주기적으로 다른 작업을 수행하는 테스트 앱을 구축하고 유사한 조건에서 각 기능이 배터리를 소모하는 방식을 비교할 수 있습니다.제어된 환경을 구축하는 것은 까다로울 수 있지만, 배수량에 큰 차이가 있을 경우 "불완전한" 테스트 조건에서도 눈에 띄는 결과가 나와 결론을 내릴 수 있습니다.
하지만 iOS 6.1.0 Safari가 시간 초과를 처리하는 방법에 대한 흥미로운 점을 발견했습니다.
- 화면을 끄면 콜백이 실행되지 않습니다.
- 결과적으로, 장기적인 타임아웃은 "목표를 놓칠 것"입니다.
내시간을 연 에도), 수 , 나는 앱의타화것면표이라는시하쉬시운올다간없바후니수도연습경이에이다로로을머할동시가른가닫다면을았화▁and▁if'앱의'▁then▁was다없▁do▁couldn쉬▁(▁the▁the),▁i운t▁app▁i니even▁after▁easy▁timer습수▁route경▁go▁display(▁screen▁mys이것로로▁the▁and▁correct▁time할.secondsLeft -= 1화면을 껐다면 (시작 시간 대비)가 "뒤에" 있어서 잘못되었을 것입니다. (화면이 꺼진 동안 setTimeout 콜백이 실행되지 않았습니다.)
해결책은 제가 다시 계산해야 한다는 것이었습니다.timeLeft = fortyMinutes - (new Date().getTime() - startTime)
또한, 제 앱의 타이머는 만료가 가까워짐에 따라 초록색에서 라임색, 노란색, 빨간색으로 바뀌어야 했습니다.이 시점에서 인터벌 코드의 효율성이 걱정되었기 때문에 적절한 시간(라임: 시작 시간 후 20분, 노란색: 30분, 빨간색: 35분)에 맞춰 색상 변경을 "스케줄"하는 것이 더 나을 것이라고 의심했습니다(이것은 매 인터벌마다 4배의 불평등 검사를 하는 것보다 선호되는 것 같았습니다.99%의 시간을 낭비할 것입니다.)
그러나 이러한 색상 변경을 예약하고 휴대폰의 화면이 목표 시간에 꺼졌다면 해당 색상 변경은 절대 일어나지 않을 것입니다.
해결책은 각 간격마다 마지막 1초 타이머 업데이트 이후 경과된 시간이 "인지 확인하는 것이었습니다.>= 2seconds." (이렇게 하면 앱은 내 전화기의 화면이 꺼져 있는지 여부를 알 수 있고, 언제 "뒤떨어졌는지" 알 수 있습니다.) 그 시점에서 필요한 경우 색상 변경을 "강제적으로" 적용하고 다음 일정을 잡을 수 있습니다.
(두말할 것도 없이, 나중에 컬러 체인저를 제거했습니다...)
그래서, 저는 이것이 제 주장을 확인시켜준다고 믿습니다.
iOS 6.1.0 Safari는 화면이 꺼진 경우 setTimeout 콜백 기능을 실행하지 않습니다.
따라서 AJAX 호출을 "스케줄"할 때도 이 점에 유의하십시오. 이 동작에도 영향을 받을 수 있기 때문입니다.
그리고, 제 제안을 이용해서, 저는 당신의 질문에 대답할 수 있습니다:
- 적어도 iOS의 경우, 우리는 setTimeout이 화면이 꺼진 동안 잔다는 것을 알고 있습니다.
- 따라서 설정된 시간 초과는 전화기에 "악몽"("잠을 자지 않도록")을 주지 않습니다.
- 이런 접근법이 가치가 있을까요?현대의 스마트폰에는 한 번에 많은 일들이 일어나고 있기 때문에 만약 내 앱이 셀을 사용하지 않는다면, 다른 앱도 마찬가지입니다.Javascript는 셀이 켜져 있는지 여부를 감지할 수 없는데, 왜 귀찮게 하나요?신경 쓸 가치가 있습니까?
이 구현이 올바르게 작동하도록 할 수 있다면 가치가 있을 것 같습니다.
AJAX 요청 시마다 지연 시간이 발생하여 앱 속도가 어느 정도 느려집니다. (결국 지연 시간은 페이지 로드 시간의 골칫거리입니다.)따라서 요청을 "묶음"함으로써 분명히 어느 정도의 이익을 얻을 수 있습니다.요청을 "배팅"할 수 있도록 $.ajax를 확장하는 것은 분명히 이점이 있습니다.
링크한 기사는 앱의 전력 소비 최적화에 초점을 맞추고 있습니다(예, 날씨 위젯 예제는 끔찍합니다).브라우저를 적극적으로 사용하는 것은 정의상 전경 작업이며, ApplicationCache와 같은 작업을 통해 네트워크 요청의 필요성을 줄일 수 있습니다.그런 다음 필요에 따라 캐시를 프로그래밍 방식으로 업데이트하고 DIY를 방지할 수 있습니다.
회의적인 측면 참고: HTML5 앱의 일부로 jQuery를 사용하고 있다면(아마도 Sencha 또는 유사한 것으로 포장되어 있음) 모바일 앱 프레임워크는 코드 자체보다 요청 최적화와 더 관련이 있을 것입니다.저는 증거가 전혀 없지만, 젠장, 이것이 맞는 것처럼 들리는군요 :)
- 어떻게 하면 이것을 단지의 진정한 수정으로 만들 수 있습니까?
ajax소드를, 추가통을{batchable:true}방법에 대한 옵션?저도 그것을 잘 이해하지 못했습니다.
완벽하게 유효한 접근법이지만 저에게는 이것이 오리 펀치가 잘못 된 것처럼 들립니다.그럴 리가 없어요기본값을 올바르게 설정한 경우에도batchable거짓으로, 개인적으로 저는 차라리 정면을 사용하고 싶습니다(아마도 자체 네임스페이스에서도?).
var gQuery = {}; //gQuery = green jQuery, patent pending :)
gQuery.ajax = function(options,callback){
//your own .ajax with blackjack and hooking timeouts, ultimately just calling
$.ajax(options);
}
- 있습니까?
setInterval또한 항상 전화기를 깨어있게 합니까?그것이 나쁜 일입니까?그렇게 하지 않는 더 좋은 방법이 있습니까?
setInterval그리고.setTimeout매우 유사한 페이크입니다. 웹 사이트가 온라인 뱅킹 비활성 프롬프트의 백그라운드에 있는 동안 후자가 실행되지 않는다고 생각하십시오. 페이지가 포그라운드에 없으면 기본적으로 실행이 중지됩니다. 관련 기능에 에 사용 접근 일 수 . API의 "지연"("iOS7")을 피할 . 그렇지 않으면 API를 사용하지 않을 이유가 없습니다.setInterval.
- 배터리가 더 빨리 소모될 수 있는 다른 것들이 있습니까?
는 어떤 이라도 (을 통해) 될pi아마도 꽤 3D 전환으로).끈 를 떠올리게 합니다 :) ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜ
- 이런 접근법이 가치가 있을까요?현대의 스마트폰에는 한 번에 많은 일들이 일어나고 있기 때문에 만약 내 앱이 셀을 사용하지 않는다면, 다른 앱도 마찬가지입니다.Javascript는 셀이 켜져 있는지 여부를 감지할 수 없는데, 왜 귀찮게 하나요?신경 쓸 가치가 있습니까?
그 기사는 날씨 앱이 불합리하게 탐욕스럽다고 지적했고, 그것은 나를 걱정하게 할 것입니다.데이터를 실제로 필요한 것보다 더 자주 가져오는 것은 개발 감독인 것처럼 보입니다.이상적인 환경에서는 OS 수준에서 이 문제를 잘 처리해야 합니다. 그렇지 않으면 여러 가지 해결 방법이 경쟁하게 될 것입니다.IMO: 높은 확장성이 다른 기사를 게시할 때까지 신경 쓰지 마세요:)
내 버전은 다음과 같습니다.
(function($) {
var batches = [],
ajax = $.fn.ajax,
interval = 5*60*1000, // Should be between 2-5 minutes
timeout = setTimeout($.fn.ajax, interval);
$.fn.ajax=function(url, options) {
var batched, returns;
if(typeof url === "string") {
batches.push(arguments);
if(options.batchable) {
return;
}
}
while (batched = batches.shift()) {
returns = ajax.apply(null, batched);
}
clearTimeout(timeout);
timeout = setTimeout($.fn.ajax, interval);
return returns;
}
})(jQuery);
이 버전은 다음과 같은 주요 이점이 있다고 생각합니다.
- 배치할 수 없는 Ajax 호출이 있는 경우 연결을 사용하여 모든 배치를 보냅니다.타이머를 재설정합니다.
- 직접 Ajax 호출에 대한 예상 반환 값을 반환합니다.
- 매개 변수 없이 $.fn.ajax()를 호출하여 배치의 직접 처리를 트리거할 수 있습니다.
한.$.ajax방법, 는나:
- 또한 보존하려고 노력합니다.
Promise의 제메즘니커된공해에서$.ajax, - 글로벌 Ajax 이벤트 중 하나를 활용하여 Ajax 호출을 트리거합니다.
- "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " ""
$.ajax전화가 걸려왔습니다. - 함수에 새내 코드: 이함에새내지이니다정합을름코드수내(다▁(▁give니:합지코:
$.batchAjax합니다.$.ajax.
자, 제가 할게요.
(function ($) {
var queue = [],
timerID = 0;
function ajaxQueue(url, settings) {
// cutom deferred used to forward the $.ajax' promise
var dfd = new $.Deferred();
// when called, this function executes the $.ajax call
function call() {
$.ajax(url, settings)
.done(function () {
dfd.resolveWith(this, arguments);
})
.fail(function () {
dfd.rejectWith(this, arguments);
});
}
// set a global timer, which will trigger the dequeuing in case no ajax call is ever made ...
if (timerID === 0) {
timerID = window.setTimeout(ajaxCallOne, 5000);
}
// enqueue this function, for later use
queue.push(call);
// return the promise
return dfd.promise();
}
function ajaxCallOne() {
window.clearTimeout(timerID);
timerID = 0;
if (queue.length > 0) {
f = queue.pop();
// async call : wait for the current ajax events
//to be processed before triggering a new one ...
setTimeout(f, 0);
}
}
// use the two functions :
$(document).bind('ajaxSend', ajaxCallOne);
// or :
//$(document).bind('ajaxComplete', ajaxCallOne);
$.batchAjax = ajaxQueue;
}(jQuery));
이 예에서 5초간의 하드 코딩된 지연은 "호출 간격이 20초 미만이면 배터리가 소모됩니다."라는 목적을 달성하지 못합니다.더 큰 것(5분?)을 넣을 수도 있고, 아예 제거할 수도 있습니다. 모든 것은 앱에 따라 다릅니다.
일반적인 질문 "5분 안에 전화기 배터리가 타지 않는 웹 앱을 어떻게 작성합니까?"와 관련하여 : 그것을 처리하려면 마법의 화살 하나 이상이 필요할 것입니다.이것은 여러분이 취해야 할 디자인 결정의 집합이며, 이것은 정말로 여러분의 앱에 달려 있습니다.
가능한 한 많은 데이터를 한 번에 로드하는 것(그리고 사용되지 않을 데이터를 보내는 것)과 필요한 것을 가져오는 것(그리고 많은 작은 개별 요청을 보내는 것) 사이에서 중재해야 합니다.
고려해야 할 몇 가지 매개 변수는 다음과 같습니다.
- 데이터 볼륨(클라이언트 데이터 계획을 낭비하지 않으려는 경우에도...),
- 서버 로드,
- 캐시할 수 있는 용량,
- "최신"이 되는 것의 중요성(채팅 앱의 5분 지연은 작동하지 않음),
- 클라이언트 업데이트 빈도(네트워크 게임은 클라이언트의 업데이트가 많이 필요하고 뉴스 앱은 더 적게 필요할 수 있음)
한 가지 일반적인 제안: "실시간 업데이트" 확인란을 추가하고 상태 클라이언트 측을 저장할 수 있습니다.이 옵션을 선택하지 않으면 클라이언트가 "새로 고침" 버튼을 눌러 새 데이터를 다운로드해야 합니다.
@Joe Frambach가 올린 글에서 다소 성장했지만 다음과 같은 추가 사항을 원했습니다.
- jXHR 및 오류/성공 콜백(제공된 경우) 유지
- 각 통화에 대해 제공된 콜백 또는 jqXHR을 트리거하면서 동일한 요청(url 및 옵션 일치 기준)을 해제합니다.
- Ajax 설정을 사용하여 보다 쉽게 구성
- 배치되지 않은 각 에이잭스가 배치를 플러시하도록 하지 마십시오. 별도의 프로세스 IMO여야 하지만 배치 플러시를 강제하는 옵션도 제공합니다.
어느 쪽이든 이 sucker는 기본 .ajax 함수를 재정의하고 영향을 주는 것보다 별도의 플러그인으로 수행하는 것이 더 나을 수 있습니다.즐기세요:
(function($) {
$.ajaxSetup({
batchInterval: 5*60*1000,
flushBatch: false,
batchable: false,
batchDebounce: true
});
var batchRun = 0;
var batches = {};
var oldAjax = $.fn.ajax;
var queueBatch = function(url, options) {
var match = false;
var dfd = new $.Deferred();
batches[url] = batches[url] || [];
if(options.batchDebounce || $.ajaxSettings.batchDebounce) {
if(!options.success && !options.error) {
$.each(batches[url], function(index, batchedAjax) {
if($.param(batchedAjax.options) == $.param(options)) {
match = index;
return false;
}
});
}
if(match === false) {
batches[url].push({options:options, dfds:[dfd]});
} else {
batches[url][match].dfds.push(dfd);
}
} else {
batches[url].push({options:options, dfds:[dfd]);
}
return dfd.promise();
}
var runBatches = function() {
$.each(batches, function(url, batchedOptions) {
$.each(batchedOptions, function(index, batchedAjax) {
oldAjax.apply(null, url, batchedAjax.options).then(
function(data, textStatus, jqXHR) {
var args = arguments;
$.each(batchedAjax.dfds, function(index, dfd) {
dfd.resolve(args);
});
}, function(jqXHR, textStatus, errorThrown) {
var args = arguments;
$.each(batchedAjax.dfds, function(index, dfd) {
dfd.reject(args);
});
}
)
});
});
batches = {};
batchRun = new Date.getTime();
}
setInterval(runBatches, $.ajaxSettings.batchInterval);
$.fn.ajax = function(url, options) {
if (options.batchable) {
var xhr = queueBatch(url, options);
if((new Date.getTime()) - batchRun >= options.batchInterval) {
runBatches();
}
return xhr;
}
if (options.flushBatch) {
runBatches();
}
return oldAjax.call(null, url, options);
};
})(jQuery);
언급URL : https://stackoverflow.com/questions/18909185/batching-requests-to-minimize-cell-drain
'codememo' 카테고리의 다른 글
| 커서가 존재하는지 확인하는 방법(열림 상태 (0) | 2023.08.01 |
|---|---|
| SKlearn, 그리드 검색: 실행 중 진행 상황을 출력하는 방법은 무엇입니까? (0) | 2023.08.01 |
| Javascript: 5의 다음 배수로 반올림합니다. (0) | 2023.08.01 |
| 장식된 기능의 서명 보존 (0) | 2023.08.01 |
| free()는 메모리를 제로로 만드는 것입니까? (0) | 2023.08.01 |