В чем преимущество использования аут / реф по сравнению с возвратом?
Я создаю игру, используя платформу XNA, поэтому я использую множество функций, которые работают с векторами. (особенно Vector2 (64-битная структура)). Что меня беспокоит, так это то, что большинство методов определены с параметрами ref и out. Вот пример:
<code>void Min(ref Vector2 value1, ref Vector2 value2, out Vector2 result) </code>
что тоже немного странно выглядит для меня. Есть и еще одинMin
что более очевидно
<code>public static Vector2 Min(Vector2 value1, Vector2 value2); </code>
В основном, почти все функции имеют перегрузки сref
s иout
s. Похоже, другое APIs.
В чем преимущество этого дизайна? XNA оптимизирован для производительности, это может быть результатом? Скажем, Quaternion требует 128b, где мимо ref меньше.
РЕДАКТИРОВАТЬ
Вот тестовый код:
<code>public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; private Vector2 vec1 = new Vector2(1, 2); private Vector2 vec2 = new Vector2(2, 3); private Vector2 min; private string timeRefOut1; private string timeRefOut2; private SpriteFont font; public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; refOut1(); refOut2(); } private Vector2 refOut1() { Vector2 min = Vector2.Min(vec1, vec2); return min; } private Vector2 refOut2() { Vector2.Min(ref vec1, ref vec2, out min); return min; } protected override void Initialize() { const int len = 100000000; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); for (int i = 0; i < len; i++) { refOut1(); } stopWatch.Stop(); timeRefOut1 = stopWatch.ElapsedMilliseconds.ToString(); stopWatch.Reset(); stopWatch.Start(); for (int i = 0; i < len; i++) { refOut2(); } stopWatch.Stop(); timeRefOut2 = stopWatch.ElapsedMilliseconds.ToString(); base.Initialize(); } protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); font = Content.Load<SpriteFont>("SpriteFont1"); } protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(); spriteBatch.DrawString(font, timeRefOut1, new Vector2(200, 200), Color.White); spriteBatch.DrawString(font, timeRefOut2, new Vector2(200, 300), Color.White); spriteBatch.End(); // TODO: Add your drawing code here base.Draw(gameTime); } } </code>
Результаты
refOut1 2200 refOut2 1400Win 7 64bit, .Net 4. XNA 4.0
Также IL код
<code>.method public hidebysig static void Min(valuetype Microsoft.Xna.Framework.Vector2& value1, valuetype Microsoft.Xna.Framework.Vector2& value2, [out] valuetype Microsoft.Xna.Framework.Vector2& result) cil managed { // Code size 69 (0x45) .maxstack 3 IL_0000: ldarg.2 IL_0001: ldarg.0 IL_0002: ldfld float32 Microsoft.Xna.Framework.Vector2::X IL_0007: ldarg.1 IL_0008: ldfld float32 Microsoft.Xna.Framework.Vector2::X IL_000d: blt.s IL_0017 IL_000f: ldarg.1 IL_0010: ldfld float32 Microsoft.Xna.Framework.Vector2::X IL_0015: br.s IL_001d IL_0017: ldarg.0 IL_0018: ldfld float32 Microsoft.Xna.Framework.Vector2::X IL_001d: stfld float32 Microsoft.Xna.Framework.Vector2::X IL_0022: ldarg.2 IL_0023: ldarg.0 IL_0024: ldfld float32 Microsoft.Xna.Framework.Vector2::Y IL_0029: ldarg.1 IL_002a: ldfld float32 Microsoft.Xna.Framework.Vector2::Y IL_002f: blt.s IL_0039 IL_0031: ldarg.1 IL_0032: ldfld float32 Microsoft.Xna.Framework.Vector2::Y IL_0037: br.s IL_003f IL_0039: ldarg.0 IL_003a: ldfld float32 Microsoft.Xna.Framework.Vector2::Y IL_003f: stfld float32 Microsoft.Xna.Framework.Vector2::Y IL_0044: ret } // end of method Vector2::Min </code>
а такж
<code>.method public hidebysig static valuetype Microsoft.Xna.Framework.Vector2 Min(valuetype Microsoft.Xna.Framework.Vector2 value1, valuetype Microsoft.Xna.Framework.Vector2 value2) cil managed { // Code size 80 (0x50) .maxstack 3 .locals init (valuetype Microsoft.Xna.Framework.Vector2 V_0) IL_0000: ldloca.s V_0 IL_0002: ldarga.s value1 IL_0004: ldfld float32 Microsoft.Xna.Framework.Vector2::X IL_0009: ldarga.s value2 IL_000b: ldfld float32 Microsoft.Xna.Framework.Vector2::X IL_0010: blt.s IL_001b IL_0012: ldarga.s value2 IL_0014: ldfld float32 Microsoft.Xna.Framework.Vector2::X IL_0019: br.s IL_0022 IL_001b: ldarga.s value1 IL_001d: ldfld float32 Microsoft.Xna.Framework.Vector2::X IL_0022: stfld float32 Microsoft.Xna.Framework.Vector2::X IL_0027: ldloca.s V_0 IL_0029: ldarga.s value1 IL_002b: ldfld float32 Microsoft.Xna.Framework.Vector2::Y IL_0030: ldarga.s value2 IL_0032: ldfld float32 Microsoft.Xna.Framework.Vector2::Y IL_0037: blt.s IL_0042 IL_0039: ldarga.s value2 IL_003b: ldfld float32 Microsoft.Xna.Framework.Vector2::Y IL_0040: br.s IL_0049 IL_0042: ldarga.s value1 IL_0044: ldfld float32 Microsoft.Xna.Framework.Vector2::Y IL_0049: stfld float32 Microsoft.Xna.Framework.Vector2::Y IL_004e: ldloc.0 IL_004f: ret } // end of method Vector2::Min </code>
акладные расходы @Seems вызваны временным вектором. Также я попробовал 1GHz WP 7.5 устройство:
1979 1677Количество тиков на порядок меньшее количество итераций.