开发者实用函数两则:统计代码行数与每行代码的执行时间

Posted sp42a

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了开发者实用函数两则:统计代码行数与每行代码的执行时间相关的知识,希望对你有一定的参考价值。

代码行数统计

作者:https://blog.csdn.net/u014800380/article/details/73770823

import org.springframework.util.ObjectUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

/**
 * 代码行数统计
 * 
 * @author https://blog.csdn.net/u014800380/article/details/73770823
 *
 */
public class CalculateRows {
	public static long classcount = 0; // Java类的数量
	public static long normalLines = 0; // 空行
	public static long commentLines = 0; // 注释行
	public static long writeLines = 0; // 代码行
	public static long allLines = 0; // 代码行

	/**
	 * 查找出一个目录下所有的.java文件
	 * 
	 * @param f    指定的文件目录
	 * @param type
	 */
	public static void treeFile(File f, String type) {
		File[] childs = f.listFiles();

		if (ObjectUtils.isEmpty(childs))
			return;

		for (File file : childs) {
			if (!file.isDirectory()) {
				if (file.getName().endsWith(type))
					countFile(file);
			} else
				treeFile(file, type);
		}
	}

	/**
	 * 
	 * @param file
	 */
	public static void countFile(File file) {
		classcount++;
		boolean comment = false;

		try (BufferedReader br = new BufferedReader(new FileReader(file));) {
			String line = "";

			while ((line = br.readLine()) != null) {
				allLines++;
				line = line.trim();

				if (line.matches("^[//s&&[^//n]]*$")) {// 这一行匹配以空格开头,但不是以回车符开头,但以回车符结尾
					normalLines++;
				} else if (line.startsWith("/*") && !line.endsWith("*/")) {// 匹配以/*......*/括住的多行注释
					commentLines++;
					comment = true;
				} else if (true == comment) {
					commentLines++;

					if (line.endsWith("*/"))
						comment = false;
					// 匹配以//开头的单行注释,及以/*......*/括住的单行注释
				} else if (line.startsWith("//") || (line.startsWith("/*") && line.endsWith("*/")))
					commentLines++;
				else // 其他的就是代码行
					writeLines++;
			}
		} catch (IOException e) {
		}
	}
}

简单统计Java方法中每行代码的执行时间

在需要调试的方法中隔几行插入 Timer.set (数字或字符)方法,程序结束前调用 Timer.print() 方法就行了。因为目的只是排查方法执行时间,调试完成后可以将 set() 方法注释掉,然后利用 Eclipse 的查错功能将所有 Timer.set() 方法找出来删除。

作者:https://my.oschina.net/drinkjava2/blog/1622179

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 简单统计Java方法中每行代码的执行时间
 * 
 */
public class Timer {
	private static String lastMark = "start";
	
	private static String TPL = "%20s, Total times:%20s,  Repeat times:%20s, Avg times:%20s ";

	private static long lastTime = System.nanoTime();

	private static final Map<String, Long> timeMap = new LinkedHashMap<>();

	private static final Map<String, Long> timeHappenCount = new LinkedHashMap<>();

	public static void set(int mark) {
		set("" + mark);
	}

	public static void set(String mark) {
		long thisTime = System.nanoTime();
		String key = lastMark + "->" + mark;
		Long lastSummary = timeMap.get(key);

		if (lastSummary == null)
			lastSummary = 0l;

		timeMap.put(key, System.nanoTime() - lastTime + lastSummary);
		Long lastCount = timeHappenCount.get(key);
		
		if (lastCount == null)
			lastCount = 0L;

		timeHappenCount.put(key, ++lastCount);
		lastTime = thisTime;
		lastMark = mark;
	}

	public static void print() {
		for (String key : timeMap.keySet()) {
			Long value = timeMap.get(key), _value = timeHappenCount.get(key);
			String.format(TPL, key, value, _value, value / _value);
		}
	}
}

使用例子:

import org.junit.Test;

import com.ajaxjs.developer.Timer;

public class TestVersion {
	@Test
	public void testVersion() {
		Timer.set(1);
		new Version();
		Timer.set(2);
		Version.tomcatVersionDetect("Tomcat/8");
		Timer.print();
	}
}

Snowflake:雪花生成器

/**
 * Twitter 的分布式自增ID算法 Snowflake:雪花生成器
 * 
 */
public class SnowflakeIdWorker {
	/** 开始时间截 (2015-01-01) */
	private final long twepoch = 1420041600000L;

	/** 机器id所占的位数 */
	private final long workerIdBits = 5L;

	/** 数据标识id所占的位数 */
	private final long datacenterIdBits = 5L;

	/** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
	private final long maxWorkerId = -1L ^ (-1L << workerIdBits);

	/** 支持的最大数据标识id,结果是31 */
	private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);

	/** 序列在id中占的位数 */
	private final long sequenceBits = 12L;

	/** 机器ID向左移12位 */
	private final long workerIdShift = sequenceBits;

	/** 数据标识id向左移17位(12+5) */
	private final long datacenterIdShift = sequenceBits + workerIdBits;

	/** 时间截向左移22位(5+5+12) */
	private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

	/** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */
	private final long sequenceMask = -1L ^ (-1L << sequenceBits);

	/** 工作机器ID(0~31) */
	private long workerId;

	/** 数据中心ID(0~31) */
	private long datacenterId;

	/** 毫秒内序列(0~4095) */
	private long sequence = 0L;

	/** 上次生成ID的时间截 */
	private long lastTimestamp = -1L;

	/**
	 * 构造函数
	 * 
	 * @param workerId     工作ID (0~31)
	 * @param datacenterId 数据中心ID (0~31)
	 */
	public SnowflakeIdWorker(long workerId, long datacenterId) {
		if (workerId > maxWorkerId || workerId < 0)
			throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));

		if (datacenterId > maxDatacenterId || datacenterId < 0)
			throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));

		this.workerId = workerId;
		this.datacenterId = datacenterId;
	}

	/**
	 * 获得下一个ID (该方法是线程安全的)
	 * 
	 * @return SnowflakeId
	 */
	public synchronized long nextId() {
		long timestamp = System.currentTimeMillis();

		// 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
		if (timestamp < lastTimestamp)
			throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));

		if (lastTimestamp == timestamp) {// 如果是同一时间生成的,则进行毫秒内序列
			sequence = (sequence + 1) & sequenceMask;

			if (sequence == 0)// 毫秒内序列溢出
				timestamp = tilNextMillis(lastTimestamp);// 阻塞到下一个毫秒,获得新的时间戳
		} else
			sequence = 0L;// 时间戳改变,毫秒内序列重置

		lastTimestamp = timestamp;// 上次生成ID的时间截

		// 移位并通过或运算拼到一起组成64位的ID
		return ((timestamp - twepoch) << timestampLeftShift) //
				| (datacenterId << datacenterIdShift) //
				| (workerId << workerIdShift) //
				| sequence;
	}

	/**
	 * 阻塞到下一个毫秒,直到获得新的时间戳
	 * 
	 * @param lastTimestamp 上次生成ID的时间截
	 * @return 当前时间戳
	 */
	protected long tilNextMillis(long lastTimestamp) {
		long timestamp = System.currentTimeMillis();

		while (timestamp <= lastTimestamp)
			timestamp = System.currentTimeMillis();

		return timestamp;
	}

	public static final SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);

	/**
	 * 新的 id,这是常用的方法
	 * 
	 * @return 新的 id
	 */
	public static long getId() {
		return idWorker.nextId();
	}

	/**
	 * 新的 id,这是常用的方法
	 * 
	 * @return 新的 id
	 */
	public static String getIdStr() {
		return getId() + "";
	}
}

以上是关于开发者实用函数两则:统计代码行数与每行代码的执行时间的主要内容,如果未能解决你的问题,请参考以下文章

统计代码行数的实用脚本

oracle查询表统计行数与注释

如何执行bash脚本时,显示行数

程序员实用工具,推荐一款代码统计神器GitStats

如何在C++中 统计多行文本中的行数、单词数及字符数

Ubuntu下如何统计代码行数