在之前的日誌調用中用到了委託實現,現在把委託去掉,效率又有一定的提高了,說的不好聽從高大上(委託)到原始的調用,代碼如下:
/*********************************************
* CLR 版本: 4.0.30319.42000
* 類 名 稱: Logger
* 機器名稱: MS-20170310FLQY
* 命名空間: Utils
* 文 件 名: Logger
* 創建時間: 2017/5/12 10:16:17
* 作 者: Choj
* 說 明:
* 修改時間:
* 修 改 人:
*
*********************************************/
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Utils
{
/// <summary>
/// 異步日誌實現類
/// </summary>
public class Logger
{
#region 屬性
/// <summary>
/// 實例化
/// </summary>
public static Logger Instance = new Logger();
/// <summary>
/// 日誌保存的路徑
/// </summary>
string LogPath = ConfigurationManager.AppSettings["LogPath"];
/// <summary>
/// 文件夾路徑
/// </summary>
string LogDir = ConfigurationManager.AppSettings["LogDir"];
/// <summary>
/// 文件夾路徑
/// </summary>
string LogDateFormat = ConfigurationManager.AppSettings["LogDateFormat"] ?? "yyyyMMddHH";
#endregion
#region 構造函數
/// <summary>
/// 默認構造函數
/// </summary>
public Logger()
{ }
/// <summary>
/// 夠着函數
/// </summary>
/// <param name="LogDir">日誌的文件夾</param>
public Logger(string LogDir)
{
this.LogDir = LogDir;
}
/// <summary>
/// 構造函數
/// </summary>
/// <param name="path"></param>
/// <param name="LogDir"></param>
public Logger(string path, string LogDir)
{
this.LogPath = path;
this.LogDir = LogDir;
}
/// <summary>
/// 構造函數
/// </summary>
/// <param name="path">路徑</param>
/// <param name="LogDir">日誌路徑</param>
/// <param name="logDateFormat">文件格式</param>
public Logger(string path, string logDir, string logDateFormat)
{
this.LogPath = path;
this.LogDir = logDir;
this.LogDateFormat = logDateFormat;
}
#endregion
#region 錯誤日誌記錄
/// <summary>
/// 添加錯誤日誌
/// </summary>
/// <param name="ex">錯誤的信息</param>
/// <param name="parms">其他的參數</param>
public void Error(Exception ex, params object[] parms)
{
var strMsg = new StringBuilder();
strMsg.AppendFormat("\r\n");
strMsg.AppendFormat("Message:{0}", ex.Message);
strMsg.AppendFormat("\r\n");
strMsg.AppendFormat("StackTrace:{0}", ex.StackTrace);
strMsg.AppendFormat("\r\n");
strMsg.AppendFormat("source:{0}", ex.Source);
strMsg.AppendFormat("\r\n");
strMsg.AppendFormat("InnerException:{0}", ex.InnerException);
strMsg.AppendFormat("\r\n");
AddQueue(strMsg.ToString(), "Error", parms);
}
/// <summary>
/// 調試日誌
/// </summary>
/// <param name="msg">信息</param>
/// <param name="parms">其他的參數</param>
public void Debug(string msg, params object[] parms)
{
AddQueue(msg, "Debug", parms);
}
/// <summary>
/// 調試日誌
/// </summary>
/// <param name="msg">信息</param>
/// <param name="parms">其他的參數</param>
public void Info(string msg, params object[] parms)
{
AddQueue(msg, "Info", parms);
}
/// <summary>
/// 警告
/// </summary>
/// <param name="msg">信息</param>
/// <param name="parms">其他的參數</param>
public void Warn(string msg, params object[] parms)
{
AddQueue(msg, "Warn", parms);
}
/// <summary>
/// 錯誤
/// </summary>
/// <param name="msg">信息</param>
/// <param name="parms">其他的參數</param>
public void Error(string msg, params object[] parms)
{
AddQueue(msg, "Error", parms);
}
/// <summary>
/// 致命錯誤
/// </summary>
/// <param name="msg">信息</param>
/// <param name="parms">其他的參數</param>
public void Fatal(string msg, params object[] parms)
{
AddQueue(msg, "Fatal", parms);
}
#endregion
#region 添加日誌到隊列
/// <summary>
/// 添加日誌到隊列
/// </summary>
/// <param name="msg"></param>
/// <param name="level"></param>
/// <param name="parms"></param>
private void AddQueue(string msg, string level, params object[] parms)
{
QueueHelper<LogEntity>.Instance.Enqueue(new LogEntity()
{
Level = level,
Msg = msg,
Parms = parms
});
}
#endregion
#region 保存日誌信息
/// <summary>
/// 初始化
/// </summary>
public void Init()
{
ThreadPool.QueueUserWorkItem(o =>
{
while (true)
{
var queue = QueueHelper<LogEntity>.Instance.Dequeue();
if (queue != null)
{
#region 基本的設置
var fileName = System.DateTime.Now.ToString(LogDateFormat) + ".log";
string path = LogPath;
if (string.IsNullOrEmpty(path))
{
path = System.AppDomain.CurrentDomain.BaseDirectory;
}
path = string.Format("{0}\\Log\\{1}\\{2}\\", path, queue.Level, LogDir);
while (path.Contains(@"\\"))
{
path = path.Replace(@"\\", @"\");
}
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string filePath = path + fileName;
#endregion
using (var sw = new StreamWriter(filePath, true))
{
var strMsg = new StringBuilder();
strMsg.AppendFormat(DateTime.Now.ToString());
strMsg.Append("\r\n");
strMsg.AppendFormat("{0}", queue.Msg);
if (queue.Parms != null)
{//--- 其他的參數 ---
foreach (var parm in queue.Parms)
{
strMsg.Append("\r\n");
strMsg.Append(parm);
}
}
strMsg.Append("\r\n");
sw.WriteLine(strMsg.ToString());
}
}
}
});
}
#endregion
}
/// <summary>
/// 保存日誌
/// </summary>
public class LogEntity
{
private string msg;
/// <summary>
/// 日誌基本信息
/// </summary>
public string Msg
{
get { return msg; }
set { msg = value; }
}
private string level;
/// <summary>
/// 日誌等級
/// </summary>
public string Level
{
get { return level; }
set { level = value; }
}
private object[] parms;
/// <summary>
/// 其他的參數
/// </summary>
public object[] Parms
{
get { return parms; }
set { parms = value; }
}
}
}
測試代碼:
Utils.Logger.Instance.Init();
var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 10000; i++)
{
Utils.Logger.Instance.Debug("Logger測試");
}
sw.Stop();
Console.WriteLine("Logger 日誌循環10000次,總耗時:" + sw.ElapsedMilliseconds);
sw = new Stopwatch();
sw.Start();
Parallel.For(0, 100, (i) =>
{
for (int j = 0; j < 100; j++)
{
Utils.Logger.Instance.Debug("Logger測試");
}
});
sw.Stop();
Console.WriteLine("Logger 並行循環10000次,總耗時:" + sw.ElapsedMilliseconds);
Console.ReadKey();
這個效率感覺應該還是可以了,但是優化的還有很多,但是思想基本就是這樣了,日誌的保存根據自己的需要可以自己添加對應的功能,比如保存到mongodb(nosql),或者關係數據庫中
1000000的數據測試的代碼和結果:
Utils.Logger.Instance.Init();
var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000000; i++)
{
Utils.Logger.Instance.Debug("Logger測試");
}
sw.Stop();
Console.WriteLine("Logger 日誌循環1000000次,總耗時:" + sw.ElapsedMilliseconds);
sw = new Stopwatch();
sw.Start();
Parallel.For(0, 100, (i) =>
{
for (int j = 0; j < 10000; j++)
{
Utils.Logger.Instance.Debug("Logger測試");
}
});
sw.Stop();
Console.WriteLine("Logger 並行循環1000000次,總耗時:" + sw.ElapsedMilliseconds);
Console.ReadKey();