Initialize reference type static fields inline

本文探讨了在Visual Studio Team System中如何通过内联初始化静态字段来提高性能,并对比了使用显式静态构造函数与内联初始化的区别。文章提供了具体的代码示例说明如何避免不必要的静态构造函数以减少运行时检查。
Visual Studio Team System 
Initialize reference type static fields inline 

 

TypeName

InitializeReferenceTypeStaticFieldsInline

CheckId

CA1810

Category

Microsoft.Performance

Breaking Change

NonBreaking

Cause

A reference type declares an explicit static constructor.

Rule Description

When a type declares an explicit static constructor, the just-in-time (JIT) compiler adds a check to each of the type's static methods and instance constructors to ensure that the static constructor was previously called. Static initialization is triggered when any static member is accessed or when an instance of the type is created. However, static initialization is not triggered if you declare a variable of the type but do not use it, which can be important if the initialization changes global state.

When all static data is initialized inline and an explicit static constructor is not declared, Microsoft intermediate language (MSIL) compilers add the beforefieldinit flag and an implicit static constructor, which initializes the static data, to the MSIL type definition. When the JIT compiler encounters the beforefieldinit flag, in most cases the static constructor checks are not added. Static initialization is guaranteed to occur at some time before any of the static fields are accessed but not before a static method or instance constructor is invoked. Note that static initialization can occur at any time after a variable of the type is declared.

Static constructor checks can reduce performance. Often a static constructor is used only to initialize static fields, in which case it is only necessary to ensure that static initialization occurs before the first access of a static field. The beforefieldinit behavior is appropriate for these and most other types. It is only inappropriate when static initialization affects global state and one of the following is true:

  • The affect on global state is expensive and is not needed if the type is not used.

  • The global state effects can be accessed without accessing any static fields of the type.

How to Fix Violations

To fix a violation of this rule, initialize all static data when it is declared and remove the static constructor.

When to Exclude Warnings

It is safe to exclude a warning from this rule if performance is not a concern; or if global state changes due to static initialization are expensive, or must be guaranteed to occur before a static method of the type is called or an instance of the type is created.

Example

The following example shows a type, StaticConstructor, that violates the rule and a type, NoStaticConstructor, that replaces the static constructor with inline initialization to satisfy the rule.

Visual Basic Copy Code
Imports System
Imports System.Resources

Namespace PerformanceLibrary

   Public Class StaticConstructor

      Shared someInteger As Integer
      Shared resourceString As String 

      Shared Sub New()

         someInteger = 3
         Dim stringManager As New ResourceManager("strings", _
            System.Reflection.Assembly.GetExecutingAssembly())
         resourceString = stringManager.GetString("string")

      End Sub

   End Class


   Public Class NoStaticConstructor

      Shared someInteger As Integer = 3
      Shared resourceString As String = InitializeResourceString()

      Shared Private Function InitializeResourceString()

         Dim stringManager As New ResourceManager("strings", _
            System.Reflection.Assembly.GetExecutingAssembly())
         Return stringManager.GetString("string")

      End Function

   End Class

End Namespace
using System;
using System.Reflection;
using System.Resources;

namespace PerformanceLibrary
{
   public class StaticConstructor
   {
      static int someInteger;
      static string resourceString;

      static StaticConstructor()
      {
         someInteger = 3;
         ResourceManager stringManager = 
            new ResourceManager("strings", Assembly.GetExecutingAssembly());
         resourceString = stringManager.GetString("string");
      }
   }

   public class NoStaticConstructor
   {
      static int someInteger = 3;
      static string resourceString = InitializeResourceString();

      static string InitializeResourceString()
      {
         ResourceManager stringManager = 
            new ResourceManager("strings", Assembly.GetExecutingAssembly());
         return stringManager.GetString("string");
      }
   }
}

Note the addition of the beforefieldinit flag on the MSIL definition for the NoStaticConstructor class.

Output
.class public auto ansi StaticConstructor
       extends [mscorlib]System.Object
{
} // end of class StaticConstructor

.class public auto ansi beforefieldinit NoStaticConstructor
       extends [mscorlib]System.Object
{
} // end of class NoStaticConstructor
/** * vhost_rdma_create_qp - Create a Queue Pair (QP) for vhost RDMA device * @dev: Pointer to the vhost RDMA device * @in: Input iovec containing command from userspace * @out: Output iovec for returning response to userspace * * This function handles the creation of a QP based on the requested type. * It allocates resources, initializes the QP, and returns the assigned QPN. * * Returns 0 on success, or a negative error code on failure. */ static int vhost_rdma_create_qp(struct vhost_rdma_device *dev, struct iovec *in, struct iovec *out) { struct vhost_rdma_cmd_create_qp *create_cmd; struct vhost_rdma_ack_create_qp *ack_rsp; struct vhost_rdma_qp *qp = NULL; uint32_t qpn; int ret = 0; /* Validate input parameters */ if (!dev || !in || !out) { RDMA_LOG_ERR("Invalid argument: null pointer detected"); return -EINVAL; } /* Safely map iovec buffers to command and response structures */ CHK_IOVEC(create_cmd, in); CHK_IOVEC(ack_rsp, out); /* Handle different QP types */ switch (create_cmd->qp_type) { case VHOST_RDMA_IB_QPT_GSI: /* Only one GSI QP is allowed, check if already created */ if (dev->qp_gsi->valid) { RDMA_LOG_ERR("GSI QP already exists, cannot create duplicate"); return -EINVAL; } qp = dev->qp_gsi; /* Use pre-allocated GSI QP */ qpn = VHOST_RDMA_GSI_QPN; /* Assign well-known QPN (e.g., 1) */ break; case VHOST_RDMA_IB_QPT_RC: case VHOST_RDMA_IB_QPT_UD: case VHOST_RDMA_IB_QPT_UC: /* Allocate QP from pool for reliable/unordered connection types */ qp = vhost_rdma_pool_alloc(&dev->qp_pool, &qpn); if (!qp) { RDMA_LOG_ERR("Failed to allocate QP from pool for type %d", create_cmd->qp_type); return -ENOMEM; } break; default: /* Unsupported QP type */ RDMA_LOG_ERR("Unsupported QP type %d", create_cmd->qp_type); return -EINVAL; } /* Initialize reference counter for the newly acquired QP */ vhost_rdma_ref_init(qp); /* Set QP number */ qp->qpn = qpn; /* Initialize QP internal state (queues, CQ bindings, etc.) */ if (vhost_rdma_qp_init(dev, qp, create_cmd)) { RDMA_LOG_ERR("Failed to initialize QP %u", qpn); ret = -EINVAL; goto err_qp_init; } /* Populate acknowledgment response with allocated QPN */ ack_rsp->qpn = qpn; /* Log successful QP creation with key attributes */ RDMA_LOG_INFO("Created QP %u | Type=%d | SQ_VQ_ID=%u | RQ_VQ_ID=%u | " "Send_CQN=%u | Recv_CQN=%u", qp->qpn, create_cmd->qp_type, qp->sq.queue.vq->id, qp->rq.queue.vq->id, create_cmd->send_cqn, create_cmd->recv_cqn); return 0; err_qp_init: /* Clean up reference on initialization failure */ vhost_rdma_drop_ref(qp, dev, qp); return ret; } static int vhost_rdma_modify_qp(struct vhost_rdma_device *dev, struct iovec *in, CTRL_NO_RSP) { struct vhost_rdma_cmd_modify_qp *cmd; struct vhost_rdma_qp *qp; int err; CHK_IOVEC(cmd, in); qp = vhost_rdma_pool_get(&dev->qp_pool, cmd->qpn); if (unlikely(qp == NULL)) { RDMA_LOG_ERR("qp not found"); } // FIXME: check in driver? err = vhost_rdma_qp_validate(dev, qp, cmd); if (err) goto err; err = vhost_rdma_qp_modify(dev, qp, cmd); if (err) goto err; return 0; err: return err; } void vhost_rdma_av_to_attr(struct vhost_rdma_av *av, struct vhost_rdma_ah_attr *attr) { struct vhost_rdma_global_route *grh = &attr->grh; rte_memcpy(grh->dgid, av->grh.dgid, sizeof(av->grh.dgid)); grh->flow_label = av->grh.flow_label; grh->sgid_index = av->grh.sgid_index; grh->hop_limit = av->grh.hop_limit; grh->traffic_class = av->grh.traffic_class; rte_memcpy(attr->dmac, av->dmac, ETH_ALEN); } int vhost_rdma_qp_query(struct vhost_rdma_qp *qp, struct vhost_rdma_ack_query_qp *rsp) { rsp->qp_state = qp->attr.qp_state; rsp->path_mtu = qp->attr.path_mtu; rsp->max_rd_atomic = qp->attr.max_rd_atomic; rsp->max_dest_rd_atomic = qp->attr.max_dest_rd_atomic; rsp->min_rnr_timer = qp->attr.min_rnr_timer; rsp->timeout = qp->attr.timeout; rsp->retry_cnt = qp->attr.retry_cnt; rsp->rnr_retry = qp->attr.rnr_retry; rsp->qkey = qp->attr.qkey; rsp->dest_qp_num = qp->attr.dest_qp_num; rsp->qp_access_flags = qp->attr.qp_access_flags; rsp->rate_limit = qp->attr.rate_limit; rsp->rq_psn = qp->resp.psn; rsp->sq_psn = qp->req.psn; rsp->cap.max_send_wr = qp->attr.cap.max_send_wr; rsp->cap.max_send_sge = qp->attr.cap.max_send_sge; rsp->cap.max_inline_data = qp->attr.cap.max_inline_data; rsp->cap.max_recv_wr = qp->attr.cap.max_recv_wr; rsp->cap.max_recv_sge = qp->attr.cap.max_recv_sge; vhost_rdma_av_to_attr(&qp->av, &rsp->ah_attr); if (qp->req.state == QP_STATE_DRAIN) { rsp->sq_draining = 1; } else { rsp->sq_draining = 0; } return 0; } static int vhost_rdma_query_qp(struct vhost_rdma_device *dev, struct iovec *in, struct iovec *out) { struct vhost_rdma_cmd_query_qp *cmd; struct vhost_rdma_ack_query_qp *rsp; struct vhost_rdma_qp *qp; CHK_IOVEC(cmd, in); CHK_IOVEC(rsp, out); qp = vhost_rdma_pool_get(&dev->qp_pool, cmd->qpn); vhost_rdma_qp_query(qp, rsp); return 0; } void vhost_rdma_qp_destroy(struct vhost_rdma_qp *qp) { qp->valid = 0; qp->qp_timeout_ticks = 0; vhost_rdma_cleanup_task(&qp->resp.task); if (qp->type == VHOST_RDMA_IB_QPT_RC) { rte_timer_stop_sync(&qp->retrans_timer); rte_timer_stop_sync(&qp->rnr_nak_timer); } vhost_rdma_cleanup_task(&qp->req.task); vhost_rdma_cleanup_task(&qp->comp.task); /* flush out any receive wr's or pending requests */ __vhost_rdma_do_task(&qp->req.task); if (qp->sq.queue.vq) { __vhost_rdma_do_task(&qp->comp.task); __vhost_rdma_do_task(&qp->req.task); } vhost_rdma_queue_cleanup(qp, &qp->sq.queue); vhost_rdma_queue_cleanup(qp, &qp->rq.queue); qp->sq.queue.vq->last_avail_idx = 0; qp->sq.queue.vq->last_used_idx = 0; qp->rq.queue.vq->last_avail_idx = 0; qp->rq.queue.vq->last_used_idx = 0; rte_free(qp->req_pkts); rte_free(qp->resp_pkts); } static int vhost_rdma_destroy_qp(struct vhost_rdma_device *dev, struct iovec *in, CTRL_NO_RSP) { struct vhost_rdma_cmd_destroy_qp *cmd; struct vhost_rdma_qp* qp; CHK_IOVEC(cmd, in); qp = vhost_rdma_pool_get(&dev->qp_pool, cmd->qpn); vhost_rdma_qp_destroy(qp); if (qp->type != VHOST_RDMA_IB_QPT_GSI) vhost_rdma_drop_ref(qp, dev, qp); return 0; } 这个也生成一条,属于examples/vhost_user_rdma模块
最新发布
12-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值