Работа TypeCasting

Попробуйте что-то как:

CREATE FUNCTION ColumnExists(@TableName varchar(100), @ColumnName varchar(100))
RETURNS varchar(1) AS
BEGIN
DECLARE @Result varchar(1);
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = @TableName AND COLUMN_NAME = @ColumnName)
BEGIN
    SET @Result = 'T'
END
ELSE
BEGIN
    SET @Result = 'F'
END
RETURN @Result;
END
GO

GRANT EXECUTE ON  [ColumnExists] TO [whoever]
GO

Тогда использование это как это:

IF ColumnExists('xxx', 'yyyy') = 'F'
BEGIN
  ALTER TABLE xxx
  ADD yyyyy varChar(10) NOT NULL
END
GO

Это должно работать над обоими SQL Server 2000 & SQL Server 2005. Не уверенный в SQL Server 2008, но не смотрите почему нет.

61
задан Martin Liversage 13 August 2012 в 19:13
поделиться

2 ответа

Его можно измерить, если это делается миллиарды раз с очень небольшим количеством другой работы. Я не знаю, будет ли CLR эффективно кэшировать факт работы приведенного текста, поэтому ему не нужно делать это снова - если этого не произойдет сейчас, это может быть сделано в более позднем выпуске. Это может быть сделано в 64-битной JIT, но не в 32-битной версии, или наоборот - вы поняли. Я сомневаюсь, что это будет иметь существенное значение для обычного кода.

54
ответ дан 24 November 2019 в 17:19
поделиться

@dkson: Я тестировал оба метода. Вот что я обнаружил на своем компьютере:

Они примерно такие же по производительности. На самом деле, второй способ оказался немного медленнее. Причина (я считаю) в стоимости дополнительной переменной и начального приведения. Конечно, если вы используете достаточное количество приведений, вы можете вернуть эту стоимость производительности. Похоже, вы окупитесь с точки зрения производительности только после сохранения 20-30 приведений.

Вот результаты двух последних тестовых запусков:

TestMuliCast\_3x:      00:00:00.5970000   
TestSingleCast\_3x:    00:00:00.6020000   
TestMuliCast\_30x:     00:00:06.0930000   
TestSingleCast\_30x:   00:00:06.0480000   

TestMuliCast\_3x:      00:00:00.6120000   
TestSingleCast\_3x:    00:00:00.6250000   
TestMuliCast\_30x:     00:00:06.5490000   
TestSingleCast\_30x:   00:00:06.4440000   

Я также проверил разницу между castclass и isinst . На основании того, что я прочитал:

http://m3mia.blogspot.com/2007/11/comparing-isinst-to-castclass.html
http://www.codeproject.com/KB/cs/ csharpcasts.aspx
http://discuss.joelonsoftware.com/default.asp?dotnet.12.635066. 13

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

TestEmptyLoop:        00:00:00.0870000   
TestDCast\_castclass:  00:00:00.2640000   
TestDCast\_isinst:     00:00:00.3780000   

TestEmptyLoop:        00:00:00.0870000   
TestDCast\_castclass:  00:00:00.2600000   
TestDCast\_isinst:     00:00:00.3750000   

Итак, мистер Скит, я поправляюсь.

Среда:

Windows Vista
Максимальная частота ядра 3,2 ГГц
.NET Framework v2.0.50727

Вот полный исходный код тестов, которые я создал и запустил: (использует структуру микробенчмаркинга Jon Skeets, доступную здесь )

using System;   
using System.Collections;

public class CastingBenchmark   
{
    static Int64 Iterations=100000000;
    static Int64 TestWork = 0;

    public static void Init(string[] args)
    {
        if (args.Length>0)
            Iterations = Int64.Parse(args[0]);
    }

    public static void Reset()
    {
        TestWork = 0;
    }

    internal class BaseType { public void TestBaseMethod() { TestWork++; } }

    internal class DerivedType : BaseType { 
        public void TestDerivedMethod() { TestWork++; }
        public void TestDerivedMethod2() { TestWork++; }
        public void TestDerivedMethod3() { TestWork++; } 
}

[Benchmark]
public static void TestMuliCast_3x()
{
    BaseType TestBaseType = new DerivedType();

    for (int x = 0; x < Iterations; x++)
    {
        ((DerivedType)TestBaseType).TestDerivedMethod();
        ((DerivedType)TestBaseType).TestDerivedMethod2();
        ((DerivedType)TestBaseType).TestDerivedMethod3();
    }
}

[Benchmark]
public static void TestSingleCast_3x()
{
    BaseType TestBaseType = new DerivedType();

    for (int x = 0; x < Iterations; x++)
    {
        DerivedType TestDerivedType = (DerivedType)TestBaseType;
        TestDerivedType.TestDerivedMethod();
        TestDerivedType.TestDerivedMethod2();
        TestDerivedType.TestDerivedMethod3();
    }
}

[Benchmark]
public static void TestMuliCast_30x()
{
    BaseType TestBaseType = new DerivedType();

    for (int x = 0; x < Iterations; x++)
    {
        //Simulate 3 x 10 method calls while casting
        for (int y = 0; y < 10; y++) {

            ((DerivedType)TestBaseType).TestDerivedMethod();
            ((DerivedType)TestBaseType).TestDerivedMethod2();
            ((DerivedType)TestBaseType).TestDerivedMethod3();
        }
    }
}

[Benchmark]
public static void TestSingleCast_30x()
{
    BaseType TestBaseType = new DerivedType();

    for (int x = 0; x < Iterations; x++)
    {
        DerivedType TestDerivedType = (DerivedType)TestBaseType;

        //Simulate 3 x 10 method calls on already-cast object
        for (int y = 0; y < 10; y++)
        {
            TestDerivedType.TestDerivedMethod();
            TestDerivedType.TestDerivedMethod2();
            TestDerivedType.TestDerivedMethod3();
        }
    }
}

    [Benchmark]
    public static void TestEmptyLoop()
    {
        for (int x = 0; x < Iterations; x++)
        {
        }
    }

    [Benchmark]
    public static void TestDCast_castclass()
    {
        BaseType TestDerivedType = new DerivedType();

        for (int x = 0; x < Iterations; x++)
        {
            ((DerivedType)TestDerivedType).TestDerivedMethod();
        }    
    }

    [Benchmark]
    public static void TestDCast_isinst()
    {
        BaseType TestDerivedType = new DerivedType();

        for (int x = 0; x < Iterations; x++)
        {
            (TestDerivedType as DerivedType).TestDerivedMethod();
        }
    }
}

И результирующий IL для методов isinst и castclass :

method public hidebysig static void TestDCast_isinst() cil managed
{
    .custom instance void BenchmarkAttribute::.ctor()
    .maxstack 2
    .locals init (
        [0] class CastingBenchmark/BaseType TestDerivedType,
        [1] int32 x)
    L_0000: newobj instance void CastingBenchmark/DerivedType::.ctor()
    L_0005: stloc.0 
    L_0006: ldc.i4.0 
    L_0007: stloc.1 
    L_0008: br.s L_0019
    L_000a: ldloc.0 
    L_000b: isinst CastingBenchmark/DerivedType
    L_0010: callvirt instance void CastingBenchmark/DerivedType::TestDerivedMethod()
    L_0015: ldloc.1 
    L_0016: ldc.i4.1 
    L_0017: add 
    L_0018: stloc.1 
    L_0019: ldloc.1 
    L_001a: conv.i8 
    L_001b: ldsfld int64 CastingBenchmark::Iterations
    L_0020: blt.s L_000a
    L_0022: ret 
}

.method public hidebysig static void TestDCast_castclass() cil managed
{
    .custom instance void BenchmarkAttribute::.ctor()
    .maxstack 2
    .locals init (
        [0] class CastingBenchmark/BaseType TestDerivedType,
        [1] int32 x)
    L_0000: newobj instance void CastingBenchmark/DerivedType::.ctor()
    L_0005: stloc.0 
    L_0006: ldc.i4.0 
    L_0007: stloc.1 
    L_0008: br.s L_0019
    L_000a: ldloc.0 
    L_000b: castclass CastingBenchmark/DerivedType
    L_0010: callvirt instance void CastingBenchmark/DerivedType::TestDerivedMethod()
    L_0015: ldloc.1 
    L_0016: ldc.i4.1 
    L_0017: add 
    L_0018: stloc.1 
    L_0019: ldloc.1 
    L_001a: conv.i8 
    L_001b: ldsfld int64 CastingBenchmark::Iterations
    L_0020: blt.s L_000a
    L_0022: ret 
}
45
ответ дан 24 November 2019 в 17:19
поделиться
Другие вопросы по тегам:

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