我听说过这个术语在日志记录中被频繁使用,但似乎找不到一个清晰的定义来解释它究竟是什么。
它只是一类更通用的日志记录/监控工具和活动吗?
请提供示例代码/场景,说明何时/如何应该使用仪器化。
我听说过这个术语在日志记录中被频繁使用,但似乎找不到一个清晰的定义来解释它究竟是什么。
它只是一类更通用的日志记录/监控工具和活动吗?
请提供示例代码/场景,说明何时/如何应该使用仪器化。
我编写执行工具。以下是我对它们的理解:
DLL重写。这是Purify和Quantify等工具所做的。此前有人回答说它们会在编译/链接后进行插装,但这是不正确的。Purify和Quantify会在第一次执行编译/链接周期后插装DLL,然后缓存结果,以便下次更快地使用。对于大型应用程序,对DLL进行分析可能非常耗时。这也存在问题——在1998-2000年间我工作的一家公司中,我们有一个大型的200万行应用程序,在插装期间会花费4个小时,并且其中2个DLL会在插装期间随机崩溃,如果任何一个失败,您都必须删除它们两个,然后重新开始。
原地插装。与DLL重写类似,但不修改DLL,磁盘上的映像保持不变。当首次加载DLL(在启动期间或调用LoadLibrary(Ex)之后)时,适当地钩住DLL函数以执行所需任务。您可以在Microsoft Detours库中看到类似于此的技术。
即时插装。类似于原地插装,但仅在首次执行方法时实际插装方法。这比原地插装更复杂,并延迟插装的惩罚,直到第一次遇到该方法。根据您所做的事情,这可能是好事或坏事。
中间语言插装。这通常用于Java和.Net语言(C#、VB.Net、F#等)。语言被编译为中间语言,然后由虚拟机执行。虚拟机提供了一个接口(JVMTI用于Java,ICorProfiler(2)用于.Net),允许您监视虚拟机正在执行的内容。其中一些选项允许您在将中间语言编译为可执行指令之前修改中间语言。
通过反射的中间语言插装。Java和.Net都提供反射API,允许发现有关方法的元数据。使用此数据,您可以动态创建新方法,并像前面提到的中间语言插装一样插装现有方法。
编译时插装。此技术用于在编译期间向应用程序中插入适当的指令。这种方法并不常用,Visual Studio 的性能分析功能提供了此功能。需要全面重建和链接。
源代码插装。此技术用于修改源代码以插入适当的代码(通常是条件编译,因此您可以将其关闭)。
链接时插装。此技术仅在用跟踪分配器替换默认内存分配器时才真正有用。早期的例子是 1990 年代初的 Solaris/HP 上的 Sentinel 内存泄漏检测器。
各种原地和即时插装方法都存在危险,因为很难安全地停止所有线程并修改代码,而不会冒险需要访问由刚刚暂停的线程持有的锁的 API 调用 - 您不希望这样做,否则您将遇到死锁。您还必须检查是否有其他线程正在执行该方法,因为如果有,则无法修改它。
基于虚拟机的插装方法要容易得多,因为虚拟机保证您可以在那个点安全地修改代码。
我想我已经涵盖了它们所有,希望对您有所帮助。
仪器化通常用于动态代码分析。
与日志记录不同,仪器化通常由软件自动完成,而日志记录需要人工智能插入日志记录代码。
来自维基百科文章的摘录
在计算机编程背景下,仪器化指的是监视或测量产品性能水平、诊断错误和编写跟踪信息的能力。程序员通过代码指令实现仪器化,以监视系统中特定的组件(例如,指令可以输出日志信息以在屏幕上显示)。当应用程序包含仪器化代码时,可以使用管理工具进行管理。仪器化对于审查应用程序的性能是必要的。仪器化方法可以分为两种类型:源仪器化和二进制仪器化。
print("something happened")
代码("手动"方式),或者通过一些在幕后运行并读取时间戳、堆栈跟踪、硬件调用等的程序("自动"方式)来实现。无论维基百科如何说,IT行业中没有标准/广泛认可的定义来描述代码仪表化。
请注意,仪表化是从仪器派生出来的名词,其含义非常广泛。
“代码”也是IT中的一切,我的意思是-数据、服务、一切。
因此,代码仪表化是一组应用程序,它是如此广泛...不值得给它一个单独的名称;-)。
这可能就是为什么这篇维基百科文章只是一个简短的介绍。