Насколько дорогой вызовы функции в JavaScript?

Я смотрел на код JavaScript других людей, и я заметил, что многие программисты склонны создавать функции, которые могли быть объединены с функциями, которые называют их. Один пример - это; функция 'initWebGL' могла быть объединена с функцией 'запуска', и она будет функционировать то же. Другой пример находится в источнике этого, где функция 'галочка', которую называют каждыми 15 миллисекундами, выполняет вызовы к двум другим функциям, которые могут точно также быть объединены с 'галочкой'. Я понимаю организационные качества этого, но мне любопытно на предмет эффекта на производительность. Делает эту хорошую практику, особенно полагая, что JavaScript является интерпретируемым языком?

8
задан Skofo 17 January 2010 в 08:25
поделиться

3 ответа

Вот какой код, который работает для меня:

public struct KBDLLHOOKSTRUCT
{
  public Int32 vkCode;
  public Int32 scanCode;
  public Int32 flags;
  public Int32 time;
  public IntPtr dwExtraInfo;
}

private static IntPtr HookCallback(
    int nCode, IntPtr wParam, IntPtr lParam)
{
  if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
  {
    KBDLLHOOKSTRUCT kbd = (KBDLLHOOKSTRUCT) Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
    Debug.WriteLine(kbd.vkCode);  // ***** your code here *****
  }
  return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

Решающее отличие от вашего кода заключается в том, что я вызываю перегрузку Marshal.PtrToStructure (IntPtr, Type), а не перегрузку (IntPtr, object). И я думаю, здесь все пошло не так для тебя. Поскольку при вызове перегрузки (IntPtr, объект) со структурой возникает следующая ошибка:

System.ArgumentException: структура не должна быть классом значений.

Очевидным исправлением этой ошибки является изменение KBDLLLHOOKSTRUCT на класс (ссылочный тип) вместо структуры (тип значения):

public class KBDLLHOOKSTRUCT    // not necessarily the right solution!

Однако это приводит к ошибке, которая означает, что MSDN означает "компоновка параметра strucureType не является последовательной или явной".

System.ArgumentException: указанная структура

Я предполагаю, что именно здесь вы находитесь сейчас, с KBDLLHOOKSTRUCT, объявленным как класс, и получением ошибки "no layout information". Существует два способа решения этой проблемы.

Во-первых, в соответствии с комментарием Эрика Ло, вы можете сохранить свой вызов Marshal.PtrToStructure как есть, сохранить KBDLLHOOKSTRUCT как класс и добавить информацию о макете в KBDLLHOOKSTRUCT:

[StructLayout(LayoutKind.Sequential)]
public class KBDLLHOOKSTRUCT { ... }

Во-вторых, согласно моему образцу кода выше, можно изменить KBDLLHOOKSTRUCT на struct вместо class и изменить вызов Marshal.PtrToStructure на перегрузку (IntPtr, Type):

public struct KBDLLHOOKSTRUCT { ... }

KBDLLHOOKSTRUCT kbd = (KBDLLHOOKSTRUCT) Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));

(В этом случае в структуру KBDLLHOOKSTRUCT можно добавить атрибут [StructLayout (LayoutKind.Sequential)] . Это технически избыточно, но может помочь читателям вашего кода распознать KBDLLHOOKSTRUCT как чувствительный к макету тип взаимодействия.)

Оба эти решения работают для меня в (по общему признанию, простом) тесте. Из двух я бы рекомендовал второй, потому что Win32/C структуры условно объявляются как struct в сценариях P/Invoke - и если ничто другое, имя, которое заканчивается в STRUCT, вероятно, должно быть структурой, а не классом!

Наконец, позвольте мне упомянуть альтернативный подход.

Вместо того, чтобы объявить LowLevelKeyboardProc как получение IntPtr как его lParam, возможно объявить это как получение касательно KBDLLHOOKSTRUCT (где KBDLLHOOKSTRUCT структура , не класс ). Это также требует внесения изменений в CallNextAdingEx, но результатом является упрощение использования информации KBDLLHOOKSTRUCT путем полного исключения вызова Marshal. Использование параметра ref также означает, что вы можете записать в структуру (что я знаю из других вопросов является вашей целью) и не нужно упаковывать его обратно после написания:

private delegate IntPtr LowLevelKeyboardProc(
    int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT kbd);

private static IntPtr HookCallback(
    int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT kbd)
{
  Debug.WriteLine(kbd.vkCode);  // look!  no marshalling!
  return CallNextHookEx(_hookID, nCode, wParam, ref kbd);
}

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
    IntPtr wParam, ref KBDLLHOOKSTRUCT kbd);

(Я, вероятно, должен предупредить вас, однако, что когда я пытался изменить kbd.vkCode, это на самом деле не повлияло на то, что появилось в текстовых полях и т.д. Я не знаю достаточно о низкоуровневых клавиатурных крючках, чтобы знать, почему нет или что мне нужно сделать, чтобы это сработало; извините.)

-121--3052352-

(Хорошо второй раз повезло..)

К вашему сведению, здесь есть еще один вопрос выполнить подключение ()на определенном сетевом адаптере по тем же линиям...

В соответствии с Cable Guy

Windows XP и Windows Server ® 2003 использовать слабую модель хоста для отправки и получает для всех IPv4 интерфейсов и сильная модель хоста для отправки и принимает для всех интерфейсов IPv6. Вы не удается настроить это поведение. Стек TCP/IP следующего поколения в Windows Vista и Windows Server 2008 поддерживает надежные серверные передачи и получает как для IPv4, так и для IPv6 по умолчанию для всех интерфейсов, кроме Интерфейс туннелирования Teredo для Реле для хоста Teredo.

Поэтому, чтобы ответить на ваш вопрос (правильно, на этот раз) в Windows XP и Windows Server 2003 IP4 нет, но для IP6 да. А для Windows Vista и Windows 2008 да (за исключением некоторых обстоятельств).

Также от http://www.codeguru.com/forum/showthread.php?t=487139

В Windows вызов bind () влияет на выбор платы только входящий трафик, не исходящий трафик. Таким образом, на клиент, работающий в многопользовательской системе (т.е. более одной интерфейсной платы), это сетевой стек, который выбирает карта для использования, и она делает выбор на основе только IP-адрес назначения, который, в свою очередь, основан в таблице маршрутизации. Вызов для привязки () не повлияет на выбор карты в любом случае.

Это связано с что-то называемое «слабой конечной системой» («Слабая E/S») модель. Vista изменен на сильная модель E/S, поэтому проблема может не возникает в Vista . Но все предыдущие в версиях Windows использовался слабый E/S модель.

Со слабой моделью E/S это таблица маршрутизации, которая определяет, какая плата используется для исходящего трафика в многосетевая система.

Проверьте, предлагают ли эти потоки некоторые insight:

"Привязка локального сокета к многоканальному узел в Windows XP не работает " http://www.codeguru.com/forum/showthread.php?t=452337

"Подключение порта к указанному Сетевая карта? " http://www.codeguru.com/forum/showthread.php?t=451117 . В этом потоке упоминается Функция CreateIpForwardEntry (), которая (Я думаю) может быть использован для создания запись в таблице маршрутизации, чтобы все исходящий IP-трафик с указанным сервер маршрутизируется через указанный адаптер.

«Работа с 2 платами Ethernet» на http://www.codeguru.com/forum/showthread.php?t=448863

"Странная привязка к многосетевому система "на http://www.codeguru.com/forum/showthread.php?t=452368

Надеюсь, что это поможет!

-121--2162181-

Для любого языка рекомендуется сначала написать код, который можно читать и обслуживать, а затем при необходимости оптимизировать.

Если ваша программа работает достаточно быстро, разделяясь на простые в переваривании фрагменты, оставьте ее путь. Если он бежит медленно, то, как упомянуто о хободаве, профиль, чтобы найти причину медлительности.

Скорее всего, это будет вызвано чем-то, кроме вызова функций, но если это вызвано, тогда начать объединение функций вместе,как только вы отследили это до этого.

9
ответ дан 5 December 2019 в 07:58
поделиться

http://www.slideshare.net/madrobby/extreme-javascript-performance слайды 10..19

10 000 вызовов имеют значение для IE и Firefox. 1 звонок - нет.

8
ответ дан 5 December 2019 в 07:58
поделиться

Лучший способ узнать, как "дорогостоящие вызовы функций", совершенно расплывчатая и контекстно-специфическая метрика, - профилировать ее самостоятельно:

4
ответ дан 5 December 2019 в 07:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: