下载app免费领取会员
比较一下Emit的赋值,反射赋值和直接赋值的效率
namespace Assignment
{
class Program
{
static SQLiteConnection conn;
static string dbStr = "test.db";
static void Main(string[] args)
{
CreateDB();
List<Book> books = new List<Book>();
for (int i = 0; i < 1000000; i++)
{
books.Add(new Book());
}
Insert(books);
Insert(new Book());
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var bs = Query<Book>();
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
stopwatch.Restart();
var bs1 = QueryEmit<Book>();
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
stopwatch.Restart();
var bs2 = Query();
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
Console.ReadLine();
}
static void CreateDB()
{
SQLiteConnection.CreateFile(dbStr);
conn = new SQLiteConnection($"Data Source={dbStr};Version=3;");
conn.Open();
string sql = "create table book (id int,name varchar(20), price double)";
SQLiteCommand command = new SQLiteCommand(sql, conn);
command.ExecuteNonQuery();
}
static void Insert(Book book)
{
string sql = "insert into book values(@id,@name,@price)";
SQLiteCommand command = new SQLiteCommand(sql, conn);
command.Parameters.AddWithValue("id", book.Id);
command.Parameters.AddWithValue("name", book.Name);
command.Parameters.AddWithValue("price", book.Price);
command.ExecuteNonQuery();
}
static void Insert(IList<Book> books)
{
string sql = "insert into book values(@id,@name,@price)";
var trans = conn.BeginTransaction();
SQLiteCommand command = new SQLiteCommand(sql, conn, trans);
foreach (var book in books)
{
command.Parameters.Clear();
command.Parameters.AddWithValue("id", book.Id);
command.Parameters.AddWithValue("name", book.Name);
command.Parameters.AddWithValue("price", book.Price);
command.ExecuteNonQuery();
}
trans.Commit();
}
static List<Book> Query()
{
List<Book> result = new List<Book>();
string sql = "select * from book";
SQLiteCommand command = new SQLiteCommand(sql, conn);
var reader = command.ExecuteReader();
while (reader.Read())
{
Book book = new Book();
book.Id = (int)reader.GetValue(0);
book.Name = (string)reader.GetValue(1);
book.Price = (double)reader.GetValue(2);
result.Add(book);
}
return result;
}
static List<T> Query<T>()
{
List<T> result = new List<T>();
string sql = "select * from book";
SQLiteCommand command = new SQLiteCommand(sql, conn);
Type type = typeof(T);
var reader = command.ExecuteReader();
var readerMap = new ReaderMap(reader);
var propertyMap = new PropertyMap(readerMap, type);
while (reader.Read())
{
T r = (T)Activator.CreateInstance(type);
int len = reader.FieldCount;
for(int i = 0; i < len; i++)
{
propertyMap[i].SetValue(r, reader.GetValue(i));
}
result.Add(r);
}
return result;
}
static List<T> QueryEmit<T>()
{
Type type = typeof(T);
List<T> result = new List<T>();
string sql = "select * from book";
SQLiteCommand command = new SQLiteCommand(sql, conn);
var reader = command.ExecuteReader();
var readerMap = new ReaderMap(reader);
var propertyMap = new PropertyMap(readerMap, type);
var func = GetSetter<T>(reader, propertyMap);
while (reader.Read())
{
T r = (T)func(reader);
result.Add(r);
}
return result;
}
static Func<SQLiteDataReader, object> GetSetter<T>(SQLiteDataReader reader, PropertyMap map)
{
Type bookType = typeof(T);
var constructor = bookType.GetConstructors().FirstOrDefault();
DynamicMethod setter = new DynamicMethod("setbook", bookType, new Type[] { typeof(SQLiteDataReader) });
setter.DefineParameter(0, ParameterAttributes.In, "reader");
var iLGenerator = setter.GetILGenerator();
iLGenerator.DeclareLocal(bookType); //Ldloc_0 book
iLGenerator.DeclareLocal(typeof(object));//Ldloc_1 reader.GetValue
iLGenerator.Emit(OpCodes.Nop);
iLGenerator.Emit(OpCodes.Newobj, constructor);
iLGenerator.Emit(OpCodes.Stloc_0);
iLGenerator.Emit(OpCodes.Nop);
var getM = typeof(DbDataReader).GetMethod("GetValue");
int len = map.Count;
for (int i = 0; i < len; i++)
{
///读数据
iLGenerator.Emit(OpCodes.Ldarg_0);
iLGenerator.Emit(OpCodes.Ldc_I4, i);
iLGenerator.Emit(OpCodes.Callvirt, getM);
iLGenerator.Emit(OpCodes.Stloc_1);
iLGenerator.Emit(OpCodes.Nop);
var tp = map[i];
iLGenerator.Emit(OpCodes.Ldloc_0);
iLGenerator.Emit(OpCodes.Ldloc_1);
if (tp.PropertyType.IsValueType)
iLGenerator.Emit(OpCodes.Unbox_Any, tp.PropertyType);
else
iLGenerator.Emit(OpCodes.Castclass, tp.PropertyType);
var mt = tp.GetSetMethod();
iLGenerator.Emit(OpCodes.Callvirt, mt);
iLGenerator.Emit(OpCodes.Nop);
}
iLGenerator.Emit(OpCodes.Ldloc_0);
iLGenerator.Emit(OpCodes.Ret);
return (Func<SQLiteDataReader, object>)setter.CreateDelegate(typeof(Func<SQLiteDataReader,object>));
}
static Book QueryBook(SQLiteDataReader reader)
{
Book book = new Book();
book.Id = (int)reader.GetValue(0);
book.Name = (string)reader.GetValue(1);
book.Price = (double)reader.GetValue(2);
return book;
}
}
public class PropertyMap
{
private PropertyInfo[] properties = null;
public PropertyMap(ReaderMap readerMap,Type type)
{
int len = readerMap.Count;
Count = len;
var ps = type.GetProperties();
properties = new PropertyInfo[len];
for(int i = 0; i < len; i++)
{
var readerItem = readerMap[i];
var tp = ps.FirstOrDefault(p => p.Name.ToUpper() == readerItem.Name.ToUpper());
if (tp != null)
{
if (tp.PropertyType.IsAssignableFrom(readerItem.Type))
{
properties[i] = tp;
}
}
}
}
public PropertyInfo this[int i]
{
get
{
return properties[i];
}
}
public int Count { get; private set; }
}
public class ReaderMap
{
private ReaderItem[] items = null;
public ReaderMap(SQLiteDataReader reader)
{
int len = reader.FieldCount;
Count = len;
items = new ReaderItem[len];
for(int i = 0; i < len; i++)
{
items[i] = new ReaderItem
{
Id = i,
Name = reader.GetName(i),
Type = reader.GetFieldType(i)
};
}
}
public int Count
{
get;
private set;
}
public ReaderItem this[int i]
{
get
{
return items[i];
}
}
}
public class ReaderItem
{
public int Id { get; set; }
public string Name { get; set; }
public Type Type { get; set; }
}
public class Book
{
public int Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public Book()
{
Id = 0;
Name = "Name";
Price = 11.9;
}
public override string ToString()
{
return $"Id; {Id}\tName: {Name}\tPrice: {Price}";
}
}
}
输出结果为
反射时间2725
Emit 时间1745
直接赋值1604
本文版权归腿腿教学网及原创作者所有,未经授权,谢绝转载。
上一篇:二次开发教程:Dapper里使用Attribute自定义映射关系
下一篇:二次开发教程:Emit 循环