Который быстрее? ByVal или ByRef?

Я нуждался в том же самом в Java. Проводя перевод ответ Scala от Zhang Zhan пользователям Spark Java API:

import org.apache.hadoop.mapred.lib.MultipleTextOutputFormat;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaSparkContext;
import scala.Tuple2;

import java.util.Arrays;


class RDDMultipleTextOutputFormat extends MultipleTextOutputFormat {

    @Override
    protected String generateFileNameForKeyValue(A key, B value, String name) {
        return key.toString();
    }
}

public class Main {

    public static void main(String[] args) {
        SparkConf conf = new SparkConf()
                .setAppName("Split Job")
                .setMaster("local");
        JavaSparkContext sc = new JavaSparkContext(conf);
        String[] strings = {"Abcd", "Azlksd", "whhd", "wasc", "aDxa"};
        sc.parallelize(Arrays.asList(strings))
                // The first character of the string is the key
                .mapToPair(s -> new Tuple2<>(s.substring(0,1).toLowerCase(), s))
                .saveAsHadoopFile("output/", String.class, String.class,
                        RDDMultipleTextOutputFormat.class);
        sc.stop();
    }
}

35
задан Community 23 May 2017 в 12:17
поделиться

6 ответов

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

http://www.developer.com/net/vb/article.php/3669066

В ответ на комментарий Топи -

, Который использует больше ресурсов во времени выполнения?

Параметры передаются стеку. Стек очень быстр, потому что его выделение памяти является просто инкрементом указателя для резервирования нового "кадра" или "записи выделения". Большинство параметров.NET не превышает размер регистра машины так мало, если какое-либо пространство "стека" используется для передачи параметров. На самом деле основные типы и указатели оба выделяются на стеке. Размер стека в.NET ограничен 1  МБ. Это должно дать Вам общее представление о том, как немного ресурсов используются передачей параметров.

можно найти этот ряд статей интересным:

Улучшающаяся Производительность Посредством Выделения Стека (управление памятью.NET: Часть 2)

, Который быстрее? ByVal или ByRef.

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

  • Ссылочный тип - Передал ByRef: 420 мс
  • Ссылочный тип - Передали ByVal: 382 мс
  • Тип Значения - Передали ByRef: 421 мс
  • Тип Значения - Передал ByVal: 416 мс
Public Sub Method1(ByRef s As String)
    Dim c As String = s
End Sub

Public Sub Method2(ByVal s As String)
    Dim c As String = s
End Sub

Public Sub Method3(ByRef i As Integer)
    Dim x As Integer = i
End Sub

Public Sub Method4(ByVal i As Integer)
    Dim x As Integer = i
End Sub

Sub Main()

    Dim s As String = "Hello World!"
    Dim k As Integer = 5

    Dim t As New Stopwatch

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method1(s)
    Next
    t.Stop()

    Console.WriteLine("Reference Type - ByRef " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method2(s)
    Next
    t.Stop()

    Console.WriteLine("Reference Type - ByVal " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method3(i)
    Next
    t.Stop()

    Console.WriteLine("Value Type - ByRef " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method4(i)
    Next
    t.Stop()

    Console.WriteLine("Value Type - ByVal " & t.ElapsedMilliseconds)

    Console.ReadKey()

End Sub

Комментирование переменной и присвоения в каждом методе -

  • Ссылочный тип - Передали ByRef: 389 мс
  • Ссылочный тип - Передали ByVal: 349 мс
  • Тип Значения - Передали ByRef: 416 мс
  • Тип Значения - Передали ByVal: 385 мс

можно было прийти к заключению, что передача ссылочных типов (строки, классы) ByVal сэкономит некоторое время. Вы могли бы также сказать, что передача оценивает типы (целое число, байт) - ByVal сэкономит некоторое время.

Снова время незначительно в главной схеме вещей. То, что более важно, использует ByVal и ByRef правильно и понимает то, что продолжается "негласно". Алгоритмы, реализованные в Ваших стандартных программах, будут больше всего, конечно, влиять на время выполнения Вашей программы много раз больше.

124
ответ дан Peter Mortensen 27 November 2019 в 06:20
поделиться

При использовании очень большого типа значения (Гуид является довольно большим, например), это может быть очень немного быстрее для передачи параметра ссылкой. В других случаях, может быть [еще 111] копирование и т.д., когда Вы передаете ссылкой, чем значением - например, если бы у Вас есть параметр байта, тогда один байт является ясно меньше, чем четыре или восемь байтов, которые указатель взял бы при передаче его ссылкой.

На практике, Вы никогда не должны почти волноваться об этом. Запишите, что большинство читаемый кодирует возможный, который почти всегда означает передающие параметры значением вместо ссылки. Я использую ByRef очень редко.

, Если Вы хотите улучшить производительность и думать, что ByRef поможет Вам, сравнительный тест она тщательно (в Вашей точной ситуации) перед согласием на нее.

РЕДАКТИРОВАНИЕ: Я отмечаю в комментариях другому (ранее принятый, теперь удаленный) отвечают, что существует большое недоразумение о том, что ByRef по сравнению с ByVal имеет в виду когда дело доходит до типов значения. Я имею статья о передаче параметров , который оказался популярным за эти годы - это находится в терминологии C#, но те же понятия относятся к VB.NET.

30
ответ дан Jon Skeet 27 November 2019 в 06:20
поделиться

Это зависит. При передаче объекта он уже передает указатель. Вот почему, если Вы передаете в ArrayList (например), и Ваш метод добавляет что-то к ArrayList, тогда код вызова также имеет тот же объект в, он - ArrayList, который был передан в, потому что это - тот же ArrayList. Единственное время, когда это не передает указатель, при передаче переменной с внутренним типом данных, как интервал или двойное, в функцию. В той точке это создает копию. Однако размер данных этих объектов является столь небольшим, что это едва имело бы значение так или иначе, с точки зрения использования памяти или скорости выполнения.

11
ответ дан Kibbee 27 November 2019 в 06:20
поделиться

Если Вы являетесь передающими в ссылочном типе, ByRef медленнее.

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

при передаче типа значения, тогда byref может быть быстрее, если структура имеет многих участников, потому что это только передает единственный указатель вместо того, чтобы копировать значения на стеке. С точки зрения доступа к участникам byref будет медленнее, потому что это должно сделать, дополнительный указатель разыменовывает (SP-> pValueType-> участник по сравнению с SP-> участник).

Большую часть времени в VB Вам не придется волноваться об этом.

В.NET редко иметь типы значения с большим количеством участников. Они являются обычно маленькими. В этом случае передача в типе значения не отличается, чем передача в нескольких аргументах процедуре. Например, если у Вас был код, который передал в Точечном объекте значением, это - перфект, совпал бы с методом, который принял значения X и Y как параметры. Видение DoSomething (x как целое число, y как целое число), вероятно, не вызвало бы проблемы перфекта. На самом деле Вы, вероятно, никогда не думали бы дважды об этом.

при определении больших типов значения Ваш сам, тогда необходимо, вероятно, пересмотреть превращение их в ссылочные типы.

Единственным другим различием является увеличение количества косвенности указателя, требуемой выполнять код. Редко, чтобы Вы когда-либо оптимизировали на том уровне. Большую часть времени, существуют или алгоритмические проблемы, которые можно решить, или узкое место перфекта является связанным IO, таким как ожидание базы данных или запись в файл, в этом случае устранение косвенности указателя не собирается помогать Вам очень.

Так, вместо того, чтобы фокусироваться на или byval или byref быстрее, я рекомендовал бы действительно фокусироваться на том, что дает Вам семантику, в которой Вы нуждаетесь. В целом это - хорошая идея использовать byval, если Вам конкретно не нужен byref. Это делает программу намного легче понять.

5
ответ дан Scott Wisniewski 27 November 2019 в 06:20
поделиться

В то время как я не знаю много о внутренностях.NET, я буду обсуждать то, что я знаю о скомпилированных языках. Это не относится к ссылочным типам и не может быть абсолютно точно о типах значения. Если Вы не знаете различия между типами значения и ссылочными типами, Вы не должны читать это. Я приму 32-разрядный x86 (с 32-разрядными указателями).

  • Передающие значения, меньшие, чем 32 бита все еще, использует 32-разрядный объект на стеке. Часть этого объекта будет "не использована" или "дополнит". Передача таких значений не использует меньше памяти, чем передача 32-разрядных значений.
  • Передающие значения, больше, чем 32 бита, будут использовать больше стекового пространства, чем указатель, и вероятно больше времени копирования.
  • , Если объект передается значением, вызываемый может выбрать объект от стека. Если объект передается ссылкой, вызываемый должен сначала выбрать адрес объекта от стека, и затем выбрать значение объекта откуда-либо. Значением означает то меньше выборки, правильно? Ну, на самом деле выборка должна быть сделана вызывающей стороной - однако, вызывающая сторона должна была уже выбрать по разным причинам, в этом случае выборку, сохраняется.
  • , Очевидно, любые изменения, внесенные в значение ссылкой, должны быть сохранены назад к RAM, тогда как параметром, передаваемым по значению может быть отброшен.
  • лучше передать значением, чем передать ссылкой только, чтобы скопировать параметр в локальную переменную и не коснуться его снова.

вердикт:

намного более важно понять то, что ByVal и ByRef на самом деле делают для Вас и понимают различие между значением и ссылочными типами, чем думать о производительности. Правило номер один к [1 111] использование, какой бы ни метод более соответствует Вашему коду .

Для больших типов значения (больше чем 64 бита), передайте ссылкой, если нет преимущество для передачи значением (таким как более простой код, "это просто имеет смысл" или интерфейсную непротиворечивость).

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

2
ответ дан Artelius 27 November 2019 в 06:20
поделиться

ByVal создает копию переменной, тогда как ByRef передачи указатель. Я поэтому сказал бы, что ByVal медленнее (из-за времени, которое требуется для копирования), и использует больше памяти.

1
ответ дан Siddharth Rout 27 November 2019 в 06:20
поделиться
Другие вопросы по тегам:

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